Skip to content

Commit

Permalink
Replace autocomplete with stimulus controller
Browse files Browse the repository at this point in the history
  • Loading branch information
hellcp-work committed Dec 28, 2023
1 parent 552816e commit 43c851d
Show file tree
Hide file tree
Showing 4 changed files with 127 additions and 49 deletions.
41 changes: 0 additions & 41 deletions src/api/app/assets/javascripts/webui/autocomplete.js
Original file line number Diff line number Diff line change
@@ -1,24 +1,4 @@
function setupAutocomplete() {
$('.obs-autocomplete').each(function() {
$(this).autocomplete({
// Note: 'append' is optional and only needed when there is no element with class ui-front
appendTo: $(this).data('append'),
source: $(this).data('source'),
minLength: 2,
search: function() {
$(this).prev().find('i').toggleClass('fa-search fa-spinner fa-spin');
},
response: function() {
$(this).prev().find('i').toggleClass('fa-search fa-spinner fa-spin');
}
});
});
}

$(document).ready(function() {

setupAutocomplete();

$('.repository-autocomplete').on('autocompleteselect autocompletechange', function(event, ui) {
var projectName,
dropdown = $(this).find('.repository-dropdown'),
Expand Down Expand Up @@ -56,25 +36,4 @@ $(document).ready(function() {
}
});
});

$('#linked_project, #review_project, #project_name, #project').on('autocompletechange', function() {
var projectName = $(this).val(),
packageInput = $('#linked_package, #review_package, #package_name, #package');

if (!packageInput.is(':visible')) return;

if (!projectName) {
packageInput.val('').attr('disabled', true);
return;
}

if (packageInput.attr('disabled')) { packageInput.removeAttr('disabled').focus(); }

var source = packageInput.autocomplete('option', 'source');

// Ensure old parameters got removed
source = source.replace(/\?.+/, '') + '?project=' + projectName;
// Update the source target of the package autocomplete
packageInput.autocomplete('option', { source: source });
});
});
20 changes: 15 additions & 5 deletions src/api/app/assets/stylesheets/webui/autocomplete.scss
Original file line number Diff line number Diff line change
@@ -1,9 +1,19 @@
ul.ui-autocomplete {
.autocomplete {
--autocomplete-icon-width: 2.5rem;

@extend .dropdown-menu;

li { @extend .dropdown-item; }
}
top: 100%;
left: var(--autocomplete-icon-width);
width: calc(100% - var(--autocomplete-icon-width));
border-top-left-radius: 0;
border-top-right-radius: 0;

.autocomplete-item {
@extend .dropdown-item;
}

.ui-helper-hidden-accessible{
display:none !important;
.autocomplete-item-text {
@extend .dropdown-item-text;
}
}
108 changes: 108 additions & 0 deletions src/api/app/javascript/controllers/autocomplete_controller.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,108 @@
import { Controller } from "@hotwired/stimulus"

export default class extends Controller {
static targets = [ "input", "results", "icon" ]
static values = { url: String }

connect() {
// Creating the autocomplete dropdown menu
const results = document.createElement("div");
results.setAttribute("data-autocomplete-target", "results");
results.classList.add("autocomplete");
this.inputTarget.insertAdjacentElement("afterend", results);

// Empty the fields between reloads
this.setEmpty();
this.inputTarget.value = '';
this.iconSearch();
}

setEmpty() {
this.resultsTarget.innerHTML = '';
const emptyText = document.createElement('span');
emptyText.classList.add("autocomplete-item-text");
emptyText.textContent = "Nothing found.";
this.resultsTarget.appendChild(emptyText);
}

urlValueChanged() {
if (this.hasResultsTarget)
this.setEmpty();
}

setResults(results) {
if (results.length < 1)
return this.setEmpty()
this.resultsTarget.innerHTML = '';
results.forEach((result) => {
let resultLink = document.createElement('a');
resultLink.setAttribute("data-action", "autocomplete#setInput");
resultLink.setAttribute("href", "#")
resultLink.classList.add('autocomplete-item');
resultLink.textContent = result;
this.resultsTarget.appendChild(resultLink);
});
}

setInput(event) {
this.input(event.target.textContent);
event.preventDefault();
}

input(value) {
this.dispatch("setInput", { detail: value })
this.inputTarget.value = value;
this.hideResults();
}

iconLoad() {
this.iconTarget.classList = 'fas fa-spinner fa-spin';
}

iconSearch() {
this.iconTarget.classList = 'fas fa-search';
}

showResults() {
this.resultsTarget.classList.add('show')
}

hideResults() {
// We need a small delay to allow for clicking on the dropdown
setTimeout(() => {
this.resultsTarget.classList.remove('show')
}, 200)
}

async search() {
this.iconLoad();
let query = this.inputTarget.value;
this.dispatch("search", { detail: query })
let url = new URL(this.urlValue, window.location.origin);
url.searchParams.set('term', query);

if (query.length >= 3) {
try {
const response = await fetch(url, {
method: "GET",
headers: {
"Content-Type": "application/json",
},
});
const raw_data = await response.text();
const data = JSON.parse(raw_data);
if (data.includes(query)) {
this.input(query);
} else {
this.setResults(data);
this.showResults();
}
} catch {
console.error("Failed to return results");
}
} else {
this.hideResults();
}
this.iconSearch();
}
}
7 changes: 4 additions & 3 deletions src/api/app/views/webui/shared/_autocomplete.html.haml
Original file line number Diff line number Diff line change
Expand Up @@ -5,12 +5,13 @@
data = local_assigns.fetch(:data, {})
html_name = local_assigns.fetch(:html_name, html_id)

.mb-3.ui-front
.mb-3{ data: { controller: 'autocomplete', 'autocomplete-url-value': data[:source] } }
= label_tag(html_id, label)
- if required
%abbr.text-danger{ title: 'required' } *
.input-group
%span.input-group-text
%i.fas.fa-search
%i.fas.fa-search{ 'data-autocomplete-target': 'icon' }
= text_field_tag(html_id, value, required: required, disabled: disabled, placeholder: 'Type to autocomplete...',
class: 'obs-autocomplete form-control', data: data, name: html_name)
class: 'form-control', data: data, name: html_name, 'data-autocomplete-target': 'input',
'data-action': 'autocomplete#search focus->autocomplete#showResults blur->autocomplete#hideResults')

0 comments on commit 43c851d

Please sign in to comment.