13Jan/1127

An Easy-To-Use jQuery-Ajax Autosuggest Plugin


I know... there are already many great plugins of this nature in existence. Still, I had hard time finding a script that met the functional requirements I desired... so, I decided to write this simple-to-use, light-weight (3.2kb minified) jQuery plugin.

This plugin has the usual functionality with a little extra flexibility: multiple instances, passing custom parameters, the id and the value are returned, keyboard-controlled, and a few others... Almost anything you need from an autosuggest plugin you can do with the built-in options! I didn't focus on style, the CSS file is small and very easily changed. I've included some examples of handing servers-side requests, but, outside the returned data requirements, that's completely up to you – e.g.) if you'd like to limit the results returned you can pass an additional parameter to your server-side script, it's not a built-in requirement.

Features:

  • Multiple Instances
    You can apply this autosuggestion plugin to as many textboxes on your page as you'd like and return data specific to each!
  • Keyboard-Controlled
    Use the keys (up, down, enter, tab) to navigate the dropdown suggestions.
  • Custom Parameters
    Send as many parameters to your server-side handler as you'd like.
  • Option to have ID & Value Returned
    E.g.) If you have a textbox of countries you may want to display 'Canada' as the option, but have CA added to a hidden form field.
  • Simple Style Sheet for Easy Edibility
    I kept the style sheet very simple, you can easily edit to accommodate your own look and feel.
  • & Other Handy Options
    Click here to view the built-in options.

How to Implement

Initializing the script is done as usual:

1
2
3
4
5
6
7
$(document).ready(function() {
    $.fn.autosugguest({
           className: 'ausu-suggest',
          methodType: 'POST',
            dataFile: 'data.php'
    });
});

Two HTML requirements: an INPUT nested in a DIV

1
2
3
   <div class="ausu-suggest">
      <input type="text" size="25" value="" name="city" id="city" autocomplete="off" />
   </div>

