How to get on the jQuery IRC channel

Tuesday, 8 December 2009

View Comments

This article looks at how to connect to the jQuery IRC channel via your web browser.


To connect is straight forward, you can go here, this will display the following:



Just enter any nickname and #jQuery as the channel and you are in.

The jQuery IRC channel is helpful if you want to get something answered quickly, there's plenty of people hanging around who could help, but... make sure you ask something specific and make sure you ask something relevant and you will be sure to get some help.
more...

Cool transitioniong effect between images using jQuery animate

This tutorial looks at using jQuery animate to transition from one image to another. jQuery's built in animate function provides a method for easily animating styles such as height, color and position. I will show you a method of toggling backwards an forwards between two images by changing on images dimensions to match the others and by fading one image out to reveal the other.


You can view a demo of this functionality here.

You can download the code for this tutorial here.



Each of the steps should work simultaneously to give a smooth transition from one image to the other. The current image will gradually change width/height while fading out to reveal the other image. The functionality will allow transistioning backwards and forwards between the two images.

This functionality is a great example of jQuery's animate function and could be applied in a variety of ways. You could extend it to cycle through several images, use it in an online catalog for different views of an item or to make an interesting photo album.

In our HTML we have a div marked with class .fade_switch, inside that are the two images that will be used to transition between:

<div class='fade_switch' style='display:block;position:relative;'>
 <img src='./images/green_present.png' />
 <img src='./images/zim.jpg'/>
</div>

This is all the markup that is needed, now let's look at our javascript:

$("document").ready(function() {
 $(".fade_switch img").each(function() {
  var img = new Image;
  img.src = this.src;
  var my_parent = $(this).parent(".fade_switch");
  
  var my_index = $(my_parent).children().index(this);
  
  var myself = $(this);
  
  $(img).load(function() {
   $(myself).data("start_w", img.width);
   $(myself).data("start_h", img.height);
   if (my_index == 0) {
    $(my_parent).css({"width":img.width, "height":img.height});
   } else {
    $(myself).hide();
   }
  });
  
  $(this).css({"position":"absolute", "top":"0px", "left":"0px"});
 });

We begin by looping over each image belonging to a .fade_switch div. We preload the image and after each image has loaded we store its dimensions by using the data function, this will be used later when we animate back to its original size (this is required by IE).

Next we check to see if it is the first image of the two, if so we set the parent .fade_switch element to the size of the image. We then hide the other image.

We finish by setting each image to position absolute, so one image sits in front of the other.

Then we have the click function for each .fade_switch div:

$(".fade_switch").click(function() {
  if (!$(this).is(':animated')) {
   var vis_img = $(this).children(":visible");
   var hid_img = $(this).children(":hidden");
   
   $(vis_img).css("z-Index", "100");
   
   var vis_width = $(vis_img).data("start_w");
   var vis_height = $(vis_img).data("start_h");
   
   var hid_width = $(hid_img).data("start_w");
   var hid_height = $(hid_img).data("start_h");
   
   $(hid_img).css({"z-Index":"1","width":vis_width,"height":vis_height}).show();
   
   
   
   $(vis_img).animate({
    "opacity" : "0",
    "width" : hid_width,
    "height" : hid_height
   }, function() {
    $(this).css("z-Index", "1").hide().css("opacity", "100");
   }); 

   $(hid_img).animate({
    "width" : hid_width,
    "height" : hid_height
   }, function() {
    $(this).css("z-Index", "100");
   });
   
   $(this).animate({
    "width" : hid_width,
    "height" : hid_height
   });
  }
 });

We first check to see that this element is not being currently animated, this is done to stop multiple clicks from screwing things up mid transition. This is done using the :animated selector: if (!$(this).is(':animated')) {

We then retrieve the two elements seperately according to whether they are visible or hidden. We set the visible image to have a zIndex of 100 so it sits on top.

Next we grab the dimensions of each of the images and set the hidden image to have the same dimensions as the visible on, but with zIndex set to 1, then we set it show (it will not appear as it sits behind the other image since it has a zIndex of one and both are absolutely positioned).

Once this is done we begin the animation. We animate the top image to opacity 0, and to shrink or grow to the behind image. Once it has completely faded and changed its dimensions we set it to zIndex 1 and hide it. We animate the back image to its original width and height and set it to zIndex 100 and we also make sure the parent div also has matching width and height.

If you have any great transitioning tricks or want to recommend any good tutorials, share them in the comments below.
more...

Accessing draggable elements from ui.droppable drop function

This post looks at the ui.droppable drop function. We will look at how to access the droppable, the element that has been dropped onto the droppable and how to access it's methods.


In most cases the droppable views the item being dropped as a draggable, whether it is a ui.sortable or a ui.draggable. To get some understanding of how this works, I came across this section of the jQuery UI Development and Planning wiki: "The droppable implementation comes with a global drag & drop manager called $.ui.ddmanager. It tracks the current draggable, has a list of all droppables at all times and its 'drag' function is called during dragging of the draggable (a 'drop' function on mouseup). It then forwards to the actual widget functions of the current intersecting droppable.". This is important to understand as when we access the element after it is dropped it is referenced via ui.draggable.

Let's take a look at the droppable API and how it explains the drop function for the ui.droppable:

This event is triggered when an accepted draggable is dropped 'over' (within the tolerance of) this droppable. In the callback, $(this) represents the droppable the draggable is dropped on. ui.draggable represents the draggable.

Code examples:
Supply a callback function to handle the drop event as an init option.

    $('.selector').droppable({
       drop: function(event, ui) { ... }
    });

So our drop function has the following signature function(event, ui) and we know that $(this) represents the droppable and ui.draggable represents the draggable.

So regardless of whether it is a ui.sortable list item or a ui.draggable being dropped on a droppable we can access the element in the following way:
$("#target").droppable({
 drop: function(event, ui) { 
  var element = $(ui.draggable);
  var DOMelement = $(ui.draggable)[0];
 }
});

You can then manipulate the item in anyway that you like using javascript or jQuery as per usual.

For a standard UI widget when looking at the file you will notice there are two types of functions; those defined with an underscore such as _clear and _trigger in ui.draggable.js and those that don't have an underscore, such as serialize and toArray in ui.sortable.js. Those with an underscore are like privately scoped functions, you cannot call them outside of the UI widget, the others you can and it is done like this. $("#my_sortable_ul").sortable("toArray");. There are also getters and setters available, examples of which are usually available in the API such as ui.droppable addClasses option which can be retrieved as such:
//getter
var addClasses = $('.selector').droppable('option', 'addClasses');
//setter
$('.selector').droppable('option', 'addClasses', false);

So now that we know how to target our element in the drop function and we know which functions are public and how to use setters and getters here is an example of how we can call those functions within the ui.droppable drop function. Note: The sortable and draggable are different in that for sortable list items it is the parent who is the ui.sortable, whereas with the draggable it is the element itself that is the ui.draggable.

// Calling functions on a ui.sortable

drop: function(event, ui) { 
 var array_values = $(ui.draggable).parent().sortable("toArray");
}

// Calling functions on a ui.draggable

drop: function(event, ui) { 
 $(ui.draggable).draggable("destroy");
}

// Accessing getter on a ui.sortable

drop: function(event, ui) { 
 var this_opacity = $(ui.draggable).parent().sortable('option', 'opacity');
}

// Accessing getter on a ui.draggable

drop: function(event, ui) { 
 var this_cursor = $(ui.draggable).draggable('option', 'cursor');
}


With a sortable once it has been dropped it may be also usefull to access the siblings of the element dropped:

// Set the background color on all of the siblings of the dropped element to red

drop: function(event, ui) { 
 $(ui.draggable).siblings().css("background", "red");
}

Using andSelf you can manipulate the siblings as well as the dropped element:

// Set the text color of all of the elements including the dropped element to blue

drop: function(event, ui) { 
 $(ui.draggable).siblings().andSelf().css("color", "blue");
}

jQuery widgets are extremely well designed and have layers of complexity that require a bit of digging. The are very simple to use, but with a bit of research you can get a great amount out of them. Hopefully this tutorial will help you understand UI widgets in a bit more detail.
more...

Using jQuery with forms - part 5 (Traversing)

Monday, 7 December 2009

View Comments

This is the fifth in a series of tutorials on using jQuery to manipulate forms. In this series I will be looking at parts of the jQuery API reference in detail. In this tutorial I will be looking at forms and jQuery Traversing.

Filtering


eq(index)

Matches the element from a group at a particular index

// Set the second radio element with name foods to checked
$("#my_form radio[name='foods']:eq(2)").attr('checked', 'checked');

filter(expr)

Removes elements from a group that do not match the expression

// Set all of the input elements that have the class error and out_of_range to red
$("#my_form :input").filter('.error, .out_of_range').css('color', 'red');

filter(fn)

Removes elements from a group that do not match the supplied function, useful if you want to remove elements based on a complex function

// Set all of the input elements that have the class error and out_of_range to red
$("#my_form :input").filter(function(index) {
 if ((index > 6) || ($(this).attr("type") == "hidden)) {
  return true;
 }
}).css('color', 'red');

is(expr)

Used to check if one of the matched elements matches the expression

// Checks to see if any of the password elements has the error class

if ($("#my_form :password").is('.error')) {
 alert('A password field is still in error');
}

map(callback)

Takes a set of elements and maps each one onto the callback

// This is a very useful function but takes some understanding, rather than looking at the function below I suggest you check out this page for practical uses of this function.

// Map all of the options from #myselect to the $(this).val() function, get the actual DOM elements and join them with a comma
alert($("#myselect option").map(function() {return $(this).val();}).get().join(', '));

not(expr)

Removes elements that do not match the expression from the set

// Get all of the input elements and remove those that are not inputs and then apply a grey background
$("#my_form :input").not(":password").css('background', 'grey');

slice(start, end)

Selects a subset of the elements based on start and end index

// Hide all of the radio elements with name foods except the first and last element
$("radio[name='foods']").slice(1, ($("radio[name='blah']").size() - 1)).hide();

Finding


add(expr)

Adds a set of elements to an existing group

// Set all of the select elements to red border then set all of the select and text elements to color blue
// This could be useful if you wanted to show which elements had been validated as well as those that are in error
$(":select").css('border', '1px solid red').add(":text").css('color', 'blue');

children(expr)

Selects all the children of an element and optionaly filters them according to the expression

// Retrieve all of the select children elements of my form that have the class validated
$("#my_form :select").children(".validated");

closest(expr)

Closest works by first looking at the current element to see if it matches the specified expression, if so it just returns the element itself. If it doesn't match then it will continue to traverse up the document, parent by parent, until an element is found that matches the specified expression. If no matching element is found then none will be returned.

// If a button is clicked it checks to see if it has the disabled class, if not it traverses up the document to find the closest element with the disabled class and then adds the matched class
$("button").click(function(e) {
  $(e.target).closest(".disabled").addClass("matched");
});

find(expr)

Searches for decendant elements that match the given expression

// Apply a yellow background to all p elements that are descendants of the .login_entry fieldset

$(":fieldset .login_entry").find("p").css('background', 'yellow');

next(expr) / nextAll(expr)

Find the next (the siblings after) sibling matching expr or find all the sibling after this element matching expr

// Set the text element directly after a disabled button to read 'this button is disabled'
$("button[disabled]").next().text("this button is disabled");

// Hide all p siblings after a disabled button
$("button[disabled]").nextAll("p").hide();

prev(expr) / prevAll(expr)

Find the previous (the siblings before) sibling matching expr or find all the siblings before this element matching expr


siblings(expr)

Find all the siblings of this element matching expr


parent(expr) / parents(expr)

Find the parent of this element (can be called on a group and filtered by expression) / Find all the parents of this element (the unique ancestors)

// If a parent contains a disabled button then hide it
$("button[disabled]").parent().hide();

Chaining


andSelf()

Find the parent of this element (can be called on a group and filtered by expression) / Find all the parents of this element (the unique ancestors)

// Find all fieldsets that contain radio elements and place a border around the radio elements and around the fieldset
$("fieldset").find(":radio").andSelf().css('border', '1px solid green');

If you found this post useful, here are part 1, part 2, part 3 and part 4 of this series.
more...

Grid based approach to improve your designs

This article looks at using the grid based design approach to improve your design efforts. Using a grid will provide clarity, structure and balance to your designs. There now exists a range of easy to use tools that can be turned on and off at will to guide you in the process of designing with a grid.


The idea of using a grid based system has been around for some while now, Smashing Magazine did one of their usual mega-link articles over two years ago now. But there are still a good reasons to have another look at the grid based approach. If you are like me and you are more on the development side and most of your design ideas suck most of the time it is a process of continual improvement. We spend most of our time concentrating on how things work and not on how they should look. The problem is that design, clarity and presentation all matter to the user experience. So, you should care.

If you are like me and work for a small team, don't have the luxury of a design team or it's just not feasible to have a mock-up for each page you work on, you will be making design decisions and trade-offs all the time. The use of a grid is a simple tool that will improve your design work. Remember it's just a guide, so you can shuffle things around to your liking. But you will find that the use of a guide as a beginning tool-block to lay out your design is a clever and practical way to improve the end result.

There are tools out there available to make designing with a grid very easy. These are simple links that can be dragged on to your toolbar and will apply the grid over the top of your page. They allow you to customise the grid and tweak your designs as you work on them. Firebug + grid = good idea!

960.gs has a jQuery based grid system which sits on a tab at the side of your page and has many options for displaying vertical and horizontal bars. It is my preferred choice as it looks great and the option to hide it without closing is helpful. As well it contains most of the options you need without being too cluttered.



The next is Allan Jardine's Grid javascript bookmarklet. Grid is highly customisable and has a full feature set. It allows you to set alignment, gutters and margins.



The last one is the simple, easy to use grid960 grid overlay bookmarklet. This has a 12 and 16 column option and an option to set the opacity. This is a good starting point if you only want to use the grid as a rough guide or you want to do some quick tweaking and don't want to worry about setting too many options.



If you want to read up more on the topic and how you can use the grid system to improve your designs I suggest you check out the 960 grid system site. The site has a good deal of showcase sites and links to other quality tutorials and resources.

The grid overlay is an easy way to make big gains in your overall site design and using these unobtrusive tools makes it easier for you to apply the grid approach to your next design.

If you have a grid designed site that you would like to share or if you have something to share on the best way to use the grid based approach let us know in the comments section below.
more...

Building a Youtube playlist queue with php and jQuery

Sunday, 6 December 2009

View Comments

This post looks at how you can use php and jQuery to build a Youtube playlist queue, be the envy of your friends at your next party and allow your friends to search and drag items to a Youtube playlist.

As a Youtube playlist refreshes each time the page refreshes there is no need to call a page refresh each you add items, once the current video has finished playing the screen refreshes and updates the playlist.




In order to get a working version of my application you will need to do the following steps:
1. Download Zend Gdata package
2. Download my application code
3. Get a Google developer key
4. Extract the Zend Gdata package
5. Extract my application inside the root folder containing the Zend Gdata package, which should look like this:
/ZendGdata-1.9.6/jyt
6. Open /ZendGdata-1.9.6/jyt/operations.php and enter your developer key on line :56 where it says $_SESSION['developerKey'] = '-set your developer key here -';

To begin with this post should be looked at as an introduction to the world of possibilities available with Gdata and php. The demo application provided is very limited, but presents a glimpse at something that could be a great application given a months development work. It should also give you a taste for how easy it is to use Gdata to build applications based on Google authenticated users.

In order to build good quality applications with Google you really need to do a bit of reading, it's not something that you can understand in a day. Google's APIs are large and you will need to read them if you want to take things further.

My demo application uses AuthSub which is the basic method for giving an application permission for using your Google data. You can read more about AuthSub here.

But the main part of the application is ZendGdata. As Zend so gracefully put it: "These packages (ZendGdata) contain everything you need to access Google's Data APIs from your PHP 5 application.". When thinking about Zend and writing small applications you may be tempted to think why bother; it was something that held me back before from looking at integrating Google application data previously. Why would you want to use Zend framework when I just want to list my damn youtube videos? Well it turns out you don't need an entire framework, you just need the ZendGdata package that can be downloaded from here.

ZendGdata works simply like any other third party API or library. It's not too large or overbearing (the library folder currently comes in at around 2MB), so don't be scared of it. But it does contain a whole bunch of useful functions for authenticating and accessing Google data.

The package also contains the documentation and also some sample applications that you can begin playing with, how cool is that.

My application is based on the Youtube application provided with the package. To begin with it generates a link to ask the user to authenticate, if you are signed in to youtube this will ask you to 'allow' or 'deny' the application access to your data.

Once authentication has taken place the application will then go and retrieve and display your first playlist (it is possible for it to display any available playlist, I have just kept things simple). You are then displayed a search box to enter terms and submit.

Once you have searched and found a video you like, simply drag the video on to the target, it will be removed from the search list. Your playlist will then update and the added video will be at the bottom.

Why did I want to build this application? Many years ago I went to a party, it was at a time when Napster was just starting to become popular, I was amazed at the limitless possibilities of what was essentially an infinite jukebox. People could go over to the computer at the party, select the tunes they wanted and they would be queued and played. Allowing anyone to come and choose the tunes they wanted to hear. CD switching was a pain in those days as you had to wait for one song to finish and for the crowed around the stereo to disperse.

So there you have it. I hope this inspires you to Google application building greatness.

Enjoy!

more...

Display Google analytics with php, jQuery and flot

Friday, 4 December 2009

View Comments

This tutorial looks at how you can display your Google Analytics results using flot, the jQuery graphing library.

Flot will allow us to plot our results on a good looking graph without the need for flash; you can even enable and disable different sites if you are tracking multiple sites.


Unfortunately due to hosting restrictions I don't have a demo for this tutorial, but you can download the code from here



We will also be using the php analytics API class written by Chris Hope available from http://www.electrictoolbox.com. This class will allow us to easily retrieve our analytics data and will allow you to customise your results (including start date etc.)

We begin with a simple placeholder in our HTML, we then call our php script analytics.php using jQuery's getJSON method. The analytics.php script first checks to see if we have a cached version of the results (the retrieval from Google is considerably slow) and then serves the cached results. If there are no cached results it retrieves the data from Google's servers and then builds an array of data for each site. This array is then converted to JSON using php's json_encode and returned to our javascript file. Our javascript file builds an array suitable for Flot and then calls Flot's plot method.

Let's have a look at some of our code, firstly the HTML:

<h1>
My sites</h1>
<div id="placeholder" style="width:600px;height:300px;">
</div>
<p id="choices" style='display:none;'>
Show:</p>

This is simply our title and place holder for our graph and site toggler.

Our javascript file is made up of three functions:

$("document").ready(function() {
   var url = "analytics.php";
   
   $.getJSON(url, {id:  Math.random()}, function(datasets) {
      if (datasets) {
         // hard-code color indices to prevent them from shifting as
         // countries are turned on/off
         var i = 0;
         $.each(datasets, function(key, val) {
            val.color = i;
            ++i;
         });
         
         // insert checkboxes 
         var choiceContainer = $("#choices");
         $.each(datasets, function(key, val) {
            choiceContainer.append('
<input type="checkbox" name="' + key +
                              '" checked="checked" id="id' + key + '">' +
                              '<label for="id' + key + '">'
                              + val.label + '</label>');
         });
         choiceContainer.find("input").click(updateGraph);
         
         plotAccordingToChoices(datasets);
         
         $("#choices").show();
      }
      
   });
});

We begin with our document ready function. This starts by calling our analytics.php file using the getJSON function and retrieves our datasets. We loop over our datasets and assign them a colour. Next we create our checkboxes to turn sites on or off and assign the updateGraph click function to these checkboxes. Finally we call our plotAccordingToChoices function and show our choices checkboxes.

function plotAccordingToChoices(datasets) {
   var data = [];
   
   var choiceContainer = $("#choices");

   choiceContainer.find("input:checked").each(function () {
      var key = $(this).attr("name");
      if (key && datasets[key]) {
         data.push(datasets[key]);
      }
   });

   var options = {
            xaxis: {
                mode: "time"
            }
        };
   
   if (data.length > 0) {
      var plotarea = $("#placeholder");
      plotarea.css("height", "250px");
      plotarea.css("width", "500px");
      $.plot( plotarea , data, options );
   }
}

Our plotAccordingToChoices function takes in our datasets and then compares the data to the checked options to see if any are disabled otherwise they are added to the data array. Our data array is then simply passed through to Flot to plot.

function updateGraph() {
   var url = "analytics.php";

   $.getJSON(url, {id:  Math.random()}, function(datasets) {
      if (datasets) {
         var i = 0;
         $.each(datasets, function(key, val) {
            val.color = i;
            ++i;
         });      
      
         plotAccordingToChoices(datasets);
      }
   });
}

Our updateGraph function simply retrieves our data again and then calls plotAccordingToChoices. You could store this information somewhere in a global or in the DOM, if that's what you're in to.

Now let's look at the php side of things.

require_once('analytics_api.php');

$login = '-enter login here-';
$password = '-enter password here-';

$modified = @filemtime("cache.txt");

$modified = date("d-m-Y", $modified);
$current = date("d-m-Y");

if ($modified && ($current == $modified)) {
   $cache = @file_get_contents("cache.txt");
} else {
   $cache = null;
}

if (!$cache) {
   $api = new analytics_api();
   if($api->login($login, $password)) {
      $api->load_accounts();
      $accounts = $api->accounts;

      $return = array();
      
      foreach ($accounts as $accountname => $account) {
         $data = $api->data($account['tableId'], 'ga:week', 'ga:visits', 'ga:week', '2009-07-05', '', '52');
         $return[$accountname]['label'] = $accountname;
         
         foreach ($data as $week_number => $week) { 
            $return[$accountname]['data'][] = array( (strtotime("2009W".$week_number) * 1000) , $week['ga:visits'] + rand(0, 400) );
         }
      }
      
      $encoded = json_encode($return);
      
      echo $encoded;
      file_put_contents("cache.txt", $encoded);
   }
} else {
   echo $cache;
}

We begin by checking our cached file and then checking the date modified to see if the cache file is from today. If the cache file exists and it is from today we simply return the contents of that file.

Otherwise, we log in to our analytics account using the $api->login($login, $password) method. We loop over each of our accounts and retrieve the data from that account:

$data = $api->data($account['tableId'], 'ga:week', 'ga:visits', 'ga:week', '2009-07-05', '', '52');

You see here when we call the data method you can specify a whole bunch of different options, I will leave these to you to investigate. We are simply going to retrieve all weekly visit data starting from 2009-07-05 up to a maximum of 52 weeks if available.

We loop over this data and store it in the return array per account name. Then once all the data has been looped over we simply JSON encode and return.

Nice and easy.

Enjoy!
more...

jQuery UI sortable drag multiple to target

Thursday, 3 December 2009

View Comments

This tutorial looks at building a jQuery sortable UI widget that allows for sorting and for dragging multiple items on to a droppable target.


This is my first attempt (and possibly last) at building this so I haven't had a chance to check this off with all options available, I only built it for a single purpose.

The demo can be viewed here

And you can download the code from here

A brief rundown on how it works: control-click to select/deselect items. When the first item is dragged the other items are cloned and the original element hidden. If the main item being dragged hits the droppable target then the element and all its siblings are removed:

$("document").ready(function() {
  $("#sortable1").multisortable({});
  $("#sortable1").disableSelection();
  $("#target").droppable({
   accept: "#sortable1 li",
   drop: function(event, ui) { 
    var elements = $(ui.draggable).siblings(".ui-multisort-grouped").andSelf();
    
    $(elements).remove();
   }
  });
});

The element being dragged and its siblings are stored in the elements variable so you can essentially do what you like with them (read attributes etc.) at this point.

Hope this helps some people.

Enjoy!
more...

Using jQuery with forms - part 4 (Attributes)

Wednesday, 2 December 2009

View Comments

This is the fourth in a series of tutorials on using jQuery to manipulate forms. In this series I will be looking at parts of the jQuery API reference in detail. In this tutorial I will be looking at forms and jQuery Attributes.

Attr


attr(name)

Retrieves the value of an attribute


// Retrieve the location that the form is submitting to
$("#my_form").attr("action"); 

attr(key, value)

Sets the value of an attribute


// Set the location that the form is submitting to, this may be 
useful when you want to set the action according to some input
$("#my_form").attr("action", "processing.php"); 

removeAttr(name)

Removes an attribute from an element


// Remove all inline styling from fields with the password class
$(".password").removeAttr("style"); 


HTML


html() / html(val)

Retrieves / sets the innerHTML of the matched element


// Retrieve the html() contents of the fieldset with ID 
#fieldset_login and then set the html to the 
contents of updatedHTML
var updatedHTML = ... some markup ...
var login_html = $("#fieldset_login").html(updatedHTML);


Text


text() / text(val)

Retrieves / sets the text contents of the matched element


// Retrieve the contents of the first label
var label_text = $("label:first").text();


Getting and setting the values of different form elements



// Retrieve and set the contents of text input
$("#my_text_input").val();
$("#my_text_input").val(new_value);

// Retrieve and set the contents of label
$("#my_label").text();
$("#my_label").text(new_value);

// Retrieve and set the contents of textarea
$("#my_textarea").val();
$("#my_textarea").val(new_value);

// Retrieve and set the value of select
$("#my_select").val()
$("#my_select").val(2) // Set select according to value

// Retrieve and set the text of select
$("#my_select :selected").text() // Text value of selected option
// Changes the text of selected option
$("#my_select :selected").text("some text") 

// Retrieve and set the text label of a button
$("#my_button").text();
$("#my_button").text("some text");

// Retrieve the button type attribute
$("#my_button").attr("type"); 

// Retrieve the value of the checked radio element
$("#my_form [name='radio_group']:checked").val();

// Check if a particular checkbox has been checked
$("#my_form [name='checkbox_group[]']").eq(1).is(":checked")

// Retrieve all the checked checkboxes in a serialized string
$("#my_form [name='checkbox_group[]']:checked").serialize() 

// Retrieve and set the contents of password input
$("#my_text_input").val();
$("#my_text_input").val(new_value);


If you found this post useful, here are part 1, part 2, and part 3 of this series.
more...

5 sites and 5 jQuery plug-ins - tools for daily use

This post looks at 5 sites that I use daily and 5 jQuery plug-ins that I use regularly. The aim of this post is to provide you with some useful tools that you can keep in your toolbox and hopefully they will also be of regular use to you. Both the sites and the plug-ins are practical, reliable and most importantly they do what they are supposed to do.

The sites that I have chosen are sites that I personally use frequently. I think it's important to know a bunch of good sites, it saves trying to remember too much: memorise the basics and keep the rest within arms reach. I visit the php API and the jQuery API several times daily, I remember the basics, but I wouldn't want to try memorising the entire php API. I've tried to choose sites that are more on the practical side, these are more tool like and less reference like. I may only use them once or twice a day for a minute or two, but they are good at what they do.

The first site is ColorPicker. No need to install any software, no adds, no clutter, it is a simple color picker and it's handy.



The next site is a Lorem Ipsum generator. I'm surprised at how often I use this. The site is Lorem 2. Lorem 2 has Lorem Ipsum text in many different formats, short/long paragraphs and short/long list items.



I'm sure most of you know about Stack Overflow and w3schools. I use these two for different reasons; I use w3schools whenever I forget the basics, it's presentation is clean and I can reference what I need to know quick and easy, it's for those times when I forget something simple and stupid like how to name radio buttons. I use Stack Overflow when I assume there should exist a practical solution to something I haven't worked out yet. It's a good way to compare your solution to your peers and a good place to get advice and feedback.



The jivebay Handling Checkboxes, Radio Buttons and Select Options in jQuery post was the inspiration for my select element cheat sheet and I still find myself referencing this post every now and then. The questions and answers in the comments section are just as good as the post itself and the answers are well written.



The last site is the dummy data generator Generate Data. This site will generate large amounts of dummy data in different formats (HTML, Excel, XML, CSV, SQL) and has a large variety of data types. You can also specify the number of rows and row names.



The 5 plugins that I have chosen are also simple and practical. Simple in that they are east to use and do not try and overcomplicate.

The main site I work on is an internal CRM, so we have a lot of tabled information. The jQuery tablesorter plugin is awesome; it allows for custom parsing for sort order and with a bit of work it is very easy to have inline editing. You can also sort on multiple rows.



The jQuery cookies plugin works across all browsers and is so easy to set up. You can have a look at this post if you want to read over some of it's features rather than reading the code itself. It has very easy set, and get functions and is lightweight.



There are currently many jQuery autogrow plugins, but my favourite is this one. It is small enough that you could just cut and paste the function out and stick it in your own utility script if needed. It also works well across all browsers without hiccups.



The same could be said for watermark plugins, there are many out there, but the one that I like to use (which has been in beta since 2007) is this one by Josh Bush. It also has built in hideAll, showAll functions which are useful when pulling values for submission via ajax.



The last one and maybe the most useful is the jQuery form plugin. For any ajax heavy application with many forms this plugin has many useful methods for serializing, resetting and submitting forms. It even has a method for submitting files via AJAX.



It is always good to have many sites and tools that you can rely upon, once you find something good make sure to bookmark it for later use and then share it around. What are some of your favourite plug-ins that you use daily? What are some sites that you can't live without?
more...

Collection of December 2009 Wallpapers

Tuesday, 1 December 2009

View Comments

I've scoured the net and tried to find some of the best December 2009 wallpapers to kick of the festive Season. I was surprised that there were so few, being Christmas and all. Here is what I came up with.

Click on any of the images below to go to the artists page and download the full sized image.
















more...

jQuery php voting widget

This tutorial looks at how to build a jQuery UI themeable voting widget using a jQuery sortable and a bit of php to store the current number of votes. The actual widget itself is quite light-weight and the only markup we need is a single unordered list. The jQuery is also minimal and most of the work is done in php to work out the what the current tally is and to store this information.



You can view the working demo this tutorial here.

You can download the code for this tutorial here.

In my implementation I have chosen to store the current number of votes as a single serialized string in a flate file, but this could easily be done in a database.

To begin with I will show you the unordered list, my list is going to contain Charlton Heston movies:
<li class="non-sortable" style="height:2.2em;">Rank your favourite Charlton Heston movies by dragging options</li>
<li class="ui-state-default movie-rank" id="movie-1"><span class='counter'>#1</span>The Ten Commandments</li>
<li class="ui-state-default movie-rank" id="movie-2"><span class='counter'>#2</span>Ben-Hur</li>
<li class="ui-state-default movie-rank" id="movie-3"><span class='counter'>#3</span>Planet of the Apes</li>
<li class="ui-state-default movie-rank" id="movie-4"><span class='counter'>#4</span>The Omega Man</li>
<li class="ui-state-default movie-rank" id="movie-5"><span class='counter'>#5</span>Soylent Green</li>
<li class="ui-state-default movie-rank" id="movie-6"><span class='counter'>#6</span>The Three Musketeers</li>
<li class="ui-state-default movie-rank" id="movie-7"><span class='counter'>#7</span>Antony and Cleopatra</li>
<li class="ui-state-default movie-rank" id="movie-8"><span class='counter'>#8</span>Beneath the Planet of the Apes </li>
<li class="ui-state-default movie-rank" id="movie-9"><span class='counter'>#9</span>El Cid</li>
<li class="ui-state-default movie-rank" id="movie-10"><span class='counter'>#10</span>Julius Caeser</li>
<li class="non-sortable"><button class="ui-button ui-state-default ui-corner-all" type="button" name="submit" style="float:right;">Submit</button></li>

If you look at the li classes above you will see there are two main types, the non-sortable and movie-rank. The jQuery sortable plugin allows us to specify which items should be sortable using the 'items' option and which items will not be part of the sorting process (that is, they stay put). We want our widget title and the submit button to stay put so lets look at the jQuery initialisation:
$("document").ready(function() {
 $("#sortable").sortable({
  placeholder: 'ui-state-highlight',
  items: '.movie-rank',
  cancel: '.non-sortable'
 });
 
 $("#sortable").disableSelection();

The three options from our sortable initialisation are placeholder, items and cancel. Place holder simply provides an indicator for where the item will be dropped, in my example this is the blue bar that appears as the item being dragged hovers over each list item. The items and cancel work as previously mentioned, basically 'items' are sortable and 'cancel' stays put. The final call to disableSelection is an undocumented jQuery UI method that prevents text selection happening on a list element so that grabbing an item to be dragged is easier and the text selection doesn't get the focus first.

Next I decided to add an update function whenever the sort order is changed. This updates the ranking of each item, so if you move #3 to the #7 position all of the numbers update to show your preferred voting order. Let's look at the code:
$('#sortable').bind('sortupdate', function(event, ui) {
 $(".counter").each(function() {
  $(this).empty();
  var index = $(".counter").index(this) + 1;
  $(this).text("#" + index);
 });
});

The sortupdate function is a special function specific to the jQuery UI sortable plugin. You can see all of the options and functions here. This is called when the sort order is updated. I simply remove all of the rankings and then update each of the elements according to their actual position amongst thier peers. This is done using the jQuery index function, which takes in a group of elements and finds the index of the element amongst that group (0 based).

The last piece of jQuery code is our submit function:
$("#sortable [name='submit']").click(function() {
 var rankings = $('#sortable').sortable('serialize');
 
 $.get("vote.php?" + rankings, {}, function(data) {
  $("#sortable").empty().html(data);
 });
});

Our sortable has another great funcion, serialize which looks at the IDs of our li elements and passes them in order as follows: arrayname-id. So I have mine set up as movie-1, movie-2 etc. so these will be returned as movie[]=1,movie[]=4,movie=[]=7... according to how we have sorted them. When this gets rebuilt in php we will have an array that is ordered in the same way as our sorted list with a reference to the index of our movie.

We then make an AJAX call using jQuery's $.get function which sends in our voting submission and waits to get the results back from our php script. Once the results are returned we simply clear out our sortable and insert the results returned from the script.

We start off our php script vote.php with retrieving the values passed in and setting up an array that has a key corresponding to the movie and the voting points allocated to that movie:
$movie_rankings = $_GET['movie'];

if ($movie_rankings && is_array($movie_rankings) && (sizeof($movie_rankings) == 10)) {
 $movie_points = array();
 
 foreach ($movie_rankings as $rank => $index) {
  if (!is_numeric($rank) || !is_numeric($index) || ($rank > 9) || ($index > 10)) exit; // Prevent hacking
  $movie_points[(int)$index] = (10 - (int)$rank);
 } 

You will see I have added a few small security checks in there to avoid someone from screwing this up completely. We begin with getting the value of movie from our $_GET variable. We then check that this wasn't empty, that it is an array and that it has exactly the right number of elements, in our case 10.

Next we create the $movie_points array to hold our votes for each movie. We loop over the rankings passed in and while we are doing this we need to check that someone hasn't just passed in garbage. We check that the $rank and $index are both numbers and that they are both less than 10, another security check. We then set the points for each movie index inside the $movie_points array, casting each value to int in case some tricky person decided to use float values.
$current_rankings = @file_get_contents("rankings.txt");

if ($current_rankings) {
 $current_rankings = unserialize($current_rankings);
 
 foreach ($current_rankings as $index => $score) {
  $movie_points[$index] += $score; 
 }
}

$ser_points = serialize($movie_points);
file_put_contents("rankings.txt", $ser_points); 

Following from that we retrieve the current rankings form our rankings.txt flat file. If the file existed we unserialize those values and loop over each value and add it to the point values just pased in by updating the $movie_points array. We then serialize the $movie_points array and store it in our flat file for later reference.

Now that we have our current standings and all our points tallied we want to build our output. Our output will contain a colourful graphical representation in the form of a bar chart, which will contain the percentages and the names of each of the movies:
arsort($movie_points);
  
$movies = array();
$movies[1] = "The Ten Commandments";
$movies[2] = "Ben-Hur";
$movies[3] = "Planet of the Apes";
$movies[4] = "The Omega Man";
$movies[5] = "Soylent Green";
$movies[6] = "The Three Musketeers";
$movies[7] = "Antony and Cleopatra";
$movies[8] = "Beneath the Planet of the Apes";
$movies[9] = "El Cid";
$movies[10] = "Julius Caeser";

$colours = array();
$colours[1] = "#E52E2E";
$colours[2] = "#E58F2E";
$colours[3] = "#E5DF2E";
$colours[4] = "#8FE52E";
$colours[5] = "#2EE56C";
$colours[6] = "#2EE5D2";
$colours[7] = "#2E49E5";
$colours[8] = "#942EE5";
$colours[9] = "#C02EE5";
$colours[10] = "#DE2EE5";

$total_points = array_sum($movie_points);

$html = '';

$counter = 1;
foreach ($movie_points as $key => $points) {
 $percent = round(($points / $total_points * 100), 0);
 $html .= "<li class='ui-state-default movie-rank non-sortable' id='movie-{$key}'><div style='background:{$colours[$counter]};height:25px;width:{$percent}%;padding:5px;margin-top:-6px;margin-left:-6px;'></div><div style='position:absolute;left:0px;top:0px;'><span class='counter'>{$percent}%</span>{$movies[$key]}</li></div>";
 $counter ++;
}

echo $html;

We begin by sorting our $movie_points from highest to lowest. Then we set up two arrays, one with the index to name mapping of our movies and the next with the colour level for our bar chart. We us php's built in array_sum to count up the total number of points already awarded, this will be used to work out percentages.

Next we loop over (from highest to lowest) each of our movies; we calculate the percentage points and then build the list item displaying our movie name, points and the coloured bar.

This is then echod out and returned to the jQuery scipt which will clear out our voting system and display the colourful results.

That's the lot.

Enjoy!
more...