Location via proxy:   
[Report a bug]   [Manage cookies]                

Handling fbAsyncInit? - use $.Deferred()

I’m excited to have come across a straightforward example of a practical usage of $.Deferred that has nothing to do with ajax calls.

I’ve seen an assortment of hacks to handle the complexity needed handle what code needs to be run after the Facebook JS SDK has been loaded onto a web page.

There are long lists of callbacks.

There are global booleans.

There are global function references, just to allow for two callbacks.

You don’t have to manually keep track of whether or not the facebook initalization callback has been called. You don’t have to manually handle overwriting the global function fbAsyncInit with references to all the other functions that you need to execute. Using a deferred object is the best way to address these issues, and can even keep you from adding any more global variables than needed.

The plan to tackle this problem is to create a deferred object that is fulfilled when the facebook SDK has finished loaded. Add callbacks wherever you need in your application to this deferred object. Once the SDK has loaded, all of the callbacks will fire, and any callbacks that are added after the SDK loads, will be fired immediately.

Once you have this in your application, anywhere after it, you can add functions that will be executed after the SDK has loaded by using window.fbAsyncInit.fbLoaded.done(callback);

Also, using this method, you can write code that waits on multiple asynchronous events using jQuery’s $.when(). A quick google should have you setup with a lot of information on how to do that.

This post was slightly inspired by reading this post on Deferred method combinators, so you will probably find that a good read if you like this. Please let me know if you have any questions on twitter.

Handling good old IE: Backbone history with pushState fallback

You’re using pushState with Backbone’s history manager? I bet you’re doing something like this…

This works just fine most of the time. For browsers where pushState is available, everything works seamlessly with the URL. For browsers without pushState, again, everything works fine using the url fragment If you start sharing URLs between these two browsers, problems start cropping up and I recently came across this issue when working with the Facebook Like/Send buttons.

If you give a regular (non-fragment) URL to a browser that does not support pushState, Backbone, by itself, won’t be able to pick up on that and add the correct fragment. The same is true in the other direction as well when attempting to pass a fragment url to a modern browser. With a little bit of extra bootsrapping code, and giving up direct access to window.location, we can easily fix this problem.

We need to address both sides of this problem.

  1. When the application starts up
  2. When a URL is generated for sharing between browsers

Since pushState is the standard, and in the future will be implemented across the board, I will use the regular URL as the canonical URL. When the application starts up, we need to jump through some hoops to get Backbone.history in the right state to support the canonical URL whether or not the browser supports pushState.

First, we need to start Backbone history, with whatever option is available for pushState. We pass the silent option as true, to ensure that no route handlers will fire. Then, if pushState is unsupported, we calculate the fragment from the current window.location and navigate to that fragment. If pushState is supported, we directly trigger the route handlers.

Now, on the other side, we need to ensure that URLs that are generated from the application are the canonical URL, regardless of pushState support in the browser doing the generation. This part is simple, as Backbone has done the heavy lifting for us. We just need to concatenate together pieces of the URL that are derived from Backbone.history.

As long as we only use this function to produce a URL that is shared between browsers, our other bit of code will handle setting up the application correctly. After some find and replace, you’re application should now be able to easily handle both modern browsers, and the browsers that we just have to grit our teeth and live with.

Since implementing this, I have no longer had any further problems between browsers with and without pushState. I’ve been able to pretend that everything supports pushState within the context of my Backbone app. I don’t think that it is a very large amount of code to add to your project to get it working, and I prize simple and short solutions. I hope that some of you out there find this useful in your application. Please let me know if you have any questions on on twitter

Demystifying jQuery’s .index()

Compared to everything in the jQuery external API, for a reason which I cannot completely pin down, .index() has always required me to look into the source to understand. I’m going to use this post to break down the four possible method signatures and possible use cases for myself, as well as anyone else who has every shared my confusion. I’m crossing my fingers that after I’m done, I’ll have this completely understood.

index() with no arguments

When index() is called with no arguments, it behaves mostly as you would expect. In the first example, it gives the zero-based index of #foo1 within it’s parent. since #foo1 is the second child of it’s parent, index() returns 1.