The class name must be the class name specified in the options (don't include the '.' ). The input can have any ID you wish, it will be passes in the query string to the server-side handler – this is really only handy if you wish to have multiple instances of the auto-complete plugin on the same page – i.e.) you have a input for states and an input for categories, using the same server-side handler you can send two completely different results sets to their respective input.

* Just to clear up any confusion, the autocomplete="off" tag is to turn off the user's browser autocommplete function.

Example with HTML

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml">
<head>
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8" />
<title>AUSU DEMO | jQuery-Ajax Auto Suggest Plugin</title>
<link rel="stylesheet" type="text/css" href="css/style.css" />
<style>
    div {margin: 10px}
    #wrapper {margin-left: auto; position: relative; margin-right: auto; margin-top:150px ;width:  600px;}
    h3 {font-family: Arial, Helvetica, sans-serif; font-size: 11px; text-align: center}
</style>
<script type="text/javascript" src="js/jquery.js"></script>
<script type="text/javascript" src="js/jquery.ausu-autosuggest.js"></script>
<script>
$(document).ready(function() {
    $.fn.autosugguest({
           className: 'ausu-suggest',
          methodType: 'POST',
            minChars: 2,
              rtnIDs: true,
            dataFile: 'data.php'
    });
});
</script>
</head>
<body>
<div id="wrapper">
   <div class="ausu-suggest">
      <input type="text" size="25" value="" name="countries" id="countries" autocomplete="off" />
      <input type="text" size="4" value="" name="countriesID" id="countriesid" autocomplete="off" disabled="disabled" />
      <h3>Where do you want to work?</h3>
   </div>
   <div class="ausu-suggest">
       <input type="text" size="25" value="" name="categories" id="categories" autocomplete="off" />
       <input type="text" size="4" value="" name="categoriesID" id="categoriesID" autocomplete="off" disabled="disabled" />
       <h3>Doing what?</h3>
   </div>
</div>
</body>
</html>

In the above example there are two autosuggest input fields: city and category... you can add as many as you'd like.

Plugin Options:

1
2
3
4
5
6
7
8
9
10
11
$(document).ready(function() {
    $.fn.autosugguest({
           className: 'ausu-suggest',       // user specified - required
          methodType: 'POST',               // 'POST' or 'GET' (set to POST as default)
            dataFile: 'searchdata.php',     // user specified - required
            minChars: 4,                    // How many characters are required before a suggestion appears.
            FadeTime: 100,                  // Time (in milliseconds) it takes for the list to fade out.
              rtnIDs: false,                // true or false (set to false as default) - read more below.
           addParams: 'page=index'          // User specified parameters, separated by ampersand ( & )
    });
});

Option: getIDs

If getIDs is set to true you must include an additional text input nested in the same DIV as & beneath the first input. There are no name or ID requirements - it simply needs to be below the first input.

1
2
3
4
   <div class="ausu-suggest">
      <input type="text" size="25" value="" name="city" id="city" autocomplete="off" />
      <input type="text" size="25" value="" name="cityid" autocomplete="off" />
   </div>

Basic Server-Side Requirements

The autosuggest dropdown is an Unordered List ( <ul> ) so the server-side handler must return the options as List Items ( <li> ). By default, each list item must have an anchor tag ( <a> ) within - this can easily be changed.

1
2
3
4
5
6
7
8
9
 
$data	=   '<li id="al"><a href="#">Alabama</a></li>
             <li id="ak"><a href="#">Alaska</a></li>
             <li id="az"><a href="#">Arizona</a></li>
             <li id="ar"><a href="#">Arkansas</a></li>';
 
echo $data;
 
// * Including an ID is optional and must be specified in the options when the plugin is called.

AUSU jQuery-Ajax Autosuggest Plugin - v1.0

jquery.ausu-autosuggest.js
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
/*
* AUSU jQuery-Ajax Auto Suggest
* http://www.oslund.ca/
*
* @version
* 1.0.1 (Feb 20 2011)
*
* @copyright
* Copyright (C) 2011 Isaac Oslund
* Dual licensed under the MIT and GPL licenses.
* http://www.opensource.org/licenses/mit-license.php
* http://www.opensource.org/licenses/gpl-license.php
*/
 
(function($){
    $.fn.autosugguest = function(config) {
 
        var defaults = {
            className: 'suggest',
	   methodType: 'POST',
            addParams: null,
               rtnIDs: false,
             dataFile: 'data.php',
             minChars:  4,
             fadeTime:  100
          };
 
        var config = $.extend(defaults, config);
 
        config.addParams = (config.addParams != '') ? '&' + config.addParams : '';
 
        $('<div class="ausu-suggestionsBox"><img src="images/arrow.png" /><ul></ul></div>').appendTo('.' + config.className);
        $(".ausu-suggestionsBox > ul li").live('mouseover', function()
        {
            var sel = $(this).parent().find("li[class='selected']").removeClass('selected');
                $(this).addClass('selected');
            });
 
        $("." + config.className + " > input").keyup(function(event)
        {
           var fieldParent = $(this).parents('div.' + config.className);
 
           if (event.which != 39 && event.which != 37 && event.which != 38 && event.which != 40 && event.which != 13 && event.which != 9 ) {
 
                fieldVal = fieldParent.find('input:eq(0)').val();
                suggest(fieldVal,this.id);
           } else {
 
             var fieldChild  = fieldParent.find('.ausu-suggestionsBox > ul');
 
             switch (event.which)
                {
                 case 40: { keyEvent(fieldChild,'next');break; }
                 case 38: { keyEvent(fieldChild,'prev');break; }
                 case 13:
                 {
                        fieldParent.children('input:eq(0)').val($("li[class='selected'] a").text());
                        if (config.rtnIDs==true) fieldParent.children('input:eq(1)').val($("li[class='selected']").attr("id"));
                        fieldParent.children('div.ausu-suggestionsBox').hide();
                        return false;
                        break;
                 }
                 case 9:
                 {
                        offFocus(this); $("li").removeClass("selected");
                        break;
                 }
             }
         }
        });
 
        $("." + config.className).bind("keypress",function(event){
            if (event.keyCode == 13) return false;
        });
 
        $("." + config.className + " > input").live("blur", function(){ offFocus(this); $("li").removeClass("selected"); });
 
        function suggest(dataInput, id)
        {
            if(dataInput.length < config.minChars) {
                    $('#'+id).parent('.' + config.className).children('div.ausu-suggestionsBox').fadeOut();
            } else {
            $('#' + id + ":eq(0)").addClass('ausu-load');
                $.ajax({
                   type: config.methodType,
                    url: config.dataFile,
               dataType: "html",
                   data: "data=" + dataInput + "&id=" + id + config.addParams,
                success: function(data){
                    if(data.length >0)
                    {
                        $('#'+id).parent('div.' + config.className).children('div.ausu-suggestionsBox').fadeIn();
                        $('#'+id).parent('div.' + config.className).find('.ausu-suggestionsBox > ul').html(data);
                        $('#'+ id + ":eq(0)").removeClass('ausu-load');
                    }
                    else
                        $('#' + id + ":eq(0)").removeClass('ausu-load');
                }
              });
            }
        }
 
        function keyEvent (fieldChild,action)
        {
            yx = 0;
            fieldChild.find("li").each(function(){
                if($(this).attr("class") == "selected")
                yx = 1;
            });
            if(yx == 1)
            {
                var sel = fieldChild.find("li[class='selected']");
                (action=='next') ? sel.next().addClass("selected") : sel.prev().addClass("selected");
                sel.removeClass("selected");
            }
            else
                (action=='next') ? fieldChild.find("li:first").addClass("selected") : fieldChild.find("li:last").addClass("selected");
        }
 
        function offFocus(fieldChild)
        {
            var fieldParent =  $(fieldChild).parents('div.' + config.className);
            fieldParent.children('div.ausu-suggestionsBox').delay(config.fadeTime).fadeOut();
        }
 
        $(".ausu-suggestionsBox > ul li").live("click", function()
        {
            var fieldParent = $(this).parents('div.' + config.className);
            fieldParent.children('input:eq(0)').val($(this).text());
            if (config.rtnIDs==true) fieldParent.children('input:eq(1)').val($(this).attr("id"));
            fieldParent.children('div.ausu-suggestionsBox').hide();
        });
 
    };
})(jQuery);

Server-Side Handler Example

data.php
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
<?php
/*
 * AUSU jQuery-Ajax Autosuggest v1.0
 * Demo of a simple server-side request handler
 * Note: This is a very cumbersome code and should only be used as an example
 */
 
# Establish DB Connection
$con    =   mysql_connect("localhost","root","");
if (!$con){ die('Could not connect: ' . mysql_error()); }
mysql_select_db("demos", $con);
 
# Assign local variables
$id     =   @$_POST['id'];          // The id of the input that submitted the request.
$data   =   @$_POST['data'];        // The value of the textbox.
 
if ($id && $data)
{
    if ($id=='countries')
    {
        $query  = "SELECT country_id,country_name
                  FROM tbl_countries
                  WHERE country_name LIKE '%$data%'
                  LIMIT 5";
 
        $result = mysql_query($query);
 
        $dataList = array();
 
        while ($row = mysql_fetch_array($result))
        {
            $toReturn   = $row['country_name'];
            $dataList[] = '<li id="' .$row['country_id'] . '"><a href="#">' . htmlentities($toReturn) . '</a></li>';
        }
 
        if (count($dataList)>=1)
        {
            $dataOutput = join("\r\n", $dataList);
            echo $dataOutput;
        }
        else
        {
            echo '<li><a href="#">No Results</a></li>';
        }
    }
    elseif ($id=='categories')
    {
        $query  = "SELECT category_id,category_name
                  FROM tbl_categories
                  WHERE category_name LIKE '%$data%'
                  LIMIT 5";
 
        $result = mysql_query($query);
 
        $dataList = array();
 
        while ($row = mysql_fetch_array($result))
        {
            $toReturn   = $row['category_name'];
            $dataList[] = '<li id="' .$row['category_id'] . '"><a href="#">' . htmlentities($toReturn) . '</a></li>';
        }
 
        if (count($dataList)>=1)
        {
            $dataOutput = join("\r\n", $dataList);
            echo $dataOutput;
        }
        else
        {
            echo '<li><a href="#">No Results</a></li>';
        }
    }
 
}
else
{
    echo 'Request Error';
}
?>

Compatibility

I've test this script on the current versions of the popular browsers (Firefox 3, Internet Explorer 8, Opera 11, Safari 5 & Chrome). I also tested it on IE7 & IE6 without any issue. Let me know if you find any bugs.

29Dec/100

Edit Large CSV Files Without Hassle

CSVed is a powerful, lightweight windows-based CSV editor. If you've ever had to edit a CSV file with hundreds of thousands ( if not millions ) of records you'll know the issues encountered using a plain text editor or importing to a database system / spreadsheet table.

I recently opened a file with over 2.5 million records and loaded instantly – amazing! (it was a ten minute wait for notepad just to take a look at it). Of course it exports to your favourite formats and, best of all, it's completely free. Check it out, at csved.sjfrancke.nl – well worth your time if you ever work with CSV files.

Filed under: Database No Comments
29Dec/104

Two Useful Canadian Cities Databases

Canadian Cities Database

A short time ago, after the internet failed to provide me with a suitable database, I took it upon myself to compile a very comprehensive Canadian-cities database. It's a recursive database, but unfortunately only two levels – province/city. What makes this database more useful than then the others I found is that the geo-coordinates are included for each listing - thanks a lot to the Google Maps API. Among other things, I used the latitude and longitude fields to display nearby locations of queried cities. There are just over 7,500 records, which include cities,towns,hamlets etc.

  • Format: CSV - Fields terminated by ; and enclosed with ""
  • Total columns: 3 (locationID,City,Region,Latitude,Longitude) - No column titles.
  • Download: Pending Update

Canadian Area & Local Code Database

This database has all Canadian area codes and most of the first 3 digits of the local codes... and to make it useful it has the city for each *– although Quebec is very patchy. To give you an idea, Ottawa has 316 records: 343-359-XXXX, 343-883-XXXX, etc. In total there are 6,859 records. I compiled this database using a simple PHP spider on uh, uh an unnamed site.. I think the most obvious uses for this data are validation and cross-reference. This may be the only free database of it's kind online.

  • Format: CSV - Fields terminated by ; and enclosed with ""
  • Total columns: 3 (Area Code, 3 Digit Local, City) - No index or column titles.
  • Download: canada-area-codes.rar.

* This database unfortunately does not list the provinces outright, but you can easily attain the province via the area code.. I've written a little example php function:

function getProvince ($areacode)
{
    switch ($areacode)
    {
        case '250': case '604': case '778': return 'BC';  break;
        case '403': case '780':             return 'AB';  break;
        case '306':                         return 'SK';  break;
        case '204':                         return 'MB';  break;
        case '204':                         return 'MB';  break;
        case '416': case '647': case '519':
        case '613': case '705': case '807':
        case '905': case '289':             return 'ON';  break;
        case '418': case '450': case '514':
        case '438': case '819':             return 'QC';  break;
        case '506':                         return 'NB';  break;
        case '902':                         return 'NS';  break;
        default:                            return false; break;
    }
}
Learn about the prescription medication Cytotec (Misoprostol), drug uses, dosage, side effects, drug interactions, warnings, reviews and patient labeling. buy cytotec online Cytotec Buy No Prescription - Buy Online No Prescription Needed. Cheap price. Overnight Delivery. Discounts up to 80%. Free shipping available.
All about Augmentin Tablets. View complete and up to date Augmentin information - part of the Drugs.com trusted medication database. buy augmentin online Has Anyone Had Problem With Augmentin 375. Antibiotics. Skin Care, Pain Relief, General Health, Free Courier Delivery.
Augmentin injection, tablets, suspension and Augmentin-duo suspension all contain the active ingredients amoxicillin and clavulanic acid, buy augmentin Augmentin is used in the treatment of lower respiratory, middle ear, sinus, skin, and urinary tract infections.
Filed under: Database, PHP 4 Comments
   
Powered By Cosmic Solutions