JSFiddle - React, Tailwind, and code Playground
by Anderson Carlos Woss
HTML
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<ul id="foo" data-rows="5">
<li data-id="0">Opção 0</li>
<li data-id="1">Opção 1</li>
<li data-id="2">Opção 2</li>
<li data-id="3">Opção 3</li>
<li data-id="4">Opção 4</li>
<li data-id="5">Opção 5</li>
<li data-id="6" class="selected">Opção 6</li>
<li data-id="7">Opção 7</li>
<li data-id="8">Opção 8</li>
</ul>
CSS
#foo {
width: 300px;
border-top: 1px solid black;
border-bottom: 1px solid black;
overflow: hidden;
list-style: none;
margin: 0;
padding: 0;
text-align: center;
color: black;
}
#foo:focus {
outline: none;
}
#foo li {
padding: 5px;
}
#foo li.selected {
font-weight: bold;
}
#foo li:hover {
color: blue;
font-weight: bold;
cursor: pointer;
}
#foo:focus li.selected, #foo:focus li:hover {
color: blue;
font-weight: bold;
cursor: pointer;
}
#foo li.selected:after {
content: '\2713';
margin-left: 10px;
}
JavaScript
$(() => {
(select => {
"use strict";
// Opções:
const options = select.children("li");
// Quantidade de opções:
const length = options.length;
// Número de opções exibidas:
const rows = parseInt(select.data("rows"));
// Altura do elemento:
const height = rows * ($(options[0]).height() + 10);
// Posição da opção selecionada:
const half = parseInt(rows/2 + 1);
// Define o tabindex do elemento:
select.attr("tabindex", 0);
// Define a altura do elemento conforme o número de opções exibidos:
select.css("height", `${height}px`);
function moveFirstToLast() {
select.append(select.children("li:first-child").remove());
}
function moveLastToFirst() {
select.prepend(select.children("li:last-child").remove());
}
function selectHalfOption() {
$(options).removeClass("selected");
select.children(`li:nth-child(${half})`).addClass("selected");
}
// Centraliza a opção selecionada.
function center() {
while (!select.children(`li:nth-child(${half})`).hasClass("selected")) {
moveFirstToLast();
}
}
center();
// Seleciona uma opção no clique:
select.on("click", "li", function (event) {
$(options).removeClass("selected");
$(this).addClass("selected");
center();
});
select.on("keydown", function (event) {
if (event.keyCode == 38) {
moveLastToFirst();
selectHalfOption();
} else if (event.keyCode == 40) {
moveFirstToLast();
selectHalfOption();
}
});
select.on("mousewheel", function (event) {
if (select.is(":focus")) {
if (event.originalEvent.wheelDelta /120 > 0) {
moveLastToFirst();
selectHalfOption();
} else {
moveFirstToLast();
selectHalfOption();
}
}
});
})($("#foo"));
});