Click here to Skip to main content
15,867,453 members
Articles / Web Development / HTML

A Watermarked Auto-complete jQuery Plugin

Rate me:
Please Sign up or sign in to vote.
4.92/5 (19 votes)
20 Aug 2011CPOL6 min read 56.7K   2.2K   47   15
This article presents a watermarked auto-complete jQuery plugin

Introduction

This article presents a watermarked auto-complete jQuery plugin.

Background

The watermarked auto-complete jQuery plugin is built upon the "jQuery UI" auto-complete. It adds a watermark to the original plugin and offers the ability to limit the user's capability to enter free text into the text box. In this article, I will present this plugin and a small demo application on how to use it.

Bug Fixes: Since the first release of this article, some friends have pointed out some bugs related to this plugin. They are the following:

  • The watermark text has a wrong capitalization.
  • The method name "distory" should be "destroy".
  • There is a functonal bug during the initialization of the plugin. The typos in the code prevent the users of the plugin to subscribe to the "select" event of the "jQuery UI" auto-complete.

These bugs have been fixed and I have uploaded the plugin in the "jquery-watermarkAutocomplete-1.0.1.zip" file. You can still download the "Watermarkautocomplete" solution to run the demo. The demo application does not touch the bugs in the plugin and should run smoothly without the bug fixes. Just remember to use the version in the "jquery-watermarkAutocomplete-1.0.1.zip" if you want to use this plugin as it is in your own application. Thanks to the friends who found the bugs.

SolutionExplorer.jpg

The Visual Studio 2010 solution is the demo application.

  • The "jquery-watermarkAutocomplete-1.0.0.js" in the "Scripts" folder is the watermarked auto-complete plugin.
  • The "Default.htm" is the web page to demonstrate how to use the plugin.

This article assumes that the readers have some basic knowledge on "jQuery". Since the data displayed in the auto-complete text box in the example comes from an "MVC" controller, you will need to have some basic knowledge on "MVC" as well.

I will first present the plugin and then show you how to use it.

The Watermarked Auto-complete Plugin

The watermarked auto-complete plugin is implemented in the "jquery-watermarkAutocomplete-1.0.0.js" file:

