Latest Code: Cross-domain requests with jQuery »

Chris Heilmann recently posted on how to use YQL to make cross-domain requests, which would usually be prohibited due to the same-domain-policy. I already knew about YQL, but I had no idea that it... (»)

I’m for comments

Posted in 'General' by James on February 7th, 2010

One of the best qualities of this industry, in my opinion, is that everyone loves to share their knowledge. Regardless of intent, whether it be ego, the pursuit of accuracy, or perhaps quasi-altruism, most of us make a point of making sure our voice is heard. The reason we’re so good at it in this industry is probably because we work on the internet, pretty much all of the time! And, let’s face it, us web developers, we’re pretty damn good at using the internet!

Anything that perpetuates this quality is something I can get behind. Communication is key!

Forgive the self-indulgent introspection but I think it’s important for me to encapsulate how I feel about this into prose, just so I “have it on file”.

I know for a fact, that if not for the comments left on various posts of mine, I would be less technically proficient than I am right now. Note that I’m not insinuating that my current level of proficiency is notably high; I’m merely stating that it would be notably lower if not for the feedback I’ve gained over the years.

In March of last year I posted a brief outline of how to use regular expressions in JavaScript. This was at a time when I was pretty confident of my knowledge in the JavaScript arena, and I think that my confidence was shown in that post. I sold the information as if it were fact — there was no visible doubt in how I wrote it. I think this ill-founded confidence is inherent in this industry, partly due to its low barrier to entry. Within a month, you feel as if you’ve conquered HTML, and then three weeks later you’re a CSS guru etc.

I don’t see anything wrong with this confidence though — for one, it’s good practice to outline a subject in a professional manner, even if you’re not entirely correct about certain things. And, most importantly, the feedback that can be gained from those more experienced is infinitely helpful. Just to be clear though, I don’t think that putting people on pedestals is conducive to a good information-sharing atmosphere — if anything, it acts as a hindrance, because you presume their utterances to be entirely correct all the time, when nobody is truly omniscient!

This was what I had to say about the RegExp.prototype.exec method in that post:

this method is exactly the same as the String.match() method, the only difference being that you pass the string as the argument and the method is run as a member of the regular expression that you’re using to search the string.

Lucas Smith chose to leave a comment telling me of my oversight. If not for him, who knows how long I would carry and “sell” this piece of incorrect information? I’m grateful to Luke and everyone else that has set me right when I have been incorrect.

If I didn’t enable comments on my blog then a casual reader would presume that my information is irrefutable, and here in lies a very dangerous prospect — not only would I not be set right by those more technically proficient, but my perception of correct information would be bound at best, by how I choose to interpret information from other sources, and at worst, by mere guesswork (as was the case in the exec oversight).

I believe that publically viewable feedback is essential to uphold accuracy. In other words, you should enable comments, so that people can tell you when you’re wrong. Obviously though, I’m talking about objective information, facts that cannot be disputed. I’m not talking about opinions or beliefs; you cannot correct someone for having the wrong opinion; it’s their opinion, and it’s likely to be founded on other pieces of scattered information and other opinions that they’ve accumulated — you can correct their understanding of the information, but not the opinion itself.

Under jQuery’s bonnet

Posted in 'Cool Stuff, JavaScript' by James on January 31st, 2010

If there’s one thing all library users should be doing more, it’s peeling back the layer of abstraction and seeing what’s really happening underneath. This is the only way to gain a true understanding of what the library provides, and who knows, maybe you’ll find some gems that you didn’t know existed.

Libraries like jQuery aren’t very small when uncompressed. Traversing a long source file trying to look for a specific method’s implementation is far from ideal. I have frequently found myself in this situation with jQuery, so today I decided to do something about it, and the result is viewable at http://james.padolsey.com/jquery.

Preview of the jQuery Source Viewer

It allows you to study specific parts of jQuery’s source. You can type in a method name and you’ll see its implementation straight away, in all its syntax-highlighted glory! It will also link’ify all function names within the presented source:

The css method's source, with certain function names as links

You can link directly to a method using the following URL pattern:

http://james.padolsey.com/jquery/[version/]methodName
 
E.g.
http://james.padolsey.com/jquery/css
http://james.padolsey.com/jquery/1.3.2/attr
http://james.padolsey.com/jquery/jQuery.proxy
 
-OR-
http://james.padolsey.com/jquery/#v=version&fn=methodName

If you don’t specify a version then 1.4 is assumed.

JavaScript’s Dark Alley

Posted in 'JavaScript' by James on January 30th, 2010

So, I happened upon an interesting thread this morning, concerning the recently released jQuery Lint. For those of you who have not dared to look, the comp.lang.javascript newsgroup is truly the proverbial dark alley of JavaScript and DOM development. I can picture it vividly, a dingy dusty cobbled walkway blackened by the thick fog of regressive opinion and unprovoked flame wars, riddled with the unquestioned prerequisite of a newsgroup’s slow death — spam on every corner!

If you have a read through that thread you’ll notice none other than the infamous David Mark. This is the same person that slammed jQuery (oh, and MooTools) for not being able to “do *anything* right” and then, not too long ago, threatened the jQuery project with legal action over some DOM attributes tests.

David had the following to say about jQuery Lint:

Well, sort of. It’s not so much the Johnny-come-lastly advisor plug- in, but the fact that it is just another horrible plug-in for an equally bad pile of JS [he means jQuery]. Anyone who would use jQuery enough to want to write a plug-in is not going to be the best candidate to wtite a browser scripting “lint.” I can’t see it.

He continues:

The idea (which is sound) is to warn developers when they are doing something incorrect (or ill-advised). I haven’t looked at the code for it (and I’m sure I never will). I find I don’t have to do that anymore as the basic rules always apply. :)

David doesn’t stop! He still continues:

[Scott Sauyet]
> It seems to be a tool to help new users learn things like that although this code is legal:

$("selector").css("color", "red").css("margin", 0);
> This would be more efficient:
$("selector").css({color: "red", margin: 0});
[David Mark]
You dump it and replace it with something better (and faster). In this case, something like:
el.style.color = "red"; 
el.style.margin = '0';
That’s smaller, faster, more readable, makes no function calls, creates no new objects and is impervious to upgrades to jQuery (typically poison). And, as we all know, jQuery doesn’t work worth a shit anyway as the “logic” in the script is mostly a diary of confused browser watchers. Get the picture?
> That doesn’t indicate anything wrong with the library any more than > any lint program indicates problems with its target environment.
Of course, you don’t need a lint to see what is wrong with the library. It’s as obviously unsuitable as a dissertation written in crayon.

According to David we should be sparing ourselves the obvious folly of abstraction and spend more time writing “smaller, faster, more readable” JavaScript:

jQuery Lint

Posted in 'JavaScript' by James on January 18th, 2010

jQuery Lint is a simple script you can download and use with jQuery. It works over the top of jQuery and diligently reports errors and any incorrect usage of jQuery. It will also, to some extent, offer guidance on best practices and performance concerns.

Unlike JSLint, jQuery Lint is a runtime reporter. To use it, you need to include it, after jQuery, in your document:

<script src="jquery.js"></script>
<script src="jquery.lint.js"></script>

jQuery lint’s main objective is to notify you of incorrect usages of jQuery’s API. So, if you pass incorrect arguments to any method then jQuery Lint will let you know. It compares your arguments to the argument signatures in jQuery’s API. It reports via Firebug, although you can quite easily plug-in your own console mechanism.

It has four different error-reporting levels (accessible via jQuery.LINT.level), zero reports nothing, three will report everything, including small things like using css().css().css() instead of css({...}). It’s quite configurable too. You can add your own checks. E.g.

jQuery.LINT.special[1].jQuery = jQuery.LINT.special[1].jQuery || [];
 
// Add check on error-reporting level one.
// Check jQuery method.
jQuery.LINT.special[1].jQuery.push(function(selector, context) {
 
    if (selector === '*') {
        return "Don't use the universal selector!";
    }
 
});

jQuery Lint tries to help you in determining where the problem occurred in your code. It’s not much help to you if it just says, “Err, you called css() incorrectly!”. If it occurred as a result of an event then Lint will say so, and if you’re using a browser that provides a stack-trace as part of its Error object (like Firefox) then Lint will also provide you with the file-name and line number. E.g.

jquery Lint - Reporting line number and file name where problem occured.

You can read more about jQuery Lint and download it at Github:

jQuery Lint @ Github

The idea of a lint-like script for jQuery has been floating around for some time. I want to thank Dave Methvin in particular, for it was his idea that sparked my interest originally.

This is quite a young project, so there will be bugs. Please report them!

Encapsulation in JavaScript

Posted in 'JavaScript' by James on January 9th, 2010

Encapsulation is a useful technique in programming which allows you to separate an abstraction’s implementation from its interface, thus enabling future changes to the implementation without affecting the interface. There are other benefits of encapsulation, such as:

  • Being able to screen (validate) new properties, via setter methods.
  • Being able to process properties before their “release”, via getter methods.
  • Making your abstraction less prone to abuse by other developers — specifically, to protect private variables and states that could compromise the effectiveness of the abstraction.

Grady Booch (author of “Object Oriented Analysis and Design”) describes encapsulation as:

“The process of compartmentalizing the elements of an abstraction that constitute its structure and behavior; encapsulation serves to separate the contractual interface of an abstraction and its implementation.”

JavaScript is often considered a toy that doesn’t know of complex design patterns or have the capacity to support techniques such as encapsulation, but, contrary to misinformed belief, JavaScript does have capacity for encapsulation. It’s just quite tricky, that’s all!

Hiding your variables in closures

It’s possible to hide variables in JavaScript. To make this happen we take advantage of the closure:

function Person(name, age) {
 
    this.toString = function() {
        return 'Name: ' + name + ', Age: ' + age;
    };
 
}

If you’re not sure what a closure is just think of it as a function defined within another function. The “child” function has access to the “parent” function’s scope.

You can see that we’re defining the toString method within the constructor.

The only reason to define a constructor’s methods anywhere other than its prototype, is in the situation where that method needs access to variables defined in the constructor’s scope. Above, the toString method needs access to the variables, name and age.

Setters (and getters)

Once we instantiate this constructor (new Person('Jim', 88);), there’s no way to change the name or age — they’re “hard-coded” in the inaccessible “parent” scope.

We can make it possible to change these values by adding a couple of setter (AKA, mutator) methods:

jQuery code smells

Posted in 'JavaScript' by James on January 5th, 2010
jQuery code smells

Here’s a quick line-up of some smelly jQuery code! “Code smells” are pieces of code that do for your eyes what bad smells do for your nostrils, and usually result in erroneous or harder-to-maintain code. I have no doubt that at least half of you will think that I’m wrong about at least half of these.

Before you stop paying attention, I’d like to wish everyone a Happy New Year! I hope you find the new design more consistent and cleaner.

May the flaming commence…

Prefixxing all jQuery objects with “$”

It’s ugly, and my text editor doesn’t like it! But mainly, it’s ugly, and is only useful for beginners. Hungarian notation is a hotly debated technique — like Marmite (and Jade Goody?), you either love it or hate it!

var $body = $('body');
$body.click(function(){
    $this = $(this);
});

I won’t say much more; I appreciate that it’s a sensitive topic for some and is mostly about personal preference.

Concatenating a bunch of things together to make a selector

I see a lot of this! It looks dirty, and just screams, “I’m succumbing to the API because I don’t know what else to do!”

$('.' + className + '[' + attrLookup + '^=' + attrPrefix ']:not(.' + notClass + ')');

This is why I think jQuery needs some other way of filtering DOM elements (possibly something like my filter hack). For now, seperating out our selectors will have to suffice:

$('.' + blah.className)
    .filter('[' + attrLookup + '^=' + attrPrefix ']')
    .not('.' + notClassName);

To be truthful, I’m on the fence with this… Maybe I’m just against string concatenation!

Be the change!

Posted in 'General, My Life' by James on December 28th, 2009
Be the change!

Stop for a second, and think about one thing. Capitalism — what has it given you? Do you see money as a basic necessity in life? Why? Because you were conditioned from the age of zero to believe that the ideals perpetuated by the status quo are, indeed, ideal.

Interestingly, uttering a suitable alternative, “communism” to the vast majority of deluded individiuals will yield only negativity — a stream of arguments against the proposed system will commence; none of which actually address what communism really is.

Communism is ultimately about the abolition of the state, a total reformation of our ideals and incentives to live. Communism has never been achieved on a significant scale before.

I don’t want to talk about communism though; it’s a tricky topic because it is, to be truthful, quite a fuzzy term, riddled with lies and misinformation. Instead, I’d like to turn your attention to a modern movement that aims to abolish the monetary system (i.e. capitalism) and replace it with a system without government, scarcity, self-interest, or monetary objectives.

No government!? “That’s abhorrent,” you utter! Well, to many of you it will be, but I don’t apologize for that; your perception of what is and isn’t abhorrent is only governed by your own psyche and the schemas that have been drilled into you from day one.

The way in which we live is quite silly really. We’re controlled by a system that merely perpetuates its own dependency, scarcity! Profit cannot be made without scarcity. Profit is immoral and only serves self-interest. Money has become, instead of a means, an end in itself! Individuals thrive for wealth more than happiness or the desire to contribute to humanity in positive ways.

