Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

converting a simple jquery code to javascript

I have a code for a simple photo gallery that had been writen with jquery, but i think it's overkill to load the entire library for such a simple thing. I want it in raw javascript.

$('#thumbs').delegate('img','click', function(){
    $('#largeImage').attr('src',$(this).attr('src').replace('thumb','large'));
    $('#description').html($(this).attr('alt'));
});

Also i'm wondering how do I attach a loading spinner to this code. thanks.

jsfiddle

like image 386
NL500 Avatar asked Apr 25 '11 12:04

NL500


2 Answers

Without using any library, it looks a bit like this, although of course there are other ways to write it:

(function() {
    var largeImage = document.getElementById('largeImage'),
        description = document.getElementById('description');

    document.getElementById('thumbs').onclick = handleGalleryClick;

    function handleGalleryClick(event) {
        var target;

        event = event || window.event;                // Handle IE difference
        target = event.target || event.srcElement;    // Another one
        if (target && target.tagName.toUpperCase() === "IMG") {
            largeImage.src = target.src.replace('thumb', 'large');
            description.innerHTML = target.getAttribute('alt');
        }
    }
})();

Make sure that script appears at the bottom of your page (just before the closing body element) or wrap it up in a window.onload although you won't be happy with how long that takes to occur, as window.onload happens after all images and such are loaded.

But: I have to agree with Frédéric's and John's comments: It's not overkill to load a library for this, and in the case of jQuery (and Prototype and YUI) you can load via the Google CDN and use something your page visitor probably already has in their cache anyway.


Update: In the comments below, scunliffe pointed out an IE bug that I've blogged in the past that could affect the above, which is magically worked around for you by jQuery. So I thought it might be useful to flag up the various complications that this simple little script has that a good library will sort out for you:

  • addEventListener vs. attachEvent: IE6 through IE8 don't support the DOM2 standard addEventListener, using Microsoft's own attachEvent instead. I actually punted on this in the above for simplicity and just used the DOM0 onclick = ... style, but there's a good reason not to do that: With the DOM0 style, you can only have a single event listener per event per element, and attaching another will detach the previous one. So my code above doesn't play nicely with others, because it will dislodge any previous DOM0 click handler (and will be dislodged by a DOM0 click handler attached after the code above runs).
  • Accessing the event object: The DOM standard says that the event object is passed into the event handler as its first argument. IE, instead, uses a global window.event object. That's the reason for my first "IE difference" above.
  • Properties on the event object: ...and similarly, the DOM standard says the actual element on which the event was fired will be the target property. IE6 through IE8 use srcElement instead. (There are other differences, too.) Hence my "Another one" comment.
  • Bug workaround: This is the conflation thing scunliffe pointed out. The above relies on document.getElementById to work correctly, but on IE6 and IE7, it doesn't. It conflates several namespaces rather than working just with id values.

...so all in all, this simple little script makes the point fairly well that libraries in general — and a good library in particular — can save you time, keep your site broadly-compatible, and are just generally worth their little cost. I don't know about the others, but for instance jQuery works around the conflation bug for you, but another well-known and well-respected library, Prototype, does not.

(Side note: Before we knock Microsoft too much, let's remember that attachEvent and srcElement probably predate the DOM2 spec; Microsoft did a lot of innovating in IE5.5 and IE6. [They invented ajax, for instance.] IE6 was — by far — the best browser available in 2001, due apologies to Opera. That said, IE6 came out after the standard did and so adding the standards stuff at that point, or several years later in IE7, might have been a worthwhile thing to do! But IE9 fixes a lot of this stuff.)

like image 172
T.J. Crowder Avatar answered Sep 30 '22 11:09

T.J. Crowder


You call it simple, but it's doing somewhat advanced things. To emulate delegate, you have to attach a click listener on the root container and check for clicks on any <img> tag.

Not to mention you have to do things like use attachEvent in IE instead of addEventListener

The code would look something like (untested):

function listen(root, callback) {
    var addEvent = 'attachEvent';
    if (typeof window.addEventListener === 'function') {
        addEvent = 'addEventListener';
    }

    root[addEvent](function (e) {
        if (/img/i.test(e.target.tagName)) {
            callback.apply(e.target);
        }
    }, false);
}

listen(document.getElementById('thumbs'), function () {
    document.getElementById('largeImage').src = this.src.replace(/thumb/ig, 'large');
    document.getElementById('description').src = this.alt;
});

In fact, as TJ's post shows below, I'm not even handling all of the IE idiosyncrasies. jQuery is not overkill considering all of the browser headaches it solves for you.

like image 24
Matt Avatar answered Sep 30 '22 11:09

Matt