使用JQuery自动完成插件Auto Complete详解


Posted in jQuery onJune 18, 2019

问题

当你查找一些特殊的东西,当你输入准确的词时,找到它可能是困难的(或者很耗时)。在输入的时候展示出结果(自动完成),使查找变得更简单。

解决方案

使用JQuery自动完成插件,更新现有图书列表页面上的搜索,当用户键入的时候立即显示结果。

讨论

自动完成插件是不会象jQuery基本库一样自动包含在MVC项目中的,所以需要做的第一件事就是的是下载插件
访问http://jquery.com/。两个主要的文件是必需的:JavaScript文件和CSS文件。把新下载的javascript文件放到你MVC应用程序的script 文件夹下。CSS文件可以直接添加到您的content目录。

这个配方也将介绍在view中使用 rendering sections。在shared文件夹下layout中自动添加了2个javascript文件和1个css文件。这些是Ajax和不唐突的Ajax和网站主css文件。每次加载的内容越多,页面视图加载越慢。与其在每个页面都去包含可能不必要的javascript和css 文件,不如在layout中添加一个新的RenderSection()。这允许特别的view在<head>标签去加载特别的javascript或css,但不是每页都添加他们。

下边是一个更新后的Views/Shared/_Layout.cshtml,他使用了一个新的RenderSection()。

<!DOCTYPE html>
<html>
<head>
<title>_Mobile</title>
<link href="@Url.Content(" rel="external nofollow" rel="external nofollow" ~/Content/Site.css")" rel="stylesheet" type="text/css" />
<script src="@Url.Content("~/Scripts/jquery-1.6.2.min.js")" type="text/javascript"></script>
<script type="text/javascript">
$(document).ready(function () {
if (window.innerWidth <= 480) {
$("link[rel=stylesheet]").attr({ href: "@Url.Content("~/Content/jquery.mobile-1.0b1.min.css")" });
}
});
</script>
@RenderSection("JavaScriptAndCSS", required: false)
</head>
<body>
<div class="page" data-role="page">
<div id="header" data-role="header">
<div id="title">
<h1>My MVC Application</h1>
</div>
<div id="logindisplay" class="ui-bar">
@Html.Partial("_LogOnPartial")
[ @Html.ActionLink("English", "ChangeLanguage", "Home", new { language = "en" }, null) ]
[ @Html.ActionLink("Français", "ChangeLanguage", "Home", new { language = "fr" }, null) ]
</div>
<div id="menucontainer" class="ui-bar">
<ul id="menu">
<li>@Html.ActionLink("Home", "Index", "Home", null, new Dictionary<string, object> {{ "data-role", "button" }})</li>
<li>@Html.ActionLink("About", "About", "Home", null, new Dictionary<string, object> { { "data-role", "button" }})</li>
</ul>
</div>
</div>
<div id="main" data-role="content">
@RenderBody()
</div>
<div id="footer" data-role="footer">
</div>
</div>
</body>
</html>

主要的CSS文件和核心的JQuery文件被留下来了,因为css在每个也都需要,并且绝大多数网页也需要JQuery。然而新的JQuery文件和不唐突的AJAX不是每个页面都需要的。

现在,有两种方式使用Autocomplete 插件:

1.在javascript中设置要搜索的数据。

2.当用户输入时通过ajax检索。

在我使用这个插件的经验看来,我发现使用解决方案1时自动完成更快。因为它并不需要每次从数据库中请求数据。然而,使用这种解决方案的限制:只有这么多字符,可传递到function中,大量的JavaScript可能会导致用户的计算机上页面加载缓慢。经过一些试验和错误,我已经确定神奇的数字是大约40,000个结果。如果结果数量超过此,最好使用选项2;否则,始终坚持,因为搜索选项1是瞬时,而不是有轻微的延迟。

在这个例子中,将搜索书籍,我们没有超过40000,所以将使用选项1。BooksController现在必须更新,以设置ViewBag为book title。自动完成功能需要支持一个JavaScript数组的支持,所以书将管道(|)分开。然后在view中,书将被转换到一个数组,使用JavaScript的split()函数。当用户完成键入他们的结果,他们应该有选择完全匹配标题,因此这个函数将被更新。如果只有1本书返回并且用户执行了搜索,它会自动重定向到本书详细介绍页面。

我们要在bookcontroller 中更新Index Action 并添加一个私有方法名为:FormatBooksForAutocomplete。

代码如下:

using System;
using System.Collections.Generic;
using System.Data;
using System.Data.Entity;
using System.Linq;
using System.Linq.Dynamic;
using System.Web;
using System.Web.Mvc;
using MvcApplication.Models;
using MvcApplication.Utils;
using PagedList;
namespace MvcApplication.Controllers
{ 
public class BooksController : Controller
{
private BookDBContext db = new BookDBContext();
//
// GET: /Books/
[OutputCache(Duration = Int32.MaxValue, SqlDependency = "MvcApplication.Models.BookDBContext:books", VaryByParam = "sortOrder;filter;page")]
public ActionResult Index(string sortOrder, string filter, string Keyword, int page = 1)
{
#region ViewBag Resources
ViewBag.Title = Resources.Resource1.BookIndexTitle;
ViewBag.CreateLink = Resources.Resource1.CreateLink;
ViewBag.TitleDisplay = Resources.Resource1.TitleDisplay;
ViewBag.IsbnDisplay = Resources.Resource1.IsbnDisplay;
ViewBag.SummaryDisplay = Resources.Resource1.SummaryDisplay;
ViewBag.AuthorDisplay = Resources.Resource1.AuthorDisplay;
ViewBag.ThumbnailDisplay = Resources.Resource1.ThumbnailDisplay;
ViewBag.PriceDisplay = Resources.Resource1.PriceDisplay;
ViewBag.PublishedDisplay = Resources.Resource1.PublishedDisplay;
ViewBag.EditLink = Resources.Resource1.EditLink;
ViewBag.DetailsLink = Resources.Resource1.DetailsLink;
ViewBag.DeleteLink = Resources.Resource1.DeleteLink;
#endregion
#region ViewBag Sort Params
ViewBag.TitleSortParam = (sortOrder == "Title") ? "Title desc" : "Title";
ViewBag.IsbnSortParam = (sortOrder == "Isbn") ? "Isbn desc" : "Isbn";
ViewBag.AuthorSortParam = (sortOrder == "Author") ? "Author desc" : "Author";
ViewBag.PriceSortParam = (sortOrder == "Price") ? "Price desc" : "Price";
ViewBag.PublishedSortParam = (String.IsNullOrEmpty(sortOrder)) ? "Published desc" : "";
// Default the sort order
if (String.IsNullOrEmpty(sortOrder))
{
sortOrder = "Published desc";
}
ViewBag.CurrentSortOrder = sortOrder;
#endregion
var books = from b in db.Books select b;
#region Keyword Search
if (!String.IsNullOrEmpty(Keyword))
{
books = books.Where(b => b.Title.ToUpper().Contains(Keyword.ToUpper()) || b.Author.ToUpper().Contains(Keyword.ToUpper()));
// Should we redirect because of only one result?
if (books.Count() == 1)
{
Book book = books.First();
return RedirectToAction("Details", new { id = book.ID });
}
}
ViewBag.CurrentKeyword = String.IsNullOrEmpty(Keyword) ? "" : Keyword;
#endregion
#region Filter switch
switch (filter)
{
case "NewReleases":
var startDate = DateTime.Today.AddDays(-14);
books = books.Where(b => b.Published <= DateTime.Today.Date 
&& b.Published >= startDate
);
break;
case "ComingSoon":
books = books.Where(b => b.Published > DateTime.Today.Date);
break;
default:
// No filter needed
break;
}
ViewBag.CurrentFilter = String.IsNullOrEmpty(filter) ? "" : filter;
#endregion
books = books.OrderBy(sortOrder);
int maxRecords = 1;
int currentPage = page - 1;
// Get all book titles
ViewBag.BookTitles = FormatBooksForAutocomplete();
return View(books.ToPagedList(currentPage, maxRecords));
}
private string FormatBooksForAutocomplete()
{
string bookTitles = String.Empty;
var books = from b in db.Books select b;
foreach (Book book in books)
{
if (bookTitles.Length > 0)
{
bookTitles += "|";
}
bookTitles += book.Title;
}
return bookTitles;
}
//
// GET: /Books/Details/5
public ActionResult Details(int id = 0, string bookTitle = "")
{
Book book = db.Books.Find(id);
return View(book);
}
//
// GET: /Books/Create
public ActionResult Create()
{
return View();
} 
//
// POST: /Books/Create
[HttpPost]
public ActionResult Create(Book book, HttpPostedFileBase file)
{
if (ModelState.IsValid)
{
// Upload our file
book.Thumbnail = FileUpload.UploadFile(file);
db.Books.Add(book);
db.SaveChanges();
return RedirectToAction("Index"); 
}
return View(book);
}
//
// GET: /Books/Edit/5
public ActionResult Edit(int id)
{
Book book = db.Books.Find(id);
return View(book);
}
//
// POST: /Books/Edit/5
[HttpPost]
public ActionResult Edit(Book book, HttpPostedFileBase file)
{
if (ModelState.IsValid)
{
// Delete old file
FileUpload.DeleteFile(book.Thumbnail);
// Upload our file
book.Thumbnail = FileUpload.UploadFile(file);
db.Entry(book).State = EntityState.Modified;
db.SaveChanges();
return RedirectToAction("Index");
}
return View(book);
}
//
// GET: /Books/Delete/5
public ActionResult Delete(int id)
{
Book book = db.Books.Find(id);
return View(book);
}
//
// POST: /Books/Delete/5
[HttpPost, ActionName("Delete")]
public ActionResult DeleteConfirmed(int id)
{ 
Book book = db.Books.Find(id);
// Delete old file
FileUpload.DeleteFile(book.Thumbnail);
db.Books.Remove(book);
db.SaveChanges();
return RedirectToAction("Index");
}
protected override void Dispose(bool disposing)
{
db.Dispose();
base.Dispose(disposing);
}
}
}

最后book/index view需要更新去初始化jQuery的自动完成。要做的第一件事是使用@节标记,包括必要的JavaScript和CSS文件。接下来,以前创建的搜索文本框更新设置一个键的IDwordSearch。

最后,JavaScript代码添加在视图的底部去在搜索文本框上建立自动完成功能。此JavaScript是有意添加在view的底部,以确保完全呈现给用户,因为在用户的电脑上建立数据是一项工作,Javascript处理可能会“堵塞”页面加载。

(译者:先呈现数据再执行javascript,js不是像传统那样放在head标签里)

这取决于结果的数量。代码如下:

@model PagedList.IPagedList<MvcApplication.Models.Book>
@if (IsAjax)
{
Layout = null;
}
@section JavascriptAndCSS {
<link rel="stylesheet" href="@Url.Content(" rel="external nofollow" rel="external nofollow" ~/Content/jquery.autocomplete.css")" type="text/css" />
<script type="text/javascript" src="@Url.Content("~/Scripts/jquery.autocomplete.js")"></script>
<script src="@Url.Content("~/Scripts/jquery.unobtrusive-ajax.min.js")" type="text/javascript"></script>
}
<h2>@MvcApplication4.Resources.Resource1.BookIndexTitle</h2>
<p>
@Html.ActionLink("Create New", "Create")
</p>
<p>
Show:
@if (ViewBag.CurrentFilter != "")
{
@Ajax.ActionLink("All", "Index", new { sortOrder = ViewBag.CurrentSortOrder, Keyword = ViewBag.CurrentKeyword }, new AjaxOptions { UpdateTargetId = "main" })
}
else
{
@:All
}
  |  
@if (ViewBag.CurrentFilter != "NewReleases")
{
@Ajax.ActionLink("New Releases", "Index", new { filter = "NewReleases", sortOrder = ViewBag.CurrentSortOrder, Keyword = ViewBag.CurrentKeyword }, new AjaxOptions { UpdateTargetId = "main" })
}
else
{
@:New Releases
}
  |  
@if (ViewBag.CurrentFilter != "ComingSoon")
{
@Ajax.ActionLink("Coming Soon", "Index", new { filter = "ComingSoon", sortOrder = ViewBag.CurrentSortOrder, Keyword = ViewBag.CurrentKeyword }, new AjaxOptions { UpdateTargetId = "main" })
}
else
{
@:Coming Soon
}
</p>
@using (Html.BeginForm())
{
@:Search: @Html.TextBox("Keyword", (string)ViewBag.CurrentKeyword, new { id = "KeywordSearch" }) <input type="submit" value="Search" />
}
@Html.Partial("_Paging")
<table>
<tr>
<th>
@Ajax.ActionLink("Title", "Index", new { sortOrder = ViewBag.TitleSortParam, filter = ViewBag.CurrentFilter, Keyword = ViewBag.CurrentKeyword }, new AjaxOptions { UpdateTargetId = "main" })
</th>
<th>
@Ajax.ActionLink("Isbn", "Index", new { sortOrder = ViewBag.IsbnSortParam, filter = ViewBag.CurrentFilter, Keyword = ViewBag.CurrentKeyword }, new AjaxOptions { UpdateTargetId = "main" })
</th>
<th>
Summary
</th>
<th>
@Ajax.ActionLink("Author", "Index", new { sortOrder = ViewBag.AuthorSortParam, filter = ViewBag.CurrentFilter, Keyword = ViewBag.CurrentKeyword }, new AjaxOptions { UpdateTargetId = "main" })
</th>
<th>
Thumbnail
</th>
<th>
@Ajax.ActionLink("Price", "Index", new { sortOrder = ViewBag.PriceSortParam, filter = ViewBag.CurrentFilter, Keyword = ViewBag.CurrentKeyword }, new AjaxOptions { UpdateTargetId = "main" })
</th>
<th>
@Ajax.ActionLink("Published", "Index", new { sortOrder = ViewBag.PublishedSortParam, filter = ViewBag.CurrentFilter, Keyword = ViewBag.CurrentKeyword }, new AjaxOptions { UpdateTargetId = "main" })
</th>
<th></th>
</tr>
@foreach (var item in Model)
{
<tr>
<td>
@Html.DisplayFor(modelItem => item.Title)
</td>
<td>
@Html.DisplayFor(modelItem => item.Isbn)
</td>
<td>
@Html.DisplayFor(modelItem => item.Summary)
</td>
<td>
@Html.DisplayFor(modelItem => item.Author)
</td>
<td>
@Html.DisplayFor(modelItem => item.Thumbnail)
</td>
<td>
@Html.DisplayFor(modelItem => item.Price)
</td>
<td>
@Html.DisplayFor(modelItem => item.Published)
</td>
<td>
@Html.ActionLink("Edit", "Edit", new { id = item.ID }) |
@Html.ActionLink("Details", "Details", new { id = item.ID }) |
@Html.ActionLink("Delete", "Delete", new { id = item.ID })
</td>
</tr>
}
</table>
@Html.Partial("_Paging")
<script type="text/javascript">
$(document).ready(function () {
var data = "@ViewBag.BookTitles".split("|");
$("#KeywordSearch").autocomplete(data);
});
</script>

为了实施选项2,一个Ajax搜索,而不是传递数据数组到自动完成函数,您可以传递一个URL。URL将需要接受查询字符串变量:q。这包含用户输入的搜索值。这将用于执行书本上包含部分匹配的搜索,并返回以分隔符分隔的字符串。JQuery文档中含有较多的这样的成品例子,也有其他的例子,去更新的输出结果(可能包括书的封面的缩略图)。

以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持三水点靠木。

