Tag Archives: jQuery

jQuery Mix Photo Gallery

Recently I coded an interesting photo gallery using jQuery. I’ve named it “jQuery Mix Photo Gallery”. I’ve included the screen-shots here.

You may have a look at the live demo here. The photo gallery is free to download. Here is the download link. You may modify it according to your need and use it in your commercial projects. Please drop a comment if you like it and suggest me how can I make it much better.

JSONP First Timer

You already know ajax is one-man’s-girl, no way to make it work cross-domain(not even subdomain) due to browsers’ same origin policy security restriction. But using ajax is so sleek, you can’t even resist yourself using it under different domains. There is always a way around for everything. Do I sound contradictory? Ajax is based on the XMLHttpRequest and as long as we use it we can’t do cross-domain data transfer. Let’s think something else other than ajax.

We are used to loading images, css, javascript files from other domains and it’s okay if we use any server-side dynamic link as the src, this is a common phenomena on web. For example:

<script type="text/javascript" src="http://www.other-domain.com/dynamic-js.php?id=5&name=Matt"></script>

There is no security restriction including javascript source from different domains, and fortunately enough you can pass GET variables (don’t over-expect for POST) with the url. This is how JSONP (JSON with padding) works, thanks to the open policy for <script> tag. May be you’r already thinking how to implement this idea, hold on! you don’t need to reinvent the wheel.

Here comes jQuery’s $.getJSON(), with this function you can pass url of another domain and get JSON data. Lemme warn you, for the very first time most of you won’t be able to make it work. Here is an example:

$.getJSON("http://www.other-domain.com/dynamic-js.php?id=5&name=Matt&jsoncallback=?",
function(data){
    // your code goes here
});

You need to understand this “jsoncallback=?” bit clearly. From your firebug Net panel you can see the “?” is replaced with “jsonp1277557614558″ (random value on each request).

JSONP Net Panel screen shot

The common mistake you’re gonna do is you expect to see something on firebug’s Console tab, but nothing there, once again JSONP is NOT Ajax request. This is merely an external javascript file being added to your document dynamically, if you don’t believe me on your firebug panel click the JS from Net tab to filter out the JS only(marked in the screen-shot above). You’ll definitely see the JSONP url there. This is the client-side part of $.getJSON(). The confusion still remains with the server-side code.

Back to “http://www.other-domain.com/dynamic-js.php?id=5&name=Matt&jsoncallback=?”, the file being called is dynamic-js.php. Put this one line of code in that file:

<?php print_r($_GET); ?>

And check the Response output from firebug’s Net tab. It’ll be something like:

Array
(
    [id] => 5
    [name] => Matt
    [jsoncallback] => jsonp1277557614558
)

In Ajax when the dataType is json the response from server-side script is just the json string:

{
	// your json data
}

Here is the most important part, unlike ajax for JSONP the $.getJSON() expects the response like:

 jsonp1277557614558({
	// your json data here
})

So you must wrap the json output with jsonp1277557614558( ). If you don’t do it the callback will fail silently without any error, which makes it tough to detect the exact problem. Remember the jsonp1277557614558 is a random string. For php the code will be something like this:

<?php
// your code here
// get the output in an array say $output_array
$jc = $_GET['jsoncallback'];
echo $jc . '(' . json_encode($output_array) . ')';
/*
// For ajax response, simply
echo json_encode($output_array);
// is enough
*/
?>

This is the most crucial thing, most programmers do the mistake for their very first time as there is no clear elaboration on $.getJSON documentation page. FYI, json_encode() function is not available on older version of php. You can get the php class from json.org.

Hope your $.getJSON() is now working! :)

Comments, criticism are most welcome.

CSS Equal Height Columns

Once upon a time people used tables for designing website layout. Definitely table tag has many advantages but it’s not that flexible & extensile. You can not use proper positioning or floating attributes css style for table based layout. It’s not that commodious to handle table width/height from Dreamweaver, the layout gets messy when you drag any border of table, td or tr as the dimensions automatically get changed. The most important incentive for the current web sphere is SEO (Search Engine Optimization) which is dramatically & automatically mended when DIV based layout is used where TABLE based layout is toilsome for search bots to crawl & takes much page loading time. And at some point it makes more sense to use table for displaying tabular formatted data only, for example gmail uses table for the email list, this could be done using UL/LI, but table is more appropriate in this case.

