Archive for the ‘News’ Category

Who won a jQuery cookbook!?

Posted in 'JavaScript, News' by James on December 11th, 2009
Who won a jQuery cookbook!?

I want to say a huge Thank You to everyone that entered the cookbook competition! It was very interesting reading through all your comments; some funny, some saddening, some very insightful and others just plain silly!

I was considering picking the winners based on the comments themselves, but after considering the sheer number of comments (over 250) and the fact that there are many more than five people that genuinely deserve a free copy, I decided to pick the winners randomly!

So, without further delay, here are the five winners (see the code that picked them):

  • 9swords

    Going to leave a word here to try my luck. I could use some more learning. I should have created a plug in by now, maybe the book could help me get there.

  • Morena

    Hi. Thanks for this possibility! I would like to win this book to gain a better and deeper understanding of jQuery. I am trying to make the best use of the online examples many sites offer, but I am still a bit “old fashioned” and still need a good printed book to highlight, comment, carry with me and draw funny faces on when I’m learning something :)

  • John Nelson

    I have a craving for some jQuery and I have no recipe to go by. Why use the frozen microwave jQuery you find on the web, when you can have fully baked goodness printed and bound? I want to have a great reference for my daily jQuery needs. It makes javascript something special.

  • Trond

    Because I haven’t read it yet?

  • Aaron

    We love jquery and need to get better at it. Being a small, non-profit, public radio station, any money i can save our .org on books… is always good!

Congratulations to these commenters! I’ll be emailing you within the next day! :)

I know that some of you would have preferred me to pick the comments based on the contents of each comment, but it just wouldn’t have been feasible. There were so many great comments – it would have been impossible to fairly decide.

Once more, congratulations to the lucky winners!

Zoomer component for sale!

Posted in 'Cool Stuff, JavaScript, News' by James on June 17th, 2009
Zoomer component for sale!

ThemeForest, one of Envato’s marketplaces, has just launched a “JavaScript” category and within it my new JavaScript component, “Zoomer“. As the description states, “‘Zoomer’ enables your users to closely inspect images by hovering their cursor over them. It’s been built as a robust, unobtrusive and highly customizable jQuery plugin.” Here’s a brief overview of its key features:

  • A fully customizable zoomer for use with any image
  • Works in all modern browsers (including IE6 )
  • This is a progressive enhancement; images will still be viewable when JavaScript is not available.
  • The Zoomer itself is highly customizable.
  • The Zoomer requires NO images – the shadows/gradients are dynamically generated by JavaScript (using VML /Canvas technologies)
  • In-depth documentation including two videos and an FAQ !

See the demo

It’s customizable!

Almost every aspect of the zoomer is customizable, here’s a preview of the jQuery options:

$.zoomer.defaultOptions = {
    zoomerClass: '_zoomer',
    zoomSrc: '',
    height: 150,
    width: 150,
    mousewheelZoom: true,
    defaultZoom: 2,
    maxZoom: 5,
    minZoom: 1,
    feedback: function(x,y,zoom){},
    onOver: function(){},
    onOut: function(){},
    zoomerOverlay: {
        className: '_zoomer-overlay',
        shadowWidth: 10,
        shadowOpacity: 0.5,
        /* Must be in "rgb(r,g,b)" format */
        shadowColor: 'rgb(0,0,0)',
        radialOpacity: 0.4,
        /* Must be in "rgb(r,g,b)" format */
        radialColor: 'rgb(0,0,0)'
    }
};

Even the shadow beneath the Zoomer is customizable – this is possible thanks to canvas/VML technologies.

Buy Zoomer (currently $5)!

Things you may not know about jQuery

Posted in 'Cool Stuff, JavaScript, My Life, News' by James on February 19th, 2009
Things you may not know about jQuery

I was going to do a bit of a series, releasing a jQuery tip every day or week or something, but I think I’m a little too lazy to commit to something like that. So I’ve compiled them all into one post! I’ll probably add to the list at later dates so make sure to bookmark it!

