Skip to content

Instantly share code, notes, and snippets.

Embed
What would you like to do?
Zipline: Build a Wikipedia Viewer
<div class="container">
<!-- Search Form -->
<div class="search-field-container">
<input class="form-control" type="text" value="" placeholder="Search" />
<ul id="search-suggestion"></ul>
</div>
<!-- /Search Form -->
<!-- Search Results -->
<div class="search-results-container"></div>
<!-- /Search Results -->
<div class="bg-img"></div>
</div>
<script type="text/template" id="search-suggestion-content">
<li>
<a href="#">
<%= searchItemName %>
</a>
</li>
</script>
<script type="text/template" id="search-results-content">
<a href="<%= searchItemLink %>" target="_blank" class="content-item">
<h4><%= searchItemName %></h4>
<p><%= searchItemDesc %></p>
</a>
</script>
/*
User Story: As a user, I can search Wikipedia entries in a search box and see the resulting Wikipedia entries.
Bonus User Story:As a user, I can click a button to see a random Wikipedia entry.
Bonus User Story:As a user, when I type in the search box, I can see a dropdown menu with autocomplete options for matching Wikipedia entries.
Hint: Here's an entry on using Wikipedia's API: http://www.mediawiki.org/wiki/API:Main_page
sample: http://codepen.io/GeoffStorbeck/full/MwgQea
open search wiki data: https://en.wikipedia.org/w/api.php?action=help&modules=opensearch
*/
var url = 'https://en.wikipedia.org/w/api.php?action=opensearch&format=json&search=&callback=jsonpcallback';
var searchVal = '',
enterKeyFlag = false;
var dropDownSuggestion = $('#search-suggestion'),
searchItemsContainer = $('.search-results-container'),
dropDownTpl = _.template($('#search-suggestion-content').html()),
searchItemsTpl = _.template($('#search-results-content').html());
// MODEL
var wikiModel = {
items: []
}
var callWikiAPI = function(searchVal) {
$.ajax({
url: url,
dataType: 'jsonp',
jsonpCallback: 'jsonpcallback',
data: $.param({
search: searchVal
}),
success: function(data) {
searchItemsContainer.html('');
dropDownSuggestion.html(''); // clear DOM display
wikiModel.items = []; // clear model array as well
for (i = 0; i < data[1].length; i++) {
var dataTpl = {
searchItemName: data[1][i],
searchItemLink: data[3][i],
searchItemDesc: data[2][i]
}
wikiModel.items.push(dataTpl);
}
}
});
}
// OBSERVER
var observer = function(changes) {
changes.forEach(function(v, i) {
// binds model to view
displayEntries(v.object.items);
});
}
Object.observe(wikiModel, observer);
// VIEWS
var displayEntries = function(v) {
v.forEach(function(d) {
dropDownSuggestion.append(dropDownTpl(d));
});
if (enterKeyFlag) {
v.forEach(function(d, i) {
searchItemsContainer.append(searchItemsTpl(d));
// after populating container with search results,
// set enterKeyFlag back to false when last item is loaded
if (i === 9) enterKeyFlag = false;
});
}
}
// EVENTS
var weatherMeView = {
dropDownCntr: 0,
searchWiki: function() { // search field - get input and store in searchVal
var tt = this;
$('input').bind('input', function(v) {
// basic search features
searchVal = '';
searchVal += v.target.value;
callWikiAPI(searchVal);
// end - basic search features
// dropdown search suggestion
dropDownSuggestion.show();
if (searchVal === '') tt.dropDownCntr = 0;
// end - dropdown search suggestion
});
},
loadSearchItems: function() { // Enter key - callwiki api when done typing in input
var tt = this;
$('body').keydown(function(e) {
if (e.keyCode === 13) {
// basic search features
enterKeyFlag = true;
callWikiAPI(searchVal);
// end - basic search features
// dropdown search suggestion
$('input')[0].value = searchVal;
dropDownSuggestion.hide();
tt.dropDownCntr = 0;
// end - dropdown search suggestion
}
});
},
navigateSuggestions: function() { // Arrow Up and Down Keys - suggestion box below search field
var tt = this;
$('body').keydown(function(v) {
var sl = dropDownSuggestion[0].children;
if (v.keyCode === 40) { // when Down key is pressed
/* NOTE:
* find a way to catch this error
* Uncaught TypeError: Cannot read property 'className' of undefined
*/
if (sl[tt.dropDownCntr].className === undefined) {
console.log('this is the end');
} else {
if (sl[tt.dropDownCntr-1] !== undefined) sl[tt.dropDownCntr-1].className = ''; // removed highlight on prev
sl[tt.dropDownCntr].className = 'selected'; // add highlight on current
searchVal = sl[tt.dropDownCntr].innerText; // get text and update searchVal
tt.dropDownCntr++;
}
}
if (v.keyCode === 38) { // when Up key is pressed
if (sl[tt.dropDownCntr-1].className === undefined) {
console.log('theres no items');
} else {
tt.dropDownCntr--;
sl[tt.dropDownCntr].className = '';
sl[tt.dropDownCntr-1].className = 'selected';
searchVal = sl[tt.dropDownCntr-1].innerText;
}
}
});
}
}
$(function() {
weatherMeView.searchWiki();
weatherMeView.loadSearchItems();
weatherMeView.navigateSuggestions();
});
<script src="//cdnjs.cloudflare.com/ajax/libs/jquery/2.1.3/jquery.min.js"></script>
<script src="//cdnjs.cloudflare.com/ajax/libs/underscore.js/1.8.2/underscore-min.js"></script>
.container
.bg-img
background: url('https://upload.wikimedia.org/wikipedia/commons/5/53/Wikipedia-logo-en-big.png')
height: 100%
width: 100%
background-size: 80%
opacity: 0.2
background-repeat: no-repeat
background-position: top center
background-attachment: fixed
position: absolute
top: 0
z-index: -1
.search-field-container
//z-index: 2
margin: 2em 0
position: relative
input
width: 100%
#search-suggestion
list-style: none
padding: 0 10px
position: absolute
top: 2.4em
width: 100%
li
background: #f2f2f2
a
width: 100%
display: inline-block
padding: 7px 1em
&.selected
border: 1px solid lightblue
background: #d6d6d6
.search-results-container
.content-item
display: block
margin-bottom: 2em
&:hover
text-decoration: none
<link href="//maxcdn.bootstrapcdn.com/bootstrap/3.3.5/css/bootstrap.min.css" rel="stylesheet" />
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment