当前位置: 移动技术网 > IT编程>开发语言>JavaScript > 使用JQuery自动完成插件Auto Complete详解

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

2019年07月18日  | 移动技术网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(" 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文档中含有较多的这样的成品例子,也有其他的例子,去更新的输出结果(可能包括书的封面的缩略图)。

以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持移动技术网。

如对本文有疑问, 点击进行留言回复!!

相关文章:

验证码:
移动技术网