Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

full-text search using Lunr.js #1726

Merged
merged 48 commits into from
May 26, 2020
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
48 commits
Select commit Hold shift + click to select a range
01bc12e
maybe solved searching??
Mar 21, 2020
bb3db48
Added comments for search
Mar 22, 2020
63739cf
attempt at a lunr search
Mar 25, 2020
11b275c
Merge branch 'gh-pages' of github.com:programminghistorian/jekyll int…
Mar 25, 2020
b679215
removed wrap terms func
Mar 26, 2020
416be39
fixed lunr ref issue
Mar 26, 2020
50c63d8
updated search for multilingual logic
Mar 26, 2020
9d3f8b7
trying to fix enter bug
Mar 27, 2020
55c298e
trying list.js update function
Mar 27, 2020
783d2ff
Merge branch 'gh-pages' of github.com:programminghistorian/jekyll int…
Mar 27, 2020
6de9a37
fixed earlier bug and got search working with filter logic
Apr 12, 2020
49b49f1
Merge branch 'gh-pages' of github.com:programminghistorian/jekyll int…
Apr 12, 2020
5a36466
fixed search bugs and got it working with filter logic
Apr 12, 2020
9f453ce
fixed search bugs and got it working with filter logic
Apr 12, 2020
76da59b
added search enable button and more comments to code
Apr 13, 2020
a07a667
Merge branch 'gh-pages' of github.com:programminghistorian/jekyll int…
Apr 27, 2020
2d9a67d
Merge branch 'gh-pages' of github.com:programminghistorian/jekyll int…
May 4, 2020
ea7577d
fixed most of the bugs in full text search
May 6, 2020
da7263f
added in support for multiple language stemmers
May 6, 2020
f85a5cc
Merge branch 'gh-pages' of github.com:programminghistorian/jekyll int…
May 6, 2020
57b02ef
create snippet templates for search terms
mdlincoln May 8, 2020
ca4fd88
updated search input to work with snippets
May 8, 2020
e8372d7
trying to comment and clean up code
May 9, 2020
2340305
FR snippets
spapastamkou May 9, 2020
a29e182
cleaned up code
May 10, 2020
e0a8ff6
Merge branch 'search-lunr-1018' of github.com:programminghistorian/je…
May 10, 2020
e3f35a6
ordered lessons by search score
May 10, 2020
6fda33e
Merge branch 'gh-pages' into search-lunr-1018
mdlincoln May 12, 2020
2a87ae0
removed abstract styling from style.css
May 12, 2020
2414455
Merge branch 'search-lunr-1018' of github.com:programminghistorian/je…
May 12, 2020
18196ae
Update snippets.yml
jenniferisasi May 13, 2020
2bb695e
added search info and search indicator
May 13, 2020
f0c0c83
switched icon to question mark
May 13, 2020
d7aa217
Merge branch 'gh-pages' of github.com:programminghistorian/jekyll int…
May 13, 2020
81245d7
fixed search info for firefox and added loader
May 14, 2020
7341f96
pulled from gh-pages
May 14, 2020
0a51f5a
cleaning up code and adding comments
May 14, 2020
a0290a6
Merge branch 'gh-pages' of github.com:programminghistorian/jekyll int…
May 14, 2020
0a88cce
cleaning code and changing url to slug
May 16, 2020
245342f
Merge branch 'gh-pages' of github.com:programminghistorian/jekyll int…
May 16, 2020
2654e91
reverted back to url and added more comments
May 16, 2020
15c7c41
removed all console.logs and added snippet
May 16, 2020
25071a8
ES translation of search documentation snippet
rivaquiroga May 21, 2020
819bf53
FR translation search documentation snippet
spapastamkou May 26, 2020
8f7230d
use md shortcut for URLs
mdlincoln May 26, 2020
b5b0520
moved js files to vendor and only loaded file for language
May 26, 2020
352f6bf
adding the vendor files again
May 26, 2020
a527945
readding js vendor and updatinggitignore
May 26, 2020
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,6 @@ _site/*
.DS_Store
tmp/

vendor/
/vendor
.bundle/
.vscode/
34 changes: 34 additions & 0 deletions _data/snippets.yml
Original file line number Diff line number Diff line change
Expand Up @@ -352,6 +352,40 @@ filtering-results:
es: Filtradas por
fr: Filtrage par
pt:
loading-search:
en: LOADING SEARCH...
es: CARGANDO LA BÚSQUEDA...
fr: RECHERCHE EN COURS...
pt:
search-lessons:
en: SEARCH LESSONS
es: BUSCAR LECCIONES
fr: RECHERCHER LES LEÇONS
pt:
start-searching:
en: START SEARCHING
es: INICIAR BÚSQUEDA
fr: DÉMARRER LA RECHERCHE
pt:
type-search-terms:
en: TYPE SEARCH TERMS...
es: ESCRIBE LOS TÉRMINOS DE BÚSQUEDA...
fr: ENTRER UN OU PLUSIEURS TERMES DE RECHERCHE...
pt:
search-info:
en: |
To search for relevant terms, enter them into the search bar and either press the enter key or the search button. All searches are case insensitive. If multiple terms are entered, results will include lessons that have all terms, as well as lessons that contain *either term*. Results with more of the terms will be scored higher in the list.

To only return results with multiple terms, add the `+` symbol before the term. For example, `+Twitter +Network` will return lessons that contain *both* "twitter" and "network". To only return results that *do not* contain a term use the `-` symbol. For example, `-Twitter +Network` will return lessons that contain "network" but not "twitter". For more detailed information, visit this guide on searching: <https://lunrjs.com/guides/searching.html>
es: |
Para buscar términos relevantes, escríbelos en la barra de búsqueda y aprieta la tecla "enter" o haz clic en el botón "buscar lecciones". Las búsquedas no distinguen mayúsculas y minúsculas. Si se ingresan múltiples términos, los resultados incluirán tanto lecciones que los contengan todos, como lecciones que contengan *solo alguno*. Los resultados que incluyan más de un término aparecerán primero en la lista.

Para obtener solo resultados con múltiples términos, agrega el símbolo `+` antes de cada uno. Por ejemplo, `+Twitter +Red` devolverá lecciones que contienen *tanto* "twitter" como "red". Para obtener solo resultados que *no* contengan cierto término, utiliza el símbolo `-`. Por ejemplo, `-Twitter +Red` devolverá lecciones que contienen "red" pero no "twitter". Para información más detallada, puedes revisar la guía sobre búsquedas (en inglés): <https://lunrjs.com/guides/searching.html>
fr: |
Pour obtenir des résultats en utilisant plusieurs termes de recherche, faites précéder chaque terme du symbole `+`. Par exemple, en insérant `+Twitter +réseau`, vous obtiendrez les tutoriels qui contiennent tous les deux termes. Pour *exclure* un terme des résultats obtenus, vous pouvez utiliser le symbole `-`. Par exemple, en insérant `-Twitter +réseau`, vous obtiendrez les tutoriels qui contiennent le terme "réseau", mais pas "Twitter". Pour en savoir plus sur les modalités de recherche, merci de consulter ce guide <https://lunrjs.com/guides/searching.html>

pt: |


# lesson headers
editor:
Expand Down
64 changes: 51 additions & 13 deletions _includes/lesson-index.html
Original file line number Diff line number Diff line change
@@ -1,32 +1,61 @@
{% comment %}
Core code for generating filterable lesson indexes on lessons.md and es/lecciones.md. This will repeatedly call lesson_describe.html in which individual lessons have their metadata formatted for display.
Core code for generating filterable lesson indexes on lessons.md and es/lecciones.md. This will repeatedly call
lesson_describe.html in which individual lessons have their metadata formatted for display.
{% endcomment %}

<!-- loading graph if search in URI -->
<div id="pre-loader">
<svg width="200" height="200" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 100 100" preserveAspectRatio="xMidYMid"
class="lds-ripple" style="background:0 0">
<circle cx="50" cy="50" r="4.719" fill="none" stroke="#1d3f72" stroke-width="2">
<animate attributeName="r" calcMode="spline" values="0;40" keyTimes="0;1" dur="3" keySplines="0 0.2 0.8 1" begin="-1.5s" repeatCount="indefinite" />
<animate attributeName="opacity" calcMode="spline" values="1;0" keyTimes="0;1" dur="3" keySplines="0.2 0 0.8 1" begin="-1.5s" repeatCount="indefinite" />
</circle>
<circle cx="50" cy="50" r="27.591" fill="none" stroke="#5699d2" stroke-width="2">
<animate attributeName="r" calcMode="spline" values="0;40" keyTimes="0;1" dur="3" keySplines="0 0.2 0.8 1" begin="0s" repeatCount="indefinite" />
<animate attributeName="opacity" calcMode="spline" values="1;0" keyTimes="0;1" dur="3" keySplines="0.2 0 0.8 1" begin="0s" repeatCount="indefinite" />
</circle>
</svg>
</div>
<ul class="filter activities">
{% for activity in site.data.activities %}
{% assign atype = activity.type %}
<li id="filter-{{ atype }}" class="filter">{{ activity[page.lang]}} ({{ alllessons | where:"activity",atype | size }})</li>
<li id="filter-{{ atype }}" class="filter">{{ activity[page.lang]}} ({{ alllessons | where:"activity",atype | size }})
</li>
{% endfor %}
</ul>

<ul class="filter topics">
{% for topic in site.data.topics %}
{% assign type = topic.type %}
{% assign count = alllessons | where:"topics",type | size }} %}
{% for topic in site.data.topics %}
{% assign type = topic.type %}
{% assign count = alllessons | where:"topics",type | size }} %}
{% if count > 0 %}
<li id="filter-{{ topic.type }}" class="filter">{{ topic.displayname[page.lang] }} ({{count}})</li>
{% endif %}
{% endfor %}
{% endfor %}
</ul>

<div id="filter-none">{{site.data.snippets.reset-button[page.lang]}} ({{ alllessons | size }})</div>
<div id="filter-none">{{site.data.snippets.reset-button[page.lang]}} ({{ alllessons | size }})</div>

<!--
this div ('lesson-list', referenced in lessonfilter.js) needs to contain the sort button/elements AND the actual list for the sort buttons to work
-->
<div id="search-div" style="text-align: center; margin-bottom: 1rem; display: none;">
<input id="loading-search" class="search-input" type="text"
placeholder="{{ site.data.snippets.loading-search[page.lang] }}" style="background-color: #efefef" disabled>
<input id="search" class="search-input" type="text" style="display: none;" placeholder="{{ site.data.snippets.type-search-terms[page.lang] }}">
<button id="search-button" disabled>{{ site.data.snippets.search-lessons[page.lang] }}</button>
<i id="search-info-button" class="fas fa-question-circle"></i>
<div id="search-info">
{{ site.data.snippets.search-info[page.lang] | markdownify }}
</div>
</div>
<div id="enable-search-div" style="text-align: center; margin-bottom: 1rem;">
<button id="enable-search-button" style="width: 100%;">{{ site.data.snippets.start-searching[page.lang] }}</button>
</div>

<div id="lesson-list">

<!--
<!--
List.js uses button classes of asc and desc to control sorting functionality. It also toggles those classes off and on with click events.
To not interfere with that, we use my-asc and my-desc to control the arrows, since our desired behavior is different from what list.js does.
More concretely: to sort asc, the button class needs to contain asc, but we use the arrow ON THE BUTTON to indicate what WILL happen,
Expand All @@ -35,18 +64,22 @@
-->
<ul class="sort-by">
<li id="sort-by-date" class="sort" data-sort="date">{{site.data.snippets.sort-by-date[page.lang]}}</li>
<li id="sort-by-difficulty" class="sort" data-sort="difficulty">{{site.data.snippets.sort-by-difficulty[page.lang]}}</li>
<li id="sort-by-difficulty" class="sort" data-sort="difficulty">{{site.data.snippets.sort-by-difficulty[page.lang]}}
</li>
</ul>

<input id="date-sort-text" type="hidden" label="{{site.data.snippets.date[page.lang]}}">
<input id="difficulty-sort-text" type="hidden" label="{{site.data.snippets.difficulty[page.lang]}}">

<h2 class="results-title">{{ site.data.snippets.filtering-results[page.lang] }}: <span id="results-value">{{ site.data.snippets.all-lessons[page.lang] }} </span> <span id="current-sort" class="sort-desc">{{site.data.snippets.date[page.lang]}}</span></h2>

<h2 class="results-title">{{ site.data.snippets.filtering-results[page.lang] }}: <span
id="results-value">{{ site.data.snippets.all-lessons[page.lang] }} </span> <span id="current-sort"
class="sort-desc">{{site.data.snippets.date[page.lang]}}</span></h2>

<ul class="list">
{% for lesson in alllessons %}
{% capture author_string %} {% include author.html %} {% endcapture %}
<li>{% include lesson_describe.html authors=author_string %}</li>
<li>{% include lesson_describe.html authors=author_string %}</li>
{% endfor %}
</ul>

Expand All @@ -56,10 +89,15 @@ <h2 class="results-title">{{ site.data.snippets.filtering-results[page.lang] }}:
<script src='//cdnjs.cloudflare.com/ajax/libs/jquery/2.1.3/jquery.min.js'></script>
<script src='//cdnjs.cloudflare.com/ajax/libs/list.js/1.5.0/list.min.js'></script>
<script src="{{ site.baseurl }}/js/URI.min.js"></script>
<script src="https://unpkg.com/lunr/lunr.js"></script>
<script src="{{ site.baseurl }}/js/vendor/lunr.stemmer.support.js"></script>
{% if page.lang != "en" %}
<script src="{{ site.baseurl }}/js/vendor/lunr.{{page.lang}}.js"></script>
{% endif %}
<script src="{{ site.baseurl }}/js/lessonfilter.js"></script>

<script>
$(function() {
$(function () {
wireButtons();
});
</script>
13 changes: 11 additions & 2 deletions _includes/lesson_describe.html
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,6 @@
{% endcomment %}

<div class="lesson-description clearfix">

{% if lesson.original %}
{% assign canonical_slug = lesson.original %}
{% else %}
Expand All @@ -23,7 +22,9 @@
<h3 class="above-title">{{ include.authors }}</h3>
<a href="{{ lesson.url }}"><h2 class="title">{{ lesson.title }}</h2></a>

<p class="abstract">{{ lesson.abstract | markdownify }}</p>
<p class="abstract">
{{ lesson.abstract | markdownify | remove: '<p>' | remove: '</p>'}}
</p>

{% comment %}
Activity and topic are hidden via CSS as a hack to let JS sorting by activity and topic work. Note that the date sort is based on translation date first, falling back to publication date.
Expand All @@ -32,5 +33,13 @@ <h3 class="above-title">{{ include.authors }}</h3>
<span class="topics">{{ lesson.topics | join: ' '}}</span>
<span class="date">{% if lesson.translation_date %}{{ lesson.translation_date }}{% else %}{{ lesson.date }}{% endif %}</span>
<span class="difficulty">{{ lesson.difficulty }}</span>
<span id="{{lesson.url}}-content" class="content"
style="display: none;">{{ lesson.content | markdownify | strip_html }}</span>
<span id="{{lesson.url}}-score" class="score"
style="display: none;">0</span>
<p id="{{lesson.url}}-search_results" class="search_results"
style="display: none;"></p>



</div>
88 changes: 82 additions & 6 deletions css/style.css
Original file line number Diff line number Diff line change
Expand Up @@ -316,6 +316,74 @@ Lessons Index
background-color:#ededed;
}

/*****************
SEARCH
*****************/

