-
Notifications
You must be signed in to change notification settings - Fork 0
/
index.js
110 lines (92 loc) · 3.04 KB
/
index.js
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
/**
* Libararies
*/
var Rx = require('rx');
var $ = require('jQuery');
var resultsStore = require('./movies');
var pagination = require('./src/pagination');
var searchUtils = require('./src/search');
/**
* Pagination
*/
var search = searchUtils.search;
var tokenize = searchUtils.tokenize;
var highlightMatches = searchUtils.highlightMatches;
var paginate = pagination.paginate;
/**
* Templates
*/
var templates = {};
templates.results = require('./templates/results.handlebars');
templates.pageNumbers = require('./templates/page-numbers.handlebars');
/**
* Page size
*/
var PAGE_SIZE = 7;
/**
* Filter updates (ie when a user enters new text in the search box)
*/
var searchInput = document.getElementById('search');
var searchEvents = Rx.Observable.fromEvent(searchInput, 'keyup')
.map(function (e) { return e.target.value })
.map(tokenize)
.map(search)
.startWith({filter: function () { return true }, query: []});
/**
* Paging updates (ie when a user selects a new page). This pattern was found at
* https://github.com/Reactive-Extensions/RxJS/blob/master/doc/gettingstarted/events.md to
* subsribe to events for dom elements that may/may not be present yet.
*/
var $pageLinks = $('.results-container');
var pagingEvents = Rx.Observable.fromEventPattern(
function addHandler (h) { $pageLinks.on('click', 'a', h)},
function delHandler (h) { $pageLinks.off('click', 'a', h)})
.map(function (e) { return parseInt(e.target.text) })
.startWith(1);
/**
* Combination of filter and paging updates (will capture any filtering/paging changes)
*/
var pageUpdates = searchEvents
.selectMany(function (search) {
return pagingEvents
.map(function (page) {
return {
filter: search.filter,
page: page,
pageSize: PAGE_SIZE,
query: search.query
}
})
.startWith({filter: search.filter, query: [], page: 1, pageSize: PAGE_SIZE});
});
/**
* Stream of page models (created when a new page update occurs)
*/
var pageModels = pageUpdates
.map(function (options) {
options.items = JSON.parse(JSON.stringify(resultsStore))
.filter(function (result) {
return options.filter(tokenize(result.title));
});
// Return the page's model
return {
query: options.query,
totalSize: options.items.length,
paginated: paginate(options)
}
});
/**
* Subscribe to the model updates and re-render the page
*/
pageModels.subscribe(function render (model) {
var items = model.paginated.items
// Add match-highlighting
.map(function (item) {
item.title = highlightMatches(item.title, model.query);
return item;
});
// Render the results
$('.results').html(templates.results({ results: items }));
// Render the pagination information
$('.pagination').html(templates.pageNumbers(model.paginated.paging));
});