JQuery自动完成插件Auto Complete(译)[亲测有效]

JQuery自动完成插件Auto Complete(译)[亲测有效]问题当你查找一些特殊的东西,问题当你查找一些特殊的东西,当你输入准确的词时,找到它可能是困难的。解决方案使用JQuery自动完成插件,更新现有图

欢迎大家来到IT世界,在知识的湖畔探索吧!

问题

当你查找一些特殊的东西,问题

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

解决方案

使用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("~/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>

欢迎大家来到IT世界,在知识的湖畔探索吧!

主要的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。

代码如下:

欢迎大家来到IT世界,在知识的湖畔探索吧!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("~/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基本库一样自动包含在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()。

欢迎大家来到IT世界,在知识的湖畔探索吧!<!DOCTYPE html>
<html>
<head>
 <title>_Mobile</title>
 <link href="@Url.Content("~/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("~/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自动完成插件Auto Complete(译)[亲测有效]

免责声明:本站所有文章内容,图片,视频等均是来源于用户投稿和互联网及文摘转载整编而成,不代表本站观点,不承担相关法律责任。其著作权各归其原作者或其出版社所有。如发现本站有涉嫌抄袭侵权/违法违规的内容,侵犯到您的权益,请在线联系站长,一经查实,本站将立刻删除。 本文来自网络,若有侵权,请联系删除,如若转载,请注明出处:https://itzsg.com/18195.html

(0)

相关推荐

发表回复

您的邮箱地址不会被公开。 必填项已用 * 标注

联系我们YX

mu99908888

在线咨询: 微信交谈

邮件:itzsgw@126.com

工作时间:时刻准备着!

关注微信