Free large icon sets for commercial and personal use

Wednesday, 28 October 2009

View Comments

Thank God for the open source community and those people who are willing to give up their time to produce top quality goods for us all to share. In this post I have a whole bunch of top quality free (as in read the license before you use them) icon sets for your personal and commercial sites.

Why is important to have a post that provides icons for commercial use? Besides being handy to have your own pool of quality icons that you can use on any site, many developers start out working on small commercial projects and it's hard to come across a range of good quality icons. Sets such as FAMFAMFAM pop up all over the web and it was the first free icon set I ever worked with and it's still used in many projects today.


I don't want to provide you with links to sites with hundreds of sets where you have to wade through to find anything decent and I don't want to provide you with "80 free icon sets for commercial and personal use" where most of the sets only have 5 icons or only two out of eighty sets can be used in commrecial projects. Folks, this is the good stuff; five sets of icons with no less than 100 icons in each.

In order to share the love, I have provided a link to the actual site where the icons reside not just a direct download link. These people have taken there time to design some top quality icons for us all to use so take the time to have a look around while you are there.

Note: licenses change, please read (and obey) the license of each set at the time of download

FAMFAMFAM Silk Icons 700+ icons




A collection of over 700 16x16 icons in .png format.
This collection is great for CMS and dashboard sites or anywhere requiring several smaller sized controls.

Download and license information here

License: Creative Commons Attribution

Min Tran's Bright! iconset 148 icons




Bright has a various assortment of large icons that are useful for any web site.
Contains a number of music related and control icons.

Download and license information here

License: Custom - permits personal and commercial

wefunction.com Function Icon Set 128 icons




The Function icon set is set of glossy icons that features bright colours and high detail.
Included in the set are a large number of social networking icons including twitter, RSS and digg.
Also noteworthy is the inclusion of credit card and paypal icons.

Download and license information here

License: From the author: "basically my licence is 'do what you want with em' as long as you don’t re-distribute them without linking to this page"

WooFunction Icon Set 178 icons




The WooFunction Icon Set includes 178 amazing web-related icons in a sophisticated and glossy design style. All 178 icons are available as 32×32 pixel PNG files.
These icons are quite useful if you are wanting to design an e-commerce site or any site that has a lot of add-remove-update functionality.

Download and license information here

