Reputation: 485
I have created a custom form that allows users to lookup a specific option by name instead of searching for it in a lengthy list--for a media browser. The code does what I want with one exception. Clicking on the dynamically added suggestions does not trigger the click event the first time you click on it.
Clicking anywhere else on the screen seems to reset this, then allowing me to be able to click on my option and select it. I'm not entirely sure why this is happening but based on the console output it seems like my code is getting stuck somewhere before being able to continue.
$(document).ready(function() {
// Custom select form
$('select.custom_select').each(function(i) {
var select = $(this);
var custom_input = select.next().children('input');
var delete_selection = custom_input.next();
var suggestion_list = delete_selection.next();
// Set defaults in the custom form
var selected = select.find(":selected");
if (selected.index() != 0) {
select.val(selected.val()).change();
custom_input.val(selected.text())
custom_input.attr('readonly', true);
delete_selection.addClass('option_selected');
}
// User is typing in the custom form
custom_input.on("change keyup paste", function() {
suggestion_list.empty();
console.log('suggestions cleared');
suggestion_list.css('visibility', 'hidden');
custom_input.removeClass('no_matches');
var user_input = custom_input.val();
if (user_input != '') {
// Show options to the user
select.children('option').each(function(i) {
let option = $(this);
var text = option.text();
if (text.toLowerCase().includes(user_input.toLowerCase())) {
var re = new RegExp('(' + user_input + ')', 'gi');
suggestion_list.append(`<li data-value="${option.val()}" data-name="${text}">${text.replace(re, '<span>$1</span>')}</li>`);
console.log('suggestion added');
}
});
if (suggestion_list.children().length == 0) {
custom_input.addClass('no_matches');
} else if (!custom_input.attr('readonly')) {
suggestion_list.css('visibility', 'visible');
suggestion_list.focus();
}
}
});
// Choose an option
suggestion_list.on('click', 'li', function() {
select.val(parseInt($(this).attr('data-value'))).change();
custom_input.val($(this).attr('data-name'))
custom_input.attr('readonly', true);
delete_selection.addClass('option_selected');
suggestion_list.css('visibility', 'hidden');
});
// Reset the custom form
delete_selection.on('click', function() {
select.val('').change();
custom_input.attr('readonly', false);
delete_selection.removeClass('option_selected');
suggestion_list.css('visibility', 'visible');
custom_input.focus();
});
});
});
.delete_selection {
display: none;
}
.option_selected {
display: initial;
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<p>Type in the input to get suggestions. Click on a list item to select it.</p>
<select class="custom_select" id="id_file" name="file">
<option value="" selected="selected">---------</option>
<option value="1">image.svg</option>
<option value="2">video.mp4</option>
<option value="3">game.iso</option>
</select>
<div class="custom_select_form">
<input type="text" spellcheck="false">
<i class="delete_selection" aria-hidden="true">X</i>
<ul>
</ul>
</div>
Upvotes: 1
Views: 191
Reputation: 14927
Try replacing:
custom_input.on("change keyup paste", function() { ... });
with just:
custom_input.on("keyup paste", function() { ... });
Explanation: binding change
will also trigger the event when you leave the filter input (when the focus is no longer on it). Since the corresponding handler uses/modifies the list of suggestions, your click event on them might be impacted.
Also note that input propertychange
are the two events that are recommended to check for actual user input, as opposed to key*
events. It would also trigger when the user pastes something. So you should do this:
custom_input.on('input propertychange', function() { ... });
Upvotes: 1