This is in reference to the code at this fiddle: http://jsfiddle.net/x8whpx09/17/
I am trying to create a search box with a result list that pops up when the user enters something. The problem I am encountering is when the user clicks anywhere other than the input element the search result list will close. I have a focusout event attached to the parent DIV, but even if I attach it to the input I get the same behavior. What I want is for the user to be able to select the scroll bar on the list and not have the list disappear. If they click outside of the input, or the list then the list should close.
Right now it closes no matter where they click unless it is in the input.
EDIT: The performSearch function body is wrapped in an AJAX request.
SOLUTION: I finally figured out what is happening. You need to bind to the mousedown event and return false in order to allow selecting the scrollbar in the dropdown. This question finally gave me the solution.
$target.on('mousedown',function (event) {
return false;
});
Here is the code at the fiddle:
var search = {
closing: null,
performSearch: function(elem, e) {
var $this = $(elem);
var $target = $('#search-results');
if ($target.length === 0) {
$target = $('<div id="search-results" class="sb-list"></div>');
$target.insertAfter($this);
var p = $this.position();
$target.css('top', (p.top + $this.height() + 15) + 'px');
$target.css('width', ($this.width() + p.left + 10) + 'px');
$target.css('width', ($this.width() + 25) + 'px');
$target.css('left', (p.left) + 'px');
$target.slideDown('fast', function() {
$target.css('overflow', 'auto');
});
$target.on('mouseover', '.sb-row', function() {
$(elem).addClass('sb-active');
$('.sb-active').removeClass('sb-active');
});
$target.on('click', '.sb-row', search.click);
//$target.parent().on('focusin focusout', search.listFocus);
} else {
$target.empty();
$target.slideDown('fast', function() {
$target.css('overflow', 'auto');
});
}
for (i = 0; i < 40; i++) {
var html = [];
html.push('<div class="sb-row' + (i == 0 ? ' sb-active' : '') + '">');
html.push('<a href="#">test result' + i + '</a>');
html.push('</div>');
var $out = $(html.join(''));
$target.append($out);
}
},
delayClose: function(e) {
console.log('delayClose');
var self = this;
console.log('results focused: ' + $('#search-results').is(':focus'));
console.log('div focused: ' + $('#parent').is(':focus'));
search.closing = window.setTimeout(function() {
search.close.apply(self, arguments);
}, 1000);
},
listFocus: function(e) {
console.log(e.type);
var self = this;
window.clearTimeout(search.closing);
},
click: function(e) {
console.log('clicked');
},
close: function(e) {
console.log('closing');
window.clearTimeout(search.closing);
var $this = $(this);
$('#search-results').slideUp('fast');
}
};
$(document).ready(function() {
$searchBox = $('#search');
$searchBox.on('focus', function(e) {
this.value = '';
this.select();
e.stopPropagation();
return false;
});
$searchBox.on('keyup', function(e) {
search.performSearch($searchBox[0], e);
});
$searchBox.parent().on('focusout', search.delayClose);
});
.sb-list {
position: absolute;
width: 250px;
top: 0;
left: 0;
height: 300px;
background: #FAFAFA;
border: solid 1px #999;
border-top: none;
display: none;
overflow: auto;
z-index: 92592;
-webkit-box-shadow: 0 2px 2px #999999;
-moz-box-shadow: 0 2px 2px #999999;
-ms-box-shadow: 0 2px 2px #999999;
box-shadow: 0 2px 2px #999999;
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/1.11.1/jquery.min.js"></script>
<div id="parent">
<input type="text" id="search" />
</div>