The first potential confusion comes from the other examples in this fiddle. When index() is called on a jquery object that contains more than one element, it does not calculate the index of the first element, as I would have expected, but rather calculates the index of the last element. This is equivalent to always calling $jqObject.last().index();

index() with a string argument

When index() is called with a string argument, there are two things to consider. The first is that jQuery will implicitly call .first() on the original jQuery object. It will be finding the index of the first element, not the last element in this case. This inconsistency always makes me stop and think, so be careful with this one.

The second point is that jQuery is querying the entire dom using the passed in string selector and checking the index within that newly queried jQuery object. For example, when using .index("div") in the last example, jQuery is selecting all of the divs in the document, and then searching for the index that contains the first element in the jquery object that .index() is called on.

index() with a jQuery object argument

In this case, the first element of the jQuery object that is passed into .index() is being checked against all of the elements in the original jQuery object. The original jQuery object, on the left side of .index(), is array-like and is searched from index 0 through length - 1 for the first element of the argument jQuery object.

index() with a DOM element argument

In this case, the DOM element that is passed into .index() is being checked against all of the elements in the original jQuery object. Once all of the other cases are understood, this should be the simplest case. It is very similar to the previous case, except since the DOM element is passed directly, it is not taken from a jQuery object container.

Hopefully this effort helps you as much as it has helped me. All in all, after reading the source for .index(), none of this is that complicated, but IMHO, not intuitive in some cases.

Screencast

Evolution of a callback. How to use jQuery’s ajax deferreds.

Changing jsFiddle’s default library to jQuery

jsFiddle is awesome and I can’t say it enough. It has become the de facto mechanism to share snippets of javascript/html/css on the web, and I love that it’s so easy to use. It’s the fastest way to try out a new idea, show someone else a problem that you’re having, or just spend some time playing. I’m really grateful to Piotr Zalewa for spending so much time in making it such a great tool.

Since I use jsFiddle so much, I’m bound to find an annoyance or two though. I have found that I very often forget to switch away from the default js library, MooTools. It’s starting to become muscle memory that every time I open jsfiddle.net, I immediately change to jQuery, but it’s not quite there yet. Not only me, but many people asking for help on freenode have the same problem. About once a day someone posts a jsfiddle link to #jquery asking why something doesn’t work, and the code looks correct, except for the library chosen on the right side.

Until yesterday, I had always assumed that this default was alphabetic. I never paid attention to the fact that M was after D in the alphabet, so Dojo should have been first with jQuery somewhere in the middle. I found out that it’s actually ordered by Piotr’s preference, and he’s actually a MooTools core developer. Also, jsFiddle is actually built on top of MooTools and Django, so it makes sense to keep that as the default.

I just wrote a chrome userscript that can be used to change the default setting to jQuery. This can be easily modified to pick your favorite, or most commonly used library. I wrote it in MooTools out of honor and respect to Piotr, and because I figured it’d be fun to learn some MooTools.

If anyone would like to add a greasemonkey version of this, just let me know and I’ll add it to the gist.

Javascript - only three “bad” parts

I know that Douglas Crockford and many others will disagree with this, but from my point of view, there are only three “bad” parts to javascript.

  1. How does this work?
  2. How does prototypical inheritance work?
  3. Named Function Expression? Function Declaration? Hoisting?

Once a developer understands these three things in Javascript, they’re solidly on their way to rolling their eyes when they’re asked if they are a ninja at cocktail parties. It is these three concepts, in my opinion, that trip up most developers as they start to build applications larger than jQuery spaghetti.

There’s a much longer list in Javascript:The Good Parts and even more in our hearts. But I don’t think that these actually trip us up in daily development. When was the last time that you had a really hard time using the void keyword or were foiled by type coersion? All of these issues, we learn once, and almost immediately understand. Either that, or developers don’t encounter these because the libraries that they use, and learn from, don’t use any (anti-)features either.

