Wednesday, September 18, 2013

How to create your own lightbox JQuery plugin - part 2

Welcome back everybody,

So let's continue. We finished last time on writing some code for our plugin, a few styles and this is pretty much it.
Now let's actually call our plugin function.Write following code in index.js:

$(document).ready(function () {
    $('.content a').lightbox({
                topmargin: 16,
                bottommargin: 16,
                border: 8,
            });
});
So here we do a selection on all "a" objects which are children of an DOM object with class "content". In our case we would get list of our hyperlinks. Then we specify some default options for our plugin and that is pretty much it.
Give it a go... Tried it? When you click on any of the images nothing happens right? Weird? Well not really. We don't do anything in our plugin, visually noticeable, but the same time prevent hyperlinks' default behavior:
e.preventDefault();
So no open your lightbox.js file and let's continue our adventure.
Next step would be to actually display something on the screen when any of the images is clicked. Find the line of comment we left there last time:
  // TODO: implementation here
and let's replace it with following:
$('#' + idPrefix + '_lightboxbg').fadeTo(300, 0.4);
What we do here is simply fading in our background.
By the way, "idPrefix" here is used to avoid creating multiple controls with the same name, in case you have multiple lists of images on the same page.

Alright so give it another go and you will see that our background is showing up. Now, when background is loaded we want to show our image container on top of it. Replace previous line of code with following:
$('#' + idPrefix + '_lightboxbg').fadeTo(300, 0.4, function () {
    $('#' + idPrefix + '_lightboximg').show();
});
No we wait till background is loaded and then we show image container. Next step is to display our image, but to do that we have to know its width and height so we can actually calculate the size of the image we are about to display.
First thing to do is to define image object:
var img = new Image();
Now we need to specify image source:
img.src = images[imgIndex];
And when image is loaded we want to perform our calculations. Please note that this image object is not added to the page and will not be yet displayed.
img.onload = function () {}
And now let's do our magic.
                        // empty container
                        $('#' + idPrefix + '_lightboximg').empty();
                        // add image
                        $('#' + idPrefix + '_lightboximg').append('<img src="' + images[imgIndex] + '"/>');
                        // add navigation div
                        $('#' + idPrefix + '_lightboximg').append('<div class="lb_navigation"></div>');
                        // add left/right arrows to loop through images
                        $('#' + idPrefix + '_lightboximg .lb_navigation').append('<div class="lb_left"><<</div>');
                        $('#' + idPrefix + '_lightboximg .lb_navigation').append('<div class="lb_right">>></div>');
                        // add close button
                        $('#' + idPrefix + '_lightboximg').append('<div class="lb_close">CLOSE</div>');
                        // add close button onclick event
                        $('#' + idPrefix + '_lightboximg .lb_close').click(function () {
                            CloseLightBox();
                        });
At this point we have to introduce a few new styles:
.lb_navigation
{
    width: 100%;
    display: block;
    position: absolute;
}
.lb_left
{
    padding: 30px 0px 0px 50px;
    display: block;
    cursor: pointer;
    font-weight: bold;
    position: absolute;   
    font-size: 20px;
}
.lb_right
{
    padding: 30px 0px 0px 50px;
    right: 0px;
    display: block;
    position: absolute;
    font-weight: bold;
    font-size: 20px;
}
.lb_close
{
    width: 75px;
    height: 30px;
    display: block;
    position: absolute;
    font-weight: bold;   
    font-size: 20px;
}
Let's add event handlers to our controls:
$('#' + idPrefix + '_lightboximg .lb_navigation .lb_left').click(function () {
    var nextImageIndex = imgIndex == 0 ? images.length - 1 : parseInt(imgIndex) - 1;
    OpenImage(nextImageIndex, topmargin, bottommargin, border);
});
$('#' + idPrefix + '_lightboximg .lb_navigation .lb_right').click(function () {
    var nextImageIndex = imgIndex == images.length - 1 ? 0 : parseInt(imgIndex) + 1;
    OpenImage(nextImageIndex, topmargin, bottommargin, border);
}); 
 Let's add the box for our description:
// add description box
                        $('#' + idPrefix + '_lightboximg').append('<div class="lb_description"><div class="lb_descpadding">' + descriptions[imgIndex] + '</div></div>');
