Selectonic helps to implement widgets with ability to select items. It could be usefull in webapp where are different widgets like menus, dropdowns with keyboard input, lists of items with actions and more. See examples below.
Lets see simple list of items with actions buttons. Try to select items with mouse or keyboard then click action button. The list has multiple selection
(function( $ ) {
'use strict';
var $el = $('#actions-list'),
actions = $el.find('.actions-list__actionbar'),
list = $el.find('.actions-list__group');
// Attach selectonic plugin
list.selectonic({
multi: true,
keyboard: true,
focusBlur: true,
selectionBlur: true,
// Before any changes
before: function(e) {
if (e.target === actions[0] || $(e.target).is('button.actions-list__button')) {
this.selectonic('cancel');
}
},
// When one or more items selectes
select: function() {
toggleActions(false);
},
// When all items clears selection
unselectAll: function() {
toggleActions(true);
}
});
actions.on('click', 'button', function(event) {
event.preventDefault();
// Get selected items from the list
// and pass them to a method
doAction( list.selectonic('getSelected') );
this.blur();
});
function toggleActions (state) {
if (state === void 0) {
actions.toggleClass('disabled');
} else {
actions.toggleClass( 'disabled', state );
}
}
function doAction (items) {
items.each(function(index, el) {
var $el = $(el);
$el.addClass('animate');
setTimeout(function() {
$el.removeClass('animate');
}, 300);
});
}
toggleActions(true);
})( jQuery );
It supports keys: Up, Down, PageUp, PageDown and HOME, END.
You could focus it by TAB, press arrow and choose item.
There are many implementations of select input, but almost all with same flaw — lack of keyboard support. Selectonic has all necessary logic for it. This example of select input demonstrates that.
(function( $, window ) {
'use strict';
var keyCode = { UP:38, DOWN:40, ESCAPE:27, ENTER:13, SPACE:32 },
Select = function( elem ) {
this.$el = $( elem );
this.button = this.$el.find('.select-trigger');
this.title = this.button.find('.select-title');
this.list = this.$el.find('.select-group');
this.isOpend = false;
this.isEnabled = true;
this.init();
};
Select.prototype.init = function() {
var _this = this;
this.button.on('blur', function( e ) {
if ( !_this.isEnabled ) { return; }
_this.close.call( _this, e );
})
.on('mouseup', function(e) {
e.stopPropagation();
});
this.$el
.on('keydown', function( e ) {
if ( !_this.isEnabled ) { return; }
_this.keyHandler.call( _this, e );
})
.on('mousedown', function(e) {
if ( !_this.isEnabled ) { return; }
var isOnButton = _this.button[0] === e.target ||
_this.title[0] === e.target;
if ( isOnButton ) {
if (!_this.isOpend) {
e.stopPropagation();
_this.open.call( _this );
} else {
_this.close.call( _this );
}
return;
}
e.preventDefault();
});
// attach selectionc with options
this.list.selectonic({
multi: false,
keyboard: true,
keyboardMode: 'toggle',
mouseMode: 'mouseup',
focusOnHover: true,
selectionBlur: false,
focusBlur: true,
// After plugin's initialisation
create: function() {
// we don't want to list reaction on keyboard in closed state
this.selectonic('disable');
},
// When item of list has been selected
select: function( e, ui ) {
e.preventDefault();
_this.selected = ui.target;
_this.setValue( ui.items.html() );
_this.close();
},
// After each works cycle
stop: function( e, ui ) {
e.preventDefault();
if ( (e.which === keyCode.ENTER && _this.isOpend) || !ui.target ) {
_this.close();
}
}
});
};
Select.prototype.keyHandler = function( e ) {
var key = e.which;
if ( !this.isOpend &&
(key === keyCode.UP || key === keyCode.DOWN || key === keyCode.SPACE )
) {
e.stopPropagation();
e.preventDefault();
this.open();
}
if ( this.isOpend && key === keyCode.ESCAPE ) {
this.close();
e.stopPropagation();
}
};
Select.prototype.open = function() {
this.$el.addClass('opend');
// Enable selectonic on the list
this.list.selectonic('enable');
if ( this.selected ) {
this.list
// Set focus on selected element
.selectonic('focus', this.selected)
// and scroll to it
.selectonic('scroll');
}
this.isOpend = true;
};
Select.prototype.close = function() {
this.$el.removeClass('opend');
// Disable plugin on the list
this.list.selectonic('disable');
this.isOpend = false;
};
Select.prototype.setValue = function( val ) {
this.title.html( val );
};
Select.prototype.disable = function() {
if ( this.isOpend ) { this.close(); }
this.list.selectonic('disable');
this.isEnabled = false;
this.$el.addClass('disabled');
};
Select.prototype.enable = function() {
if ( this.isOpend ) { this.list.selectonic('enable'); }
this.isEnabled = true;
this.$el.removeClass('disabled');
};
$.fn.mySelect = function( options ) {
if (!this.length) { return this; }
var obj;
if ( options && typeof options === 'string' ) {
obj = this.data('plugin_select');
obj[options].call( obj );
} else {
this.each(function() {
var $this = $(this);
obj = new Select(this);
$this.data('plugin_select', obj);
});
}
return $(this);
};
})( jQuery, window );
Try to play with options and methods. For all possible options and methods see docs on GitHub.
You can select/unselect items by plugin interface. Plugin accept selector or element:
elem.selectonic('select', someElements);
elem.selectonic('select', ":even");
elem.selectonic('select', "li:eq(3)");
See all methods in the docs.
Requires jQuery 1.7+
Tested in Firefox, Chrome, Safari, Opera, IE8+
Author: Alexey Novichkov
License: Released under the MIT License. Feel free to use it in personal and commercial projects.