Skip to content

Commit

Permalink
Merge pull request #14 from dahliacreative/search
Browse files Browse the repository at this point in the history
Search functionality
  • Loading branch information
dahliacreative authored Jul 28, 2016
2 parents d202b7d + 6cb054e commit 6f4f8f9
Show file tree
Hide file tree
Showing 18 changed files with 570 additions and 100 deletions.
16 changes: 16 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,22 @@ bower install --save jquery-selectron
$('.selectron').selectron();
```

###Search
You can enable search by passing the option when you initialize the plugin.
```
$('.selectron').selectron({
search: true
});
```
Alternativley you can enable/disable search on inidividual instances using a data attribute:
```
<select class="selectron" data-selectron-search="true">
<option value="">Please select something</option>
<option value="1">Option 1</option>
<option value="2">Option 2</option>
</select>
```

##Themes
There are three default themes, light, dark and block. The light theme is applied by default, to apply the dark theme simply add the `selectron--dark` class to your select, and to apply the block theme simply add `selectron--block`.
```
Expand Down
166 changes: 143 additions & 23 deletions dist/selectron.js
Original file line number Diff line number Diff line change
Expand Up @@ -6,19 +6,18 @@
// |___/\___|_|\___|\___|\__|_| \___/|_| |_|
//
// --------------------------------------------------------------------------
// Version: 1.1.5
// Version: 2.0.0
// Author: Simon Sturgess
// Website: dahliacreative.github.io/selectron
// Docs: dahliacreative.github.io/selectron/docs
// Docs: dahliacreative.github.io/selectron
// Repo: github.com/dahliacreative/selectron
// Issues: github.com/dahliacreative/selectron/issues
// --------------------------------------------------------------------------