Lately most web designers use DIV for page layout designing for its flexibility and robustness. Unlike table div has a big problem (in fact it’s the nature of div) when you want to give same height to multi-columns div based page layout, you can not do that very easily. I always used javascript for this purpose, but wished if I could do it with css, cos when the javascript is disabled the page layout will be not as expected in most of the cases.

Yes it is possible to create equal height columns with css! You can make the height of multiple floated divs equal using CSS only and no javascript or invalid css. Before beginning I assume you have adequate knowledge on HTML, CSS, javascript and you have already Firebug add-on installed on your Firefox :)

Lemme start from the beginning:

Default three column layout

default-three-column-layout
Link to the HTML page

When you apply float left and fixed width to multiple adjacent divs, by default the layout looks like the above screen shot. You can see it from browser or have a look at the source code (html/css) on the following link above. You see as the contents are not same in the 3 divs, the height is different.
The next example is making the height of the 3 divs same using javascript (jQuery).

Three column layout – equal height using jQuery

Three column layout - equal height using jQuery
Link to the HTML page

This is mostly and widely used for making equal height columns using javascript. I’ve used jQuery here. You may have a look at the source code from the link above.

$(function(){
	var H = 0;
	$("div").each(function(i){
		var h = $("div").eq(i).height();
		if(h > H) H = h;
	});
	$("div").height(H);
});

Now here comes the css equal height technique! The mantra is to use a large amount of bottom padding and the same amount of negative bottom margin to the floated divs and keep them inside an overflow hidden div. That’s all, and the magic happens!

Three column layout – equal height using pure CSS

CSS Equal Height - three column layout
Link to the HTML page

Let me get into details on how to do it. At First have a look at this link. Here I’ve used a huge amount (9000px) of bottom padding and the same amount of negative bottom margin (-9000px). But this makes the columns look so long and still not equal height at bottom. Now on this link I’ve used a holder div with overflow:hidden and that’s it, it is doing the magic by hiding the overflow section.

body{margin-bottom:50px}
div.holder { overflow:hidden }
div.holder div { float:left; width:30%; background-color:#9C0; margin-right:5px; padding:10px; padding-bottom:9000px; margin-bottom:-9000px }

Hope it’s clear now.

There is another method which use a background image with 1px height and color matched with the div’s bg color and body’s bg color. Please have a look at the html link, it’s self-explanatory.

Three column layout – equal height using pure CSS with Background Image

CSS Equal Height - three column layout using bg image
Link to the HTML page

Now I’ll try border to the columns and we’ll see the problem and it’s solution.

Three column layout – equal height with border

CSS Equal Height - three column layout using border
Link to the HTML page

Here you can see bottom border is missing which is obvious as we’ve used a huge bottom padding, from Firebug if you turn off overflow:hidden to the holder div and scroll down at the bottom of the page you’ll see the bottom border there but not equal height.
So how to solve this issue? There are 2 ways to do it – using a bg image in a tricky way or another pure tricky css hack.

Three column layout – equal height with bottom border fix using bg image

CSS Equal Height - three column layout using border fix
Link to the HTML page

Here I’ve used a 1px bg image for the background image and placed it at left-bottom of the bottom-border div with no-repeat and also applied 1px bottom padding. The holder div is inside the bottom-border div. Please feel free to play around with firebug!

This is the last method for bottom border fix without any bg image, just pure css.

Three column layout – equal height with bottom border fix using pure css and no bg image

CSS Equal Height - three column layout using border fix
Link to the HTML page

I’m not gonna explain the details of this last method, find it out yourself! :)

jQuery Drop down menu without setTimeout

I worked a lot with drop-down menus like most of you. There are many stable versions of DD menus using pure javascript & CSS or only CSS with cross-browser support and you’ll get them free from many menu maker websites or desktop applications. So I’m not going to reinvent the wheel.

I’m a freaking fan of jQuery and always use it for drop-down menus with my custom jQuery code. It’s a must to use a delay for javascript driven dd menus even for jQuery when you want to give it some effect like slideDown or slideUp (For CSS dropdown menus it’s not possible & thus no need to use delay). I always wished to use jQuery without any setTimeout function for the drop-down menus. And I did it which I’m gonna share with you.

$(function () {
    $("ul>li").hover(function () {
        $(this).find("ul.sub").slideDown('fast');
        $(this).addClass("hover");
        $(this).hover(
        function () {},
        function () {
            $(this).find("ul.sub").slideUp('fast');
        });
    },
    function () {
        $(this).removeClass("hover");
    })
})

Here it is in action

The main tricky part is using hover inside hover function:

$(this).hover(
function () {},
function () {
    $(this).find("ul.sub").slideUp('fast');
});

This removes the mouseover function (first function of hover) when mouse hover into the li so the slideDown does not happen again when the mouse enter into the inner ul/li. Hope that makes sense. You may like to add a delay and do some more fine tunes.

Happy Coding!

Adulterating twitter

Twitter is a simple yet very powerful platform for sharing status updates among the followers. At first its intention was for personal uses, but now it’s beyond personal, it’s being used for spreading business updates. Already the total number of twitter followers of a website is considered for the valuation of its traffic. The more followers you have the more value your website gains. To get more followers you need to follow more people.

