“Positive and negative. You’re a bit, aren’t you?”
As a self-taught programmer that never had a class on the differences between functional, procedural and object oriented programming, this was really helpful.
Last weekend I spent some time with the canvas API and doing this pi calculation thing I’d heard someone talking about.
What’s going on here? Well, there’s a script that makes a new canvas on the page. First it draws a grid, then an arc and then it starts putting random dots on the grid (in this case little circles). If the dot is within a certain distance of the center (it’s sqrt(x^2+y^2) <= radius) we count it as a hit. Otherwise, we don’t. The more dots we put in, the closer we get to calculating pi. I’m not a math person, but this idea of calculating pi using random numbers and throwing darts at a grid seemed like a fun way to get a little more familiar with the etch-a-sketch of the internet.
Excellent set of articles - especially if you (like me) have no idea how emulators work.
As a front-end guy, I don’t get to write tests very often. But, for a recent rewrite of some old code, I decided that I wanted a way to know that the rewrite I did would not only make the code easy to read and use, but also make it more efficient. I figured the best way to guarantee that the code still worked the same way was to write tests for the old stuff and then make sure they ran on the rewrite. Even better, many testing frameworks (harnesses?), will tell how long the tests took to run. A colleague pointed me to Jasmine.js and I’m really enjoying working with it. It was super easy to get up and running quickly, but also has a lot of depth that I haven’t even gotten close to understanding (the section on spies is particularly impenetrable for my weak-ass brain).
And others are giving excellent blog in the meantime. Here are two sites I’ve been reading:
I came across an interesting situation at work last week and thought I’d give a go of explaining it.
Problem:
You’ve written a widget that uses jQuery. In fact, you wrote your widget as a jQuery plugin (really just to attach it to the jQuery object instead of global scope). You know that some sites will already have jQuery and other sites won’t. You also know that sometimes those sites will be running an older version of jQuery that your widget can’t use, but at the same time, their site will break if you slap on a newer version of jQuery. How do you optionally use your version of jQuery without clobbering theirs? Even better, how do you make sure that their jQuery doesn’t clobber yours?
Solution:
The first time we solved this problem, we just downloaded the new version of jQuery every time and then used jQuery.noConflict(); and jQuery.noConflict(true); (a deep noConflict), but found that this would typically clobber the other site’s version of jQuery and lead to confusion. The next thing we tried was to just create out own version of jQuery (this is really easy to accomplish by just changing the very last line of the main jQuery file from window.jQuery = window.$ = jQuery to window.myjQuery = jQuery (this is version 1.4.2 and I think this could also be accomplished using the make file in the source). This is a total sandbox and works great, but it does require downloading an entirely separate version of jQuery every time you want to use your widget.
Downloading jQuery twice === bad, so what to do? The next obvious thing to try was testing to see if the site was already using a jQuery version that was close to ours and only download a newer version when necessary, otherwise, just assigning a new name for our widget to use to the existing jQuery:
if( typeof jQuery !== 'undefined' && jQuery.fn.jquery >= '1.3.2'){
window.myjQuery = jQuery;
document.write( [script tag for widget.no-jquery.js] );*
} else {
document.write( [script tag for widget.jquery.js] );
}
* obviously you could script a dom element to avoid document.write - this is for brevity
This all worked fine until we realized that one site was loading another copy of jQuery (yes… another) after our script had already checked and attached itself to the jQuery on the page. What does that mean? It means that because ou myjQuery object isn’t a clone of jQuery, but just a reference, anything that we attached to the myjQuery object as a plugin in our widget.js script (e.g. $.myAwesomeWidget()) will be blown away by the second copy of jQuery that they download. The obvious solution of screaming at whoever is using two copies of jQuery on the page and allowing them to freely clobber each other didn’t appear to be a wise career move, so we had to come up with something else: a way to clone the jQuery object and slap it onto our window.myjQuery.
The first thing I thought was “oh, why don’t we just say: myjQuery = jQuery.clone();” Unfortunately, the jQuery.clone() function is great for DOM elements, but not for jQuery itself. The next thing I thought was “Well, functions are objects, right, so why can’t we just use the jQuery.extend() function to make myjQuery a copy of jQuery”. This didn’t didn’t seem to work very well as the result would be an object and not a function. We were losing the prototype information on jQuery (at least - that’s what I think was happening without being the type of guy to fully understand prototypal inheritance, it’s hard to be sure).
I figured, jQuery did something crazy when it did its noConflict() call that might yield some clues, but found a dead end there as well as it just seemed to move jQuery around instead of making a new copy.
What to do?
Reading the actual code of the library ended up bringing about what seems to be a working solution. Right on the very first var of the jquery core, we see this:
// Define a local copy of jQuery
var jQuery = function( selector, context ) {
// The jQuery object is ...
return new jQuery.fn.init( selector, context );
},
If the jQuery object is actually just an init constructor, maybe we can use that combined with extending the object to create our own. Hence, we ended up with something like this:
window.myjQuery = function(selector, context){
return new jQuery.fn.init( selector, context);
};
myjQuery = jQuery.extend(true, myjQuery, jQuery);
With this in place, we appear to be able to just use myjQuery like jQuery itself, but can mess with one and not affect the other (i.e. we can use plugins again - yay!)
The big caveat here is that I would never do this if I didn’t have to. One of the tough parts about building any widget is shoring it up so that it can’t get clobbered. Javascript makes this especially difficult because of its freewheeling nature of letting any script overwrite other scripts. I feel like most devs just solve this problem by always downloading the library twice, but this leads to slow loading pages and just seems lazy to me. I’d love to see some best practices for javascript widgets and I’d guess that the likelihood of finding something like that will increase as flash gives way to javascript. Caja might solve this problem, though I haven’t had a change to give it a review beyond the welcome page.
Two posts came across my radar in the past 24 hours.
Learning from XAuth: Cross-domain localStorage
Using local storage and an iframe to do cross-domain user data by Nicholas Zakas (who I remembered from a video of a talk he did on maintainable javascript almost four years ago). We’ve been doing an iframe trick to set cross-domain cookies between subdomains at work, but this is so much more elegant. As usual, it makes me want to run into the office and rewrite everything. Iframes are slow, but their cross-browser support is excellent and the semi-recent availability of cross-document messaging (see caniuse.com for availability) makes them well-suited to the need for cross-domain data.
Handlebars.js is an extension of the mustache.js javascript templating framework. I was first introduced to a javascript templating framework called handlebarJS at SXSW during a session on using a server-side javascript layer to do templating and communicating solely in JSON. Apparently, these are different. Yes. Two libraries for javascript templating, one called handlebars.js and the other called HandlebarJS.
Anyhoo, The draw for a developer to javascript templating is that templating can be done server- or client-side (assuming, of course, that users have javascript). This means that using localstorage, cookies, or just some dumb events on the page with no data associated with them, we can re-template a page and know that it will look the same on refresh without having to do a serverside call (especially handy for offline use).
The only other javascript templating engine that I’d heard of before this was Microsoft’s jQuery plugin. It’s nice to see the room filling up and probably time for yours truly to start messing around with these (and also run to the office to start rewriting everything).
It’s been a long month with a lot of travel, so less and less time for blogging about my experiences with JavaScript. I was lucky enough to have some time on my vacation to rewrite one of work’s major hunks of JavaScript. A few days of reducing global variables, speeding up loops, and creating a custom jQuery plugin to link it all together was more fun that I’d like to admit. My favorite trick that came out of the whole thing was learning to be able to quickly map any variable to another variable for a block of code.
(function($){
// Code using $ goes here
})($otherJquery);
Scope gets a little funny here if you want to work with things outside of the anonymous function, but there’s always window to attach to and use if you want to be evil and there the benefit of knowing that the functions that you do write won’t accidentally override anyone else.
My next big task at the office is to create a strategy for keeping user sessions up to date on the client side and in a key-value store. There will probably be a good amount of research that I skip when I dive right in and then have to learn the hard way. I’ll try to make sure to come back and document it here.
Also, I just got HTML Up and Running in the mail and can’t wait to start dissecting the new JS APIs for geolocation and offline storage.
Discovered canto.js - an API for working with the <canvas> element written by David Flanagan (via Think Vitamin). I’m psyched to play with it as soon as I get some time.