Skip to content

Commit 4214b84

Browse files
WIP: Add really fast search
This rewrite eschews jQuery, and instead relies on modern browser APIs. This makes search fast enough that it's able to run without the need of debounce.
1 parent b71c13c commit 4214b84

File tree

3 files changed

+90
-23
lines changed

3 files changed

+90
-23
lines changed

css/style.css

Lines changed: 15 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -155,11 +155,24 @@ header #j {
155155
box-shadow: 0 0 10px #7be;
156156
}
157157

158-
html.no-js #project-list, html.no-js footer {
158+
html.no-js footer {
159159
visibility: visible;
160160
}
161161

162-
#project-list, footer {
162+
#project-list {
163+
display: grid;
164+
grid-gap: 1em 30px;
165+
grid-template-columns: repeat( auto-fill, minmax( 200px, 1fr ) );
166+
grid-auto-rows: 0;
167+
visibility: hidden;
168+
}
169+
170+
html.no-js #project-list {
171+
grid-auto-rows: auto;
172+
visibility: visible;
173+
}
174+
175+
footer {
163176
visibility: hidden;
164177
}
165178

@@ -169,13 +182,6 @@ html.no-js #project-list, html.no-js footer {
169182
font-size: 11pt;
170183
}
171184

172-
#main .category {
173-
width: 230px;
174-
padding-left: 30px;
175-
float: left;
176-
margin-bottom: 1em;
177-
}
178-
179185
#main .category h2 {
180186
font-size: 14pt;
181187
font-weight: bold;

index.html.erb

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -37,6 +37,7 @@
3737
<div id="project-list">
3838
<% @categories.sort_by { |c, ps| c.downcase }.each do |category, projects| %>
3939
<div class="category">
40+
<div class="masonry-content">
4041
<h2><%= category %></h2>
4142
<ul>
4243
<% projects.each do |project| %>
@@ -50,6 +51,7 @@
5051
</li>
5152
<% end %>
5253
</ul>
54+
</div>
5355
</div>
5456
<% end %>
5557
</div>

js/main.js

Lines changed: 73 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -1,18 +1,77 @@
1-
$('#project-list').
2-
masonry({ transitionDuration: 0, columnWidth: 260 }).
3-
css({visibility: 'visible'});
4-
$('footer').css({visibility: 'visible'});
5-
6-
$('#search-query').on('change keyup paste input', function(event) {
7-
var query = $.trim(event.target.value.toLowerCase());
8-
var projects = $('#project-list li');
9-
if (query == '') {
10-
projects.show();
1+
function resizeMasonryItem(item){
2+
/* Get the grid object, its row-gap, and the size of its implicit rows */
3+
var grid = document.querySelector('#project-list'),
4+
rowGap = parseInt(window.getComputedStyle(grid).getPropertyValue('grid-row-gap')),
5+
rowHeight = parseInt(window.getComputedStyle(grid).getPropertyValue('grid-auto-rows'));
6+
7+
/*
8+
* Spanning for any brick = S
9+
* Grid's row-gap = G
10+
* Size of grid's implicitly create row-track = R
11+
* Height of item content = H
12+
* Net height of the item = H1 = H + G
13+
* Net height of the implicit row-track = T = G + R
14+
* S = H1 / T
15+
*/
16+
var rowSpan = Math.ceil((item.querySelector('.masonry-content').getBoundingClientRect().height+rowGap)/(rowHeight+rowGap));
17+
18+
/* Set the spanning as calculated above (S) */
19+
item.style.gridRowEnd = 'span '+rowSpan;
20+
}
21+
22+
function resizeAllMasonryItems(){
23+
// Get all item class objects in one list
24+
var allItems = document.querySelectorAll('#project-list > .category');
25+
26+
/*
27+
* Loop through the above list and execute the spanning function to
28+
* each list-item (i.e. each masonry item)
29+
*/
30+
for(var i=0;i<allItems.length;i++){
31+
resizeMasonryItem(allItems[i]);
32+
}
33+
34+
document.querySelector('#project-list').style.visibility = 'visible';
35+
}
36+
37+
var masonryEvents = ['load', 'resize'];
38+
masonryEvents.forEach( function(event) {
39+
window.addEventListener(event, resizeAllMasonryItems);
40+
} );
41+
42+
function applySearch(rawQuery){
43+
var query = rawQuery.toLowerCase().trim();
44+
45+
var categories = document.querySelectorAll('#project-list > .category');
46+
var seenCategories = [];
47+
var projects = document.querySelectorAll('#project-list li');
48+
49+
for(var i=0; i<projects.length;i++){
50+
var project = projects[i];
51+
if (project.dataset.search.indexOf(query) == -1) {
52+
project.style.display = 'none';
1153
} else {
12-
projects.hide().filter('[data-search*="' + query + '"]').show();
54+
var projectCategory = project.parentNode.parentNode.parentNode;
55+
projectCategory.style.display = '';
56+
project.style.display = '';
57+
seenCategories.push(projectCategory);
58+
}
59+
}
60+
61+
for(var i=0; i<categories.length;i++){
62+
var category = categories[i];
63+
if(seenCategories.indexOf(category) == -1){
64+
category.style.display = 'none';
1365
}
14-
$('#project-list .category').show().not(':has(li:visible)').hide();
15-
$('#project-list').masonry('layout');
66+
}
67+
}
68+
69+
var searchEvents = ['change', 'keyup', 'paste', 'input'];
70+
searchQuery = document.querySelector('#search-query');
71+
searchEvents.forEach(function(event){
72+
searchQuery.addEventListener(event, function(event){ applySearch(event.target.value) });
1673
});
1774

18-
$('#search-query').focus().change();
75+
window.addEventListener('load', function(){
76+
applySearch(searchQuery.value);
77+
});

0 commit comments

Comments
 (0)