(function(window, $) {

$.fn.selectron = function() {
$.fn.selectron = function(options) {
return this.each(function() {
new Selectron($(this)).build();
new Selectron($(this), options).build();
});
};

Expand All @@ -27,13 +26,17 @@
// --------------------------------------------------------------------------
// Selectron Constructor
// --------------------------------------------------------------------------
var Selectron = function (select) {
var Selectron = function(select, options) {
if(select.hasClass('selectron__select') || select[0].tagName !== 'SELECT') {
return;
}
this.opts = $.extend({}, options);
this.isTouch = ('ontouchstart' in window) || (navigator.maxTouchPoints > 0) || (navigator.msMaxTouchPoints > 0);
this.isDisabled = select.prop('disabled');
this.select = select;
if(select[0].hasAttribute('data-selectron-search')) {
this.opts.search = select.data('selectron-search');
}
};

// --------------------------------------------------------------------------
Expand All @@ -54,10 +57,22 @@ Selectron.prototype.build = function() {
.toggleClass('selectron--is-touch', this.isTouch);

if(!this.isTouch) {
if(this.opts.search) {
this.search = $('<input/>', {
'type': 'text',
'class': 'selectron__search' ,
'placeholder': 'Search'
});
this.noResults = $('<li/>', {
'class': 'selectron__no-results',
'text': this.select.data('no-results-text') || 'Sorry there are no matching results'
});
}
this.searchTerm = '';
this.trigger = $('<button/>', { 'class': 'selectron__trigger', 'type': 'button' });
this.options = $('<ul/>', { 'class': 'selectron__options' });
this.wrapper.append(this.trigger, this.options);
this.wrapper.append(this.trigger, this.search, this.options);
this.isOpen = false;
this.registerEvents();
this.populateOptions();
}
Expand All @@ -73,13 +88,18 @@ Selectron.prototype.clearSearchTerm = function() {
// --------------------------------------------------------------------------
// Close options
// --------------------------------------------------------------------------
Selectron.prototype.closeOptions = function() {
Selectron.prototype.closeOptions = function(search) {
if(!this.optionsAreHovered) {
var hovered = this.options.find('.selectron__option--is-hovered');
hovered.removeClass('selectron__option--is-hovered');
this.options.removeClass('selectron__options--is-open selectron__options--is-overflowing');
this.trigger.removeClass('selectron__trigger--is-open selectron__trigger--is-overflowing');
this.isOpen = false;
if(!search || (search === true && !this.triggerIsHovered)) {
var hovered = this.options.find('.selectron__option--is-hovered');
hovered.removeClass('selectron__option--is-hovered');
this.options.removeClass('selectron__options--is-open selectron__options--is-overflowing');
this.trigger.removeClass('selectron__trigger--is-open selectron__trigger--is-overflowing');
if(this.search) {
this.search.removeClass('selectron__search--is-open selectron__search--is-overflowing');
}
this.isOpen = false;
}
}
};

Expand Down Expand Up @@ -126,6 +146,40 @@ Selectron.prototype.createOption = function(selectOption, isInGroup) {
return option;
};

// --------------------------------------------------------------------------
// Filter Options
// --------------------------------------------------------------------------
Selectron.prototype.filterOptions = function(e) {
var searchTerm = this.search.val().toLowerCase(),
options = this.select.find('option:not([value=""])'),
matchedItems = 0;

this.options.empty();
if(searchTerm === '') {
this.populateOptions();
return;
}

for (var i = 0; i < options.length; i++) {
var option = $(options[i]),
text = option.text().toLowerCase(),
matches = text.indexOf(searchTerm) > -1;

if(matches) {
this.options.append(this.createOption(option));
matchedItems ++;
}
}

if(matchedItems < 1) {
this.options.append(this.noResults);
} else {
var firstOption = this.options.find('.selectron__option:first-child');
firstOption.addClass('selectron__option--is-hovered');
this.noResults.remove();
}
}

// --------------------------------------------------------------------------
// Handle Keystrokes
// --------------------------------------------------------------------------
Expand All @@ -135,16 +189,18 @@ Selectron.prototype.handleKeyStrokes = function(e) {
spaceKeyPressed = e.which === 32,
upArrowKeyPressed = e.which === 38,
downArrowKeyPressed = e.which === 40,
escapeKeyPressed = e.which === 27,
alphaNumbericKeyPressed = (e.which >= 48 && e.which <= 57) || (e.which >= 65 && e.which <= 90) || e.which === 8,
self = this;

if(!this.isOpen && (upArrowKeyPressed || downArrowKeyPressed || enterKeyPressed)) {
return false;
}

if(enterKeyPressed) {
this.closeOptions();
this.updateSelection(hovered);
if(escapeKeyPressed || enterKeyPressed) {
if(enterKeyPressed) {
this.updateSelection(hovered);
}
}

if(spaceKeyPressed) {
Expand Down Expand Up @@ -178,7 +234,7 @@ Selectron.prototype.handleKeyStrokes = function(e) {
this.updateScrollPosition(nextElement);
}

if(alphaNumbericKeyPressed || spaceKeyPressed) {
if((alphaNumbericKeyPressed || spaceKeyPressed) && !this.search) {
clearTimeout(this.searchTimeout);

this.searchTimeout = setTimeout(function() {
Expand Down Expand Up @@ -222,6 +278,13 @@ Selectron.prototype.openOptions = function() {
.addClass('selectron__trigger--is-open')
.toggleClass('selectron__trigger--is-overflowing', isOverflowing);

if(this.search) {
this.search
.addClass('selectron__search--is-open')
.toggleClass('selectron__search--is-overflowing', isOverflowing)
.focus();
}

this.isOpen = true;
}
};
Expand Down Expand Up @@ -264,11 +327,11 @@ Selectron.prototype.populateOptions = function() {
}
});

var firstOption = this.options.find('.selectron__option:first');
firstOption.addClass('selectron__option--is-hovered');
var firstOption = this.options.find('.selectron__option:first-child');
this.placeholderExists = firstOption.data('value') === '';

this.updateTrigger();
if(!this.isOpen) {
this.updateTrigger();
}
};

// --------------------------------------------------------------------------
Expand All @@ -292,9 +355,15 @@ Selectron.prototype.registerEvents = function() {
}
},
'blur': function() {
if(!$(this).is(':hover')) {
if((!self.search || !self.triggerIsHovered) && self.isOpen) {
self.closeOptions();
}
},
'mouseenter': function() {
self.triggerIsHovered = true;
},
'mouseleave': function() {
self.triggerIsHovered = false;
}
});

Expand All @@ -316,6 +385,35 @@ Selectron.prototype.registerEvents = function() {
self.optionsAreHovered = false;
}
});

if(this.search) {
this.search.on({
'keydown': function(e) {
var upArrowKeyPressed = e.which === 38,
downArrowKeyPressed = e.which === 40;

if(downArrowKeyPressed || upArrowKeyPressed) {
e.preventDefault();
}
},
'keyup': function(e) {
var upArrowKeyPressed = e.which === 38,
downArrowKeyPressed = e.which === 40,
leftArrowKeyPress = e.which === 37,
rightArrowKeyPress = e.which === 39,
enterKeyPressed = e.which === 13;

if(downArrowKeyPressed || upArrowKeyPressed || leftArrowKeyPress || rightArrowKeyPress || enterKeyPressed) {
self.handleKeyStrokes(e);
} else {
self.filterOptions(e);
}
},
'blur': function() {
self.closeOptions(true);
}
});
}
};

// --------------------------------------------------------------------------
Expand All @@ -324,6 +422,7 @@ Selectron.prototype.registerEvents = function() {
Selectron.prototype.toggleOptions = function(e) {
e.stopPropagation();
if(!this.isDisabled) {

var win = $(window),
optionsBottom = this.options.offset().top + this.options.height(),
scrollPosition = win.scrollTop(),
Expand All @@ -340,6 +439,15 @@ Selectron.prototype.toggleOptions = function(e) {
this.trigger.toggleClass('selectron__trigger--is-open')
.toggleClass('selectron__trigger--is-overflowing', isOverflowing);

if(this.search) {
this.search.toggleClass('selectron__search--is-open')
.toggleClass('selectron__search--is-overflowing', isOverflowing);
}

if(!this.isOpen && this.search) {
this.search.focus();
}

this.isOpen = this.trigger.hasClass('selectron__trigger--is-open');
}
};
Expand Down Expand Up @@ -378,6 +486,14 @@ Selectron.prototype.updateSelection = function(selected) {
selected.addClass('selectron__option--is-selected').siblings().removeClass('selectron__option--is-selected');
this.updateTrigger();
this.select.val(value).trigger('change');
if(this.search) {
this.search.val('');
this.options.empty();
this.populateOptions();
} else if(this.isOpen) {
this.closeOptions();
this.trigger.focus();
}
};

// --------------------------------------------------------------------------
Expand All @@ -392,9 +508,13 @@ Selectron.prototype.updateTrigger = function() {
this.trigger.html(content);
this.trigger.toggleClass('selectron__trigger--is-filled', !isPlaceholder);
this.optionsAreHovered = false;
this.closeOptions();
if(this.isOpen) {
this.closeOptions();
this.trigger.focus();
}
};


// --------------------------------------------------------------------------
// Update Value
// --------------------------------------------------------------------------
Expand Down
Loading

0 comments on commit 6f4f8f9

Please sign in to comment.