Not only are issues like with and eval not often encountered, but also, tools like jshint/lint, remove any accidental uses. Chances are, as long as a developer l/hints their code, they’ll be making a conscious decision to use the potentially dangerous parts of the language. It isn’t so with these three concepts. Without this understanding, it is very difficult to become productive in javascript.

Other than these three concepts, I’d argue that Javascript is no more “bad” than any other mainstream programming language, like PHP or even Java. There are gotchas in every language and at least JS has most of them described very well in The Good Parts and online documentation.

I could give you my own explanations here, but so many others have done a much better job than I could. There are a lot of options. If you still feel confused after reading one, just go on to the next one. If you still feel confused after reading every single one. Find me or someone else in ##javascript on freenode.

How does this work?How does prototypical inheritance work?

The key here is to first learn about prototypical inheritance using Object.create and then come back to trying to understand what the new operator is doing. Most tutorials mess this up, by explaining it the “classical” way first, and subsequently lead to much confusion about following the prototype chain and this and that.

Named Function Expression? Function Declaration? Hosting?

Do you have more examples or blog posts? Let me know on twitter and I’ll add them to this list.

jQuery NYC - jQuery Plugin Unit Testing

Here’s the video for the talk that I gave to jQuery NYC. I’m planning on blogging about it the techniques that I use. For right now, hopefully the talk helps some people. The slides can be found at http://bit.ly/jquery-unit-testing

jQuery Plugin Unit Testing from John K. Paul on Vimeo.

leiningen setup on OSX Lion - stop the java.lang.NoSuchMethodError: clojure.lang.KeywordLookupSite.<init>(ILclojure/lang/Keyword;)V

In trying to setup Himera on my local machine to see if I could reproduce a browser bug, my console threw this error in my face. It was significantly larger before the snip, but I’ve left the important parts.

Johns-iMac:himera jpaul$ lein help Exception in thread "main" java.lang.RuntimeException: java.lang.NoSuchMethodError: clojure.lang.KeywordLookupSite.(ILclojure/lang/Keyword;)V at clojure.lang.Util.runtimeException(Util.java:165) snip... Caused by: java.lang.NoSuchMethodError: clojure.lang.KeywordLookupSite.(ILclojure/lang/Keyword;)V at leiningen.util.paths$native_arch_path.(paths.clj:32) at leiningen.util.paths__init.load(Unknown Source) at leiningen.util.paths__init.(Unknown Source) snip... ... (way more than) 11 more

I had just installed leiningen immediately before using brew install leiningen and clojure before that using brew install clojure. Since these were all homebrew formula’s I wasn’t expecting any problems like this, but it seems like the leiningen version in homebrew is not built with the most recent version of clojure, 1.3.0.

I figured it out after a healthy dose of googling and weeding through many stack overflow posts about other problems. In order to use the version of leiningen that comes from homebrew (1.6.2), I needed to have the older version of clojure, 1.2.1 installed. lein install org.clojure/clojure "1.2.1" fixed it for me and now I get what I was expecting


Johns-iMac:himera jpaul$ lein help
Leiningen is a tool for working with Clojure projects.

Several tasks are available:
classpath   Print the classpath of the current project.
clean       Remove compiled class files and jars from project.
snip...

su VS sudo su VS sudo -u -i

This post was partially inspired by half an hour of unsuccessful googling in trying to figure out how I should be getting into a shell as another user with no password required. The other part of the inspiration came from the responses to this tweet where I was inspired to dig deeper about these ubiquitus shell commands. I use sudo/su almost every day with no deep understanding of what it does, and I figured it was time to change that.

The differences between these three possible ways to enter a shell as different users were not apparent to me at all, and I’m pretty sure that other people share my confusion or misunderstandings.

su <user>

The su command lets any user change their user id and start a shell as another user. With no extra arguments, as far as I can tell su <username> is exactly the same as attempting to login remotely as that user, but preserves the environment variables set from the original shell. You are prompted for a password, that is the password of the user that you are attempting to change into. The exception to this behavior is if you are already logged into the shell as root. If you are already root, no password is requested.

sudo su <user>