And here comes our math:
// do the math
                        var hh = $('#' + idPrefix + '_lightboximg .lb_description').height();
                        var extramargin = parseInt(topmargin) + parseInt(bottommargin) + parseInt(border) * 2 + parseInt(hh);
                        var ih = this.height;
                        var iw = this.width;
                        var sh = $(window).height();
                        var sw = $(window).width();
                        if (ih > parseInt(sh) - parseInt(extramargin)) {
                            iw = parseInt((parseInt(sh) - parseInt(extramargin)) * parseInt(iw) / parseInt(ih));
                            ih = sh - extramargin;
                        }
                        if (iw > sw) {
                            ih = parseInt(parseInt(sw) * parseInt(ih) / parseInt(iw));
                            iw = sw;
                        }
                        var leftmargin = -(iw / 2); 
Now we need to apply correct sizes to our controls and we are almost ready to go:
$('#' + idPrefix + '_lightboximg').css('top', topmargin);
                        $('#' + idPrefix + '_lightboximg').css('height', ih + border * 2);
                        $('#' + idPrefix + '_lightboximg').css('margin-left', leftmargin);
                        $('#' + idPrefix + '_lightboximg img').css('height', ih);
                        $('#' + idPrefix + '_lightboximg img').css('margin', border);
                        $('#' + idPrefix + '_lightboximg .lb_navigation').css('top', parseInt(ih / 3));
                        $('#' + idPrefix + '_lightboximg .lb_navigation .lb_left').css('left', border);
                        $('#' + idPrefix + '_lightboximg .lb_navigation .lb_right').css('right', border);
                        $('#' + idPrefix + '_lightboximg .lb_close').css('top', border);
                        $('#' + idPrefix + '_lightboximg .lb_close').css('right', border);
                        if ($.isFunction(options.callback)) {
                            options.callback.call(this);
                        }
Let's touch up our styles a bit, here is a complete file I have for now:
.lb_imgholder
{
    padding: 0px;
    left: 50%;
    display: block;
    position: fixed;
    z-index: 7001;
    background-color: rgb(0, 0, 0);
}
.lb_navigation
{
    width: 100%;
    display: block;
    position: absolute;
}
.lb_left
{
    padding: 30px 0px 0px 50px;
    display: block;
    cursor: pointer;
    font-weight: bold;
    position: absolute;
    font-size: 20px;
    color: #FFFFFF;
    background-color: #000000;
}
.lb_right
{
    padding: 30px 0px 0px 50px;
    right: 0px;
    display: block;
    position: absolute;
    font-weight: bold;
    font-size: 20px;
    color: #FFFFFF;
    background-color: #000000;
    cursor: pointer;
}
.lb_close
{
    width: 75px;
    height: 30px;
    display: block;
    position: absolute;
    font-weight: bold;
    font-size: 20px;
    color: #FFFFFF;
    background-color: #000000;
    cursor: pointer;
}
.lb_description
{
    width: 100%;
    color: rgb(255, 255, 255);
    font-family: Arial;
    font-size: 12px;
    display: block;
    position: absolute;
    background-color: rgb(0, 0, 0);
}
.lb_descpadding
{
    padding: 8px;
} 
 Alright, let's test it:

Looks more or less alright, but we don't have the description. Now we have to touch up our html file adding "desc" attribute to our hyperlinks, something like this:
<a href="IMG_0191.jpg" desc="Cancun Beach">
            <img src="tn_IMG_0191.jpg" border="0" /></a> <a href="IMG_1162.jpg" desc="Pelican over the water">
                <img src="tn_IMG_1162.jpg" border="0" /></a> <a href="IMG_2875.jpg" desc="Macarons...">
                    <img src="tn_IMG_2875.jpg" border="0" /></a>
 Now give it another try:

Now play with it, you can re-size your browser, add longer captions, our heights and width should be calculated correctly. Also looping through images.
So here we go, we've done it! :-) Congratulations :-)

Things to improve:
design (you probably would want to replace our navigation links to some fancy images)
you can also display some gif image (showling some spinning wheel indicating that image is loading) when navigation buttons are clicked. So in case it takes some time to load each image, we would first display loading gif and once image is loaded would replace it with actual image.

Well i will let you play with it. In case you guys want actual files please let me know.

Cheers,
Your GPTeam

0 comments:

Post a Comment