Do you have a tip nobody knows about? – Add it in the comments…

  • $.fn is just a shortcut to jQuery.prototype.
  • You can test if a jQuery collection contains any elements by trying to access the first element, e.g. if($(selector)[0]){...}.
  • jQuery normalizes the event object across all browsers! Have a look at all the available properties/methods over here: http://docs.jquery.com/Events/jQuery.Event.
  • When you create a plugin you have access to the jQuery chain’s previous object:
    jQuery.fn.doSomething = function() {
        this; // => $('a')
        this.prevObject; // => $('li')
        // Remember chaining in your plugins:
        return this;
    };
     
    jQuery('li').show()
        .find('a').doSomething();
     
    // You could even create a new 'root' plugin:
    // (Returns the 'root' of a chain)
    jQuery.fn.root = function() {
        // Root is always document so we have to 
        // go back to one before the last:
        var root = this;
        while(root.prevObject.prevObject) {
            root = root.prevObject;
        }
        return root;
    };
     
    $('li').find('a').children().root(); // <= $('li') is returned
    // Using root() is the same as using end().end() in this situation
  • You can namespace events! This is especially useful for plugin development:
    jQuery.fn.myPlugin = function() {
     
        // Clean up after yourself!
     
        jQuery.myPlugin = {
            cleanUp: function() {
     
                // Remove all click handlers binded
                // as a result of the plugin:
                jQuery('*').unbind('click.myPlugin');
     
                // ALternatively, remove ALL events:
                jQuery('*').unbind('.myPlugin');
     
            }
        };
     
        return this.bind('click.myPlugin', function() {
            // Do something...
        });
    };
     
    // Note, you can also namespace data:
    // E.g. $(elem).data('whatever.myPlugin',value);
  • You can access all event handlers bound to an element (or any object) through jQuery’s event storage:
    // List bound events:
    console.dir( jQuery('#elem').data('events') );
     
    // Log ALL handlers for ALL events:
    jQuery.each($('#elem').data('events'), function(i, event){
        jQuery.each(event, function(i, handler){
            console.log( handler.toString() );
        });
    });
     
    // You can see the actual functions which will occur
    // on certain events; great for debugging!
  • jQuery natively supports JSONP (‘JSON with padding’) which effectively means you can make cross-domain "Ajax" requests (although not strictly Ajax since it doesn’t use XHR). For this to work the requested domain must have some JSONP API in place (it must be able wrap the JSON with a specified callback function). An example:
    function getLatestFlickrPics(tag,callback) {
        var flickrFeed = 'http://api.flickr.com/services/feeds/photos_public.gne?tags='
                       + tag + '&tagmode=any&format=json&jsoncallback=?';
        jQuery.getJSON(flickrFeed, callback);
    }
     
    // Usage:
    getLatestFlickrPics('ferrari', function(data){
        jQuery.each(data.items, function(i, item){
            $("<img/>").attr("src", item.media.m).appendTo('body');
        });
    });
  • You might find it a little messy but jQuery enables us to create an entire DOM structure within a single chain:
    // Create and inject in one chain:
    jQuery('<div/>')
        .append('<p><a href="#">Foo</a></p>')
        .find('p a')
            .click(function(){
                // Do something...
                return false;
            })
            .end()
        .append('<p><a href="#">Bar</a></p>')
        .find('p:eq(1) a')
            .click(function(){
                // Do something else...
                return false;
            })
            .end()
        .appendTo('body');
  • Accessing the DOM elements within a jQuery collection is incredibly easy:
    var HTMLCollection = $('div').get();
     
    // Alternatively, if you only want the first element:
    $('div').get(0);
    $('div').get()[0];
    $('div')[0];
  • Not only can you bind events to DOM elements; you can also bind a custom event to ANY object!
    function Widget() {
        // Do something...
    };
     
    var myPhotoWidget = new Widget('photos');
     
    jQuery(myPhotoWidget).bind('photoAdd', function() {
        // Custom event handling...
    });
     
    // Trigger event:
    jQuery(myPhotoWidget).trigger('photoAdd');
  • Finding the index of a selected element is very easy. jQuery gives us the ‘index’ method:
    $('table tr').click(function(){
        // Find index of clicked table row:
        var index = $('table tr').index(this);
    });
  • You can create your own filter selectors. I did a post on this a while back, but take a look at an example anyway:
    $.expr[':'].external = function(elem,index,match) {
        var url = elem.href || elem.src,
            loc = window.location;
        return !!url.match(new RegExp('^' + loc.protocol + '//' + '(?!' + loc.hostname + ')' ));
    };
     
    // You can now use it within your selectors:
     
    // Find all external anchors:
    $('a:external');
     
    // Find all external script elements:
    $('script:external');
     
    // Determine if link is external:
    $('a#mylink').is(':external'); // true/false
  • I see quite a lot of people still using JavaScript’s FOR or WHILE constructs to create loops in their jQuery scripts. There’s nothing wrong with this but be aware that jQuery’s ‘each’ method can also iterate over arrays and objects!
    var myArr = ['apple','banana','orange'];
     
    $.each(myArr, function(index, item) {
        // Do something with 'item'
        // return false to BREAK
        // return true to CONTINUE
    });
  • The ‘filter’ method accepts a String selector or a function. When using it with a function you must return false to remove the element from the stack and true to keep it:
    $('div').filter(function(){
        return this.childNodes.length > 10; // Must return a Boolean
    });
  • You don’t have to give new elements IDs or classes to reference them later, just cache them into a variable:
    var myInjectedDiv = $('<div/>').appendTo('body');
     
    // Use 'myInjectedDiv' to reference the element:
    myInjectedDiv.bind('click', function(){
        // ...
    });
  • jQuery’s ‘map’ method is incredibly useful, the passed function will be run on every item of the passed array (or object) and whatever the function returns each time is added to the new array, take a look:
    // Create an array containing all anchor HREF attributes:
    var URLs = $.map($('a'), function(elem, index){
        return elem.href;
    });
     
    // URLs = ['http://google.com', 'http://whatever.com', 'http://yahoo.com']
  • This isn’t jQuery related but it can be very useful. When you need to compare two different ways of doing something (performance-wise) you can use the Firebug console to log the time taken to complete a chunk of code, for example:
    console.time('My first method');
    // Do something...
    console.timeEnd('My first method');
     
    console.time('My second method');
    // Do something else...
    console.timeEnd('My second method');
     
    // Firebug will log the time (in milliseconds) taken
    // to complete each chunk...