jQuery 相关文章推荐
jQuery导航条固定定位效果实例代码
May 26 jQuery
原生js jquery ajax请求以及jsonp的调用方法
Aug 04 jQuery
jQuery选择器之表单元素选择器详解
Sep 19 jQuery
jQuery EasyUI开发技巧总结
Sep 26 jQuery
jQuery实现切换隐藏与显示同时切换图标功能
Oct 29 jQuery
jquery自定义显示消息数量
Dec 19 jQuery
jQuery Validate插件ajax方式验证输入值的实例
Dec 21 jQuery
jQuery中each方法的使用详解
Mar 18 jQuery
利用jquery和BootStrap实现动态滚动条效果
Dec 03 jQuery
jquery实现动态改变css样式的方法分析
May 27 jQuery
JavaScript或jQuery 获取option value值方法解析
May 12 jQuery
jquery插件实现轮播图效果
Oct 19 jQuery
使用异步controller与jQuery实现卷帘式分页
Jun 18 #jQuery
使用jQuery mobile NuGet让你的网站在移动设备上同样精彩
Jun 18 #jQuery
如何使用CSS3和JQuery easing 插件制作绚丽菜单
Jun 18 #jQuery
如何用webpack4.0撸单页/多页脚手架 (jquery, react, vue, typescript)
Jun 18 #jQuery
通过JQuery,JQueryUI和Jsplumb实现拖拽模块
Jun 18 #jQuery
如何使用CSS3+JQuery实现悬浮墙式菜单
Jun 18 #jQuery
jquery中为什么能用$操作
Jun 18 #jQuery
You might like
别人整理的服务器变量:$_SERVER
2006/10/20 PHP
php trim 去除空字符的定义与语法介绍
2010/05/31 PHP
php自动获取字符串编码函数mb_detect_encoding
2011/05/31 PHP
php根据isbn书号查询amazon网站上的图书信息的示例
2014/02/13 PHP
PHP实现将浏览历史页面网址保存到cookie的方法
2015/01/26 PHP
Laravel 5.3 学习笔记之 配置
2016/08/28 PHP
如何通过View::first使用Laravel Blade的动态模板详解
2017/09/21 PHP
csdn 批量接受好友邀请
2009/02/19 Javascript
让GoogleCode的SVN下的HTML文件在FireFox下正常显示.
2009/05/25 Javascript
jQuery-Easyui 1.2 实现多层菜单效果的代码
2012/01/13 Javascript
JavaScript中:表达式和语句的区别[译]
2012/09/17 Javascript
重写javascript中window.confirm的行为
2012/10/21 Javascript
jquery中event对象属性与方法小结
2013/12/18 Javascript
jQuery实现二级下拉菜单效果
2016/01/05 Javascript
谈谈target=_new和_blank的不同之处
2016/10/25 Javascript
JavaScript中访问id对象 属性的方式访问属性(实例代码)
2016/10/28 Javascript
JQuery获取鼠标进入和离开容器的方向
2016/12/29 Javascript
微信小程序网络请求的封装与填坑之路
2017/04/01 Javascript
Vue Ajax跨域请求实例详解
2017/06/20 Javascript
layui的select联动实现代码
2019/09/28 Javascript
JavaScript switch语句使用方法简介
2019/12/30 Javascript
JS绘图Flot应用图形绘制异常解决方案
2020/10/16 Javascript
python解决汉字编码问题:Unicode Decode Error
2017/01/19 Python
Python面向对象实现一个对象调用另一个对象操作示例
2019/04/08 Python
Python定义一个函数的方法
2020/06/15 Python
Selenium之模拟登录铁路12306的示例代码
2020/07/31 Python
HTML5实现分享到微信好友朋友圈QQ好友QQ空间微博二维码功能
2018/01/03 HTML / CSS
学生党支部先进事迹
2014/02/04 职场文书
2014社区三八妇女节活动方案
2014/03/30 职场文书
个人租房协议书样本
2014/10/01 职场文书
英文产品推荐信
2015/03/27 职场文书
学校安全管理制度
2015/08/06 职场文书
关于食品安全的演讲稿范文(三篇)
2019/10/21 职场文书
SQLServer2019 数据库的基本使用之图形化界面操作的实现
2021/04/08 SQL Server
《帝国时代4》赛季预告 新增内容编译器可创造地图
2022/04/03 其他游戏
Python爬虫网络请求之代理服务器和动态Cookies
2022/04/12 Python