11
;( function( window ) {
18
function hasParent( e, p ) {
20
var el = e.target||e.srcElement||e||false;
21
while (el && el != p) {
22
el = el.parentNode||false;
30
function extend( a, b ) {
32
if( b.hasOwnProperty( key ) ) {
42
function SelectFx( el, options ) {
44
this.options = extend( {}, this.options );
45
extend( this.options, options );
52
SelectFx.prototype.options = {
57
stickyPlaceholder : true,
59
onChange : function( val ) { return false; }
66
SelectFx.prototype._init = function() {
69
var selectedOpt = this.el.querySelector( 'option[selected]' );
70
this.hasDefaultPlaceholder = selectedOpt && selectedOpt.disabled;
73
this.selectedOpt = selectedOpt || this.el.querySelector( 'option' );
76
this._createSelectEl();
79
this.selOpts = [].slice.call( this.selEl.querySelectorAll( 'li[data-option]' ) );
82
this.selOptsCount = this.selOpts.length;
85
this.current = this.selOpts.indexOf( this.selEl.querySelector( 'li.cs-selected' ) ) || -1;
88
this.selPlaceholder = this.selEl.querySelector( 'span.cs-placeholder' );
97
SelectFx.prototype._createSelectEl = function() {
98
var self = this, options = '', createOptionHTML = function(el) {
99
var optclass = '', classes = '', link = '';
101
if( el.selectedOpt && !this.foundSelected && !this.hasDefaultPlaceholder ) {
102
classes += 'cs-selected ';
103
this.foundSelected = true;
106
if( el.getAttribute( 'data-class' ) ) {
107
classes += el.getAttribute( 'data-class' );
110
if( el.getAttribute( 'data-link' ) ) {
111
link = 'data-link=' + el.getAttribute( 'data-link' );
114
if( classes !== '' ) {
115
optclass = 'class="' + classes + '" ';
118
return '<li ' + optclass + link + ' data-option data-value="' + el.value + '"><span>' + el.textContent + '</span></li>';
121
[].slice.call( this.el.children ).forEach( function(el) {
122
if( el.disabled ) { return; }
124
var tag = el.tagName.toLowerCase();
126
if( tag === 'option' ) {
127
options += createOptionHTML(el);
129
else if( tag === 'optgroup' ) {
130
options += '<li class="cs-optgroup"><span>' + el.label + '</span><ul>';
131
[].slice.call( el.children ).forEach( function(opt) {
132
options += createOptionHTML(opt);
134
options += '</ul></li>';
138
var opts_el = '<div class="cs-options"><ul>' + options + '</ul></div>';
139
this.selEl = document.createElement( 'div' );
140
this.selEl.className = this.el.className;
141
this.selEl.tabIndex = this.el.tabIndex;
142
this.selEl.innerHTML = '<span class="cs-placeholder">' + this.selectedOpt.textContent + '</span>' + opts_el;
143
this.el.parentNode.appendChild( this.selEl );
144
this.selEl.appendChild( this.el );
150
SelectFx.prototype._initEvents = function() {
154
this.selPlaceholder.addEventListener( 'click', function() {
155
self._toggleSelect();
159
this.selOpts.forEach( function(opt, idx) {
160
opt.addEventListener( 'click', function() {
162
self._changeOption();
164
self._toggleSelect();
169
document.addEventListener( 'click', function(ev) {
170
var target = ev.target;
171
if( self._isOpen() && target !== self.selEl && !hasParent( target, self.selEl ) ) {
172
self._toggleSelect();
177
this.selEl.addEventListener( 'keydown', function( ev ) {
178
var keyCode = ev.keyCode || ev.which;
184
self._navigateOpts('prev');
189
self._navigateOpts('next');
194
if( self._isOpen() && typeof self.preSelCurrent != 'undefined' && self.preSelCurrent !== -1 ) {
195
self._changeOption();
197
self._toggleSelect();
202
if( self._isOpen() && typeof self.preSelCurrent != 'undefined' && self.preSelCurrent !== -1 ) {
203
self._changeOption();
204
self._toggleSelect();
210
if( self._isOpen() ) {
211
self._toggleSelect();
221
SelectFx.prototype._navigateOpts = function(dir) {
222
if( !this._isOpen() ) {
223
this._toggleSelect();
226
var tmpcurrent = typeof this.preSelCurrent != 'undefined' && this.preSelCurrent !== -1 ? this.preSelCurrent : this.current;
228
if( dir === 'prev' && tmpcurrent > 0 || dir === 'next' && tmpcurrent < this.selOptsCount - 1 ) {
230
this.preSelCurrent = dir === 'next' ? tmpcurrent + 1 : tmpcurrent - 1;
234
$(this.selOpts[this.preSelCurrent]).addClass('cs-focus');
242
SelectFx.prototype._toggleSelect = function() {
246
if( this._isOpen() ) {
247
if( this.current !== -1 ) {
249
this.selPlaceholder.textContent = this.selOpts[ this.current ].textContent;
251
$(this.selEl).removeClass('cs-active');
254
if( this.hasDefaultPlaceholder && this.options.stickyPlaceholder ) {
256
this.selPlaceholder.textContent = this.selectedOpt.textContent;
258
$(this.selEl).addClass('cs-active');
265
SelectFx.prototype._changeOption = function() {
267
if( typeof this.preSelCurrent != 'undefined' && this.preSelCurrent !== -1 ) {
268
this.current = this.preSelCurrent;
269
this.preSelCurrent = -1;
273
var opt = this.selOpts[ this.current ];
276
this.selPlaceholder.textContent = opt.textContent;
279
this.el.value = opt.getAttribute( 'data-value' );
282
var oldOpt = this.selEl.querySelector( 'li.cs-selected' );
284
$(oldOpt).removeClass('cs-selected');
286
$(opt).addClass('cs-selected');
289
if( opt.getAttribute( 'data-link' ) ) {
291
if( this.options.newTab ) {
292
window.open( opt.getAttribute( 'data-link' ), '_blank' );
295
window.location = opt.getAttribute( 'data-link' );
300
this.options.onChange( this.el.value );
306
SelectFx.prototype._isOpen = function(opt) {
307
return $(this.selEl).hasClass('cs-active');
313
SelectFx.prototype._removeFocus = function(opt) {
314
var focusEl = this.selEl.querySelector( 'li.cs-focus' )
316
$(focusEl).removeClass('cs-focus' );
323
window.SelectFx = SelectFx;