To follow the followers of a popular person/website go to the “followers” page (for example the followers page of php_projects is http://twitter.com/php_projects/followers). On each page you’ll see 20 people. There you’ll see the follow button (a human head with + symbol) beside each follower. Click on that button and you’ll become a follower of that person. Twitter uses ajax for this action. So you can simultaneously click on all the follow buttons on that page. When you target to follow a large number of people your wrist will get stuck clicking on the follow buttons.

But you can make this process fully automated! As twitter uses jquery, a simple one line of jQuery code can trigger click event on all the buttons at once. I’m not sure if twitter is aware of that or not. If you use FireBug you can run the code from console tab.

jQuery("li.follow-action button").trigger("click");

Also you can do it directly from address bar. Just paste this code in your address bar, press enter and see the magic!

javascript:jQuery("li.follow-action button").trigger("click"); void(0);

Screen shot of the code in action:
adulterating twitter in action

Hope you’ll find it useful for your business.

Advanced cycle plugin integration

On my another post I mentioned that cycle is a great jQuery plugin. I use it very often for slideshow. Recently I used it on a project where the slideshow had many(20+) wallpaper sized images. So loading time was a great issue.

The default cycle integration includes all the images during page loading which is okay for small images, but highly affects the page loading time for high resolution images. cycle plugin is highly flexible! I fixed the issue by loading images dynamically one after another at the end of each slide, literally before the beginning of each slide.

Here is how I did it:

<div id="slideshow"><!-- slides will be added here --></div>
var gallery = ["images/1.jpg", "images/2.jpg", "images/3.jpg", "images/4.jpg", "images/5.jpg", "images/6.jpg", "images/7.jpg", "images/8.jpg", "images/9.jpg", "images/10.jpg", "images/11.jpg", "images/12.jpg", "images/13.jpg", "images/14.jpg"]; // and so on.. array of images
// Array clone function.
Array.prototype.clone = function () {
    var arr = new Array();
    for (var property in this) {
        arr[property] = typeof(this[property]) == 'object' ? this[property].clone() : this[property];
    }
    return arr;
}
var gal = null; // gal should be global as I'll use it inside onBefore function
$(function () {
    gal = gallery.clone(); // cloning the array is not mandatory, but doing so will keep the main array unchanged.
    $('#slideshow').empty().append('<img src="' + gal.pop() + '" /><img src="' + gal.shift() + '" /><img src="' + gal.shift() + '" />') // adding the last, first and second element of the array to the slideshow div, then start the cycle plugin.
    .cycle({
        startingSlide: 1,
        // this is required (1 is the 2nd slide) as the first slide is the last element of the array. if you use manual next/prev button clicking on #prev will show the first element.
        before: onBefore, // loads the next image at the beginning of each slide. (NOT all at once)
        next: "#next",
        prev: "#prev"
    });
    var totalSlideCount = 1 + gal.length;
    function onBefore(curr, next, opts, fwd){
        // at first addSlide is not defined, so we should return.
	if (!opts.addSlide) return;
	// if all the elements of the array are added no need to add them again!
        if (opts.slideCount == totalSlideCount) return;
	// shift or pop from slide array
        var nextSlideSrc = fwd ? gal.shift() : gal.pop();
	// add next slide
        opts.addSlide('<img src="' + nextSlideSrc + '" />', fwd == false);
    }
});

In this code above, cloning the array is optional. I used it as I needed the main array for later use. Probably you know if you use the global array reference to a local variable and apply pop()/shift()/push() functions to the local variable, the global one will be affected. cos the local variable is just a reference to the address of the global array variable.

At first the last, 1st and 2nd elements of the array are added to the #slideshow div and the cycle is started from the 2nd slide. Before starting of each slide onBefore function is called. The onBefore function adds new slide to the slideshow and stops when all the array elements are added to the slide.

You may use it for small size images also if you need to improve the page loading duration.

IE6 fix for select box over absolute positioned element

IE6 sux. General css/javascript hover drop-down menu uses a div or ul with position:absolute. No matter how much you increase the value of z-index the select box (windowed element) will always remain on top most – yes only on a special browser, Internet Explorer 6. The reason is IE6 considers select element as windowed element and keeps it always on top layer.

IE6 select box over div

Solution is using iframe on top of select element, as iframe is also a windowed element placing it on top of select box fix the problem.

IE6 select box over div prob fixed using iframe

Here is the typical HTML code for this drop-down menu:

<div class="top-menus" style="left: 221px; top: 127px;">
<iframe frameborder="0" scrolling="no" align="bottom" marginheight="0" marginwidth="0" src="javascript:'';" style="height: 200px;"></iframe>
    <ul>
      <li><a href="#">Bracelets</a></li>
      <li><a href="#">Rings</a></li>
      <li><a href="#">Earrings</a></li>
      <li><a href="#">Necklaces</a></li>
    </ul>
</div>

The inline css is calculated using jQuery offset() function. FYI, you can easily get the width,height,left,top position of any element using jQuery(“element”).offset(). Make sure the width and height of the iframe is exactly same of it’s overlying UL element. If you apply any border to the UL, you have to consider that during calculating the proper width/height of the iframe.

This is the sample jQuery code:

var timer = null; // global
$("#top-nav a").hover(function(){
	clearTimeout(timer);
	$("#top-nav a:not('.cur')").removeClass("selected");
	$(this).addClass("selected");

	var o = $(this).offset();
	var left = o.left + 1; // 1px extra for border
	var top = o.top + 32; // 32px for placing it just below the horizontal menu
	if($(".top-menus").length){
		if(left == $(".top-menus").offset().left)
			return;
		else $(".top-menus").remove();
	}

	$("body").prepend('<div style="left:'+left+'px;top:'+top+'px;" class="top-menus"><iframe src="javascript:\'\';" marginwidth="0" marginheight="0" align="bottom" scrolling="no" frameborder="0"></iframe><ul>'+html+'</ul></div>');
		$(".top-menus").find(".parent, .child").remove();
		var hi = $(".top-menus").find("ul").height();
		$("iframe").height(hi + 2); // extra 2px for border

}, function(){
	clearTimeout(timer);
	timer = setTimeout(function(){$("body").find("iframe,.top-menus").remove(); $("#top-nav a:not('.cur')").removeClass("selected");},300);
});

$(".top-menus").live("mouseover",function(){
	clearTimeout(timer);
}).live("mouseout",function(){
	clearTimeout(timer);
	timer = setTimeout(function(){$("body").find("iframe,.top-menus").remove(); $("#top-nav a:not('.cur')").removeClass("selected");},300);
});

I know this code won’t exactly fulfill your requirement, you can get the main idea from this and write your own code yourself. You can see it in action on www.trendtogo.com.

SEO tips: Reduce your unwanted external links using jQuery

In SEO one of the most important factor is reducing the external links. A common practice is using rel=”nofollow” or rel=”external nofollow” or rel=”nofollow me” with <a> tag to reduce the page rank leakage. But do you know there may be some external links on your blog which you are not aware of at all! In most cases WordPress blogs have links to wordpress.org and the theme provider’s site at bottom which does not have the “nofollow” attribute. The indexing and ranking procedure of search engine is still a mystery and there are rumors that some spiders follow the nofolllow links! So adding a nofollow is not always the good solution. Some WP plugins and widget codes insert direct link to their sites.

It may sound odd.. the most popular social bookmarking widget AddThis button code has direct link to their site and we never bother to look inside their code. Here is the AddThis button code:

<!-- AddThis Button BEGIN -->
<div>
<script type="text/javascript">
	var addthis_pub="4a11abc75f3cd444";
</script>
<a href="http://www.addthis.com/bookmark.php?v=20"
onmouseover="return addthis_open(this, '', '[URL]', '[TITLE]')"
onmouseout="addthis_close()"
onclick="return addthis_sendto()">
<img src="http://s7.addthis.com/static/btn/sm-plus.gif" width="16" height="16" alt="Bookmark and Share" style="border:0"/>
</a>
<script type="text/javascript" src="http://s7.addthis.com/js/200/addthis_widget.js"></script>
</div><!-- AddThis Button END -->

You see there is a direct link to http://www.addthis.com/bookmark.php?v=20. If you remove this the code won’t work and adding nofollow is not a good solution. I modified their code in my own way and removed the link.
To do this first I saved the js (http://s7.addthis.com/js/200/addthis_widget.js) that is loaded at first from the addthis server. According to their TOS there is no problem if I cache their js code and use an image of my own choice. So I used a different addthis image with shadow which you can see at top-left side of this post and added a pseudo class “bkmrk” to it.

This is the php code for the template:

<img class="bkmrk" src="<?php bloginfo('template_url'); ?/>/images/addthis.gif" alt="bookmark" title="< ?php the_title(); ?>" name="< ?php the_permalink(); ?>" border="0" />

The title of the img tag is title of the post and the value of the name attribute is permalink.

Then I included the js and jQuery library and used this simple code on domready:

jQuery(function(){
    jQuery("img.bkmrk").each(function(){
        var url = jQuery(this).attr("name");
        var title = jQuery(this).attr("title");
        jQuery(this).wrap('<a onclick="return addthis_sendto()" onmouseout="addthis_close()" onmouseover="return addthis_open(this, \'\', \'' + url + '\', \'' + title + '\')" href="http://abcoder.com/"></a>');
    });

    jQuery("span#wp").replaceWith('<a rel="external nofollow" href="http://wordpress.org" title="WordPress" target="_blank">WordPress</a>');
    jQuery("span#theme").replaceWith('<a rel="external nofollow" href="http://web2themes.com" title="WordPress Themes" target="_blank">Web 2.0 Themes</a>');
});

This code simply adds the same functionality but the big difference is search bots won’t find the links as this is done using javascript. So if you see the html source code you won’t see any direct link to addthis.com. The last 2 lines of the code is for links to wordpress.org and web2themes.com.
Isn’t it smart?

However I’m not 100% sure if adapting this method is legal or not! So use this at your own risk. On some blogs I’ve noticed this method being used for links to the commentators website. But right now I’m not sure which wordpress plugin they use for this purpose.

jQuery cycle plugin as carousel

The jQuery cycle plugin is really amazing! I love this plugin for its huge options for image/div slide show. Right now I’m working on a project which has 3 slideshow on one page. One is simple fade effect with text divs, another one is also fade effect with div + image + text and play/pause, next/back option. The third one is a simple carousel with continuous play mode.

I implemented the first two easily with cycle plugin. But I got stuck with the carousel one. The play and the next state is fine as I used the “scrollLeft” fx. The problem is when I click previous button the fx should be “scrollRight” and not “scrollLeft”. I thought it may need a little complex customized function to do this job of applying different transition effect on previous and next event. I had no clue for it. Even no help from google search! I do not like using a lot of plugins at a time. I know there is jCarousel / jCarousel lite plugin for this, but I still believe there must be a way for doing this with cycle.

It took several hours to find out the simple solution. It’s already inside the cycle plugin, but kinda hidden! I am using the “scrollHorz” fx effect and it is fixed now. WOW! again I discovered that “cycle” is really a marvelous plugin of jQuery.

Here is the example on the malsup site: http://www.malsup.com/jquery/cycle/scrollhv.html

This is the simple code I used:

$('#carousels').cycle({
    prev: '#left-arrow',
    next: '#right-arrow',
    pause: 1,
    fx: 'scrollHorz',
    timeout: 6000
});

IE6 png alpha transparency fix for dynamically loaded images via ajax

IE6 is always a nightmare for web developers. The most painful drawback is it does not support the alpha transparency of transparent png images and you know how to solve this problem using iepngfix or jquery.pngFix.js.

You must be thinking.. what is new in my post then!! Have you ever used any of them for dynamic png images? Some people call it “Loading an image via ajax”. Let me explain what I mean by “dynamic png images”.. say you have a page where clicking on a link does not reload the page, but load a transparent/semitransparent png image. Most specifically, I was working on a project where user types some text in a text box, it is converted to transparent png image on the fly using php and then it is displayed inside a div which has a graph-paper like background-image. This whole thing is done without reloading the page at all.

It looks okay on FF, safari, IE7 but on IE6 the transparent portion looks Grey. The iepngfix.htc script didn’t help, cos it only works on the images which are loaded and showed at the beginning of page loading. After the page is fully loaded and you load another png image using ajax this script won’t work. But I could not do that for my project as it is meant to be loaded dynamically using ajax for the sake of advanced user experience.

I started googling for it, no luck. Finally I modified a portion of code used in the iepngfix.htc file and fixed the problem using this simple javascript code. (FYI, I was using YUI so only the browser checking part is done using it, you can use jQuery or pure javascript for browser detection)

var textImage = new Image();
textImage.src = "text.png"; // src of the png image. okay if not ie6
if (YAHOO.env.ua.ie > 5 && YAHOO.env.ua.ie < 7) { // if IE 5+ or 6 or 6+
    var timg_src = textImage.src;  // textImage
    var new_img = new Image();  // just as a preloader
    new_img.src = timg_src;

    new_img.onload = function(){ // remember, the image is being loaded dynamically, so apply the filter after it is loaded.
        var ti = document.getElementById("textImage"); // the ID of the img tag where it'll be loaded
        ti.style.width = new_img.width; // you can get the width/height of image after it is fully loaded
        ti.style.height = new_img.height; // and you must "DEFINE" the image height/width. "auto" height/width won't work!

        // This is it. apply the filter :)
        ti.style.filter = "progid:DXImageTransform.Microsoft.AlphaImageLoader(src='" + timg_src + "', sizingMethod='scale')";
        ti.setAttribute('src', 'blank.gif'); // don't forget this part. the image src is replaced with a blank gif image.
    }
}

Here is another version of the code which is not for dynamic images. It’s alternative of iepngfix.htc. In some cases you may not like using iepngfix.htc, rather want to control it yourself. For example if your page has hundreds of png images which are not transparent and only a few images that are transparent, in this case using iepngfix.htc will make the whole process too slow. I applied a pseudo class “png” to all png images & divs with png background image with fixed height & width and applied this simple jQuery code:

$(window).load(function(){ // after all the images are loaded
    if ($.browser.msie && parseInt($.browser.version.substr(0, 1)) < 7) { // ie6 or 5
        $("img.png").each(function(){
            $(this).css("filter", "progid:DXImageTransform.Microsoft.AlphaImageLoader(src='" + $(this).attr('src') + "', sizingMethod='scale')").attr("src", "images/blank.gif");
        });
        $("div.png").each(function(){
            var bg = $(this).css("backgroundImage");
            bg.match(/^url[("']+(.*\.png)[)"']+$/i);
            bg = RegExp.$1;
            $(this).css("filter", "progid:DXImageTransform.Microsoft.AlphaImageLoader(src='" + bg + "', sizingMethod='crop')").css("backgroundImage", "none");
        });
    }
});

Hope you’ll find it helpful. Please let me know if you have any better idea.