Skip to content

Commit

Permalink
signup: Implement autocomplete for affiliations in custom registratio…
Browse files Browse the repository at this point in the history
…n template

* Add autocomplete functionality for user affiliations without third-party libraries.
* Fetch suggestions from affiliations API based on user input and display in .
* Cache suggestions for performance and use a debounce mechanism to limit API calls using vanilla JS.
  • Loading branch information
Samk13 committed May 17, 2024
1 parent 4aaa9c5 commit 1feaacc
Showing 1 changed file with 84 additions and 0 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@

This file is part of Invenio.
Copyright (C) 2015-2020 CERN.
Copyright (C) 2024 KTH Royal Institute of Technology.

Invenio is free software; you can redistribute it and/or modify it
under the terms of the MIT License; see LICENSE file for more details.
Expand Down Expand Up @@ -51,3 +52,86 @@ <h5 class="ui grey header">
</div>
</div>
{% endblock %}

{% block javascript %}
{{ super() }}
<script>
async function fetchAffiliations(query, callback) {
try {
const response = await fetch(`/api/affiliations?size=5&suggest=${query}`);
if (!response.ok) {
throw new Error(`HTTP error! status: ${response.status}`);
}
const data = await response.json();
const suggestions = data.hits.hits.map(hit => hit.title.en).slice(0, 3);
callback(suggestions);
} catch (error) {
console.error("Error fetching affiliations:", error);
callback([]);
}
}

function autocomplete(inputElement) {
const cache = new Map();
const debounceTimeout = 100;
let debounceTimer;

// Create and append the datalist element with a unique ID
const datalistId = `affiliations-list-${Math.random().toString(36).substr(2, 9)}`;
const datalist = document.createElement('datalist');
datalist.id = datalistId;
document.body.appendChild(datalist);

// Link the datalist to the input element
inputElement.setAttribute('list', datalist.id);
inputElement.addEventListener("input", handleInput);
inputElement.addEventListener("keydown", handleTabPress);

function handleInput() {
clearTimeout(debounceTimer);
debounceTimer = setTimeout(() => {
const query = inputElement.value.trim().toLowerCase();
if (!query) return;

if (cache.has(query)) {
updateDatalist(cache.get(query));
} else {
fetchAffiliations(query, suggestions => {
cache.set(query, suggestions);
updateDatalist(suggestions);
});
}
}, debounceTimeout);
}

function handleTabPress(e) {
if (e.key === 'Tab' && datalist.options.length > 0) {
inputElement.value = datalist.options[0].value;
}
}

function updateDatalist(suggestions) {
datalist.innerHTML = '';
const fragment = document.createDocumentFragment();

// Add suggestions to the datalist
suggestions.forEach(suggestion => {
const option = document.createElement('option');
option.value = suggestion;
fragment.appendChild(option);
});
datalist.appendChild(fragment);
}
}

document.addEventListener("DOMContentLoaded", function () {
const inputElement = document.getElementById("profile.affiliations");
if (inputElement) {
autocomplete(inputElement);
} else {
console.error('Input element with id "profile.affiliations" not found.');
}
});

</script>
{% endblock javascript %}

0 comments on commit 1feaacc

Please sign in to comment.