Hugo Search : un moteur de recherche interne (JQueryUI: Autocomplete + JSON)

Article publié, le et modifié le
4 minute(s) de lecture

Cet article contient 718 mots.
Source brute de l'article : MD

Description

Il y a quelques mois, j’ai écrit ce premier article pour obtenir un moteur de recherche basique en s’aidant de la méthode autocomplete() de JQueryUI : Hugo Search : un moteur de recherche interne (JQueryUI Autocomplete)

Et, puis je me suis rappelé que, parmi les flux de syndication, j’en génère un au format JSON, le bien nommé feed.json, disponible à partir de la page d’accueil. Je me suis demandé si je pouvais réutiliser mon code, et je découvre que notre fameux SSG Hugo a une fonction native getJSON.

Reprenons le code…

Code

Hugo

Je construis une variable $feed qui injectera la valeur du chemin absolu de mon fichier feed.json.

{{- $baseURL := (printf "%s%s/" $.Site.BaseURL $.Site.Language.Lang) | absLangURL -}}
{{- $feed := (printf "%s%s" $baseURL "/feed.json") | safeURL -}}

JQuery

La partie du code JQuery est sensiblement la même, à la différence près est que la fonction range d’Hugo va directement appeler le contenu retourné par la fonction getJSON. La suite du traitement est faite par la méthode autocomplete() de JQuery, ni plus ni moins.

Voici le code :

Code : javascript

$(function() {
    var projects = [
		{{- with getJSON $feed -}}
		{{- range .items -}}
		{{- $url := safeURL .url -}}
		{{- $title := safeHTML .title -}}
		{{- $desc := safeHTML .summary -}}  
		{
			value: "{{ $title }}",
			label: "{{ $desc }}",
			url:"{{ $url }}"		
		},
		{{- end -}}
		{{- end -}}
    ];
    $("#search").autocomplete({
		minLength: 0,
		source: projects,
		focus: function( event, ui ) {
			$("#search").val( ui.item.label );
			return false;
		},
		select: function( event, ui ) {
			$("#search").val( ui.item.label );
			$("#replyer").val( ui.item.value );
			return false;
		}
	})
    .data('ui-autocomplete')._renderItem = function(ul, item) {
        return $('<li>')
        .append('<a href="' + item.url + '" alt="'+ item.label + '">' + item.value + '</a>' )
        .appendTo(ul);
    };
});

HTML

La partie de code HTML est toujours aussi simple :

Code : html

<input id="search" class="form-control" placeholder="{{ i18n "searchHolderTitle" }}">
<input id="replyer" type="hidden">

TL;DR

L’ensemble du code :

Fichier : html

 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
{{- $baseURL := (printf "%s%s/" $.Site.BaseURL $.Site.Language.Lang) | absLangURL -}}
{{- $feed := (printf "%s%s" $baseURL "/feed.json") | safeURL -}}
{{- if not (in $baseURL "localhost:1313") -}}
<div class="search">
	<input id="search" class="form-control" placeholder="{{ i18n "searchHolderTitle" }}">
	<input id="replyer" type="hidden">                
	<script>
		$(function() {
            var projects = [
            {{- with getJSON $feed -}}
            {{- range .items -}}
            {{- $url := safeURL .url -}}
            {{- $title := safeHTML .title -}}
            {{- $desc := safeHTML .summary -}}              
            {
                value: "{{ $title }}",
                label: "{{ $desc }}",
                url:"{{ $url }}"
            },
            {{- end -}}
            {{- end -}}
            ];
            $( "#search" ).autocomplete({
                minLength: 0,
                source: projects,
                focus: function( event, ui ) {
                $( "#search" ).val( ui.item.label );
                return false;
                },
                select: function( event, ui ) {
                $( "#search" ).val( ui.item.label );
                $( "#replyer" ).val( ui.item.value );
                return false;
                }
            })
            .data('ui-autocomplete')._renderItem = function(ul, item) {
            return $('<li>')
            .append('<a href="' + item.url + '" alt="'+ item.label + '">' + item.value + '</a>' )
            .appendTo(ul);
            };
        });
	</script>		
	<hr>
</div>
{{- end -}}

Explications :

Les plus avisés remarqueront un détail qui a son importance :

  • regardez bien la ligne trois, j’ai implémenté une condition qui teste si on est dans l’environnement de développement local, si oui le code n’est pas généré.
    Pour l’explication, lire la section Erreur

Pour ce qui est de la démonstration, c’est ce qu’il y a sur la page d’accueil de ce site ;)

Erreur

Q : Lors de la génération en local, vous avez une multitude d’erreur, telle que la suivante et le serveur s’arrête tout seul :
ERROR 2020/08/27 08:16:41 Failed to get JSON resource “http://localhost:1313/fr/feed.json”: Get “http://localhost:1313/fr/feed.json”: dial tcp [::1]:1313: connect: connection refused

R : Et, oui, en local, le serveur n’est pas capable d’appeler une donnée qui n’est pas encore générée. C’est pourquoi dans le script final, une condition est imbriquée pour vérifier l’environnement de création.


Documentations