JavaScript
 (function ($) {
    // jQuery methods
    var methods = {
        init: function (options) {
            // default options
            var settings = {
                watermarkstyle: { "color": "grey", "font-style": "italic" },
                watermarktext: "Please Enter some text",
                autocompletesource: null,
                autocompleteselect: null,
                autocompletechange: null,
                allowfreetext: false,
                watermarkenabled: true
            }
 
            return this.each(function () {
                if (options) {
                    var $this = $(this);
 
                    // merge the input options with the default options
                    $.extend(settings, options);
                    if (!settings.regulartextstyle) {
                        var regulartextstyle = {
                            "color": $this.css("color"),
                            "font-style": $this.css("font-style")
                        }
 
                        settings.regulartextstyle = regulartextstyle;
                    }
                    settings.watermarktext = $.trim(settings.watermarktext);
 
                    // initiate the jQuery data for each selected dom object
                    // this may introduce redundant data sets, but it also allows
                    // individual configuration if needed later.
                    var instancedata = { options: $.extend({}, settings), data: {} };
                    $this.data("watermarkAutocomplete", instancedata);
 
                    // setup auto complete if the source functions are provided
                    // through the option Json object.
                    if (instancedata.options.autocompletesource) {
                        $(this).autocomplete({
                            source: instancedata.options.autocompletesource,
                            select: function (event, ui) {
                                if (instancedata.options.autocompleteselection) {
                                    instancedata.options.autocompleteselection(event, ui);
                                }
 
                                instancedata.data.autocompleteselection = ui.item;
                            },
                            change: function (event, ui) {
                                var $this = $(this);
                                if (instancedata.options.autocompletechange) {
                                    instancedata.options.autocompletechange(event, ui);
                                }
                                if (!instancedata.options.allowfreetext) {
                                    clearfreetext($this, instancedata.options, 
					instancedata.data);
                                }
                            }
                        });
                    }
 
                    // null the selection when user type in anything
                    $this.bind("keyup.watermarkAutocomplete", function () {
                        var instancedata = $(this).data("watermarkAutocomplete");
                        instancedata.data.autocompleteselection = null;
                    });
 
                    // clear watermark when focus
                    $this.bind("focus.watermarkAutocomplete", function () {
                        var $this = $(this);
                        var instancedata = $this.data("watermarkAutocomplete");
                        if (instancedata.options.watermarkenabled) {
                            clearwatermark($this, instancedata.options);
                        }
                    });
 
                    // apply watermark when lose focus
                    $this.bind("blur.watermarkAutocomplete", function () {
                        var $this = $(this);
                        var instancedata = $this.data("watermarkAutocomplete");
                        if (instancedata.options.watermarkenabled) {
                            applywatermark($this, instancedata.options);
                        }
                    })
 
                    // Set the initial watermark
                    if (instancedata.options.watermarkenabled) {
                        applywatermark($this, instancedata.options);
                    }
                }
            });
        },
 
        enablewatermark: function (enable) {
            return this.each(function () {
                var $this = $(this);
                var instancedata = $this.data("watermarkAutocomplete");
                instancedata.options.watermarkenabled = enable;
 
                if (enable) {
                    applywatermark($this, instancedata.options);
                }
                else {
                    clearwatermark($this, instancedata.options);
                }
            });
        },
 
        allowfreetext: function (allow) {
            return this.each(function () {
                var $this = $(this);
                var instancedata = $this.data("watermarkAutocomplete");
 
                instancedata.options.allowfreetext = allow;
                if (!instancedata.options.allowfreetext) {
                    clearfreetext($this, instancedata.options, instancedata.data);
                }
            });
        },
 
        destroy: function () {
            return this.each(function () {
                var $this = $(this);
                var instancedata = $this.data("watermarkAutocomplete");
                clearwatermark($this, instancedata.options);
                $this.removeData("watermarkAutocomplete");
                $this.unbind(".watermarkAutocomplete");
                $this.autocomplete("destroy");
            });
        }
    };
 
    // The jQuery entry point
    $.fn.watermarkAutocomplete = function (method) {
        if (methods[method]) {
            return methods[method].apply(this, Array.prototype.slice.call(arguments, 1));
        } else if (typeof method === "object" || !method) {
            return methods.init.apply(this, arguments);
        } else {
            $.error("Method " + method + "does not exist on jQuery.watermarkAutocomplete");
        }
    };
 
    // utility functions
    var applywatermark = function ($this, options) {
        var text = $.trim($this.val());
        if ((text == "") || (text == options.watermarktext)) {
            $this.css(options.watermarkstyle);
            $this.val(options.watermarktext);
        }
    };
 
    var clearwatermark = function ($this, options) {
        var text = $.trim($this.val());
        if (text == options.watermarktext) {
            $this.val("");
        }
        $this.css(options.regulartextstyle);
    };
 
    var clearfreetext = function ($this, options, data) {
        if (!data.autocompleteselection) {
            $this.val("");
            if (options.watermarkenabled) {
                applywatermark($this, options);
            }
        }
    };
 
})(jQuery);

This article is not intended to show you how to write "jQuery" plugins. If you are interested in writing a plugin, you can refer to the "Official plugin authoring guidelines". To use this plugin though, we can use the following options to configure the text box:

  • Property "watermarkenabled" - true/false. We can use this option to control if the watermark text should be displayed when the text box is empty. The default is "true".
  • Property "allowfreetext" - true/false. We can use this option to control if the auto-complete text box allows free text. The default is "false".
  • Property "watermarkstyle" - the CSS style when the auto-complete box is watermarked. The default is ""{ "color": "grey", "font-style": "italic" }".
  • Property "watermarktext" - the watermark text. The default text is "Please enter some text".
  • Function "autocompletesource" - A function called when the user types in some text into the auto-complete box. It should provide a list of that matches the user input.
  • Function "autocompleteselect" - A function called when an item is selected from the auto-complete list.
  • Function "autocompletechange" - A function called when the auto-complete box looses focus if the text in the auto-complete box is changed.

When initiating the auto-complete box, if the "autocompletesource" function is not provided in the options, the text box will behave as a watermarked text box. Besides the options, this plugin also provides the following methods to allow you to change the behavior of the auto-complete box after it is initialized. According to the "Official plugin authoring guidelines", these methods should be called with the following syntax:

  • Method "enablewatermark". It should be called like "$(selector).watermarkAutocomplete('enablewatermark', true/false)". It is used to change if we want to show the watermark text when the text box is empty.
  • Method "allowfreetext". It should be called like "$(selector).watermarkAutocomplete('allowfreetext', true/false)". It is used to change if we want to allow free text input to the auto-complete box.
  • Method "destroy". It should be called like "$(selector).watermarkAutocomplete('destroy')". Calling this method will un-bind the plugin with the text box and free all the resources used.

Now let us take a look at the demo application to see how to use this "jQuery" plugin.

