Last active
February 17, 2016 15:10
-
-
Save bland-industries/5c08b0637901fc08e52e to your computer and use it in GitHub Desktop.
Built this search function with auto complete from ajax. Somewhat specific to my needs but can be adapted to others. The server site is up to you.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
<input type="text" id="searchBox" style="width:300px" class="input-xlarge" /> | |
<div id='resultContainer'></div> | |
<script type="text/javascript" scr='/search.js'></script> | |
<script type="text/javascript"> | |
FundSearch.Presenter.create('#searchBox', '#resultContainer', '/search.php'); | |
</script> |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
var Observer = { | |
add: function (obj) { | |
var eventBroker = {}; | |
obj.bind = function bind(eventName, handler) { | |
if (eventName in eventBroker) { | |
eventBroker[eventName].push(handler); | |
} else { | |
eventBroker[eventName] = []; | |
eventBroker[eventName].push(handler); | |
} | |
}; | |
obj.trigger = function trigger(eventName) { | |
var args = Array.prototype.slice.call(arguments, 1); | |
for (var i = 0; i < eventBroker[eventName].length; i++) { | |
eventBroker[eventName][i].apply(this, args); | |
} | |
}; | |
obj.unbind = function unbind(eventName, handler) { | |
if (eventBroker[eventName] !== undefined) { | |
var handlerIndex = eventBroker[eventName].indexOf(handler); | |
if (handlerIndex > -1) { | |
eventBroker[eventName].splice(handlerIndex, 1); | |
} | |
} | |
}; | |
return obj; | |
} | |
}; | |
var FundSearch = {}; | |
FundSearch.View = { | |
create: function (searchBoxSel, resultContainerSel) { | |
var view = Observer.add({}); | |
searchBox = $(searchBoxSel); | |
resultContainer = $(resultContainerSel); | |
view.getSearchTerm = function() { | |
return searchBox.val(); | |
} | |
function moveHighlight(selected, newSelected, contingency) { | |
if (selected.length) { | |
selected.toggleClass("js_selectedSearch"); | |
if (newSelected.length) { | |
newSelected.toggleClass("js_selectedSearch"); | |
} else { | |
resultContainer.find("ul a:" + contingency).addClass("js_selectedSearch"); | |
} | |
} else { | |
resultContainer.find("ul a:" + contingency).addClass("js_selectedSearch"); | |
} | |
} | |
view.highlightNextSearch = function() { | |
selected = resultContainer.find(".js_selectedSearch"); | |
newSelected = selected.next(); | |
contingency = "first-child"; | |
moveHighlight(selected, newSelected, contingency); | |
} | |
view.highlightPrevSearch = function() { | |
selected = resultContainer.find(".js_selectedSearch"); | |
newSelected = selected.prev(); | |
contingency = "last-child"; | |
moveHighlight(selected, newSelected, contingency); | |
} | |
view.clickSearchLink = function () { | |
selected = resultContainer.find(".js_selectedSearch"); | |
if (!selected.length) { | |
selected = resultContainer.find("ul a:first-child"); | |
} | |
if (selected.length) { | |
selected[0].click(); | |
} | |
} | |
searchBox.keyup(function (e) { | |
if (e.keyCode != 38 && e.keyCode != 40 && e.keyCode != 13) { | |
view.trigger('searchBoxKeyUp'); | |
} | |
e.preventDefault(); // prevent the default action (scroll / move caret) | |
}); | |
$(document).keydown(function(e) { | |
switch(e.which) { | |
case 38: // up | |
view.trigger('arrowUpKeyUp'); | |
searchBox.blur(); | |
break; | |
case 40: // down | |
view.trigger('arrowDownKeyUp'); | |
searchBox.blur(); | |
break; | |
case 13: //enter | |
view.trigger('enterKeyUp'); | |
break; | |
default: return; // exit this handler for other keys | |
} | |
e.preventDefault(); // prevent the default action (scroll / move caret) | |
}); | |
// This is where the list is being built. This will change as the designer needs to change things. | |
view.updateSearchResults = function (results) { | |
string = "SearchTerm: " + results.searchTerm + "<br>"; | |
string += "<ul>"; | |
for (var i = 0; i < results.results.length; i++) { | |
string += "<a href='/fund/" + results.results[i].id + "'>" | |
string += "<li>" | |
string += ": " + results.results[i].firm; | |
string += ": " + results.results[i].name; | |
if (results.results[i].tickers.charAt(0) != ",") { | |
string += ": " +results.results[i].tickers; | |
} | |
string += "</li></a>"; | |
}; | |
string += "</ul>"; | |
resultContainer.html(string); | |
} | |
return view; | |
} | |
}; | |
FundSearch.Presenter = { | |
create: function (searchBoxSel, resultContainerSel, theURL) { | |
var presenter = {}; | |
var model = FundSearch.Model.create(theURL); | |
var view = FundSearch.View.create(searchBoxSel, resultContainerSel); | |
waiting = false; | |
function makeSearching () { | |
searchTerm = view.getSearchTerm(); | |
if (searchTerm.length >= 3) { | |
model.newSearch(searchTerm); | |
} | |
waiting = false; | |
} | |
function updateSearchResults(results) { | |
currentSearchTerm = view.getSearchTerm(); | |
if (currentSearchTerm == results.searchTerm) { | |
view.updateSearchResults(results); | |
} | |
} | |
// user types into the search box | |
view.bind('searchBoxKeyUp', function(){ | |
if (!waiting) { | |
waiting = true; | |
setTimeout(makeSearching, 250); | |
} | |
}) | |
// user presses the up arrow key | |
view.bind('arrowUpKeyUp', function(){ | |
if (!waiting) { | |
view.highlightPrevSearch(); | |
} | |
}) | |
// user presses the down arrow key | |
view.bind('arrowDownKeyUp', function(){ | |
if (!waiting) { | |
view.highlightNextSearch(); | |
} | |
}) | |
// user presses the enter key | |
view.bind('enterKeyUp', function(){ | |
if (!waiting) { | |
view.clickSearchLink(); | |
} | |
}) | |
// And the results are in boys and girls. | |
model.bind('resultsIn', function (results){ | |
view.updateSearchResults(results); | |
}) | |
} | |
}; | |
FundSearch.Model = { | |
create: function (theURL) { | |
var model = Observer.add({}); | |
// cache the search results | |
searchList = {}; | |
model.newSearch = function (searchTerm) { | |
if (!(searchTerm in searchList)) { | |
data = {"searchTerm": searchTerm}; | |
$.ajax ({ | |
url: theURL, | |
type: "POST", | |
dataType: "json", | |
data: data, | |
success: successFunc, | |
error: errorFunction, | |
}); | |
} else { | |
// return cached data | |
successFunc(searchList[searchTerm]); | |
} | |
}; | |
function successFunc (result) { | |
// Currently does not inform user of success of form submission | |
searchList[result.searchTerm] = result; | |
model.trigger('resultsIn', result); | |
} | |
function errorFunction (xhr, status, strErr) { | |
// Currently does not inform user of failure of form submission | |
// console.log("fail"); | |
} | |
return model; | |
} | |
}; |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment