Skip to content

Commit

Permalink
Refactor autocomplete and add free autocomplete widget for arbitrary …
Browse files Browse the repository at this point in the history
…inputs (#600)
  • Loading branch information
jochenklar committed Oct 10, 2023
1 parent bb5f093 commit 6a9172e
Show file tree
Hide file tree
Showing 7 changed files with 75 additions and 32 deletions.
1 change: 1 addition & 0 deletions rdmo/core/settings.py
Original file line number Diff line number Diff line change
Expand Up @@ -318,6 +318,7 @@
('radio', _('Radio buttons'), 'rdmo.projects.widgets.RadioWidget'),
('select', _('Select drop-down'), 'rdmo.projects.widgets.SelectWidget'),
('autocomplete', _('Autocomplete'), 'rdmo.projects.widgets.AutocompleteWidget'),
('freeautocomplete', _('Free autocomplete'), 'rdmo.projects.widgets.FreeAutocompleteWidget'),
('range', _('Range slider'), 'rdmo.projects.widgets.RangeWidget'),
('date', _('Date picker'), 'rdmo.projects.widgets.DateWidget'),
('file', _('File upload'), 'rdmo.projects.widgets.FileWidget')
Expand Down
75 changes: 64 additions & 11 deletions rdmo/projects/static/projects/js/project_questions/services.js
Original file line number Diff line number Diff line change
Expand Up @@ -941,7 +941,6 @@ angular.module('project_questions')
}
}
} else {
console.log('next');
service.next();
}
} else {
Expand Down Expand Up @@ -1372,12 +1371,22 @@ angular.module('project_questions')

// unset the searching flag
value.searching = false;

// activate the first item
if (question.widget_type == 'autocomplete' && angular.isDefined(value.items[0])) {
value.items[0].active = true;
}
});
}
} else {
// if no search was performed, do the searching on the client
value.autocomplete_search = false;
value.items = question.options_fuse.search(value.autocomplete_input);

// activate the first item
if (question.widget_type == 'autocomplete' && angular.isDefined(value.items[0])) {
value.items[0].active = true;
}
}
} else {
value.items = [];
Expand Down Expand Up @@ -1420,8 +1429,19 @@ angular.module('project_questions')
value.autocomplete_input = next.text;
}
} else if ($event.code == 'Enter' || $event.code == 'NumpadEnter') {
if (angular.isDefined(active)) {
if (value.autocomplete_input == '') {
service.resetAutocomplete(value);
} else if (angular.isDefined(active)) {
service.selectAutocomplete(value, value.items[active]);
} else if (question.widget_type == 'freeautocomplete') {
var matchingOptions = $filter('filter')(value.items, function(item) {
return item.text.toLowerCase() == value.autocomplete_input.toLowerCase();
})
if (matchingOptions.length > 0) {
service.selectAutocomplete(value, matchingOptions[0]);
} else {
service.selectAutocomplete(value, null);
}
}
} else if ($event.code == 'Escape') {
if (value.selected === '') {
Expand All @@ -1437,24 +1457,57 @@ angular.module('project_questions')
// called when the user clicks on an option of the autocomplete field
service.selectAutocomplete = function(value, option) {
value.autocomplete_locked = true;
value.selected = option.id.toString();
value.autocomplete_text = option.text;

if (option === null) {
value.text = value.autocomplete_input;
value.selected = '';
value.autocomplete_text = value.text;
} else {
value.text = '';
value.selected = option.id.toString();
value.autocomplete_text = option.text;
value.autocomplete_input = option.text;
}

service.changed(value, true);
}

// called when the user clicks outside the autocomplete field
service.blurAutocomplete = function(value) {
if (value.selected === '') {
value.autocomplete_input = '';
value.autocomplete_text = '';
value.items = null;
service.blurAutocomplete = function(question, value) {
if (question.widget_type == 'freeautocomplete') {
if (value.autocomplete_input == '') {
service.resetAutocomplete(value);
} else {
var matchingOptions = $filter('filter')(value.items, function(item) {
return item.text.toLowerCase() == value.autocomplete_input.toLowerCase();
})
if (matchingOptions.length > 0) {
service.selectAutocomplete(value, matchingOptions[0]);
} else {
service.selectAutocomplete(value, null);
}
}
} else {
value.autocomplete_locked = true;
value.autocomplete_input = value.autocomplete_text;
if (value.selected === '') {
service.resetAutocomplete(value);
} else {
value.autocomplete_locked = true;
value.autocomplete_input = value.autocomplete_text;
}
}
}

// called when an empty string is entered in the autocomplete field
service.resetAutocomplete = function(value) {
value.text = '';
value.selected = '';
value.autocomplete_input = '';
value.autocomplete_text = '';
value.items = null;

service.changed(value, true);
}

// called when the user clicks in the autocomplete field
service.unlockAutocomplete = function(question, value, set_prefix, set_index, index) {
value.autocomplete_locked = false;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -28,10 +28,8 @@

<div class="question col-md-{$ question.width || 12 $}" ng-show="element.isQuestion" ng-init="question = element">
<div ng-hide="valueset.hidden.questions[question.id]">
{% for widget in widgets %}
{% if widget.template_name %}
{% include widget.template_name %}
{% endif %}
{% for template_name in widgets %}
{% include template_name %}
{% endfor %}
</div>
</div>
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
{% load i18n %}

<div class="form-group" ng-if="question.widget_type === 'autocomplete'">
<div class="form-group" ng-if="question.widget_type === 'autocomplete' || question.widget_type === 'freeautocomplete'">
{% include 'projects/project_questions_question_label.html' %}
{% include 'projects/project_questions_question_help.html' %}
{% include 'projects/project_questions_question_warning.html' %}
Expand Down Expand Up @@ -30,7 +30,7 @@
ng-focus="service.filterAutocomplete(question, value)"
ng-change="service.filterAutocomplete(question, value);"
ng-keydown="service.keydownAutocomplete(question, value, $event)"
ng-blur="service.blurAutocomplete(value)"
ng-blur="service.blurAutocomplete(question, value)"
ng-class="{'default-value': service.isDefaultValue(question, value)}"
placeholder="{% trans 'Please type and select.' %}"/>

Expand Down
2 changes: 1 addition & 1 deletion rdmo/projects/views/project.py
Original file line number Diff line number Diff line change
Expand Up @@ -272,7 +272,7 @@ def get(self, request, *args, **kwargs):
return redirect('project_error', pk=self.object.pk)
else:
context = self.get_context_data(object=self.object)
context['widgets'] = get_widgets()
context['widgets'] = {widget.template_name for widget in get_widgets() if widget.template_name}
return self.render_to_response(context)


Expand Down
5 changes: 5 additions & 0 deletions rdmo/projects/widgets.py
Original file line number Diff line number Diff line change
Expand Up @@ -31,6 +31,11 @@ class AutocompleteWidget(Widget):
widget_class = 'autocomplete'


class FreeAutocompleteWidget(Widget):
template_name = 'projects/project_questions_form_group_autocomplete.html'
widget_class = 'autocomplete'


class DateWidget(Widget):
template_name = 'projects/project_questions_form_group_date.html'
widget_class = 'date'
Expand Down
14 changes: 0 additions & 14 deletions rdmo/questions/constants.py

This file was deleted.

0 comments on commit 6a9172e

Please sign in to comment.