The Data Model of the Demo Application

The data model of this demo application is implemented in the "LanguageRepository.cs" file in the "Models" folder:

C#
using System;
using System.Collections.Generic;
using System.Linq;
using System.Web;
 
namespace Watermarkautocomplete.Models
{
    public class Language
    {
        public int Id { get; set; }
        public string Name { get; set; }
    }
 
    public static class LanguageRepository
    {
        public static List<Language> Languages { get; set; }
        static LanguageRepository()
        {
            Languages = new List<Language>();
            Languages.Add(new Language { Id = 1, Name = "Basic" });
            Languages.Add(new Language { Id = 2, Name = "Fortran" });
            Languages.Add(new Language { Id = 3, Name = "Smalltalk" });
            Languages.Add(new Language { Id = 4, Name = "Cobal" });
            Languages.Add(new Language { Id = 5, Name = "Lisp" });
            Languages.Add(new Language { Id = 6, Name = "Prolog" });
            Languages.Add(new Language { Id = 7, Name = "Matlab" });
            Languages.Add(new Language { Id = 8, Name = "C" });
            Languages.Add(new Language { Id = 9, Name = "C++" });
            Languages.Add(new Language { Id = 10, Name = "C#" });
            Languages.Add(new Language { Id = 11, Name = "Java" });
            Languages.Add(new Language { Id = 12, Name = "PHP" });
            Languages.Add(new Language { Id = 13, Name = "Python" });
            Languages.Add(new Language { Id = 14, Name = "Javascript" });
            Languages.Add(new Language { Id = 15, Name = "Ruby" });
        }
    }
}

The "LanguageRepository" class defines a list of computer languages. This demo application will show you how to display the languages that match the text in the text box to auto-complete the user entry.

The "Default.htm" Page

The "default.htm" page is the web page that uses the watermarked auto-complete plugin:

HTML
<!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>
    <title>Watermark Autocomplete Demo</title>
    <link href="Content/redmond/jquery-ui-1.8.14.custom.css" 
		rel="stylesheet" type="text/css" />
 
    <script src="Scripts/jquery-1.6.2.js" type="text/javascript"></script>
    <script src="Scripts/jquery-ui-1.8.14.custom.min.js" type="text/javascript"></script>
    <script src="Scripts/jquery-watermarkAutocomplete-1.0.0.js" 
	type="text/javascript"></script>
    <script src="Scripts/Default.htm.js" type="text/javascript"></script>
</head>
 
<body>
<div>
    <input type="text" id="txtAutoComplete" style="width: 150px" />
</div>
</body>
</html>

In this example, I will show you how to apply the watermarked auto-complete plugin to the text box "txtAutoComplete". The watermarked auto-complete plugin is built upon the "jQuery UI". We will need to refer to the following libraries as well as the "jquery-watermarkAutocomplete-1.0.0.js" file in the "Default.htm" file:

The JavaScript code that sets up the watermarked auto-complete effect for the text box "txtAutoComplete" is implemented in the "Default.htm.js" file.

The "Default.htm.js" script file

The client script for the "Default.htm" page is implemented in the "Default.htm.js" file:

JavaScript
$(document).ready(function () {
    var dataSourceUrl = "DataSource/GetData";
    var maxResult = 5;
 
    // Prepare a simple option object
    var options = {
        autocompletesource: function (request, response) {
            var term = $.trim(request.term);
            var dataToServer = { searchText: term, maxResults: maxResult };
 
            $.ajax({
                url: dataSourceUrl, type: "POST", dataType: "json",
                data: dataToServer, success: function (data) {
                    response($.map(data, function (v) {
                        var Id = v.Id;
                        var Name = v.Name;
                        return { label: Name, value: Name, Id: Id };
                    }));
                }
            });
        }
    };
 
    // Set up the watermarked autocomplete text box
    $("#txtAutoComplete").watermarkAutocomplete(options);
});

Although this plugin offers some more options, this demo application tries to keep it simple by taking advantage of the default options. When I initiate the auto-complete text box, I only provided the "autocompletesource" function. When the user types some text into the text box, an "Ajax" call is made to the server to bring the matching computer languages.

The MVC Controller "DataSourceController"

The "MVC" controller that receives the "Ajax" call and returns the matching list of the computer languages is implemented in the "DataSourceController.cs" file in the "Controllers" folder:

C#
using System;
using System.Collections.Generic;
using System.Linq;
using System.Web;
using System.Web.Mvc;
using Watermarkautocomplete.Models;
 
