Skip to content

Commit fa763e8

Browse files
authored
Create search.js
from 1a9d33e
1 parent a2a4601 commit fa763e8

File tree

1 file changed

+240
-0
lines changed

1 file changed

+240
-0
lines changed

src/search.js

Lines changed: 240 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,240 @@
1+
/**
2+
* A simple JSON search
3+
* Requires jQuery (v 1.7+)
4+
*
5+
* @author Mat Hayward - Erskine Design
6+
* @author Rishikesh Darandale <Rishikesh.Darandale@gmail.com>
7+
* @version 1.1
8+
*/
9+
10+
/* ==========================================================================
11+
Initialisation
12+
========================================================================== */
13+
14+
var q, jsonFeedUrl = '/feeds/feed.json',
15+
$searchForm = $('[data-search-form]'),
16+
$searchInput = $('[data-search-input]'),
17+
$resultTemplate = $('#search-result'),
18+
$resultsPlaceholder = $('[data-search-results]'),
19+
$foundContainer = $('[data-search-found]'),
20+
$foundTerm = $('[data-search-found-term]'),
21+
$foundCount = $('[data-search-found-count]'),
22+
allowEmpty = true,
23+
showLoader = true,
24+
loadingClass = 'is--loading',
25+
indexVar;
26+
27+
28+
$(document).ready( function() {
29+
// hide items found string
30+
$foundContainer.hide();
31+
// initiate search functionality
32+
initSearch();
33+
});
34+
35+
/* ==========================================================================
36+
Search functions
37+
========================================================================== */
38+
39+
/**
40+
* Initiate search functionality.
41+
* Shows results based on querystring if present.
42+
* Binds search function to form submission.
43+
*/
44+
function initSearch() {
45+
if(!sessionStorage.getItem('lunrIndex')) {
46+
// get the data
47+
getData();
48+
} else {
49+
// Get search results if q parameter is set in querystring
50+
if (getParameterByName('q')) {
51+
q = decodeURIComponent(getParameterByName('q'));
52+
$searchInput.val(q);
53+
execSearch(q);
54+
}
55+
}
56+
57+
// Get search results on submission of form
58+
$(document).on('submit', $searchForm, function(e) {
59+
e.preventDefault();
60+
q = $searchInput.val();
61+
execSearch(q);
62+
});
63+
}
64+
65+
/**
66+
* Get the JSON data
67+
* Get the generated feeds/feed.json file so lunr.js can search it locally.
68+
* Store the index in sessionStorage
69+
*/
70+
function getData(indexVar) {
71+
jqxhr = $.getJSON(jsonFeedUrl)
72+
.done(function(loaded_data){
73+
// save the actual data as well
74+
sessionStorage.setItem('actualData', JSON.stringify(loaded_data));
75+
// set the index fields
76+
indexVar = lunr(function () {
77+
this.field('id');
78+
this.field('title');
79+
this.field('content', { boost: 10 });
80+
this.field('author');
81+
loaded_data.forEach(function (doc, index) {
82+
if ( doc.search_omit != 'true' ) {
83+
// console.log('adding to index: ' + doc.title);
84+
this.add($.extend({ 'id': index }, doc));
85+
}
86+
}, this)
87+
});
88+
// store the index in sessionStorage
89+
sessionStorage.setItem('lunrIndex', JSON.stringify(indexVar));
90+
// Get search results if q parameter is set in querystring
91+
if (getParameterByName('q')) {
92+
q = decodeURIComponent(getParameterByName('q'));
93+
$searchInput.val(q);
94+
execSearch(q);
95+
}
96+
})
97+
.fail( function() {
98+
console.log('get json failed…');
99+
})
100+
.always( function() {
101+
console.log('finally…');
102+
});
103+
}
104+
105+
/**
106+
* Get the search result from lunr
107+
* @param {String} q
108+
* @returns search results
109+
*/
110+
function getResults(q) {
111+
var savedIndexData = JSON.parse(sessionStorage.getItem('lunrIndex'));
112+
// console.log('Indexed var from sessionStorage: ' + savedIndexData);
113+
return lunr.Index.load(savedIndexData).search(q);
114+
}
115+
116+
/**
117+
* Executes search
118+
* @param {String} q
119+
* @return null
120+
*/
121+
function execSearch(q) {
122+
if (q != '' || allowEmpty) {
123+
if (showLoader) {
124+
toggleLoadingClass();
125+
}
126+
processResultData(getResults(q));
127+
}
128+
}
129+
130+
/**
131+
* Toggles loading class on results and found string
132+
* @return null
133+
*/
134+
function toggleLoadingClass() {
135+
$resultsPlaceholder.toggleClass(loadingClass);
136+
$foundContainer.toggleClass(loadingClass);
137+
}
138+
139+
/**
140+
* Process search result data
141+
* @return null
142+
*/
143+
function processResultData(searchResults) {
144+
$results = [];
145+
146+
// console.log('Search Results: ' + searchResults);
147+
var resultsCount = 0,
148+
results = '';
149+
150+
// Iterate over the results
151+
searchResults.forEach(function(result) {
152+
var loaded_data = JSON.parse(sessionStorage.getItem('actualData'));
153+
var item = loaded_data[result.ref];
154+
var result = populateResultContent($resultTemplate.html(), item);
155+
resultsCount++;
156+
results += result;
157+
});
158+
159+
160+
if (showLoader) {
161+
toggleLoadingClass();
162+
}
163+
164+
populateResultsString(resultsCount);
165+
showSearchResults(results);
166+
}
167+
168+
/**
169+
* Add search results to placeholder
170+
* @param {String} results
171+
* @return null
172+
*/
173+
function showSearchResults(results) {
174+
// Add results HTML to placeholder
175+
$resultsPlaceholder.html(results);
176+
}
177+
178+
/**
179+
* Add results content to item template
180+
* @param {String} html
181+
* @param {object} item
182+
* @return {String} Populated HTML
183+
*/
184+
function populateResultContent(html, item) {
185+
html = injectContent(html, item.title, '##Title##');
186+
html = injectContent(html, item.link, '##Url##');
187+
if (item.excerpt) {
188+
html = injectContent(html, item.excerpt, '##Excerpt##');
189+
} else {
190+
html = injectContent(html, '', '##Excerpt##');
191+
}
192+
if (item.date) {
193+
html = injectContent(html, item.date, '##Date##');
194+
} else {
195+
html = injectContent(html, '', '##Date##');
196+
}
197+
return html;
198+
}
199+
200+
/**
201+
* Populates results string
202+
* @param {String} count
203+
* @return null
204+
*/
205+
function populateResultsString(count) {
206+
if (typeof window.history.replaceState == 'function') {
207+
history.replaceState({}, '', '?q='+encodeURIComponent(q));
208+
}
209+
210+
$foundTerm.text(q);
211+
$foundCount.text(count);
212+
$foundContainer.show();
213+
}
214+
215+
/* ==========================================================================
216+
Helper functions
217+
========================================================================== */
218+
219+
220+
/**
221+
* Gets query string parameter - taken from http://stackoverflow.com/questions/901115/how-can-i-get-query-string-values-in-javascript
222+
* @param {String} name
223+
* @return {String} parameter value
224+
*/
225+
function getParameterByName(name) {
226+
var match = RegExp('[?&]' + name + '=([^&]*)').exec(window.location.search);
227+
return match && decodeURIComponent(match[1].replace(/\+/g, ' '));
228+
}
229+
230+
/**
231+
* Injects content into template using placeholder
232+
* @param {String} originalContent
233+
* @param {String} injection
234+
* @param {String} placeholder
235+
* @return {String} injected content
236+
*/
237+
function injectContent(originalContent, injection, placeholder) {
238+
var regex = new RegExp(placeholder, 'g');
239+
return originalContent.replace(regex, injection);
240+
}

0 commit comments

Comments
 (0)