why.xingtongworld.com项目
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
 
 
 
 
 

1599 lines
56 KiB

(function($) {
// @@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@ //
// ----------------------------------------- DATA ----------------------------------------- //
// @@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@ //
var Data = {
// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ defaults
//default settings values
defaults: {
//style
width: '100%',
size: 'medium',
themes: [],
//texts
placeholder: 'Select an item',
//controls
removable: false,
empty: false,
search: false,
//ajax
ajax: false,
data: {},
//positionning
scrollContainer: null
},
// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ setDefaults
//set default settings values
setup: function(opts) {
//controls provided settings keys
var defKeys = Object.keys(this.defaults);
var optKeys = Object.keys(opts);
var isOk = true;
optKeys.forEach(function(k) {
if($.inArray(k, defKeys) === -1) {
console.error('selectMania | wrong setup settings');
isOk = false;
}
});
//if provided settings are ok
if(isOk) {
this.defaults = $.extend(true, {}, Data.defaults, opts);
}
}
};
// @@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@ //
// ---------------------------------------- ENGINE ---------------------------------------- //
// @@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@ //
var Engine = {
// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ internalSettings
//insert internal data into settings object
internalSettings: function($originalSelect, settings) {
var thisEngine = this;
//initialize interal data
settings.multiple = false;
settings.values = [];
//if select is multiple
settings.multiple = $originalSelect.is('[multiple]');
//if select is disabled
settings.disabled = $originalSelect.is('[disabled]');
//loop through selected options
$originalSelect.find('option:selected').each(function() {
//insert selected value data
settings.values.push({
value: this.value,
text: this.text
});
});
//send back settings
return settings;
},
// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ getAttrSettings
//get selectMania settings stored as attributes
getAttrSettings: function($originalSelect) {
var attrData = {};
//available attributes
var attrs = ['width','size','placeholder','removable','empty','search','scrollContainer'];
//loop through attributes
attrs.forEach(function(attr) {
//if attribute is set on select
if($originalSelect.is('[data-'+attr+']')) {
//insert data
var elAttr = $originalSelect.attr('data-'+attr);
if(elAttr === 'true' || elAttr === 'false') {
elAttr = elAttr === 'true';
}
attrData[attr] = elAttr;
}
});
//send back select attributes data
return attrData;
},
// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ initialize
//initialize selectMania on original select
initialize: function($originalSelect, userSettings) {
var thisEngine = this;
//clone settings before starting work
var settings = $.extend(true, {}, userSettings);
//get select settings stored as attributes
var attrSettings = thisEngine.getAttrSettings($originalSelect);
//merge settings with attributes
settings = $.extend(settings, attrSettings);
//set selected value as empty if explicitly asked
if(settings.empty) {
$originalSelect.val('');
}
//insert internal data into settings
settings = thisEngine.internalSettings($originalSelect, settings);
//control ajax function type and size
if(thisEngine.controlSettings($originalSelect, settings)) {
//build selectMania elements
var $builtSelect = Build.build($originalSelect, settings);
//attach original select element to selectMania element
$builtSelect.data('selectMania-originalSelect', $originalSelect);
//attach selectMania element to original select element
$originalSelect.data('selectMania-element', $builtSelect);
//if ajax is activated
if(settings.ajax !== false) {
//initialize ajax data
thisEngine.initAjax($builtSelect, settings);
}
//update clean values icon display
thisEngine.updateClean($builtSelect);
//add witness / hding class original select element
$originalSelect.addClass('select-mania-original');
//insert selectMania element before original select
$builtSelect.insertBefore($originalSelect);
//move original select into selectMania element
$originalSelect.appendTo($builtSelect);
//bind selectMania element
Binds.bind($builtSelect);
}
},
// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ update
//update selectMania element according to original select element
update: function($originalSelect) {
var thisEngine = this;
//selectMania elements
$selectManiaEl = $originalSelect.data('selectMania-element');
$valueList = $selectManiaEl.find('.select-mania-values').first();
$itemList = $selectManiaEl.find('.select-mania-items').first();
//update disabled status
if($originalSelect.is('[disabled]')) {
$selectManiaEl.addClass('select-mania-disabled');
}
else {
$selectManiaEl.removeClass('select-mania-disabled');
}
//remove selectMania values and items
$selectManiaEl.find('.select-mania-value').remove();
$itemList.empty();
//build and insert selected values
$originalSelect.find('option:selected').each(function() {
if($(this).is(':selected')) {
$valueList.append(Build.buildValue({
value: this.value,
text: this.text
}));
}
});
//build and insert items
$itemList.append(Build.buildItemList($originalSelect.children()));
//update clean values icon display
thisEngine.updateClean($selectManiaEl);
//rebind selectMania element
Binds.bind($selectManiaEl);
},
// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ destroy
//destroy selectMania on targeted original select
destroy: function($originalSelect) {
//selectMania element
$selectManiaEl = $originalSelect.data('selectMania-element');
//move original select out of the selectMania element
$originalSelect.insertAfter($selectManiaEl);
//remove selectMania element
$selectManiaEl.remove();
//remove class from original select
$originalSelect.removeClass('select-mania-original');
},
// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ openDropdown / closeDropdown
//open items dropdown
openDropdown: function($dropdown) {
var thisEngine = this;
//select-mania element
var $selectManiaEl = $dropdown.closest('.select-mania');
//if scroll container option is set
if($selectManiaEl.is('[data-selectMania-scrollContainer]')) {
//scroll container element
var $scrollContainer = $($selectManiaEl.attr('data-selectMania-scrollContainer'));
//position absolute dropdown
Engine.positionDropdown($dropdown);
//apply positionning class
$dropdown.addClass('select-mania-absolute');
//bind scroll container to close dropdown on scroll
$scrollContainer.off('scroll.selectMania').on('scroll.selectMania', function() {
//unbind close dropdown on scrolling
$scrollContainer.off('scroll.selectMania');
//close open dropdown
Engine.closeDropdown($('.select-mania-dropdown.open'));
});
//reposition dropdown when window is resized
$(window).off('resize.selectMania').on('resize.selectMania', function() {
//position absolute dropdown
Engine.positionDropdown($dropdown);
});
}
//open dropdown
$dropdown.stop().addClass('open').slideDown(100);
//scroll dropdown to top
$dropdown.find('.select-mania-items').scrollTop(0);
//focus search input
thisEngine.focusSearch($dropdown);
//bind keyboard control
$(document).off('keydown.selectMania').on('keydown.selectMania', Binds.keyboardControl);
},
//close items dropdown
closeDropdown: function($dropdown) {
var $selectManiaEl = $dropdown.data('selectMania-element');
//unbind keyboard control
$(document).off('keydown.selectMania');
//remove every hover class from items
$dropdown.find('.select-mania-item').removeClass('select-mania-hover');
//if dropdown has aboslute positionning
if($dropdown.hasClass('select-mania-absolute')) {
//select-mania inner element
var $selectManiaInner = $dropdown
.data('selectMania-element')
.find('.select-mania-inner')
.first();
//move back the dropdown inside select-mania element
$dropdown
.removeClass('open')
.hide()
.insertAfter(
$selectManiaInner
);
//unbind repositioning on resize
$(window).off('resize.selectMania');
//unbind close dropdown on scrolling
var $scrollContainer = $($selectManiaEl.attr('data-selectMania-scrollContainer'));
if($scrollContainer.length > 0) {
$scrollContainer.off('scroll.selectMania');
}
}
//if dropdown has standard positionning
else {
//close dropdown
$dropdown.stop().removeClass('open').slideUp(100);
}
},
// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ positionDropdown
//position dropdown relative to its select-mania element
positionDropdown: function($dropdown) {
var $selectManiaEl = $dropdown.data('selectMania-element');
//item list scroll data
var $itemList = $dropdown.find('.select-mania-items');
var itemListScroll = $itemList.scrollTop();
//data for calculating dropdown absolute position
var selectManiaElPos = $selectManiaEl.offset();
var selectManiaElWidth = $selectManiaEl.outerWidth();
var selectManiaElHeight = $selectManiaEl.outerHeight();
//append dropdown to body in absolute position
$dropdown.appendTo('body').css({
position: 'absolute',
top: selectManiaElPos.top + selectManiaElHeight,
left: selectManiaElPos.left,
width: selectManiaElWidth
});
//force item list scroll to its initial state
$itemList.scrollTop(itemListScroll);
},
// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ selectItem
//perform item selection in dropdown
selectItem: function($item) {
//dropdown element
var $dropdown = $item.closest('.select-mania-dropdown');
//selectMania element
var $selectManiaEl = $dropdown.data('selectMania-element');
//select original element
var $originalSelect = $selectManiaEl.data('selectMania-originalSelect');
//if item not already selected
if(!$item.is('.select-mania-selected')) {
//clicked item value
var itemVal = $item.attr('data-value');
//build value element
var $value = Build.buildValue({
value: itemVal,
text: $item.text()
});
//if select multiple
if($selectManiaEl.is('.select-mania-multiple')) {
//insert value element in selectMania values
$selectManiaEl.find('.select-mania-values').append($value);
//add value in original select element
Engine.addMultipleVal($originalSelect, itemVal);
}
//if select not multiple
else {
//unselect every other items
$dropdown.find('.select-mania-item').removeClass('select-mania-selected');
//insert value element in selectMania values
$selectManiaEl.find('.select-mania-values .select-mania-value').remove();
$selectManiaEl.find('.select-mania-values').append($value);
//change value in original select element
$originalSelect.val(itemVal);
}
//set clicked item as selected
$item.addClass('select-mania-selected');
//trigger original select change event
$originalSelect.trigger('change');
}
//if absolute position dropdown
if($dropdown.is('.select-mania-absolute')) {
//position absolute dropdown
Engine.positionDropdown($dropdown);
}
//if select not multiple
if(!$selectManiaEl.is('.select-mania-multiple')) {
//close dropdown
Engine.closeDropdown($dropdown);
}
//update clear values icon display
Engine.updateClean($selectManiaEl);
//rebind selectMania element
Binds.bind($selectManiaEl);
},
// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ focusSearch
//focus search input in dropdown
focusSearch: function($dropdown) {
$dropdown.find('.select-mania-search-input').focus();
},
// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ addMultipleVal
//add value to multiple original select
addMultipleVal: function($originalSelect, val) {
var originalVals = $originalSelect.val();
if(!(originalVals instanceof Array)) {
originalVals = [];
}
originalVals.push(val);
$originalSelect.val(originalVals);
},
// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ removeMultipleVal
//remove value from multiple original select
removeMultipleVal: function($originalSelect, val) {
var originalVals = $originalSelect.val();
if(!(originalVals instanceof Array)) {
originalVals = [];
}
originalVals.splice($.inArray(val, originalVals), 1);
$originalSelect.val(originalVals);
},
// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ updateClean
//display / hide clean values icon according to current values
updateClean: function($selectManiaEl) {
//original select element
var $originalSelect = $selectManiaEl.data('selectMania-originalSelect');
//if value is not empty
if($originalSelect.val() !== null && $originalSelect.val().length > 0) {
//display clean values icon
$selectManiaEl.find('.select-mania-clear-icon').show();
}
//if empty value
else {
//hide clean values icon
$selectManiaEl.find('.select-mania-clear-icon').hide();
}
},
// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ doSearch
//do search in items dropdown
doSearch: function($selectManiaEl) {
//dropdown
var $dropdown = $selectManiaEl.data('selectMania-dropdown');
//search value
var searchVal = $dropdown.find('.select-mania-search-input').first().val();
searchVal = searchVal.toLowerCase().trim();
//if empty search value
if(searchVal === '') {
//display all items
$dropdown.find('.select-mania-group, .select-mania-item').removeClass('select-mania-hidden');
//stop function
return;
}
//loop through dropdown items
$dropdown.find('.select-mania-item').each(function() {
//if item text matches search value
if($(this).text().toLowerCase().indexOf(searchVal) !== -1) {
//display item
$(this).removeClass('select-mania-hidden');
}
//if item text don't match search value
else {
//hide item
$(this).addClass('select-mania-hidden');
}
});
//show / hide optgroups if contain results / empty
$dropdown.find('.select-mania-group').each(function() {
if($(this).find('.select-mania-item:not(.select-mania-hidden)').length > 0) {
$(this).removeClass('select-mania-hidden');
}
else {
$(this).addClass('select-mania-hidden');
}
});
},
// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ doSearchAjax
//do ajax search in items dropdown
doSearchAjax: function($selectManiaEl) {
var thisEngine = this;
//dropdown
var $dropdown = $selectManiaEl.data('selectMania-dropdown');
//search value
var thisSearch = $dropdown.find('.select-mania-search-input').first().val();
//pause ajax scroll
$selectManiaEl.data('selectMania-ajaxReady', false);
//reset current page number
$selectManiaEl.data('selectMania-ajaxPage', 1);
//loading icon
thisEngine.dropdownLoading($selectManiaEl);
//call ajax function
var thisAjaxFunction = $selectManiaEl.data('selectMania-ajaxFunction');
var thisAjaxData = $selectManiaEl.data('selectMania-ajaxData');
thisAjaxFunction(thisSearch, 1, thisAjaxData, function(optHTML) {
//remove loading icon
thisEngine.dropdownLoading($selectManiaEl, true);
//replace current items with sent options
Engine.replaceItems($selectManiaEl, optHTML);
//rebind select
Binds.bind($selectManiaEl);
//reset ajax scroll data
thisEngine.initAjax($selectManiaEl);
});
},
// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ addItems / replaceItems
//add items to dropdown
addItems: function($selectManiaEl, optionsHTML) {
var thisEngine = this;
thisEngine.addOrReplaceItems($selectManiaEl, optionsHTML, false);
},
//replace dropdown items
replaceItems: function($selectManiaEl, optionsHTML) {
var thisEngine = this;
thisEngine.addOrReplaceItems($selectManiaEl, optionsHTML, true);
},
//add / replace dropdown items
addOrReplaceItems: function($selectManiaEl, optionsHTML, replace) {
var thisEngine = this;
//dropdown
var $dropdown = $selectManiaEl.data('selectMania-dropdown');
//original select element
var $originalSelect = $selectManiaEl.data('selectMania-originalSelect');
//items dropdown
var $itemsContainer = $dropdown.find('.select-mania-items');
//options jquery parsing
var $options = $(optionsHTML);
//get selectMania element values
var selectedVals = thisEngine.getVal($selectManiaEl);
//loop through selected values
selectedVals.forEach(function(val) {
$options
//search for options matching selected value
.filter(function() {
return $(this).attr('value') === val.value && $(this).text() === val.text;
})
//set matching options as selected
.prop('selected', true);
});
//build items list
$builtItems = Build.buildItemList($options);
//if items are meant to be replaced
if(replace === true) {
//empty old options except selected ones
$originalSelect.find('option').remove(':not(:checked)');
//empty items dropdown
$itemsContainer.empty();
}
//add items to selectMania dropdown
$itemsContainer.append($builtItems);
//add options to original select element
$originalSelect.append($options);
//rebind selectMania element
Binds.bind($selectManiaEl);
},
// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ initAjax
//reset selectMania element ajax data and attach ajax function
initAjax: function($selectManiaEl, settings) {
//if ajax settings are provided to be attached
if(typeof settings === 'object') {
//attach ajax function
if(settings.hasOwnProperty('ajax') && typeof settings.ajax === 'function') {
$selectManiaEl.data('selectMania-ajaxFunction', settings.ajax);
}
//attach ajax data
if(settings.hasOwnProperty('data') && typeof settings.data === 'object') {
$selectManiaEl.data('selectMania-ajaxData', settings.data);
}
}
//reset ajax data
$selectManiaEl.data('selectMania-ajaxPage', 1);
$selectManiaEl.data('selectMania-ajaxReady', true);
$selectManiaEl.data('selectMania-ajaxScrollDone', false);
},
// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ dropdownLoading
//display / hide loading icon inside items dropdown
dropdownLoading: function($selectManiaEl, hide) {
//if hide icon requested
var isHide = false;
if(typeof hide !== 'undefined' && hide === true) {
isHide = true;
}
//dropdown inner list element
$dropdownContainer = $selectManiaEl.find('.select-mania-items-container').first();
//remove loading icon if exists
$dropdownContainer.find('.icon-loading-container').remove();
//if show icon requested
if(isHide !== true) {
//build loading icon
var $loadingIcon = $('<div class="icon-loading-container"></div>');
$loadingIcon.append('<i class="icon-loading"></i>');
//insert loading icon
$dropdownContainer.append($loadingIcon);
}
},
// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ getVal
//get parsed selected values
getVal: function($selectManiaEl) {
var valObjs = [];
//loop though values elements
$selectManiaEl.find('.select-mania-value').each(function() {
//selected value text
var thisText = $(this).find('.select-mania-value-text').first().text();
//insert selected value object
valObjs.push({
value: $(this).attr('data-value'),
text: thisText
});
});
//send back parsed selected values
return valObjs;
},
// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ clear
//clear select values
clear: function($selectManiaEl) {
//dropdown
var $dropdown = $selectManiaEl.data('selectMania-dropdown');
//empty selectMania values
$selectManiaEl.find('.select-mania-value').remove();
//unselect items in dropdown
$dropdown.find('.select-mania-item').removeClass('select-mania-selected');
//empty values in original select element
var $originalSelect = $selectManiaEl.data('selectMania-originalSelect');
if($selectManiaEl.is('.select-mania-multiple')) {
$originalSelect.val([]);
}
else {
$originalSelect.val('');
}
},
// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ setVal
//set parsed values as selected values
setVal: function($selectManiaEl, valObjs) {
var thisEngine = this;
//original select element
var $originalSelect = $selectManiaEl.data('selectMania-originalSelect');
//clear select values before setting provided values
thisEngine.clear($selectManiaEl);
//if there's more than one value in the values and select is not multiple
if(valObjs.length > 1 && !$selectManiaEl.is('.select-mania-multiple')) {
//keep only first value
valObjs = valObjs.slice(0, 1);
}
//loop through values
valObjs.forEach(function(val) {
//parse value object
var valObj = $.extend({
value: '',
text: '',
selected: true
}, val);
//set value in selectMania element
thisEngine.setOneValSelectMania($selectManiaEl, valObj);
//set value in original select
thisEngine.setOneValOriginal($originalSelect, valObj);
});
//update clean values icon display
thisEngine.updateClean($selectManiaEl);
//rebind selectMania element
Binds.bind($selectManiaEl);
},
//set one value on selectMania element
setOneValSelectMania: function($selectMania, valObj) {
//build value element for selectMania element
var $value = Build.buildValue(valObj);
//insert built value element in selectMania element
$selectMania.find('.select-mania-values').append($value);
//check if corresponding item exists in dropdown
var $searchItem = $selectMania.find('.select-mania-item[data-value="'+valObj.value+'"]').filter(function() {
return $(this).text() === valObj.text;
});
//if item exists in dropdown
if($searchItem.length > 0) {
//set item as selected
$searchItem.first().addClass('select-mania-selected');
}
},
//set one value on original select element
setOneValOriginal: function($originalSelect, valObj) {
//check if corresponding option exists in original select
var $searchOpt = $originalSelect.find('option[value="'+valObj.value+'"]').filter(function() {
return $(this).text() === valObj.text;
});
//if option doesn't exist in original select
if($searchOpt.length < 1) {
//build option for original select
var $option = Build.buildOption(valObj);
//insert built option in original select
$originalSelect.append($option);
}
//if option already exists in original select
else {
//fond option element
var $foundOption = $searchOpt.first();
//set option as selected
$foundOption[0].selected = true;
}
},
// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ controls
//control target element
controlTarget: function($target, controls) {
//error if element is not a select
if($.inArray('isSelect', controls) !== -1 && !$target.is('select')) {
console.error('selectMania | invalid select element');
console.log($target[0]);
return false;
}
//error if plugin not initialized
if($.inArray('isInitialized', controls) !== -1 && !$target.hasClass('select-mania-original')) {
console.error('selectMania | select is not initialized');
console.log($target[0]);
return false;
}
//error if plugin already initialized
if($.inArray('notInitialized', controls) !== -1 && $target.hasClass('select-mania-original')) {
console.error('selectMania | ignore because already initialized');
console.log($target[0]);
return false;
}
//control method was called on single element
if($.inArray('isSingle', controls) !== -1 && $target.length > 1) {
console.error('selectMania | check method can be called on single element only');
console.log($target[0]);
return false;
}
//if control ok
return true;
},
//control selectMania settings
controlSettings: function($target, settings) {
//control ajax function type
if(settings.ajax !== false && typeof settings.ajax !== 'function') {
settings.ajax = false;
console.error('selectMania | invalid ajax function');
console.log($target[0]);
console.log(settings);
return false;
}
//error if invalid size provided
if($.inArray(settings.size, ['tiny','small','medium','large']) === -1) {
settings.size = 'medium';
console.error('selectMania | invalid size');
console.log($target[0]);
console.log(settings);
return false;
}
//error if invalid sroll container provided
if(settings.scrollContainer !== null && $(settings.scrollContainer).length < 1) {
settings.scrollContainer = null;
console.error('selectMania | invalid scroll container');
console.log($target[0]);
console.log(settings);
return false;
}
//if control ok
return true;
},
//control selectMania values
controlValues: function($target, values) {
//error if values is not an array
if(!(values instanceof Array)) {
console.error('selectMania | values parameter is not a valid array');
console.log($target[0]);
console.log(values);
return false;
}
//if control ok
return true;
},
// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ navigateItem
//navigate hover to next or previous item in dropdown
navigateItem: function($dropdown, nextOrPrevious) {
//selectMania element
var $selectManiaEl = $dropdown.closest('.select-mania');
//item scrollable list
var $itemList = $dropdown.find('.select-mania-items');
//active enabled items
var validItemSelector = '.select-mania-item:not(.select-mania-disabled):not(.select-mania-hidden)';
if($selectManiaEl.hasClass('select-mania-multiple')) {
validItemSelector += ':not(.select-mania-selected)';
}
var $validItems = $dropdown.find(validItemSelector);
//current hovered item
var $hoveredItem = $dropdown.find(validItemSelector+'.select-mania-hover');
//item to target
var $targetItem = $();
//if there is currently a hovered item
if($hoveredItem.length > 0) {
//if arrow up get previous item
if(nextOrPrevious === 'next') {
$targetItem = $validItems.slice($validItems.index($hoveredItem) + 1).first();
}
//if arrow down get next item
else if(nextOrPrevious === 'previous') {
$targetItem = $validItems.slice(0, $validItems.index($hoveredItem)).last();
}
}
//no current hovered item
else {
//hovers first item
$targetItem = $validItems.first();
}
//if target item exists hover this item
if($targetItem.length > 0) {
//remove hover from every item
$dropdown.find('.select-mania-item').removeClass('select-mania-hover');
//add hover class to target item
$targetItem.addClass('select-mania-hover');
//data for item visibility calculation
var $targetItemPosition = $targetItem.position();
var $targetItemHeight = $targetItem.outerHeight(true);
var $itemListHeight = $itemList.height();
var $itemListScrollTop = $itemList.scrollTop();
//if target item not visible in item list (above)
if($targetItemPosition.top < 0) {
//scroll to see item
$itemList.scrollTop($itemListScrollTop + $targetItemPosition.top);
}
//if target item not visible in item list (below)
else if($targetItemPosition.top + $targetItemHeight > $itemListHeight) {
//scroll to see item
$itemList.scrollTop($itemListScrollTop + $targetItemPosition.top + $targetItemHeight - $itemListHeight);
}
}
}
};
// @@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@ //
// ---------------------------------------- BUILD ----------------------------------------- //
// @@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@ //
var Build = {
// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ build
//build selectMania element
build: function($originalSelect, settings) {
var thisBuild = this;
//class for selectMania size
var sizeClass = 'select-mania-'+settings.size;
//explicit selectMania width style
var widthStyle = 'style="width:'+settings.width+';"';
//general selectMania div
var $selectManiaEl = $('<div class="select-mania '+sizeClass+'" '+widthStyle+'></div>');
//class for multiple
if(settings.multiple) {
$selectManiaEl.addClass('select-mania-multiple');
}
//class for disabled
if(settings.disabled) {
$selectManiaEl.addClass('select-mania-disabled');
}
//classes for themes
if(settings.themes instanceof Array && settings.themes.length > 0) {
//loop through themes
settings.themes.forEach(function(theme) {
//applies theme class
$selectManiaEl.addClass('select-mania-theme-'+theme);
});
}
//class for activated ajax
if(settings.ajax !== false) {
$selectManiaEl.addClass('select-mania-ajax');
}
//attribute for scroll container
if(settings.scrollContainer !== null) {
$selectManiaEl.attr('data-selectMania-scrollContainer', settings.scrollContainer);
}
//build inner elements
var $innerElements = thisBuild.buildInner(settings);
//build dropdown
var $dropdown = thisBuild.buildDropdown($originalSelect, settings);
//insert elements
$selectManiaEl.append($innerElements).append($dropdown);
//attach dropdown to select-mania element
$selectManiaEl.data('selectMania-dropdown', $dropdown);
//attach select-mania element to dropdown
$dropdown.data('selectMania-element', $selectManiaEl);
//send back selectMania element
return $selectManiaEl;
},
// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ buildInner
//build inner elements
buildInner: function(settings) {
var thisBuild = this;
//inner div
var $inner = $('<div class="select-mania-inner"></div>');
//values div
var $values = $('<div class="select-mania-values"></div>');
//insert placeholder
var $placeholder = $('<div class="select-mania-placeholder">'+settings.placeholder+'</div>');
$values.append($placeholder);
//insert selected values
settings.values.forEach(function(val) {
$values.append(thisBuild.buildValue(val));
});
$inner.append($values);
//insert clean values icon
var $clean = $('<div class="select-mania-clear"></div>');
if(settings.removable || settings.multiple) {
$clean.append('<i class="select-mania-clear-icon icon-cross">');
}
$inner.append($clean);
//insert dropdown arrow icon
$inner.append($('<div class="select-mania-arrow"><i class="select-mania-arrow-icon icon-arrow-down"></i></div>'));
//send back inner elements
return $inner;
},
// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ buildValue
//build selected value
buildValue: function(valObj) {
//selected value element html
var valHtml = '<div class="select-mania-value" data-value="'+valObj.value+'">'+
'<div class="select-mania-value-text">'+valObj.text+'</div>'+
'<div class="select-mania-value-clear">'+
'<i class="select-mania-value-clear-icon icon-cross"></i>'+
'</div>'+
'</div>';
//send back selected value element
return $(valHtml);
},
// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ buildOption
//build option for original select
buildOption: function(valObj) {
//build option
var $opt = $('<option value="'+valObj.value+'">'+valObj.text+'</option>');
//set option selected status
$opt[0].selected = valObj.selected;
//send back option element
return $opt;
},
// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ buildDropdown
//build items dropdown
buildDropdown: function($originalSelect, settings) {
var thisBuild = this;
//class for sizing
var sizeClass = 'select-mania-'+settings.size;
//dropdown element
var $dropdown = $('<div class="select-mania-dropdown '+sizeClass+'"></div>');
//insert search input in dropdown if activated
if(settings.search) {
var $dropdownSearch = $('<div class="select-mania-dropdown-search"></div>');
$dropdownSearch.append('<input class="select-mania-search-input" />');
$dropdown.append($dropdownSearch);
}
//build items container
var $itemListContainer = $('<div class="select-mania-items-container"></div>');
var $itemList = $('<div class="select-mania-items"></div>');
//build and insert items list
$itemList.append(thisBuild.buildItemList($originalSelect.children()));
//insert items list into dropdown
$itemListContainer.append($itemList);
$dropdown.append($itemListContainer);
//classes for themes
if(settings.themes instanceof Array && settings.themes.length > 0) {
//loop through themes
settings.themes.forEach(function(theme) {
//applies theme class
$dropdown.addClass('select-mania-theme-'+theme);
});
}
//send back items dropdown
return $dropdown;
},
// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ buildItemGroup
//build items list
buildItemList: function($optList) {
var thisBuild = this;
//empty item list
$itemList = $();
//loop through original select children
$optList.each(function() {
//if optgroup
if($(this).is('optgroup')) {
//build and insert item group
$itemList = $itemList.add(thisBuild.buildItemGroup($(this)));
}
//if option
else if($(this).is('option')) {
//build and insert item
$itemList = $itemList.add(thisBuild.buildItem($(this)));
}
});
//send back build items list
return $itemList;
},
// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ buildItemGroup
//build dropdown items group
buildItemGroup: function($optgroupEl) {
var thisBuild = this;
//build group element
$group = $('<div class="select-mania-group"></div>');
var $groupInner = $('<div class="select-mania-group-inner"></div>');
//build group title element
var $groupTitle = $('<div class="select-mania-group-title"></div>');
//if group icon is set
if($optgroupEl.is('[data-icon]')) {
//insert group title icon
$groupTitle.append('<div class="select-mania-group-icon"><i class="'+$optgroupEl.attr('data-icon')+'"></i></div>');
}
//insert group title text
$groupTitle.append('<div class="select-mania-group-text">'+$optgroupEl.attr('label')+'</div>');
//insert group title in group element
$group.append($groupTitle);
//if group is disabled set class
var groupIsDisabled = $optgroupEl.is(':disabled');
if(groupIsDisabled) {
$group.addClass('select-mania-disabled');
}
//build and insert items
$optgroupEl.find('option').each(function() {
$groupInner.append(thisBuild.buildItem($(this), groupIsDisabled));
});
$group.append($groupInner);
//send back items group
return $group;
},
// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ buildItem
//build dropdown item
buildItem: function($optionEl, forceDisabled) {
var optionEl = $optionEl[0];
//build item html
var $item = $('<div class="select-mania-item" data-value="'+optionEl.value+'"></div>');
//if option icon is set
if($optionEl.is('[data-icon]')) {
//insert item icon
$item.append('<div class="select-mania-item-icon"><i class="'+$optionEl.attr('data-icon')+'"></i></div>');
}
//insert item text
$item.append('<div class="select-mania-item-text">'+optionEl.text+'</div>');
//if item is disabled set class
if($optionEl.is(':disabled') || Tools.def(forceDisabled) === true) {
$item.addClass('select-mania-disabled');
}
//if item is selected add class
if($optionEl.is(':selected')) {
$item.addClass('select-mania-selected');
}
//send back item
return $item;
}
};
// @@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@ //
// ---------------------------------------- BINDS ----------------------------------------- //
// @@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@ //
var Binds = {
// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ bind
//bind all selectMania controls
bind: function($selectManiaEl) {
var thisBinds = this;
//original select element
var $originalSelect = $selectManiaEl.data('selectMania-originalSelect');
//dropdown
var $dropdown = $selectManiaEl.data('selectMania-dropdown');
//if select is not disabled
if(!$selectManiaEl.is('.select-mania-disabled')) {
//click outside select
$(document).off('click.selectMania').on('click.selectMania', thisBinds.documentClick);
//focus / blur original select element
$originalSelect.off('focus.selectMania').on('focus.selectMania', thisBinds.focus);
$originalSelect.off('blur.selectMania').on('blur.selectMania', thisBinds.blur);
//clear values
$selectManiaEl.find('.select-mania-clear-icon').off('click.selectMania').on('click.selectMania', thisBinds.clearValues);
//clear select multiple individual value
$selectManiaEl.find('.select-mania-value-clear-icon').off('click.selectMania').on('click.selectMania', thisBinds.clearValue);
//open / close dropdown
$selectManiaEl.find('.select-mania-inner').off('click.selectMania').on('click.selectMania', thisBinds.dropdownToggle);
//item hover in dropdown
$dropdown.find('.select-mania-item:not(.select-mania-disabled)').off('mouseenter.selectMania').on('mouseenter.selectMania', thisBinds.hoverItem);
//item selection in dropdown
$dropdown.find('.select-mania-item:not(.select-mania-disabled)').off('click.selectMania').on('click.selectMania', thisBinds.itemSelection);
//search input in dropdown
$dropdown.find('.select-mania-search-input').off('input.selectMania').on('input.selectMania', thisBinds.inputSearch);
//prevents body scroll when reached dropdown top or bottom
$dropdown.find('.select-mania-items').off('wheel.selectMania').on('wheel.selectMania', thisBinds.scrollControl);
//ajax scroll
if($selectManiaEl.is('.select-mania-ajax')) {
$dropdown.find('.select-mania-items').off('scroll.selectMania').on('scroll.selectMania', thisBinds.scrollAjax);
}
}
//if select is disabled unbind controls
else {
//focus / blur original select element
$originalSelect.off('focus.selectMania');
$originalSelect.off('blur.selectMania');
//clear values
$selectManiaEl.find('.select-mania-clear-icon').off('click.selectMania');
//clear select multiple individual value
$selectManiaEl.find('.select-mania-value-clear-icon').off('click.selectMania');
//open / close dropdown
$selectManiaEl.find('.select-mania-inner').off('click.selectMania');
//item hover in dropdown
$dropdown.find('.select-mania-item:not(.select-mania-disabled)').off('mouseenter.selectMania');
//item selection in dropdown
$dropdown.find('.select-mania-item:not(.select-mania-disabled)').off('click.selectMania');
//search input in dropdown
$dropdown.find('.select-mania-search-input').off('input.selectMania');
//prevents body scroll when reached dropdown top or bottom
$dropdown.find('.select-mania-items').off('wheel.selectMania');
//ajax scroll
$dropdown.find('.select-mania-items').off('scroll.selectMania');
}
},
// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ dropdownToggle
//BIND ONLY - open / close dropdown
dropdownToggle: function(e) {
e.stopPropagation();
//select-mania element
var $selectManiaEl = $(this).closest('.select-mania');
//dropdown element
var $dropdown = $selectManiaEl.data('selectMania-dropdown');
//if dropdown open
if($dropdown.is('.open')) {
//close dropdown
Engine.closeDropdown($dropdown);
}
//if dropdown closed
else {
//close every open dropdown
Engine.closeDropdown($('.select-mania-dropdown.open'));
//open target dropdown
Engine.openDropdown($dropdown);
}
},
// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ documentClick
//BIND ONLY - click outside select
documentClick: function(e) {
//if click not in open dropdown
if($(e.target).closest('.select-mania-dropdown').length < 1) {
//close every open dropdown
Engine.closeDropdown($('.select-mania-dropdown.open'));
}
},
// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ clearValues
//BIND ONLY - clear values
clearValues: function(e) {
e.stopPropagation();
//selectMania element
var $selectManiaEl = $(this).closest('.select-mania');
//dropdown
var $dropdown = $selectManiaEl.data('selectMania-dropdown');
//original select element
var $originalSelect = $selectManiaEl.data('selectMania-originalSelect');
//clear values
Engine.clear($selectManiaEl);
//if absolute position dropdown
if($dropdown.is('.select-mania-absolute')) {
//position absolute dropdown
Engine.positionDropdown($dropdown);
}
//trigger original select change event
$originalSelect.trigger('change');
//update clear values icon display
Engine.updateClean($selectManiaEl);
},
// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ clearValue
//BIND ONLY - clear select multiple individual value
clearValue: function(e) {
e.stopPropagation();
//selectMania element
var $selectManiaEl = $(this).closest('.select-mania');
//dropdown
var $dropdown = $selectManiaEl.data('selectMania-dropdown');
//value to delete
var $value = $(this).closest('.select-mania-value');
//unselect item in dropdown
$dropdown
.find('.select-mania-item[data-value="'+$value.attr('data-value')+'"]')
.removeClass('select-mania-selected');
//remove value from selectMania element
$value.remove();
//remove value from original select element
var $originalSelect = $selectManiaEl.data('selectMania-originalSelect');
Engine.removeMultipleVal($originalSelect, $value.attr('data-value'));
//if absolute position dropdown
if($dropdown.is('.select-mania-absolute')) {
//position absolute dropdown
Engine.positionDropdown($dropdown);
}
//trigger original select change event
$originalSelect.trigger('change');
//update clear values icon display
Engine.updateClean($selectManiaEl);
},
// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ itemSelection
//BIND ONLY - item selection in dropdown
itemSelection: function() {
var $selectedItem = $(this);
//select item in dropdown
Engine.selectItem($selectedItem);
},
// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ inputSearch
//BIND ONLY - dropdown search input
inputSearch: function() {
var $input = $(this);
//selectMania element
$selectManiaEl = $input.closest('.select-mania-dropdown').data('selectMania-element');
//timer duration according to select multiple or not
var thisTime = 200;
if($selectManiaEl.is('.select-mania-ajax')) {
thisTime = 400;
}
//clear timeout
clearTimeout($input.data('selectMania-searchTimer'));
//search input timeout
$input.data('selectMania-searchTimer', setTimeout(function() {
//ajax search
if($selectManiaEl.is('.select-mania-ajax')) {
Engine.doSearchAjax($selectManiaEl);
}
//normal search
else {
Engine.doSearch($selectManiaEl);
}
}, thisTime));
},
// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ scrollAjax
//BIND ONLY - dropdown ajax scroll
scrollAjax: function(e) {
var $itemList = $(this);
//dropdown element
var $dropdown = $itemList.closest('.select-mania-dropdown');
//selectMania element
var $selectManiaEl = $dropdown.data('selectMania-element');
//if ajax scroll is not over
if($selectManiaEl.data('selectMania-ajaxScrollDone') !== true) {
//if scroll reached bottom with 12px tolerance
if($itemList.scrollTop() >= $itemList[0].scrollHeight - $itemList.outerHeight() - 12) {
//if ajax scroll is ready
if($selectManiaEl.data('selectMania-ajaxReady') === true) {
//page number to call
var thisPage = $selectManiaEl.data('selectMania-ajaxPage') + 1;
//search value
var thisSearch = $selectManiaEl.find('.select-mania-search-input').first().val();
//pause ajax scroll
$selectManiaEl.data('selectMania-ajaxReady', false);
//enregistre nouvelle page en cours
$selectManiaEl.data('selectMania-ajaxPage', thisPage);
//loading icon
Engine.dropdownLoading($selectManiaEl);
//call ajax function
var thisAjaxFunction = $selectManiaEl.data('selectMania-ajaxFunction');
var thisAjaxData = $selectManiaEl.data('selectMania-ajaxData');
thisAjaxFunction(thisSearch, thisPage, thisAjaxData, function(optHTML) {
//remove loading icon
Engine.dropdownLoading($selectManiaEl, true);
//if options returned
if(optHTML.trim() !== '') {
//add items to dropdown from sent options
Engine.addItems($selectManiaEl, optHTML);
//rebind selectMania element
Binds.bind($selectManiaEl);
//set ajax scroll as ready
$selectManiaEl.data('selectMania-ajaxReady', true);
}
//if no options sent back
else {
//ajax scroll is over
$selectManiaEl.data('selectMania-ajaxScrollDone', true);
}
});
}
}
}
},
// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ scrollControl
//BIND ONLY - prevents body scroll when reached dropdown top or bottom
scrollControl: function(e) {
var $thisDropdown = $(this);
if(e.originalEvent.deltaY < 0) {
return ($thisDropdown.scrollTop() > 0);
}
else {
return($thisDropdown.scrollTop() + $thisDropdown.innerHeight() < $thisDropdown[0].scrollHeight);
}
},
// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ focus / blur
//BIND ONLY - focus selectMania when original select is focused
focus: function(e) {
var $originalSelect = $(this);
//selectMania element
var $selectManiaEl = $originalSelect.data('selectMania-element');
//add focus class to selectMania element
$selectManiaEl.addClass('select-mania-focused');
//bind keyboard dropdown opening
$originalSelect.off('keydown.selectMania').on('keydown.selectMania', Binds.keyboardOpening);
},
//BIND ONLY - unfocus selectMania when original select is focused
blur: function(e) {
var $originalSelect = $(this);
//selectMania element
var $selectManiaEl = $originalSelect.data('selectMania-element');
//remove focus class from selectMania element
$selectManiaEl.removeClass('select-mania-focused');
//unbind keyboard dropdown opening
$originalSelect.off('keydown.selectMania');
},
// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ hoverItem
//BIND ONLY - hover status on dropdown items
hoverItem: function(e) {
var $item = $(this);
//dropdown
var $dropdown = $item.closest('.select-mania-dropdown');
//remove hover from every item
$dropdown.find('.select-mania-item').removeClass('select-mania-hover');
//apply hover class
$item.addClass('select-mania-hover');
},
// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ keyboardOpening / keyboardControl
//BIND ONLY - keyboard dropdown opening
keyboardOpening: function(e) {
var $originalSelect = $(this);
//selectMania element
var $selectManiaEl = $originalSelect.data('selectMania-element');
//dropdown
var $dropdown = $selectManiaEl.data('selectMania-dropdown');
//list of key codes triggering opening beside characters (enter, spacebar, arrow keys)
var openingKeys = [13,32,37,38,39,40];
//if dropdown is closed and triggering key pressed
if(!$dropdown.hasClass('open') && $.inArray(e.keyCode, openingKeys) !== -1) {
e.preventDefault();
e.stopPropagation();
//unfocus original select
$originalSelect.blur();
//opens dropdown
Engine.openDropdown($dropdown);
}
},
//BIND ONLY - keyboard control within dropdown
keyboardControl: function(e) {
//currently open dropdown
var $dropdown = $('.select-mania-dropdown.open').first();
//list of control keys (tab, enter, escape, arrow up, arrow down)
var controlKeys = [9,13,27,38,40];
//if a selectMania dropdown is open and key pressed is a control key
if($dropdown.length > 0 && $.inArray(e.keyCode, controlKeys) !== -1) {
e.preventDefault();
e.stopPropagation();
//switch key pressed
switch(e.keyCode) {
//enter
case 13:
//currently hovered element
var $hoverItem = $dropdown.find('.select-mania-item:not(.select-mania-disabled):not(.select-mania-hidden).select-mania-hover').first();
//if hovered element exists
if($hoverItem.length > 0) {
//select item in dropdown
Engine.selectItem($hoverItem);
}
break;
//tab
case 9:
//escape
case 27:
//close dropdown
Engine.closeDropdown($dropdown);
break;
//arrow up
case 38:
//hover previous item in dropdown
Engine.navigateItem($dropdown, 'previous');
break;
//arrow down
case 40:
//hover next item in dropdown
Engine.navigateItem($dropdown, 'next');
break;
}
}
}
};
// @@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@ //
// ---------------------------------------- TOOLS ----------------------------------------- //
// @@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@ //
var Tools = {
// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ def
//force null if var is undefined
def: function(v) {
if(typeof v === 'undefined') {
return null;
}
return v;
}
};
// @@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@ //
// --------------------------------------- METHODS --------------------------------------- //
// @@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@ //
var Methods = {
// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ init
//initialize selectMania
init: function(opts) {
//settings provided by user
var settings = $.extend(true, {}, Data.defaults, opts);
//loop through targeted elements
return this.each(function() {
//current select to initialize
var $originalSelect = $(this);
//controls if element is a select and plugin is not already initialized
if(Engine.controlTarget($originalSelect, ['isSelect','notInitialized'])) {
//initialize selectMania on original select
Engine.initialize($originalSelect, settings);
}
});
},
// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ update
//update selectMania items and values
update: function() {
//loop through targeted elements
return this.each(function() {
//current select to destroy
var $originalSelect = $(this);
//controls if selectMania initialized
if(Engine.controlTarget($originalSelect, ['isInitialized'])) {
//update selectMania
Engine.update($originalSelect);
}
});
},
// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ destroy
//destroy selectMania
destroy: function() {
//loop through targeted elements
return this.each(function() {
//current select to destroy
var $originalSelect = $(this);
//controls if selectMania initialized
if(Engine.controlTarget($originalSelect, ['isInitialized'])) {
//destroy selectMania
Engine.destroy($originalSelect);
}
});
},
// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ check
//check if selectMania initialized
check: function() {
//controls method was called on single element
if(Engine.controlTarget(this, ['isSingle'])) {
//send back if plugin initialized or not
return this.hasClass('select-mania-original');
}
},
// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ get
//returns parsed selected values
get: function() {
//controls if single element and plugin initialized
if(Engine.controlTarget(this, ['isSingle','isInitialized'])) {
//selectMania element
var $selectManiaEl = this.data('selectMania-element');
//get and return parsed selected values
return Engine.getVal($selectManiaEl);
}
},
// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ set
//set parsed values as selected values
set: function(values) {
//controls if single element and plugin initialized
if(Engine.controlTarget(this, ['isSingle','isInitialized'])) {
//controls values are valid
if(Engine.controlValues(this, values)) {
//selectMania element
var $selectManiaEl = this.data('selectMania-element');
//get and return parsed selected values
Engine.setVal($selectManiaEl, values);
}
}
},
// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ clear
//clear values
clear: function() {
//loop through targeted elements
return this.each(function() {
//current select to destroy
var $originalSelect = $(this);
//controls if plugin initialized
if(Engine.controlTarget($originalSelect, ['isInitialized'])) {
//selectMania element
var $selectManiaEl = $originalSelect.data('selectMania-element');
//clear values
Engine.clear($selectManiaEl);
//trigger original select change event
$originalSelect.trigger('change');
//update clear values icon display
Engine.updateClean($selectManiaEl);
}
});
},
// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ setup
//setup default settings values
setup: function() {
//loop through targeted elements
return this.each(function() {
//current select to destroy
var $originalSelect = $(this);
//controls if plugin initialized
if(Engine.controlTarget($originalSelect, ['isInitialized'])) {
//selectMania element
var $selectManiaEl = $originalSelect.data('selectMania-element');
//clear values
Engine.clear($selectManiaEl);
//trigger original select change event
$originalSelect.trigger('change');
//update clear values icon display
Engine.updateClean($selectManiaEl);
}
});
}
};
// @@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@ //
// --------------------------------------- HANDLER ---------------------------------------- //
// @@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@ //
//plugin methods handler
$.fn.selectMania = function(methodOrOpts) {
//stop right away if targeted element empty
if(this.length < 1) { return; }
//call method
if(Methods[methodOrOpts]) {
//remove method name from call arguments
var slicedArguments = Array.prototype.slice.call(arguments, 1);
//call targeted mathod with arguments
return Methods[methodOrOpts].apply(this, slicedArguments);
}
//call init
else if(typeof methodOrOpts === 'object' || !methodOrOpts) {
//call init with arguments
return Methods.init.apply(this, arguments);
}
//error
else {
console.error('selectMania | wrong method called');
console.log(this);
}
};
//plugin setup handler
$.extend({
selectManiaSetup: function(opts) {
//set default settings values
Data.setup(opts);
}
});
})(jQuery);