65.9K
CodeProject 正在变化。 阅读更多。
Home

带水印的自动完成 jQuery 插件

starIconstarIconstarIconstarIcon
emptyStarIcon
starIcon

4.92/5 (19投票s)

2011年8月17日

CPOL

6分钟阅读

viewsIcon

62624

downloadIcon

2231

本文介绍了一个带水印的自动完成 jQuery 插件。

引言

本文介绍了一个带水印的自动完成 jQuery 插件。

背景

带水印的自动完成 jQuery 插件建立在“jQuery UI”自动完成功能的基础上。它为原始插件添加了水印,并提供了限制用户在文本框中输入自由文本的功能。在本文中,我将介绍这个插件以及一个演示如何使用它的简单演示应用程序。

Bug 修复:自本文初次发布以来,一些朋友指出了该插件的一些错误。它们如下:

  • 水印文本的大小写错误。
  • 方法名“distory”应为“destroy”。
  • 插件初始化期间存在功能性错误。代码中的拼写错误阻止了插件用户订阅“jQuery UI”自动完成的“select”事件。

这些错误已得到修复,我已将该插件上传到“jquery-watermarkAutocomplete-1.0.1.zip”文件中。您仍然可以下载“Watermarkautocomplete”解决方案来运行演示。演示应用程序不包含插件中的错误,并且应该可以顺利运行,无需错误修复。只需记住,如果您想在自己的应用程序中使用此插件,请使用“jquery-watermarkAutocomplete-1.0.1.zip”中的版本。感谢找到这些错误的朋友。

SolutionExplorer.jpg

Visual Studio 2010 解决方案是演示应用程序。

  • Scripts”文件夹中的“jquery-watermarkAutocomplete-1.0.0.js”是带水印的自动完成插件。
  • Default.htm”是演示如何使用该插件的网页。

本文假定读者对“jQuery”有一定的基本了解。由于示例中自动完成文本框显示的数据来自“MVC”控制器,因此您还需要对“MVC”有一定的基本了解。

我将首先介绍该插件,然后向您展示如何使用它。

带水印的自动完成插件

带水印的自动完成插件实现在“jquery-watermarkAutocomplete-1.0.0.js”文件中。

 (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);

本文无意展示如何编写“jQuery”插件。如果您有兴趣编写插件,可以参考“官方插件编写指南”。但是,要使用此插件,我们可以使用以下选项来配置文本框:

  • 属性“watermarkenabled” - true/false。我们可以使用此选项来控制在文本框为空时是否显示水印文本。默认为“true”。
  • 属性“allowfreetext” - true/false。我们可以使用此选项来控制自动完成文本框是否允许自由输入文本。默认为“false”。
  • 属性“watermarkstyle” - 自动完成框显示水印时的 CSS 样式。默认值为 ""{ "color": "grey", "font-style": "italic" }"
  • 属性“watermarktext” - 水印文本。默认文本为“Please enter some text”。
  • 函数“autocompletesource” - 当用户在自动完成框中键入文本时调用的函数。它应提供一个与用户输入匹配的列表。
  • 函数“autocompleteselect” - 当从自动完成列表中选择一项时调用的函数。
  • 函数“autocompletechange” - 当自动完成框失去焦点且文本已更改时调用的函数。

初始化自动完成框时,如果选项中未提供“autocompletesource”函数,文本框将表现为带水印的文本框。除了选项之外,该插件还提供了以下方法,允许您在自动完成框初始化后更改其行为。根据“官方插件编写指南”,这些方法应使用以下语法调用:

  • 方法“enablewatermark”。应如此调用:“$(selector).watermarkAutocomplete('enablewatermark', true/false)”。它用于更改当文本框为空时是否显示水印文本。
  • 方法“allowfreetext”。应如此调用:“$(selector).watermarkAutocomplete('allowfreetext', true/false)”。它用于更改是否允许向自动完成框输入自由文本。
  • 方法“destroy”。应如此调用:“$(selector).watermarkAutocomplete('destroy')”。调用此方法将解除插件与文本框的绑定并释放所有使用的资源。

现在让我们看看演示应用程序,了解如何使用这个“jQuery”插件。

演示应用程序的数据模型

此演示应用程序的数据模型实现在“Models”文件夹的“LanguageRepository.cs”文件中。

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" });
        }
    }
}

LanguageRepository”类定义了一个计算机语言列表。此演示应用程序将向您展示如何显示与文本框中的文本匹配的语言,以自动完成用户的输入。

“Default.htm”页面

default.htm”页面是使用带水印的自动完成插件的网页。

<!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>

在此示例中,我将向您展示如何将带水印的自动完成插件应用于文本框“txtAutoComplete”。带水印的自动完成插件建立在“jQuery UI”的基础上。我们还需要在“Default.htm”文件中引用以下库以及“jquery-watermarkAutocomplete-1.0.0.js”文件:

为文本框“txtAutoComplete”设置带水印的自动完成效果的 JavaScript 代码实现在“Default.htm.js”文件中。

“Default.htm.js”脚本文件

Default.htm”页面的客户端脚本实现在“Default.htm.js”文件中。

$(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);
});

尽管此插件提供了一些额外的选项,但此演示应用程序试图通过利用默认选项来保持简单。当我初始化自动完成文本框时,我只提供了“autocompletesource”函数。当用户在文本框中输入一些文本时,会向服务器发出一个“Ajax”调用,以获取匹配的计算机语言。

MVC 控制器“DataSourceController”

接收“Ajax”调用并返回匹配的计算机语言列表的“MVC”控制器实现在“Controllers”文件夹的“DataSourceController.cs”文件中。

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));
        }
    }
}

我们现在完成了带水印的自动完成插件以及演示如何使用它的应用程序。我们可以测试运行我们的应用程序。

运行应用程序

DefaultWatermark.jpg

当应用程序在 Web 浏览器中启动时,我们看到带水印的自动完成文本框,正如预期的那样。

SelectionList.jpg

如果我们输入一些文本,自动完成插件会发出一个“Ajax”调用,以获取匹配的计算机语言列表供我们选择。由于我们的数据源中语言数量有限,只有某些文本才能带来匹配的语言列表。在这种情况下,“Java”和“Javascript”都与我们输入的文本“j”匹配。

Selected.jpg

然后我们可以选择一个选项,文本框将自动完成我们的选择。

AddText.jpg

当我们设置自动完成时,我们选择不允许用户输入自由文本。然后我们可以键入其他文本,例如“Java A”。由于“Java A”不在选择列表中,当文本框失去焦点时,文本将被清除并显示水印。

DefaultWatermark.jpg

关注点

  • 本文介绍了一个带水印的自动完成 jQuery 插件。
  • 我已尽力遵守“官方插件编写指南”,并且该插件应在很大程度上符合这些指南。但如果您发现任何需要更改的地方,请告诉我。
  • 此插件建立在“jQuery UI”自动完成插件的基础上。如果您觉得需要“jQuery UI”提供的某些功能而此插件没有,您可以直接使用“jQuery UI”插件。
  • 我希望您喜欢我的文章,希望本文能以某种方式帮助您。

历史

  • 第一次修订 - 2011年8月17日
© . All rights reserved.