Getting the real time in JavaScript

Posted in 'Code Snippets, JavaScript, News, PHP, Uncategorized, Usability' by James on January 29th, 2009

Getting the time in JavaScript is pretty simple. Using the Date constructor will give us the time as set on the user’s computer, but what if we want the accurate time, or the time in a different timezone?

Even with getTimezoneOffset() you’re still relying on the client!

It turns out that the only way of getting a complete and accurate time from any timezone requires a little bit of server interaction. Luckily there are a few APIs out there that offer this service (actually, there’s only one; well I couldn’t find any others)!

Here we’re using the ‘json-time’ API developed by Simon Willson:

JSON-time

function getTime(zone, success) {
    var url = 'http://json-time.appspot.com/time.json?tz=' + zone,
        ud = 'json' + (+new Date());
    window[ud]= function(o){
        success && success(new Date(o.datetime), o);
    };
    document.getElementsByTagName('head')[0].appendChild((function(){
        var s = document.createElement('script');
        s.type = 'text/javascript';
        s.src = url + '&callback=' + ud;
        return s;
    })());
}

Usage

The first parameter of the callback function is the time (having been passed through the Date constructor), so you can use Date methods such as getSeconds() etc. The second parameter is the entire object returned from the JSON request.

// Alert GMT:
getTime('GMT', function(time){
    alert(time);
});
 
// Get London time, and format it:
getTime('Europe/London', function(time){
    var formatted = time.getHours() + ':' 
                  + time.getMinutes() + ':'
                  + time.getSeconds();
    alert( 'The time in London is ' + formatted );
});

For reference, here’s a list of all the available timezones (to use one, remove the backslash).

jQuery version

$.getTime = function(zone, success) {
    var url = 'http://json-time.appspot.com/time.json?tz='
            + zone + '&callback=?';
    $.getJSON(url, function(o){
        success && success(new Date(o.datetime), o);
    });
};
 
// Usage:
$.getTime('GMT', function(time){
    alert(time);
});

MooTools version

You’ll need to download the JsonP class.

function getTime(zone, success) {
    var url = 'http://json-time.appspot.com/time.json';
    new JsonP(url, {
        data: { tz: zone },
        onComplete: function(o){
            success && success(new Date(o.datetime), o);
        }
    }).request();
}
 
// Usage:
getTime('GMT', function(time){
    alert(time);
});

Thank you Simon Willison for making this API; seriously, I searched around the entire internets just for one damn API and I almost lost hope!

Reque.st – for shorter URLs

Posted in 'General, News' by James on October 12th, 2008
Reque.st – for shorter URLs

Recently, I’ve been working on a URL-shortening service similar to tinyurl.com. It’s called Reque.st and features a sweet-looking homepage, some Ajax’y goodness and a "custom pointer" option.

Using it is incredibly simple. All you need to do is enter the long url which you want to shorten and hit "shorten" – you also have the option of specifying a "pointer" which can be related to the URL. For example if I have a long URL linking to a PDF report:

http://very-very-long-url.com/pdfsection/pdf/2008/01/01/pdf/newer/
?specify=129483&isThisVeryLong=true&borderOfTyping=yep#ImportantPartOfThePDF

I could shorten it and add a custom pointer of "my-pdf-report" so to get to the above URL you would go to:

http://reque.st/my-pdf-report

Useful, huh!?

JustTweetIt.com launched

Posted in 'General, News, Twitter' by James on October 7th, 2008
JustTweetIt.com launched

Dani McDaniel of ‘Anidan Design‘ and Adelle Charles of ‘Fuel your Creativity‘ recently launched ‘Just Tweet it’ (JustTweetIt.com), a site which offers twitter users the opportunity to submit themselves to a global directory of fellow tweeters. The directory is split up into various subdirectories sorted by interests & professions. Obviously I’ve put myself in with the ‘web developers’!

From the site:

Just Tweet It was created to make it easier for people using the popular micro-blogging service Twitter to find other “Tweeters” with similar interests.

For news and updates on the new site make sure you follow @justtweetit on Twitter.

A superb idea from Adelle and Dani and congrats to them on the successful launch! :)

Welcome to my new blog!

Posted in 'General, News' by James on October 4th, 2008
Welcome to my new blog!

Hello, welcome to my personal blog. To find out more about me, you can visit the "about me" page. I’m currently running another blog called "Enhance the user experience" – it mainly focuses on web development tutorials and various script releases. I’m hoping to do a couple of webdev related posts each month on this blog too since I don’t want all to be personal.

Since this website of mine is entirely new there a bound to be a couple of issues, if you spot a major one please let me know. Also any feedback or suggestions on the design of this site are much appreciated! By the way the relevance of the car is that it is new, much like this website! ;)

I’ve done a post discussing a couple of the new features over here for those interested.

PS. I’d like to thank Adelle Charles of "Fuel your Creativity" for helping out with the design!