diff --git a/.eslintrc.json b/.eslintrc.json index 3173b3f..d0a4832 100644 --- a/.eslintrc.json +++ b/.eslintrc.json @@ -4,7 +4,7 @@ "jquery": true }, "extends": "jquery", - "rules": { - "no-console": "off" + "rules": { + "no-console": "off" } } \ No newline at end of file diff --git a/README.md b/README.md index 5b9de30..c8324b1 100644 --- a/README.md +++ b/README.md @@ -1,10 +1,14 @@ # jQuery Stylize Select Plugin +![GitHub last commit](https://img.shields.io/github/last-commit/glebkema/jquery-stylize-select) +![GitHub tag (latest by date)](https://img.shields.io/github/v/tag/glebkema/jquery-stylize-select) +![GitHub release (latest by date including pre-releases)](https://img.shields.io/github/v/release/glebkema/jquery-stylize-select?include_prereleases) + The drop-down list for the select field itself is almost not styled. This plugin adds blocks around it and creates the necessary event handlers. So you can stylize the look of these blocks using the CSS. The plugin simplifies website development. The CSS file contains only the properties required for the functioning of the drop-down list and the field with the selection result. You need to stylize them yourself. -Based on [Custom Select Menu](https://codepen.io/wallaceerick/pen/ctsCz), CodePen by [Wallace Erick](https://codepen.io/wallaceerick). +Inspired by [Wallace Erick](https://codepen.io/wallaceerick)'s CodePen "[Custom Select Menu](https://codepen.io/wallaceerick/pen/ctsCz)". ## The plugin creates 3 blocks and uses 6 style classes diff --git a/app/js/jquery-stylize-select.js b/app/js/jquery-stylize-select.js index a5505a6..68ae296 100644 --- a/app/js/jquery-stylize-select.js +++ b/app/js/jquery-stylize-select.js @@ -2,9 +2,8 @@ * jQuery Stylize Select Plugin * Description: This plugin adds HTML blocks around the and all blocks we add @@ -36,7 +35,8 @@ $list, $listOptions; - $select.hide() + $select + .hide() .wrap($('
', { 'class': settings.classSelect.slice(1), // 'class': (settings.classSelect.slice(1) + ' ' + settings.classSelectAdd.slice(1)).trim(), @@ -66,94 +66,109 @@ } $listOptions = $list.children('li'); - updateSelect((function() { - var indexSelected = $select.prop('selectedIndex'); // https://stackoverflow.com/a/13556979/6263942 - return (indexSelected < 0 ? null : $listOptions.eq(indexSelected)); - }())); // NB: () + $select + .change(function() { + if (this.selectedIndex > -1) { // or $(this).prop('selectedIndex') + var $selectedOption = $list.children('[rel=\'' + $(this).val() + '\']'); + if ($selectedOption) { + $selectStyled + .html($selectedOption.html()) + .attr('style', function() { + var newStyle = $selectedOption.attr('style'); + return ( newStyle ? newStyle : null ); + }); + $selectedOption.addClass(settings.classSelected.slice(1)) + .siblings(settings.classSelected) + .removeClass(settings.classSelected.slice(1)); + } + } + }) + .change(); // put the initial content in $selectStyled - $select.parent(settings.classSelect).focusout(function(event) { - if (! this.contains(event.relatedTarget)) { - closeSelect(); - } - }); - - $selectStyled.click(function() { - toggleSelect(); - return false; // stopPropagation & stopImmediatePropagation are not enough to prevent the `document.click` event - }) - .keydown(function(event) { - var charCode = event.charCode || event.keyCode || event.which; - switch (charCode) { - case 27: // esc - event.stopPropagation(); + $select.parent(settings.classSelect) + .focusout(function(event) { + if (! this.contains(event.relatedTarget)) { closeSelect(); - break; - case 13: // enter - case 32: // space - event.preventDefault(); - event.stopPropagation(); - toggleSelect(); - break; - case 38: // arrow up - if ($selectStyled.hasClass(STR_ACTIVE)) { - event.preventDefault(); + } + }); + + $selectStyled + .click(function() { + toggleSelect(); + return false; // stopPropagation & stopImmediatePropagation don`t prevent the document.click` event + }) + .keydown(function(event) { + var charCode = event.charCode || event.keyCode || event.which; + switch (charCode) { + case 27: // escape event.stopPropagation(); closeSelect(); - } - break; - case 40: // arrow down - event.preventDefault(); - event.stopPropagation(); - if ($selectStyled.hasClass(STR_ACTIVE)) { - $listOptions.not(':hidden').first().focus(); - } else { - openSelect(); - } - break; - } - }); + break; + case 13: // enter + case 32: // space + event.preventDefault(); + event.stopPropagation(); + toggleSelect(); + break; + case 38: // arrow up + if ($selectStyled.hasClass(STR_ACTIVE)) { + event.preventDefault(); + event.stopPropagation(); + closeSelect(); + } + break; + case 40: // arrow down + event.preventDefault(); + event.stopPropagation(); + if ($selectStyled.hasClass(STR_ACTIVE)) { + $listOptions.filter(':visible').first().focus(); + } else { + openSelect(); + } + break; + } + }); - $listOptions.click(function(event) { - event.stopPropagation(); - updateSelect($(this)); - $selectStyled.focus(); - }) - .keydown(function(event) { - var $next, $prev, - charCode = event.charCode || event.keyCode || event.which; - switch (charCode) { - case 27: // esc - event.stopPropagation(); - closeSelect(); - $selectStyled.focus(); - break; - case 13: // enter - case 32: // space - event.preventDefault(); - event.stopPropagation(); - updateSelect($(this)); - $selectStyled.focus(); - break; - case 38: // arrow up - event.preventDefault(); - event.stopPropagation(); - $prev = $(this).prevAll(':visible:first'); // prev() has a problem with hidden options - if ($prev.length) { - $prev.focus(); - } else { + $listOptions + .click(function(event) { + event.stopPropagation(); + performSelect($(this)); + }) + .keydown(function(event) { + var $next, $prev, + charCode = event.charCode || event.keyCode || event.which; + switch (charCode) { + case 27: // escape + event.stopPropagation(); + closeSelect(); $selectStyled.focus(); - } - break; - case 40: // arrow down - event.preventDefault(); - event.stopPropagation(); - $next = $(this).nextAll(':visible:first'); - if ($next.length) { - $next.focus(); - } - break; - } - }); + break; + case 13: // enter + case 32: // space + event.preventDefault(); + event.stopPropagation(); + performSelect($(this)); + break; + case 38: // arrow up + event.preventDefault(); + event.stopPropagation(); + $prev = $(this).prevAll(':visible:first'); // prev() has a problem with hidden options + if ($prev.length) { + $prev.focus(); + } else { + $selectStyled.focus(); + } + break; + case 40: // arrow down + event.preventDefault(); + event.stopPropagation(); + $next = $(this).nextAll(':visible:first'); + if ($next.length) { + $next.focus(); + } + break; + } + }); $(document).click(closeSelect); @@ -169,6 +184,12 @@ $selectStyled.toggleClass(STR_ACTIVE).next(settings.classList).toggle(); } + function performSelect($newOption) { + updateSelect($newOption); + closeSelect(); + $selectStyled.focus(); + } + function toggleSelect() { if ($selectStyled.hasClass(STR_ACTIVE)) { closeSelect(); @@ -177,18 +198,9 @@ } } - function updateSelect($selectedItem) { - if ($selectedItem && ! $selectedItem.hasClass(settings.classDisabled.slice(1))) { - $selectStyled.html($selectedItem.html()) - .attr('style', function() { - var newStyle = $selectedItem.attr('style'); - return ( newStyle ? newStyle : null ); - }); - $selectedItem.addClass(settings.classSelected.slice(1)) - .siblings(settings.classSelected) - .removeClass(settings.classSelected.slice(1)); - $select.val($selectedItem.attr('rel')).change(); - closeSelect(); + function updateSelect($newOption) { + if ($newOption && ! $newOption.hasClass(settings.classDisabled.slice(1))) { + $select.val($newOption.attr('rel')).change(); // run event handlers for the `change` event } } }); @@ -196,4 +208,8 @@ return this; }; + $.fn.stylizeSelect.defaults = { + classSelect: '.stylize-select', + }; + }( jQuery )); diff --git a/dist/jquery-stylize-select.js b/dist/jquery-stylize-select.js index 38c4424..34dad01 100644 --- a/dist/jquery-stylize-select.js +++ b/dist/jquery-stylize-select.js @@ -2,9 +2,8 @@ * jQuery Stylize Select Plugin * Description: This plugin adds HTML blocks around the and all blocks we add @@ -36,7 +35,8 @@ $list, $listOptions; - $select.hide() + $select + .hide() .wrap($("
", { "class": settings.classSelect.slice(1), // "class": (settings.classSelect.slice(1) + " " + settings.classSelectAdd.slice(1)).trim(), @@ -66,94 +66,109 @@ } $listOptions = $list.children("li"); - updateSelect((function() { - var indexSelected = $select.prop("selectedIndex"); // https://stackoverflow.com/a/13556979/6263942 - return (indexSelected < 0 ? null : $listOptions.eq(indexSelected)); - }())); // NB: () + $select + .change(function() { + if (this.selectedIndex > -1) { // or $(this).prop("selectedIndex") + var $selectedOption = $list.children("[rel=\"" + $(this).val() + "\"]"); + if ($selectedOption) { + $selectStyled + .html($selectedOption.html()) + .attr("style", function() { + var newStyle = $selectedOption.attr("style"); + return ( newStyle ? newStyle : null ); + }); + $selectedOption.addClass(settings.classSelected.slice(1)) + .siblings(settings.classSelected) + .removeClass(settings.classSelected.slice(1)); + } + } + }) + .change(); // put the initial content in $selectStyled - $select.parent(settings.classSelect).focusout(function(event) { - if (! this.contains(event.relatedTarget)) { - closeSelect(); - } - }); - - $selectStyled.click(function() { - toggleSelect(); - return false; // stopPropagation & stopImmediatePropagation are not enough to prevent the `document.click` event - }) - .keydown(function(event) { - var charCode = event.charCode || event.keyCode || event.which; - switch (charCode) { - case 27: // esc - event.stopPropagation(); + $select.parent(settings.classSelect) + .focusout(function(event) { + if (! this.contains(event.relatedTarget)) { closeSelect(); - break; - case 13: // enter - case 32: // space - event.preventDefault(); - event.stopPropagation(); - toggleSelect(); - break; - case 38: // arrow up - if ($selectStyled.hasClass(STR_ACTIVE)) { - event.preventDefault(); + } + }); + + $selectStyled + .click(function() { + toggleSelect(); + return false; // stopPropagation & stopImmediatePropagation don`t prevent the document.click` event + }) + .keydown(function(event) { + var charCode = event.charCode || event.keyCode || event.which; + switch (charCode) { + case 27: // escape event.stopPropagation(); closeSelect(); - } - break; - case 40: // arrow down - event.preventDefault(); - event.stopPropagation(); - if ($selectStyled.hasClass(STR_ACTIVE)) { - $listOptions.not(":hidden").first().focus(); - } else { - openSelect(); - } - break; - } - }); + break; + case 13: // enter + case 32: // space + event.preventDefault(); + event.stopPropagation(); + toggleSelect(); + break; + case 38: // arrow up + if ($selectStyled.hasClass(STR_ACTIVE)) { + event.preventDefault(); + event.stopPropagation(); + closeSelect(); + } + break; + case 40: // arrow down + event.preventDefault(); + event.stopPropagation(); + if ($selectStyled.hasClass(STR_ACTIVE)) { + $listOptions.filter(":visible").first().focus(); + } else { + openSelect(); + } + break; + } + }); - $listOptions.click(function(event) { - event.stopPropagation(); - updateSelect($(this)); - $selectStyled.focus(); - }) - .keydown(function(event) { - var $next, $prev, - charCode = event.charCode || event.keyCode || event.which; - switch (charCode) { - case 27: // esc - event.stopPropagation(); - closeSelect(); - $selectStyled.focus(); - break; - case 13: // enter - case 32: // space - event.preventDefault(); - event.stopPropagation(); - updateSelect($(this)); - $selectStyled.focus(); - break; - case 38: // arrow up - event.preventDefault(); - event.stopPropagation(); - $prev = $(this).prevAll(":visible:first"); // prev() has a problem with hidden options - if ($prev.length) { - $prev.focus(); - } else { + $listOptions + .click(function(event) { + event.stopPropagation(); + performSelect($(this)); + }) + .keydown(function(event) { + var $next, $prev, + charCode = event.charCode || event.keyCode || event.which; + switch (charCode) { + case 27: // escape + event.stopPropagation(); + closeSelect(); $selectStyled.focus(); - } - break; - case 40: // arrow down - event.preventDefault(); - event.stopPropagation(); - $next = $(this).nextAll(":visible:first"); - if ($next.length) { - $next.focus(); - } - break; - } - }); + break; + case 13: // enter + case 32: // space + event.preventDefault(); + event.stopPropagation(); + performSelect($(this)); + break; + case 38: // arrow up + event.preventDefault(); + event.stopPropagation(); + $prev = $(this).prevAll(":visible:first"); // prev() has a problem with hidden options + if ($prev.length) { + $prev.focus(); + } else { + $selectStyled.focus(); + } + break; + case 40: // arrow down + event.preventDefault(); + event.stopPropagation(); + $next = $(this).nextAll(":visible:first"); + if ($next.length) { + $next.focus(); + } + break; + } + }); $(document).click(closeSelect); @@ -169,6 +184,12 @@ $selectStyled.toggleClass(STR_ACTIVE).next(settings.classList).toggle(); } + function performSelect($newOption) { + updateSelect($newOption); + closeSelect(); + $selectStyled.focus(); + } + function toggleSelect() { if ($selectStyled.hasClass(STR_ACTIVE)) { closeSelect(); @@ -177,18 +198,9 @@ } } - function updateSelect($selectedItem) { - if ($selectedItem && ! $selectedItem.hasClass(settings.classDisabled.slice(1))) { - $selectStyled.html($selectedItem.html()) - .attr("style", function() { - var newStyle = $selectedItem.attr("style"); - return ( newStyle ? newStyle : null ); - }); - $selectedItem.addClass(settings.classSelected.slice(1)) - .siblings(settings.classSelected) - .removeClass(settings.classSelected.slice(1)); - $select.val($selectedItem.attr("rel")).change(); - closeSelect(); + function updateSelect($newOption) { + if ($newOption && ! $newOption.hasClass(settings.classDisabled.slice(1))) { + $select.val($newOption.attr("rel")).change(); // run event handlers for the `change` event } } }); @@ -196,4 +208,8 @@ return this; }; + $.fn.stylizeSelect.defaults = { + classSelect: ".stylize-select", + }; + }( jQuery )); diff --git a/dist/jquery-stylize-select.min.js b/dist/jquery-stylize-select.min.js index b468972..4969063 100644 --- a/dist/jquery-stylize-select.min.js +++ b/dist/jquery-stylize-select.min.js @@ -2,8 +2,7 @@ * jQuery Stylize Select Plugin * Description: This plugin adds HTML blocks around the + + + + + diff --git a/tests/tests.js b/tests/tests.js index 0ec174b..18d144d 100644 --- a/tests/tests.js +++ b/tests/tests.js @@ -6,8 +6,18 @@ jQuery(document).ready(function($) { $tests.stylizeSelect(); } + + //**** debug $tests.change(function() { console.log($(this).attr('id'), 'changes to "' + $(this).find(":selected").text() + '"'); }); + + //**** tests + var changeValueByScript = 'changeValueByScript', + $changeValueByScript = $('#' + changeValueByScript); + $changeValueByScript.val(2).change(); // trigger `change` after setting the value: https://api.jquery.com/val/ + $('label[for="' + changeValueByScript + '"]').children('span').html($changeValueByScript.val()); + console.log('changeValueByScript has been changed to', $changeValueByScript.val()); + });