使用JQuery自动完成插件Auto Complete详解
这篇文章主要介绍了使用JQuery自动完成插件Auto Complete详解,使用JQuery自动完成插件,更新现有图书列表页面上的搜索,当用户键入的时候立即显示结果。,需要的朋友可以参考下
问题 当你查找一些特殊的东西,当你输入准确的词时,找到它可能是困难的(或者很耗时)。在输入的时候展示出结果(自动完成),使查找变得更简单。 解决方案 使用JQuery自动完成插件,更新现有图书列表页面上的搜索,当用户键入的时候立即显示结果。 讨论 自动完成插件是不会象jQuery基本库一样自动包含在MVC项目中的,所以需要做的第一件事就是的是下载插件 这个配方也将介绍在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 data-role="page" div id="header" data-role="header" div id="title" h1 My MVC Application /h1 /div div id="logindisplay" @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" 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不是每个页面都需要的。 plete 插件: 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 plete。 代码如下: 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 = plete(); return View(books.ToPagedList(currentPage, maxRecords)); private plete() 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的自动完成。。接下来,以前创建的搜索文本框更新设置一个键的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/plete.css")" type="text/css" / script type="text/javascript" src="@Url.Content("~/Scripts/plete.js")" /script script src="@Url.Content("~/Scripts/jquery.unobtrusive-ajax.min.js")" type="text/javascript" /script h2 @MvcApplication4.Resources.Resource1.BookIndexTitle /h2 @Html.ActionLink("Create New", "Create") Show: @if (ViewBag.CurrentFilter != "") @Ajax.ActionLink("All", "Index", new { sortOrder = ViewBag.CurrentSortOrder, Keyword = ViewBag.CurrentKeyword }, new AjaxOptions { UpdateTargetId = "main" }) @:All nbsp; | nbsp; @if (ViewBag.CurrentFilter != "NewReleases") @Ajax.ActionLink("New Releases", "Index", new { filter = "NewReleases", sortOrder = ViewBag.CurrentSortOrder, Keyword = ViewBag.CurrentKeyword }, new AjaxOptions { UpdateTargetId = "main" }) @:New Releases nbsp; | nbsp; @if (ViewBag.CurrentFilter != "ComingSoon") @Ajax.ActionLink("Coming Soon", "Index", new { filter = "ComingSoon", sortOrder = ViewBag.CurrentSortOrder, Keyword = ViewBag.CurrentKeyword }, new AjaxOptions { UpdateTargetId = "main" }) @:Coming Soon @using (Html.BeginForm()) @:Search: @Html.TextBox("Keyword", (string)ViewBag.CurrentKeyword, new { id = "KeywordSearch" }) input type="submit" value="Search" / @Html.Partial("_Paging") table @Ajax.ActionLink("Title", "Index", new { sortOrder = ViewBag.TitleSortParam, filter = ViewBag.CurrentFilter, Keyword = ViewBag.CurrentKeyword }, new AjaxOptions { UpdateTargetId = "main" }) /th @Ajax.ActionLink("Isbn", "Index", new { sortOrder = ViewBag.IsbnSortParam, filter = ViewBag.CurrentFilter, Keyword = ViewBag.CurrentKeyword }, new AjaxOptions { UpdateTargetId = "main" }) /th Summary /th @Ajax.ActionLink("Author", "Index", new { sortOrder = ViewBag.AuthorSortParam, filter = ViewBag.CurrentFilter, Keyword = ViewBag.CurrentKeyword }, new AjaxOptions { UpdateTargetId = "main" }) /th Thumbnail /th @Ajax.ActionLink("Price", "Index", new { sortOrder = ViewBag.PriceSortParam, filter = ViewBag.CurrentFilter, Keyword = ViewBag.CurrentKeyword }, new AjaxOptions { UpdateTargetId = "main" }) /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) @Html.DisplayFor(modelItem = item.Title) /td @Html.DisplayFor(modelItem = item.Isbn) /td @Html.DisplayFor(modelItem = item.Summary) /td @Html.DisplayFor(modelItem = item.Author) /td @Html.DisplayFor(modelItem = item.Thumbnail) /td @Html.DisplayFor(modelItem = item.Price) /td @Html.DisplayFor(modelItem = item.Published) /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").plete(data); /script 为了实施选项2,一个Ajax搜索,而不是传递数据数组到自动完成函数,您可以传递一个URL。URL将需要接受查询字符串变量:q。这包含用户输入的搜索值。这将用于执行书本上包含部分匹配的搜索,并返回以分隔符分隔的字符串。JQuery文档中含有较多的这样的成品例子,也有其他的例子,去更新的输出结果(可能包括书的封面的缩略图)。 以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持凡科。 |