.search-input {
width:55%;
clear:both;
margin-bottom:1rem;
background-color:#fefefe;
color:#666;
border:1px solid #999;
font: .9rem/1.1rem 'Open Sans',
sans-serif;
padding: .4rem .6rem;
border-radius: 3px;
display:inline-block;
text-transform:uppercase;
text-decoration: none;
}

#search-button,
#enable-search-button {
background-color: #efefef;
color: rgb(153, 143, 143);
width: 35%;
font: .9rem/1.1rem 'Open Sans',
sans-serif;
padding: .4rem .6rem;
border: none;
border-radius: 3px;
display: inline-block;
text-transform: uppercase;
text-decoration: none;
}

@media only screen and (max-width: 767px) {
/* phones */
#search-button,
#enable-search-button {
width: 80%;
}
}


#search-info-button {
padding: 0.5rem;
color: rgb(153, 143, 143);
}

#search-info {
display: none;
height:0px;
background:#efefef;
overflow:hidden;
transition:0.5s;
-webkit-transition:0.5s;
width: 100%;
text-align: left;
box-sizing: border-box;
}

#search-info.visible {
display: block;
height: fit-content;
height: -moz-max-content;
padding: 10px;
margin-top: 10px;
}

/*****************
SORT BUTTONS
Expand Down Expand Up @@ -426,19 +494,27 @@ Lessons Index
clear:none;
}

p.abstract {
font: .8rem/1.2rem 'Open Sans', sans-serif;
margin:0;
}

.list .date,
.lesson-description .activity,
.lesson-description .topics,
.lesson-description .difficulty {
display: none;
}


#pre-loader {
visibility: hidden;
display: flex;
justify-content: center;
align-items: center;
height: 100vh;
width: 100%;
position: fixed;
top: 0;
left: 0;
z-index: 9999;
transition: opacity 0.3s linear;
background: rgba(211, 211, 211, 0.8);
}
/* =============================================================================
Top Navigation Bar
========================================================================== */
Expand Down
Loading