License: GNU GPL (doesn't mention which version)

Everaldo.com Crystal Project 1300 icons in different sizes




This is one of my favourite icon sets. The quality is awesome.
Considering the large number of icons here, there are a million uses.

Download and license information here

License: GNU LGPL

more...

Using jQuery with forms - part 1

Tuesday, 27 October 2009

View Comments

Every day when writing code I come across a form of some type. Forms are the main way we capture user data outside of page/click tracking. How forms are displayed and handled are vital to the quality of information you receive from the user and also the overall usability of a site.

jQuery has a wealth of plug-ins that can help us deal with some of the major obstacles when handling forms; submit via Ajax, clearing/resetting a form, validation etc. jQuery can also help us to access and manipulate form elements with ease to provide a greater level of usability and improve interaction across a site. In this tutorial I will go over some of the basics of using jQuery with form elements.


To begin with I always like to add an ID to the form element itself. You can access a form using its name or some other selector but for readability I prefer to use an ID and use attribute selectors for other parts of the form e.g.

<form id="example_form" name="example_form">
</form>

You could access this form either via its ID or via its name e.g.

$("#example_form")

or

$("[name='example_form']")


Once you add on another field with an attribute it becomes obvious why using the ID selector is more readable:

$("#example_form [name='address']")

or

$("[name='example_form'] [name='address']")


Then we know that anything that comes below our id selector is a child of form element. And we can even retrieve all of those elements using the children() function as follows:

$("#example_form").children();

You can also retrieve any of the forms attributes name, ID, method etc. using the attribute function attr():

$("#example_form").attr("name");
$("#example_form").attr("ID");
$("#example_form").attr("method");

You can set/change these values using the same function by passing in a value as a second argument:

$("#example_form").attr("name", "form_new_name");
$("#example_form").attr("ID", "form_new_ID");
$("#example_form").attr("method", "post");

Or remove an attribute altogether:

$("#example_form").removeAttr("name");

To access any of our child elements we simply specify our forms ID selector, followed by a space and then the child selector:

$("#example_form select") // Retrieve all the select child elements

$("#example_form .label") // Retrieve all the child elements with the class label

$("#example_form :input") // Retrieve all the child elements that are inputs (input, textarea, select and button elements)

To perform an action on an element(s) we simply specify the selector as above and then the function:

$("#example_form select").remove() // Remove all the select elements from our form

$("#example_form select").hide() // Hide all the select elements on our form

$("#example_form select").show() // Show all the select elements on our form

To set or retrieve a value will vary on the type of element i.e. radio, select, text input

$("#example_form [name='text_input']").val() // Gets the value of a text input
$("#example_form [name='text_input']").val('new value') // Sets the value of a text input
$("#example_form [name='text_input']").val('')// Clears the value of a text input

$("#example_form [name='select_input']").val() // Get the option value of the selected element
$("#example_form [name='select_input']").val("1") // Sets the value of the select according to the option value
$("#example_form [name='select_input'] :selected").text() // Get the text of the selected element

$("#example_form [name='radio_input']").val() // Get the text of the checked radio
$("#example_form [name='radio_input'][value='some_value']").attr("checked", "checked") // Set a radio button to checked according to its value attribute

I will be releasing a series of tutorials over the coming days (weeks?) that will cover in detail form manipulation. In the mean time check out the jQuery API for further functionality.


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

Preview of what's new in jQuery 1.4

Wednesday, 21 October 2009

View Comments

Update!

This post was written before jQuery 1.4 was released and is now out of date. If you would like to see a run down of what is in the jQuery 1.4 release, look at my latest post here
Thanks,
Tim.

jQuery and other javascript libraries have significantly changed the way that sites are written. In particular, with visual elements and selectors it has opened up a whole new world of speed and accessabilty for developers. With an easy to use API, long gone are the days of writing lengthy javascript code; we can now build fast, attractive and responsive elements with a few lines of code. With all of this it is with great excitement that we look forward to the next major release of jQuery, jQuery 1.4. And why wouldn't you be? The team behind jQuery guarantees that this next release will be better, faster and contain even more useful functionality.


It is awesome to think that as jQuery pushes the boundaries that they uncover the need for newer functionality. So as jQuery grows we discover even more ways to improve the way we code and approach site design.

So when can we expect the jQuery 1.4 release to arrive? John recently mentioned on the jQuery blog that we could be seeing 1.4 arrive as soon as January 2010. In his own words: "we'll probably release 1.4 on jQuery’s 4th birthday in January."

In this post I am going to provide a sneak peak of some of the features listed on the jQuery 1.4 Roadmap. These are the features that may make it in to the 1.4 release of jQuery. As you can see, some of these have been knocked off in earlier releases so this is a give or take list, but will give us a good idea on what the jQuery team are looking to deliver.

As the 1.4 roadmap is not a detailed document I will do my best to spell out what these features are likely to include. As the roadmap is not a definitive document this is speculative, but gives a good insight into what we might see in a few months time.

Lazy loader / require

The example given at the beginning of the roadmap indicates the possiblity to require certain js/css files to load before the document ready function with the use of a function call similar to jQuery.require("foo.js");. It is currently possible to load CSS and javascript files on-the-fly easily using something like firebug and also destroy css files. I suspect this feature will include both options; being able to have certain .js and .css files completed loading before the $("document").ready function is called and also the ability to include .js and .css files on-the-fly with an easy to use API. Also have a look at this link for similar existing functionality.

contains

$.contains which may end up being $.has is used to determine if an element is inside another one e.g. jQuery("div").contains(DOMElement). This functionality already exists in this form $(".container").contains(event.target) would return the same elements as $(".container:has(" + event.target + ")").

radio class

The idea is that radioClass method (inspired by Ext Core) adds a class to one element and removes it from its siblings. The idea would be something similar to this $(foo).radioClass('on'); would be equivelant of $(foo).addClass('on').siblings().removeClass('on');

copy entire object

Would provide a method to clone an element as well as the associatied data objects (see bug filed here. Currently the clone method allows you to clone the element as well as its event handlers, but not the associated data objects. We may end up seeing a single method to deep copy and element including all events, data etc.

set offset

Code sample already provided so we can see what is likely to be included. A method to set or get the specific left and top position of the matched elements, relative the the browser window by calling setXY

mouse wheel

I have come across many places asking why this hasn't been included in jQuery yet. This an event listener for the mouse wheel and would trigger an event when the mouse wheel is rolled. Don't expect anything magic out of this like tracking velocity as this is usually just a 1 or a 0 in most browsers. Here is a good rundown

new live events

1.4 should see four new $.live event handlers with the implementation of .live("change"), .live("submit"), .live("blur") and .live("focus") added to the existing events already available.

improved param serialization

Ability to serialize paramaters within an object. You begin with something like this $.param({page: {name: 'Foo', author: 'Bar'}) and end up with something like page[name]=Foo&page[author]=Bar. Have a look at this request for more detail.

Synchronized animations

The demonstration here speaks for itself. A way to have animations happening synchronously. Good idea to view source on that page a have a look through the code. John has definitely been working hard with animations and javascript, have a look at his processing.js project if you would like a good idea of what's possible.
more...

Good practice Branching and Tagging with version control

Tuesday, 20 October 2009

View Comments

In this tutorial I will go over my preferred method for branching, tagging and comitting. I will steer away from calling this best practice as there are other ways to do this, but I will go so far as to say this is a clean method that works and ensures you can easily keep control of your different working versions, easily reintegrate changes from different paths and restore previous versions for testing / fixing. Which should be your aim for tagging and branching.


If you like to discuss, there are several reasonable discussion going on at Stack Overflow. If you are interested here, here and here.

If you are using subversion to manage your version control and you haven't done so yet, take the time to read the book.

Let's start by going over some common definitions that I'll be using throught the tutorial:

Trunk - this is where your main version of your application will be held; any maintstream development will take place on the trunk version of your application

Branch - a branch is a work-in-progress version of your application and will be for fixing a particular release or for developing new features which may or may not be reintegrated into the trunk at a later stage

Tag - start by thinking that a tag is a version that will never be altered again; it is like a piece of boxed software that has already hit the shelves, if you want to make changes, you will need to call it something else, if it was 7.0.1 you will might call the work in progress the 7.0.2 version

Commit - saving a version of your changes to the repository

Merge / merging - taking the changes from one version of your application and moving it to another version


I will begin with our trunk. If you have been using a version control system, but haven't been branching or tagging you will have a good idea of how the trunk works. For any simple system the whole repository is used as the trunk and will look like this:

* Repository is created.
* Files are committed in and out of repository by individuals and are worked on
* Changes are then committed back to the repository
* Any new development that may cause issues is not committed until it has been tested then it is committed to the repository
* A release is made simply by checking out a version of the repository at a point in time when the team is happy that it is stable
* Any further tweeks made before a full release are made to the repository and the version for release is just updated

This is a pretty standard workflow for many smaller teams and will give you a good idea of what our trunk will look like. As development goes along our trunk continues to grow in a straight line; the repository is rarely reverted and past changes are not reflected on, just modified. The trunk contains all of our changes and just keeps going up and up.



This is a perfectly fine way to operate, but let's go over some of the benefits of being able to tag and branch:
* By branching we can multiple versions of the system being worked on that can either be abandoned or reintegrated at any point. The beauty of this is that any changes made don't need to be held back from being committed and won't infect the trunk with untested / unstable code. Think of smaller part of your team having to work on a new feature that will take over 3 months; having them not commit for that time will mean they will need to work outside of the repository and will be difficult to integrate changes.
* By branching we can easily reintegrate individual commits to the branch back in to the trunk as they are tested
* By tagging we know exactly what is in a release that has been passed on to a customer or is on your production server currently. No more guessing as to which commits went in to production last month.
* By tagging we can easily retrieve a tagged version from the repository for testing purposes
* By tagging you can retrieve the tagged version, make changes just to that tag and then create a new tag. Think of this, your production 7.5.1 version has an issue that you only just found and your team has already made 100+ commits to the trunk in that time. Rather than making the changes on the live version, you just grab the 7.5.1 tagged version, make your changes to it, create a 7.5.1.1 tagged version and move the new version to production. There will no longer be any chance of new changes being moved to production without testing.

Be aware that by using branching and tagging, each branch or tag is like a mini-repository, you can check-out and commit to you branches and tags as well as your trunk.

We'll now look at branching. Branches are work-in-progess versions of your application. There are a few different reasons that you may want to branch;
1. You want to start developing some new functionality that may or may not be integrated into the trunk at a later stage.
2. You are getting ready for a release, but you may still have some final non-major changes to be made.
3. You want to start working on a version based on a previous tag because you have discovered an issue with that tag, but the trunk has already progressed past that tag.



With each of the scenarios above there is a particular workflow. The generic workflow is as follows:
* Create a branch by copying a particular revision of your application; either by copying a tagged version or by taking the latest version of your repository.
* Make changes to your branch and commit until you are finished.
* Tag your branch for any future operations and then remove your branch so that nobody else continues to perform work on it
* Reintegrate the changes to your branch back in to your trunk if necessary

Now let's have a look at home we can apply our workflow to each of our branching scenarios above:
1.
* Create a branch by copying the trunk
* Develop the new functionality
* Tag the version with new functionality
* Add the new functionality to the trunk if necessary by merging changes from the tagged version to the trunk
2.
* Create a branch by copying the trunk
* Test the branch as though it were the release version
* If there are any changes make these to the branch and merge back to the trunk as necessary
* When there are no further changes to be made create a tagged version and then remove the branch
* Move the tagged version to production server
3.
* Create a branch based upon the tag with a bug in it
* Make the fix on the branch and merge the change into the trunk if necessary
* Create a tagged version of the branch and remove the branch
* Move the tagged version in to production (if necessary)

You should now be able to see the benefit of branching and tagging. Your production version is protected from accidental changes and your working trunk version is developed independantly and alongside any major changes.

Your version control software should have features to allow for branching and tagging and to easily merge changes. I prefer to use subversion with TortoiseSVN client as the above operations are done with a few clicks.

The best way to structure your folders for branching and tagging should be similar to the follow to alow you to easily view your versions:


/branches
/4.1.7
/4.2.1.1
/tags
/4.1.6
/4.2.1
/4.2.2
/trunk
..trunk files



I also recommend you use a visual repository browser so that you can easily view changes and commit mesasges to each of your versions. We are using websvn
more...

How and why not to remove dotted links form Firefox

Thursday, 15 October 2009

View Comments

This tutorial looks at fixing the issue with the dotted area around links in Firefox.


If you do a search on google for 'dotted links firefox', almost all of the pages will have a title such as 'Remove dotted links from Firefox', 'Destroy annoying dotted links on Firefox' or 'How the hell do I get rid of dotted border around links in Firefox!!!'.





The sad thing is that these dotted links, although giving some designers a headache are actually there for a good reason and... shouldn't be removed!


The good reason for having these dots here is so that others who have issues with mobility e.g. they can't use a mouse, need to be able to see which element on a page has focus so that they can press their enter button at the appropriate time.


Like everything else in the world, the internet should be for everyone to share, so we should be doing our best as developer designer to ensure that our websites are accessible. (More visitors the better right?)


After this tutorial I will be placing a couple of links about acessibility that will hopefully give you some further background into accessability issues and the internet.


Before I go in to the issue, just some background. Many people run in to this problem when trying to use the combination of the text-indent css rule along with a background image, popularised by Mike Rundle in this post. Which in itself is a good practice, it is helpful for screen readers (read the post for more info).


Ok, on to the problem. Have a look at the code below and you will see an <a> tag that with a link inside that has the text indented so it no longer appears on the screen.



<div style='float:right;'>
<a href='#' style='text-indent:-10000px;display:block;width:40px;height:40px;background:red;'>
Hello
</a>
</div>

Here it is below. If you are using Firefox and you click on the red box you will notice the dotted line stretches accross the page.




Now look at the example below and notice how the dotted line raps nicely around the red box.




This is fixed simply by using the css rule overflow:hidden. Once this simple rule is in place the dotted indicator wraps nicely around the <a> tag. Considering coders much better than ourselves spend their time build browsers like Firefox with the best intentions in mind (that include industry best standards and practices); take time to consider why things may not appear correctly in your browser before wanting to chop them out.



<div style='float:right;'>
<a href='#' style='text-indent:-10000px;display:block;width:40px;height:40px;background:red;overflow:hidden;'>
Hello
</a>
</div>

Here are some links that you may find helpful.

more...

Easy pagination with jQuery and Ajax

In this tutorial I would like to go over an easy way to display your database data with jQuery using Ajax and pagination.

If you would like a brief introduction to using Ajax with jQuery you can have a look at this tutorial. jQuery makes it very easy to send Ajax requests.

You can view the demo of this tutorial here

You can download the files for this tutorial here

Pagination is the process of chunking up your data into fixed sizes so that you only view one fixed size chunk at a time and can navigate easily backwards and forwards through other chunks. You can see this process on sites like digg and ebay. Usually the navigation links show the first page, the last page, a next and previous link and a small range of page numbers. The pagination links in this tutorial will look something like this:


Pagination allows your users to digest information in small, easily digestible pieces and with a familiar interface for navigating backwards and forwards through that information.

Using Ajax we can provide a way to navigate through larger amounts of information loading one page at a time. This should reduce the load on the server and minimise page reloading times. The use of Ajax should be weighed up as it is not appropriate for all sites.

Lets start by thinking what our page will look like. We will have our information (displayed one page at a time) and another section to display which page we are currently on and navigation to other pages. I will name the two secions #content and #paginator. The main aim is to update the #content information each time someone clicks on a #paginator page link. So we start with three main functions:


function initialize() {
// Display first page

// Display initial status of page links with the first page selected

}

function displayPage(current_page) {
// Retrieve data from table equivelant to page size (for this example 10 rows) based on which page we are currently on (current_page) and return formatted rows
}

function displayLinks(current_page) {
// Create page links with first and last links based upon which page we are currently on (current_page)

// Attach event listeners to our page links
}


Now lets think about where each of these functions should reside; Since we want our program to retrieve the data on the fly and we are going to use Ajax we will have our displayPage functionality sitting in the backend (whatever your preffered language, I will be using php). We will place our initialize function in javascript so that it can load the pages and I have decided since the page links are essentially the same element and require little processing I will have javascript render the page links also. We will still need to have another function in the javascript to make the Ajax request to the php file whenever a page link is clicked. So lets have another look at our functions.


/*** Javascript - page.js ***/

function initialize() {
// Load first page into #content

// Call displayLinks(1)
}

function displayLinks(current_page) {
// Create / refresh page links with first and last links based upon which page we are currently on (current_page)

// Attach event listeners to our page links which will call updatePage function when clicked
}

function updatePage(clicked_element) {
// Get the current_page based upon the text of the selected element

// Call php displayPage(current_page) function via Ajax to get data and load this into #content section

// Update links on the page by calling displayLinks(current_page)
}


/*** php - loaddata.php***/

function displayPage(current_page) {
// Get the names from the database by calling $data = getNames(current_page)

// Format raw data by calling $formatted_data = formatData($data)

// Return $formatted_data
}

function getNames(current_page) {
// Retrieve data from table equivelant to page size (for this example 10 rows) based on which page we are currently on using SQL

// Return rows
}

function formatData(data) {
// We are simply going to attach <p> tags to the columns 'firstname lastname' for each row then return this as a single string
}


We now have most of our pseudocode written out and we should be able to start coding from here. With a little bit of css the finished product will be a simple, good looking and easy to use Ajax program that will show us pages of names, 10 at a time.

The glue that is going to hold our application together is jQuery. If you are unfamiliar with jQuery I suggest you begin by having a look at this tutorial Getting started with jQuery. jQuery will supply many of the methods we need for getting the joby done in an easy straight forward way.

There is on last function we are missing. In order to display a link to the last page we will need to retrieve the page count from the database. As this needs to be used each time displayLinks is called we will retrieve this from the database once and store it in a hidden input element on the page.

It's probably best if we start with php file so that you can know what we the data will look like when it is retrieved by our Ajax calls.


/*** php - loaddata.php***/

<?php
if (isset($_REQUEST['action'])) {
$action = $_REQUEST['action'];

switch ($action) { // We will determine which function to call based on an action paramater passed in through the url
case 'get_rows':
displayPage();
break;
case 'row_count':
getRowCount(); // Return the number of rows in the database
break;
default;
break;
}

exit;
} else {
return false;
}

// Returns the number of rows from the table we are querying
function getRowCount() {
$db = array(
// Database connection details
);

$link = mysql_connect($db['host'], $db['login'], $db['password']);

mysql_select_db($db['database']);

$strSQL = "SELECT COUNT(*) FROM names";
$result = mysql_query($strSQL);
$count = mysql_fetch_row($result);

echo $count[0];
}


// Retrieves raw data from the database then formats it and then returns the formatted rows as a string
function displayPage() {
$start_row = isset($_REQUEST['start'])?$_REQUEST['start']:0;
$start_row = 10 * (int)$start_row;

$employees = getNames($start_row);

$formatted_names = "<div id='formatted_eployees'>" . formatData($employees) . "</div>";

echo $formatted_names;
}

// Retrieves rows from the names table
function getNames($start_row = 0) {
$db = array(
// Database connection details
);

$link = mysql_connect($db['host'], $db['login'], $db['password']);

mysql_select_db($db['database']);

$strSQL = "SELECT * FROM names ORDER BY id ASC LIMIT {$start_row}, 10"; // Returns 10 rows based on the current row

$result = mysql_query($strSQL);

$employees = array();

while ($row = mysql_fetch_assoc($result)) {
$employees[] = $row;
}

return $employees;
}

// Returns the rows as a formatted string
function formatData($data) {
$formatted = '';
foreach ($data as $dat) {
$formatted .= '<p>' . $dat['firstname'] . ' ' . $dat['lastname'] . '</p>';
}
return $formatted;
}

?>


It should be clear now what our backend script is doing. It has two main functions which will be called depending on the action variable passed in through the URL. Either returning the number of rows in the table or returning our 10 rows of formatted data as a string based upon which is our current row. If you would like to be able to call the pagintation SQL string using MSSQL here is the code:


$strSQL = "
SELECT TOP 10 * FROM (
SELECT *, ROW_NUMBER() OVER (ORDER BY ID) AS RowNumber FROM names
) AS results
WHERE RowNumber > {$start_row}";


Now lets have a look at the javascript file:


/*** Javascript - page.js ***/

$("document").ready(function() {
// Load first page into #content
$("#content").load("loaddata.php?action=get_rows");

// Call displayLinks(1)
$.get("loaddata.php?action=row_count", function(data) {
$("#page_count").val(Math.ceil(data / 10)); // Store the number of pages in the hidden input #page_count
displayLinks(1);
});
}

// Create / refresh page links with first and last links based upon which page we are currently on (current_page)
function displayLinks(current_page) {
var pages = $("#page_count").val();

if (pages <= 5) {
$("#content").after("<div id='paginator'><a href='#' class='pagor selected'>1</a><a href='#' class='pagor'>2</a><a href='#' class='pagor'>3</a><a href='#' class='pagor'>4</a><a href='#' class='pagor'>5</a><div style='clear:both;'></div></div>");
$(".pagor").click(function() {
var index = $(".pagor").index(this);
$("#content").load("loaddata.php?action=get_rows&start=" + index);
$(".pagor").removeClass("selected");
$(this).addClass("selected");
});
} else {
if (current_page < 5) {
// Draw the first 5 then have ... link to last
var pagers = "<div id='paginator'>";
for (i = 1; i <= 5; i++) {
if (i == current_page) {
pagers += "<a href='#' class='pagor selected'>" + i + "</a>";
} else {
pagers += "<a href='#' class='pagor'>" + i + "</a>";
}
}
pagers += "<div style='float:left;padding-left:6px;padding-right:6px;'>...</div><a href='#' class='pagor'>" + Number(pages) + "</a><div style='clear:both;'></div></div>";

$("#paginator").remove();
$("#content").after(pagers);

// Attach event listeners to our page links which will call updatePage function when clicked
$(".pagor").click(function() {
updatePage(this);
});
} else if (current_page > (Number(pages) - 4)) {
// Draw ... link to first then have the last 5
var pagers = "<div id='paginator'><a href='#' class='pagor'>1</a><div style='float:left;padding-left:6px;padding-right:6px;'>...</div>";
for (i = (Number(pages) - 4); i <= Number(pages); i++) {
if (i == current_page) {
pagers += "<a href='#' class='pagor selected'>" + i + "</a>";
} else {
pagers += "<a href='#' class='pagor'>" + i + "</a>";
}
}
pagers += "<div style='clear:both;'></div></div>";

$("#paginator").remove();
$("#content").after(pagers);

// Attach event listeners to our page links which will call updatePage function when clicked
$(".pagor").click(function() {
updatePage(this);
});
} else {
// Draw the number 1 element, then draw ... 2 before and two after and ... link to last
var pagers = "<div id='paginator'><a href='#' class='pagor'>1</a><div style='float:left;padding-left:6px;padding-right:6px;'>...</div>";
for (i = (Number(current_page) - 2); i <= (Number(current_page) + 2); i++) {
if (i == current_page) {
pagers += "<a href='#' class='pagor selected'>" + i + "</a>";
} else {
pagers += "<a href='#' class='pagor'>" + i + "</a>";
}
}
pagers += "<div style='float:left;padding-left:6px;padding-right:6px;'>...</div><a href='#' class='pagor'>" + pages + "</a><div style='clear:both;'></div></div>";

$("#paginator").remove();
$("#content").after(pagers);

// Attach event listeners to our page links which will call updatePage function when clicked
$(".pagor").click(function() {
updatePage(this);
});
}
}
}

function updatePage(clicked_element) {
// Get the current_page based upon the text of the selected element
var selected = $(clicked_element).text();

// First update content
$("#content").load("loaddata.php?action=get_rows&start=" + (selected - 1));

// Then update links
displayLinks(selected);
}



Ok, that looks like a lot to look at, but I'll break it down into smaller chunks.

The intialize function is now $("document").ready according to jQuery. This function is almost identical to our pseudocode so I don't think I need to go over it in detail. It retrieves and then stores the number of pages. It then loads the first pages content and lastly it loads in the page links section.

Our big one is the display links function and I think I should write this out into pseudocode so that we can understand it a bit better:


function displayLinks(current_page) {
// Retrieve the maximum page from the hidden element and store it in var pages
var pages = $("#page_count").val();

// If the number of pages is less than five:
// Always display links 1 2 3 4 5
// When someone clicks on 1 2 3 4 5 {
// Get the index of the clicked on element
// Switch the selected class to the clicked on element
// Load page data according to the index of the clicked on element
}

// If the number of pages is more than five:
// We are going to have three different cases:
// 1. If we are on the first five links display like this 1 2 3 4 5 ... (last_element)
// 2. If we are on the last five links display like this 1 ... (last - 4) (last - 3) (last - 2) (last - 1) (last_element)
// 3. Otherwise display like this 1 ... 17 18 [19] 20 21 ... (last_element)


// Each of our three steps above does the following:

// Store our links in the var pagers

// Remove paginator from the screen
$("#paginator").remove();

// Attach pagers after the #content section
$("#content").after(pagers);

// Attach event listeners to our links
$(".pagor").click(function() {
updatePage(this);
});
}


Finally the updatePage function does three things. Gets the index of the clicked on link. Then updates the content and links.

You can now have a look at how it all comes together here.
more...

Beginners jQuery AJAX tutorial

Tuesday, 13 October 2009

View Comments

This tutorial aims to go over how to use jQuery for Ajax requests. It should be easy enough for anyone to understand and hopefully be a good reference point for those who already have a good understanding on jQuery and would like an introduction to jQuery AJAX.

Go here to see the demo for this tutorial

Once you have completed this tutorial you should be able to use jQuery to make a request to another php script on your server and insert it into your already loaded page. The steps should be as follows:

  • Load a page and include jQuery

  • Call a javascript function that will send the jQuery Ajax request and execute the php script on your server

  • The php script will return some data to the javascript function

  • The function will then insert this data into your page without reloading



The best place to start before reading through this tutorial is to have a look over the Ajax section of the jQuery API. In particular have a look at the 'Ajax Requests' section and at the different methods available.

Our basic file structure will look like this:

  • index.html - Our HTML page that contains our initial content and includes jQUery and our page.js files

  • page.js - The javascript file that contains our function to load in the content via Ajax from our php script

  • content.php - The php file which will provide us with our extra content



The index.html file contains a link which when clicked calls the addContent javascript function. This function then calls the jQuery Ajax function jQuery.get This function calls creates a XMLHttpRequest to retrieve the output of our content.php file.

The content.php file simply echoes out one line of code which is returned to the javascript function and is stored in the data variable.

Lets have a look at our content.php and page.js files

<?php
echo "<p>This is some content loaded via Ajax</p>";
?>



function addContent() {
var data = $.get("content.php", function(data) {
$("body").append(data);
});
}


The addContent function is called when 'Click here' link is clicked.

The function specified in the the $.get call is the callback function for when our data is returned successfully from the content.php script. The contents of the data variable is then simply appended to the body.

And like magic you now have your first working Ajax functionality. Our php file in this example was very limited, but you can use Ajax requests to retrieve, update and delete information on your database without reloading the page. You can also load certain content based upon user interaction without reloading the whole page.

There are however some issues with using Ajax and excessive use of Ajax can have a negative effect on usability so you should consider your use of Ajax before using it on your site.

Here are some cons to using jQuery, all of which have various work arounds, but should be taken in to consideration when implementing Ajax:

  • By default Ajax content cannot be bookmarked, so if you update your page with Ajax it may be hard to be bookmarked in a certain state.

  • Some users may be confused if your page is updated with AJAX content especially if certain controls are changed or removed and the page is not reloaded.

  • Some times requests may take several seconds to be returned and users may be left wondering when they can continue using the page.

  • All failures should be handled gracefully otherwise a user can be left in limbo.

more...