namespace Watermarkautocomplete.Controllers
{
    public class DataSourceController : Controller
    {
        [HttpPost]
        public ActionResult GetData(string searchText, int maxResults)
        {
            searchText = searchText.ToUpper();
            var languages = LanguageRepository.Languages;
            var selected = from language in languages
                           where language.Name.ToUpper()
                                .StartsWith(searchText)
                           orderby language.Name
                           select language;
 
            return Json(selected.Take(maxResults));
        }
    }
}

We now complete the watermarked auto-complete plugin and the demo application on how to use it. We can test run our application.

Run the Application

DefaultWatermark.jpg

When the application launches in the web browser, we see the auto-complete text box. As expected, it is watermarked.

SelectionList.jpg

If we type in some text in the text box, the auto-complete plugin issues an "Ajax" call to bring the match list of the computer languages for us to select from. Since we have limited number of languages in our data source, only certain text can bring us a matching language list. In this case, we have both "Java" and "Javascript" that match our input text "j".

Selected.jpg

We can then select one of the choices and the text box is auto-completed with our selection.

AddText.jpg

When we setup the auto-completion, we chose not to allow the user to input free text. We can then type some other text in the text box like "Java A". Since "Java A" is not a language in the selection list, when the text box loses focus, the text is cleared and the watermark is shown.

DefaultWatermark.jpg

Points of Interest

  • This article presented a watermarked auto-complete jQuery plugin.
  • I have made my effort to comply with the "Official plugin authoring guidelines" and this plugin should largely fulfill the guidelines. But if you see any places that I need to change, please let me know.
  • This plugin is built upon the "jQuery UI" auto-complete plugin. If you feel that you need certain functionalities provided by the "jQuery UI" but not this plugin, you can use the "jQuery UI" plugin directly.
  • I hope you like my postings and I hope this article can help you one way or the other.

History

  • First revision - 8/17/2011

License

This article, along with any associated source code and files, is licensed under The Code Project Open License (CPOL)


Written By
United States United States
I have been working in the IT industry for some time. It is still exciting and I am still learning. I am a happy and honest person, and I want to be your friend.

Comments and Discussions

 
QuestionHow to use it with default values Pin
demouser74314-Nov-18 22:25
demouser74314-Nov-18 22:25 
QuestionMessage Closed Pin
22-Jul-14 1:24
Binu198522-Jul-14 1:24 
AnswerRe: Nice one Pin
Dr. Song Li22-Jul-14 3:11
Dr. Song Li22-Jul-14 3:11 
QuestionMy very thnx Pin
FatihSahin30-Aug-11 2:11
FatihSahin30-Aug-11 2:11 
GeneralMy vote of 5 Pin
joeyespo22-Aug-11 10:59
joeyespo22-Aug-11 10:59 
QuestionLooks very nice Pin
HaBiX21-Aug-11 20:40
HaBiX21-Aug-11 20:40 
GeneralMy vote of 5 Pin
Md. Marufuzzaman20-Aug-11 19:15
professionalMd. Marufuzzaman20-Aug-11 19:15 
QuestionGreat article and pluging one bug Pin
poporopo19-Aug-11 20:11
poporopo19-Aug-11 20:11 
AnswerRe: Great article and pluging one bug Pin
Dr. Song Li20-Aug-11 3:44
Dr. Song Li20-Aug-11 3:44 
GeneralMy vote of 5 Pin
ezekjh19-Aug-11 13:02
ezekjh19-Aug-11 13:02 
This is a great piece of code. Good job.
Questionhighly interesting Pin
Pascal Ganaye18-Aug-11 23:42
Pascal Ganaye18-Aug-11 23:42 
AnswerRe: highly interesting Pin
Dr. Song Li19-Aug-11 1:29
Dr. Song Li19-Aug-11 1:29 
GeneralMy vote of 5 Pin
Anurag Gandhi18-Aug-11 19:31
professionalAnurag Gandhi18-Aug-11 19:31 
GeneralI will be using this very soon Pin
Sacha Barber17-Aug-11 22:48
Sacha Barber17-Aug-11 22:48 
GeneralRe: I will be using this very soon Pin
Dr. Song Li18-Aug-11 4:08
Dr. Song Li18-Aug-11 4:08 

General General    News News    Suggestion Suggestion    Question Question    Bug Bug    Answer Answer    Joke Joke    Praise Praise    Rant Rant    Admin Admin   

Use Ctrl+Left/Right to switch messages, Ctrl+Up/Down to switch threads, Ctrl+Shift+Left/Right to switch pages.