Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Hi! i have add some support to the selectbox #31

Open
wants to merge 7 commits into
base: master
Choose a base branch
from
Open
Changes from 1 commit
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Prev Previous commit
Next Next commit
now you can config the plugin using data attrs
Yo can use the data attribute to set the options in the plugin, example;

```html

<select data-menu-class="mytestclass">
  <option value="ar" data-domain="http://www.turismocity.com.ar/"> Argentina</option>
  <option>Chile</option>
</select>

<script>
$(function(){
  $('select').customSelectMenu();
})
</script>
```
eugenioclrc committed Jul 4, 2014
commit de293bb659cd04837c16ab16792d1a96a2c00225
454 changes: 224 additions & 230 deletions custom-select-menu.jquery.js
Original file line number Diff line number Diff line change
@@ -1,230 +1,224 @@
(function( $ ) {

'use strict';
$.fn.customSelectMenu = function( options ) {

// Create some defaults, extending them with any options that were provided
var settings = $.extend( {
menuClass : 'custom-select-menu', /* The class name for the custom select menu div */
openedClass : 'opened', /* The class given to the label when the menu is visible */
selectedClass : 'selected', /* The class given to the list item when an option has been selected */
selectionMadeClass : 'selection-made' /* The class given to the label when an option has been selected */
}, options);

function updateMenu(selection, $this) {
// Whenever you click on a menu item or press return/enter, we need to update a few things...
// Set up some vars...
var /*customMenuName = selection.parent().attr( 'data-select-name' ),
NEVER USED
Get the name of the menu */
customOptionValue = selection.attr( 'data-option-value' ), /* Get the option value */
customOptionText = selection.text(); /* Get the option text (for the label) */

//hiddenInput = $('input[name="' + customMenuName + '"]'); /* Get the hidden input */

// Remove 'selected' class from currently selected option
selection.parent().find( '.' + settings.selectedClass ).removeClass( settings.selectedClass );

// Add a class of 'selected' to the option
selection.addClass( settings.selectedClass );

// Pass the value to the hidden input
//hiddenInput.val( customOptionValue );
$this.val(customOptionValue).change();

// Update the label
selection.parent().parent().find( 'label' ).text( customOptionText );

// If the hidden input value isn't empty give the label a class to show it was selected
if($this.val() !== '') {
selection.parent().parent().find( 'label' ).addClass( settings.selectionMadeClass );
} else {
selection.parent().parent().find( 'label' ).removeClass( settings.selectionMadeClass );
}

// Close the menu
selection.parent().hide();

// Toggle the opened class on the label
if( selection.parent().css('display') !== 'none' ) {
selection.parent().parent().find( 'label' ).toggleClass( settings.openedClass );
} else {
selection.parent().parent().find( 'label' ).removeClass( settings.openedClass );
}

}

return this.each(function() {

var $this = $(this),
selectName = $this.attr( 'name' ), /* Get the name of the original menu */
selectId = $this.attr( 'id' ), /* Get the id of the original menu */
newHiddenInput,
newContainer,
newLabel,
labelText,
newList,
newOption,
selectedOption,
selectedOptionValue;


// Hide the original select menu
$this.hide();

// Create a div to contain the custom menu.
// Give the container div a tabindex of 0 so that it can have focus (arrow key navigation, etc. won't work without this)
// Source: http://snook.ca/archives/accessibility_and_usability/elements_focusable_with_tabindex
newContainer = $( '<div class="' + settings.menuClass + '">' ).attr( 'tabindex', 0 );

// If the original select menu has an id, then give that id to the container div
if( selectId ) {
newContainer.attr( 'id', selectId );
$this.removeAttr('id');
}

// Create a hidden input field so we can keep track of which option they choose
newHiddenInput = $this;

// Set up the first selected option and create the label
if( $this.find( ':selected' ) ) {
// Find the selected option if one exists...
selectedOption = $this.find( ':selected' );
selectedOptionValue = selectedOption.attr( 'value' );

// Set the label text to the selected option text
labelText = selectedOption.text();

// Create a label to show the selected option
if( !selectedOptionValue ) {
newLabel = $( '<label>' + labelText + '</label>' );
} else {
newLabel = $( '<label class="' + settings.selectionMadeClass + '">' + labelText + '</label>' );

// Add the selected option value to the hidden input

}

} else {
// Otherwise just get the first option...
// NOTE: Most browsers will set the first option as selected if no other option
// is selected, but the behavior for this is inconsistent across browsers,
// so we need this as a backup.
// Source: http://www.w3.org/TR/html401/interact/forms.html#h-17.6.1
labelText = $this.find( ':first' ).text();
newLabel = $( '<label>' + labelText + '</label>' );
}

// Append an unordered list to contain the custom menu options and hide it
newList = $( '<ul data-select-name="' + selectName + '">' ).hide();

// Add the custom select menu container to the DOM after the original select menu
// and append the label, list and hidden input to it
$this.after( newContainer.append( newLabel, newList ) );

// Loop through all the options and create li's to append to the custom menu
$this.find( 'option' ).each(function(){
var optionName = $(this).text(),
optionValue = $(this).attr( 'value' ),
markSelected = (optionName === labelText) ? ' class="' + settings.selectedClass + '"' : '';

// Make sure we have a value before setting one on the newOption
if( !optionValue ) {
newOption = $( '<li' + markSelected + '>' + optionName + '</li>' );
} else {
newOption = $( '<li data-option-value="' + optionValue + '"' + markSelected + '>' + optionName + '</li>' );
}

newList.append( newOption );
});

// Listen for click events on the custom select menu container
newContainer.on( 'click', function( event ){
var target = $(event.target);

// When the label is clicked, toggle the menu
if( target.is( 'label' ) ){
newLabel.toggleClass( settings.openedClass );
newLabel.parent().find( 'ul' ).toggle();
}

// When an option is clicked, update the menu with that option
if( target.is( 'li' ) ){
updateMenu( target, $this );
}
});

// Use arrows keys to navigation the menu
newContainer.on( 'keyup', function( e ) {
// Arrows keys open the menu
if( e.keyCode === 38 || e.keyCode === 40 ) {
$(this).find( newLabel ).addClass( settings.openedClass );
$(this).find( newList ).show();
}

var li = $(this).find( 'li' ),
selectedLi = $(this).find( '.' + settings.selectedClass ),
nextLi = '',
prevLi = '';

if( e.keyCode === 40 ) {
selectedLi.removeClass( settings.selectedClass );
nextLi = selectedLi.next();
if( nextLi.length > 0 ) {
nextLi.addClass( settings.selectedClass );
} else {
li.first().addClass( settings.selectedClass );
}
}

if( e.keyCode === 38 ) {
selectedLi.removeClass( settings.selectedClass );
prevLi = selectedLi.prev();
if( prevLi.length > 0 ) {
prevLi.addClass( settings.selectedClass );
} else {
li.last().addClass( settings.selectedClass );
}
}

// Pressing return/enter updates and closes the menu
if( e.keyCode === 13 ) {
updateMenu( $(this).find( '.' + settings.selectedClass ) , $this);
}
});

// If the container div loses focus and the menu is visible, close it
newContainer.on( 'blur', function() {
if( $(this).find( newList ).is( ':visible' ) ) {
$(this).find( newLabel ).removeClass( settings.openedClass );
$(this).find( newList ).hide();
}
});

// Pressing esc closes the menu
$('html').on( 'keyup', function( e ) {
if( e.keyCode === 27 ) {
newLabel.removeClass( settings.openedClass );
newList.hide();
}
});

// Hide the menu if you click outside of it
// Source: http://forum.jquery.com/topic/close-toggled-div-when-clicking-outside-of-it
$('html').on( 'mousedown', function( event ) {
var target = $(event.target);

// NOTE: addBack() requires jQuery 1.8 and later
// (you might be able to use andSelf() for < 1.8, but it has been deprecated)
if ( !target.parents().addBack().is( '.' + settings.menuClass + ' ul, .' + settings.menuClass + ' label' ) ) {
// Clicked outside
$('.' + settings.menuClass + ' label').removeClass( settings.openedClass );
$('.' + settings.menuClass + ' ul').hide();
}
});

});

};

})( jQuery );
(function ($) {
'use strict';
$.fn.customSelectMenu = function (options) {
var settings = $.extend($(this).data(), options);
// Create some defaults, extending them with any options that were provided
settings = $.extend({
menuClass : 'custom-select-menu', /* The class name for the custom select menu div */
openedClass : 'opened', /* The class given to the label when the menu is visible */
selectedClass : 'selected', /* The class given to the list item when an option has been selected */
selectionMadeClass : 'selection-made' /* The class given to the label when an option has been selected */
}, settings);

function updateMenu(selection, $this) {
// Whenever you click on a menu item or press return/enter, we need to update a few things...
// Set up some vars...
var customOptionValue = selection.attr('data-option-value'), /* Get the option value */
customOptionText = selection.text(); /* Get the option text (for the label) */

//hiddenInput = $('input[name="' + customMenuName + '"]'); /* Get the hidden input */

// Remove 'selected' class from currently selected option
selection.parent().find('.' + settings.selectedClass).removeClass(settings.selectedClass);

// Add a class of 'selected' to the option
selection.addClass(settings.selectedClass);

// Pass the value to the hidden input
//hiddenInput.val( customOptionValue );
$this.val(customOptionValue).change();

// Update the label
selection.parent().parent().find('label').text(customOptionText);

// If the hidden input value isn't empty give the label a class to show it was selected
if ($this.val() !== '') {
selection.parent().parent().find('label').addClass(settings.selectionMadeClass);
} else {
selection.parent().parent().find('label').removeClass(settings.selectionMadeClass);
}

// Close the menu
selection.parent().hide();

// Toggle the opened class on the label
if (selection.parent().css('display') !== 'none') {
selection.parent().parent().find('label').toggleClass(settings.openedClass);
} else {
selection.parent().parent().find('label').removeClass(settings.openedClass);
}
}

return this.each(function () {

var $this = $(this),
selectName = $this.attr('name'), /* Get the name of the original menu */
selectId = $this.attr('id'), /* Get the id of the original menu */
newHiddenInput,
newContainer,
newLabel,
labelText,
newList,
newOption,
selectedOption,
selectedOptionValue;


// Hide the original select menu
$this.hide();

// Create a div to contain the custom menu.
// Give the container div a tabindex of 0 so that it can have focus (arrow key navigation, etc. won't work without this)
// Source: http://snook.ca/archives/accessibility_and_usability/elements_focusable_with_tabindex
newContainer = $('<div class="' + settings.menuClass + '">').attr('tabindex', 0);

// If the original select menu has an id, then give that id to the container div
if (selectId) {
newContainer.attr('id', selectId);
$this.removeAttr('id');
}

// Create a hidden input field so we can keep track of which option they choose
newHiddenInput = $this;

// Set up the first selected option and create the label
if ($this.find(':selected')) {
// Find the selected option if one exists...
selectedOption = $this.find(':selected');
selectedOptionValue = selectedOption.attr('value');

// Set the label text to the selected option text
labelText = selectedOption.text();

// Create a label to show the selected option
if (!selectedOptionValue) {
newLabel = $('<label>' + labelText + '</label>');
} else {
newLabel = $('<label class="' + settings.selectionMadeClass + '">' + labelText + '</label>');

// Add the selected option value to the hidden input

}

} else {
// Otherwise just get the first option...
// NOTE: Most browsers will set the first option as selected if no other option
// is selected, but the behavior for this is inconsistent across browsers,
// so we need this as a backup.
// Source: http://www.w3.org/TR/html401/interact/forms.html#h-17.6.1
labelText = $this.find(':first').text();
newLabel = $('<label>' + labelText + '</label>');
}

// Append an unordered list to contain the custom menu options and hide it
newList = $('<ul data-select-name="' + selectName + '">').hide();

// Add the custom select menu container to the DOM after the original select menu
// and append the label, list and hidden input to it
$this.after(newContainer.append(newLabel, newList));

// Loop through all the options and create li's to append to the custom menu
$this.find('option').each(function () {
var optionName = $(this).text(),
optionValue = $(this).attr('value'),
markSelected = (optionName === labelText) ? ' class="' + settings.selectedClass + '"' : '';

// Make sure we have a value before setting one on the newOption
if (!optionValue) {
newOption = $('<li' + markSelected + '>' + optionName + '</li>');
} else {
newOption = $('<li data-option-value="' + optionValue + '"' + markSelected + '>' + optionName + '</li>');
}

newList.append(newOption);
});

// Listen for click events on the custom select menu container
newContainer.on('click', function (event) {
var target = $(event.target);

// When the label is clicked, toggle the menu
if (target.is('label')) {
newLabel.toggleClass(settings.openedClass);
newLabel.parent().find('ul').toggle();
}

// When an option is clicked, update the menu with that option
if (target.is('li')) {
updateMenu(target, $this);
}
});

// Use arrows keys to navigation the menu
newContainer.on('keyup', function (e) {
// Arrows keys open the menu
if (e.keyCode === 38 || e.keyCode === 40) {
$(this).find(newLabel).addClass(settings.openedClass);
$(this).find(newList).show();
}

var li = $(this).find('li'),
selectedLi = $(this).find('.' + settings.selectedClass),
nextLi = '',
prevLi = '';

if (e.keyCode === 40) {
selectedLi.removeClass(settings.selectedClass);
nextLi = selectedLi.next();
if (nextLi.length > 0) {
nextLi.addClass(settings.selectedClass);
} else {
li.first().addClass(settings.selectedClass);
}
}

if (e.keyCode === 38) {
selectedLi.removeClass(settings.selectedClass);
prevLi = selectedLi.prev();
if (prevLi.length > 0) {
prevLi.addClass(settings.selectedClass);
} else {
li.last().addClass(settings.selectedClass);
}
}

// Pressing return/enter updates and closes the menu
if (e.keyCode === 13) {
updateMenu($(this).find('.' + settings.selectedClass), $this);
}
});

// If the container div loses focus and the menu is visible, close it
newContainer.on('blur', function () {
if ($(this).find(newList).is(':visible')) {
$(this).find(newLabel).removeClass(settings.openedClass);
$(this).find(newList).hide();
}
});

// Pressing esc closes the menu
$('html').on('keyup', function (e) {
if (e.keyCode === 27) {
newLabel.removeClass(settings.openedClass);
newList.hide();
}
});

// Hide the menu if you click outside of it
// Source: http://forum.jquery.com/topic/close-toggled-div-when-clicking-outside-of-it
$('html').on('mousedown', function (event) {
var target = $(event.target);

// NOTE: addBack() requires jQuery 1.8 and later
// (you might be able to use andSelf() for < 1.8, but it has been deprecated)
if (!target.parents().addBack().is('.' + settings.menuClass + ' ul, .' + settings.menuClass + ' label')) {
// Clicked outside
$('.' + settings.menuClass + ' label').removeClass(settings.openedClass);
$('.' + settings.menuClass + ' ul').hide();
}
});

});

};
})(jQuery);