后台查询结果 PDFSearchResult实体类:
[DataContract(Name = "PDFSearchResult")] public class PDFSearchResult { public PDFSearchResult(string title, string fileUrl) { Title = title; FileUrl = fileUrl; } [DataMember(Name = "title")] public string Title { get; set; } [DataMember(Name = "fileUrl")] public string FileUrl { get; set; } }
另外,有一个PagedResult泛型类,PagedResult<T>
[DataContract(Name = "pagedCollection", Namespace = "")] public class PagedResult<T> { public PagedResult(long totalItems, long pageNumber, long pageSize); [DataMember(Name = "items")] public IEnumerable<T> Items { get; set; } [DataMember(Name = "pageNumber")] public long PageNumber { get; } [DataMember(Name = "pageSize")] public long PageSize { get; } [DataMember(Name = "totalItems")] public long TotalItems { get; } [DataMember(Name = "totalPages")] public long TotalPages { get; } // // Summary: // Calculates the skip size based on the paged parameters specified // // Remarks: // Returns 0 if the page number or page size is zero public int GetSkipSize(); }
后台,采用Web Api (/api/SearchApi/GetPDFSearchResults/), 返回值类型为 PagedResult<PDFSearchResult>, 是Json类型返回值
在页面表现UI层,有两个tab,左边的tab显示的是页面的搜索结果searchResult, 右边的tab显示的是pdf文件的搜索结果PDFSearchResult
页面SearchResult.cshtml如下:
<section id="searchListing" class="row search"> <div> <div class="tabs"> <ul class="tab"> <li data-ui="tab-nav"><a href="#">Web Page Results</a></li> <li data-ui="tab-nav"><a href="#">PDF Results</a></li> </ul> </div> <div class="tabContent"> <div id="resultsArea" class="search-results" style="display:block;" data-ui="tab-content"> <div id="NoResultsMessage" style="display:none;"> <p class="results-title">No Results For<strong class="search-term"></strong>'</p> </div> <div id="HasResultsMessage" style="display:none;"> <p class="results-title">Search Results For<strong class="search-term"></strong>'</p> </div> <div class="results" id="SearchResultsContainer"> <article class="row"> <a href="#"> <div> <h2></h2> <p></p> <p class="link">Read more</p> </div> </a> </article> </div> <ul class="pagination"> <li><a href="#" class="prev"><i class="gi icon-arrow"></i></a></li> <li class="page"><a href="#"></a></li> <li><a href="#" class="next"><i class="gi icon-arrow"></i></a></li> </ul> </div> <div id="PDFResultArea" class="search-results" style="display:none;" data-ui="tab-content"> <div id="NoPDFResultsMessage" style="display:none;"> <p class="results-title">No Results For<strong class="search-term"></strong>'</p> </div> <div id="HasPDFResultsMessage" style="display:none;"> <p class="results-title">Search Results For<strong class="search-term"></strong>'</p> </div> <div class="results" id="SearchPDFResultsContainer"> <article class="row"> <a href="#"> </a> </article> </div> <ul class="pagination"> <li><a href="#" class="prev"><i class="gi icon-arrow"></i></a></li> <li class="page"><a href="#"></a></li> <li><a href="#" class="next"><i class="gi icon-arrow"></i></a></li> </ul> </div> </div> </div> </section>
这里,在页面展示上,应该看上去如下图:
为了在同一个页面,也就是SearchResult.cshtml中实现这个tab功能,我用JQuery写了个tab功能,如下
tab.js
function tabs(state,control,show){ $(control + "> li").on(state, function(){ $(this).addClass("on").siblings().removeClass("on"); var index = $(this).index(); $(show + "> div").eq(index).show().siblings().hide(); }) $(control + "> li").eq(0).attr("class", "on"); $(show + "> div").eq(0).show(); } tabs("click", ".tab", ".tabContent");
The css style 如下
.tabs { position: relative; margin-top: 60px; margin-bottom: 20px; } .tabs > ul { list-style: none; border-bottom: 1px solid #c0c0c0; margin-top: 0; padding: 0; } .tabs > ul > li { float: left; margin-bottom: -1px; } [dir="rtl"] .tabs > ul > li { float: right; } .tabs > ul > li a { display: block; line-height: 2; margin-right: .2rem; padding: 0 1rem; border: 1px solid transparent; text-decoration: none; cursor: pointer; } [dir="rtl"] .tabs > ul > li a { margin-right: 0; margin-left: .2rem; } .tabs > ul > li a:hover { background: #fff !important; border: 1px solid #fff !important; color: #ff7900; } .tabs > ul > li > [aria-selected="true"], .tabs > ul > li > [aria-selected="true"]:hover { background: red !important; } .tabs > ul li.on { background-color: #fff; border: 1px solid #c0c0c0; border-bottom-color: transparent; color: #454545; cursor: default; } .tabs > ul li.on a { color: #ff7900; } .tabs > * { display: none; } .tabs > ul, .tabs [tabIndex="0"] { display: block; }
然后,我写了一个Jquery Plugin来实现PDFSearchResult的展示功能,也就是说JSON结果,展示到SearchResult.cshtml页面上
在这个Jquery plugin中,调用ajax来调用web api (/api/SearchApi/GetPDFSearchResults/),返回json结果,展现到web页面上
view.pdfsearch.js
(function ($) { $.fn.PDFSearch = function (options) { return this.each(function () { var pdfSearch = $(this); pdfSearch.pdfResultArea = pdfSearch.find("#PDFResultArea"); pdfSearch.noPDFResultMessage = pdfSearch.pdfResultArea.find("#NoPDFResultsMessage"); pdfSearch.hasPDFResultMessage = pdfSearch.pdfResultArea.find("#HasPDFResultsMessage"); pdfSearch.PDFResultContainer = pdfSearch.pdfResultArea.find("#SearchPDFResultsContainer"); pdfSearch.searchPDFResultTemplate = pdfSearch.PDFResultContainer.find("article").clone(); pdfSearch.queryField = $("input[name='search']"); pdfSearch.searchTermLabel = $(".search-term"); pdfSearch.oldTerm = undefined; pdfSearch.term = pdfSearch.queryField.val(); //Paging elements pdfSearch.paginationWrapper = pdfSearch.pdfResultArea.find('ul.pagination'); pdfSearch.pageTemplate = pdfSearch.paginationWrapper.find('.page').clone(); pdfSearch.pagePrevious = pdfSearch.paginationWrapper.find('.prev'); pdfSearch.pageNext = pdfSearch.paginationWrapper.find('.next'); // Page tracking pdfSearch.pageSize = 10; pdfSearch.pageNumber = 1; pdfSearch.totalPages = 0; // Sets up pagination for search results. pdfSearch.paginate = function (data) { pdfSearch.totalPages = data.totalPages; pdfSearch.paginationWrapper.find('.page').remove(); if (pdfSearch.totalPages > 1) { pdfSearch.pagePrevious.toggle(data.pageNumber > 1); pdfSearch.pageNext.toggle(data.pageNumber < pdfSearch.totalPages); for (i = 1; i < pdfSearch.totalPages + 1; i++) { var page = pdfSearch.pageTemplate.clone(); var link = page.find('a'); if (i == data.pageNumber) page.addClass('active'); page.data('page', i); link.text(i); pdfSearch.pageNext.parent().before(page).before(' '); } pdfSearch.paginationWrapper.show(0); } else { pdfSearch.paginationWrapper.hide(0); } } pdfSearch.previous = function (evt) { return pdfSearch.goToPage(evt, pdfSearch.pageNumber - 1); } pdfSearch.next = function (evt) { return pdfSearch.goToPage(evt, pdfSearch.pageNumber + 1); } pdfSearch.goToPage = function (evt, pageNumber) { pdfSearch.pageNumber = pageNumber || $(this).data('page'); if (pdfSearch.pageNumber > pdfSearch.totalPages) pdfSearch.pageNumber = pdfSearch.totalPages - 1; if (pdfSearch.pageNumber < 1) pdfSearch.pageNumber = 1; pdfSearch.searchPDF(); return false; } // filter change handler pdfSearch.handleQuery = function (evt) { pdfSearch.term = $(this).val(); if (pdfSearch.oldTerm != pdfSearch.term) { pdfSearch.oldTerm = pdfSearch.term; pdfSearch.searchPDF(); } return false; } pdfSearch.searchPDF = function () { pdfSearch.pdfResultArea.addClass("loading"); $.ajax({ type: "GET", url: "/umbraco/api/SearchApi/GetPDFSearchResults/", dataType: "json", data: { filter: pdfSearch.term, pageNumber: pdfSearch.pageNumber, pageSize: pdfSearch.pageSize }, success: function (data) { pdfSearch.searchTermLabel.text(pdfSearch.term); pdfSearch.noPDFResultMessage.hide(); pdfSearch.hasPDFResultMessage.hide(); pdfSearch.paginate(data); pdfSearch.PDFResultContainer.empty(); if (!data.items || data.items.length == 0) { pdfSearch.noPDFResultMessage.show(); } else { // Binding search result to UI for (var i = 0; i < data.items.length; i++) { var pdfResult = data.items[i]; var PdfResultTemplate = pdfSearch.searchPDFResultTemplate.clone(); _populatePDFContent(pdfResult, PdfResultTemplate); pdfSearch.PDFResultContainer.append(PdfResultTemplate); } pdfSearch.hasPDFResultMessage.show(); } }, complete: function () { pdfSearch.searchTermLabel.text(pdfSearch.term); pdfSearch.pdfResultArea.removeClass("loading"); } }); }; _populatePDFContent = function (result, template) { var pdfLinkElem = $(template.find("a")); pdfLinkElem.attr("href", result.fileUrl); pdfLinkElem.attr("target", "_blank"); pdfLinkElem.html(result.title); }; pdfSearch.queryField.on("keyup", pdfSearch.handleQuery); // Setup pagination triggers. pdfSearch.pagePrevious.on("click", pdfSearch.previous); pdfSearch.pageNext.on("click", pdfSearch.next); // Bind to all future page clicks. pdfSearch.paginationWrapper.on('click', 'li.page', pdfSearch.goToPage); pdfSearch.searchPDF(); }); } }(jQuery)); $(function () { $('section.search').PDFSearch(); });