The sudo su command has similar behavior to su, but it changes which password you have to enter, if any. This command requires you to use sudo, which means that the su command will be running as root. As described earlier, if su runs as root, you will not need to enter the target user’s password.

Now the question is, how can you run sudo. This depends on how your user has been configured in the /etc/sudoers file. There are many tutorials that you can find about how that file works, how it’s formatted, and what options are available, but, in my case, there was only one consideration. My user had the NOPASSWD option set, so I do not have to use a password in order to sudo. If you did not have that option set, you would have to enter a password in order to use sudo, but it would be your own password, not root’s nor the target user’s.

Additionally, I used the word similar earlier because sudo su does not preserve the environment variables of the original shell.

sudo -u <user> -i

The sudo -u <user> -i command is what you need to run if you want to simulate precisely the initial logged in state of another user. The -i option is supposed to stand for simulate initial login. It will create the proper shell, source .bashrc/.bash_profile files, and drop you into the target user’s home directory. The only use that I can see for this is, as a system administrator, debugging issues that are user specific. So far, I have not needed it.


In this exercise, I found that sudo su was the right option for me to achieve my desired effect. I could sudo su to the user I wanted to be, and no password was required.

There is a lot more to learn about these commands, aside from the particular options that I’ve described here. Reading through the man pages, there are many possible configurations that more precisely control environment variables, which shell to start with, and many other things. I haven’t yet found a reason to use all of them as a programmer, but they’re definitely good to know.

Follow me @johnkpaul

See you in the comments!

References:

What does scale really mean to a mobile browser? With pictures.

Within the past few weeks, A List Apart came out with an article about the pixel identity crisis. There’s a lot of buzz around the hardware pixel vs the device specific reference pixel and whether or not CSS media queries and device-pixel-ratio can help. I read through that article and realized that it did a really good job at explaining the concepts. Since I’m not a mobile developer at my day job, I haven’t needed to delve very deeply with these issues, but I have had one common itch to scratch.

In most of my desktop web work, I need to at least make the pages that I develop look and behave decently on the iPad/iPhone, if not a wider variety of mobile devices. The boiler plate that I need to worry about is usually the viewport metatag, which has the potential to be very confusing. I haven’t yet found a good tutorial that made initial-scale make half as much sense as pixel ratios do in that ALS article, so here it goes.

The <meta name="viewport"> tag has a content attribute with many different options such as width, min/max-scale and initial-scale.

Width is the most straightforward. It specifies the number of pixels wide that the content of the page is intended to be. If max/min/initial-scale is specified, this is really being used as a minimum viewport width. No matter what, the device user will be able to scroll to see at least this amount of pixels.

Scale on the other hand, takes a little bit more of an explanation. In these explanations, I will be using this 1280x960 image. The image is made up of 10px by 10px squares.

The way that I make sense of scale is with an equation. This equation has 3 variables.

  • D = The actual device width, in hardware or reference pixels (320)
  • S = The scale value itself (1)
  • N = The number of pixels of content actually displayed on the device
The equation that we can use to express the relationship between these number is.

image

When the initial scale is set to 1, only 320 pixels of the 1280 total width image are displayed. This is because the width of the iPhone device is 320 pixels and 320/1 = 320.

image

When we double the initial scale, to 2, only 180 pixels are displayed at first.

image

When the initial scale is reduced to .5, 640 pixels are displayed.

image

And finally, when the initial scale is reduced to .25, 1280 pixels are displayed.

image

These images only show initial scale, in order to show how many pixels are displayed at different scales.

A more important lesson from this, is how to use max and minimum scale. If I were to set minimum-scale=.50 in my viewport metatag, my user would never be able to get a closer look than 640 pixels per full portrait width. Personally, I find this always obnoxious when I come across it myself, but I am sure that there are valid uses of it.

Along the same vein. if you set maximum-scale=1, your user would be unable to view more than 320 pixels of width at one time, and they would be forced to pan around to see all of the content.

Lastly, although the example that I am using here is a iPhone, all of this math works out exactly the same for the myriad mobile devices out there.

I’d love to hear what you think in the comments. Also, you can follow me @johnkpaul