There is a movement, and it is new, and it is seeking to rid the world of corrupt powers that only seek to gain more power. This movement does not insist upon itself; it is simply a set of ideas that will set us free. It will allow you to live every day without the stress caused by money or work or politics or deceit!

What’s your job? Eventually, it will be replaced by machines. It will. And when the day comes when 90% of jobs are carried out through technology people won’t need to work. Your incentives will change. No longer will your life be governed by your nine to five roll. You will learn and willingly commit time and knowledge to better humanity.

Crime is inherent in a system that perpetuates scarcity and thus poverty. Why would we live in a such a system? Because we have no choice? No, you’re wrong, we do!

You may think my views are naive, and my world views, while noble, are far from practical. Well, frankly, open your mind just a smidge! How many new ideas and changes were slammed by the majority before being accepted as the norm?

I’m not asking for anything really. I just want you to watch the Zeitgeist movies, and perhaps look further into the Zeitgeist movement, and its cause, The Venus Project.

The world can change! And you can be that change!

Macros in jQuery

Posted in 'JavaScript' by James on December 26th, 2009
Macros in jQuery

Creating a plugin for jQuery is incredibly simple and is a very useful way to abstract complex behaviours so that they can be used repeatedly as part of your jQuery “chains”.

But, when the time comes, and you’re faced with the decision to either create a jQuery plugin or to simply create a regular function, everything suddenly becomes quite complicated. First, you’ll wonder whether the piece of behaviour you want to abstract is best kept under the jQuery namespace, and then you’ll doubt its applicability to the DOM-centred jQuery chain, and then sometimes you’ll recede to something you’re much more comfortable with, a regular ol’ JavaScript function.

If we forget about the plugins available online, and we simply focus on your plugins, made and used within a specific project, then the question of whether a plugin is really the right route becomes all the more difficult to answer. Are you going to benefit from extending jQuery’s API? Will the readability of your code benefit?

For example:

function applyColors(elems) {
    $(elems).css({
        color: config.color,
        backgroundColor: config.bgColor,
        borderColor: config.bdColor
    });
}
 
// Call it:
var myElems = $('div.something');
applyColors(myElems);

applyColors encapsulates some behaviour that is needed frequently, and that’s why it’s been abstracted into a function. To some, this approach is lacking in that it doesn’t harness the full power of jQuery, and more specifically, jQuery’s plugin mechanism. How about this:

jQuery.fn.applyColors = function( {
    return this.css({
        color: config.color,
        backgroundColor: config.bgColor,
        borderColor: config.bdColor
    });
};
 
// Call it:
$('div.something').applyColors();

Cleaner? More readable? I think so.

Many developers are not prepared to extend jQuery’s API with their own simple abstractions. I don’t know why. But, I hope, that jQuery macros can help in lowering the barrier to extending jQuery.

Gapless wall of images

Posted in 'JavaScript' by James on December 20th, 2009
Gapless wall of images

Given a set of arbitrarily sized images and a container with fixed dimensions, fit as many of the images within the container as you can, without leaving any big gaps in between images. How would you do it?

Well, I had a go, and this is a brief overview of how it works.

Obviously, it wasn’t possible to simply line the images up as a grid, because they all have varying (and unpredictable) widths and heights. Considering this, I only saw one logical way of doing it… progressively!

Place an image — determine the remaining space and use it to place the next image, and so on. Placing the first image is easy; just stick it up in the top left corner and go from there!

Diagram of placement mechanism

A single placement will open up, potentially, three new positions. Out of them, the top-most one could be used for next placement, or the left-most, whichever you fancy.

I chose to track the availability of pixels using a basic two-dimensional array:

// Nine occupied pixels:
[
    [1,1,1,0,0,0,0,0,0,0],
    [1,1,1,0,0,0,0,0,0,0],
    [1,1,1,0,0,0,0,0,0,0],
    [0,0,0,0,0,0,0,0,0,0],
    [0,0,0,0,0,0,0,0,0,0],
    [0,0,0,0,0,0,0,0,0,0],
    [0,0,0,0,0,0,0,0,0,0],
    [0,0,0,0,0,0,0,0,0,0],
    [0,0,0,0,0,0,0,0,0,0],
    [0,0,0,0,0,0,0,0,0,0]
];

The width given to any image upon placement is defined by the amount of pixels free to the right of that image and the height is calculated similarly. There’s a configurable maximum width and height so that the first image doesn’t take up the entire space. Eventually, there is no space left, and the procedure halts.

You can find the code at Github, under “PhotoWall”.

I’ve also put a pretty boring demo online, and yes, I know it’s a bit messed up at the bottom edge — like everything, it’s a work in progress :) .