Skip to content

Instantly share code, notes, and snippets.

@VictorHugoBatista
Last active September 4, 2019 11:56
Show Gist options
  • Select an option

  • Save VictorHugoBatista/5988bcc087cfea0038aeca25ff540dd9 to your computer and use it in GitHub Desktop.

Select an option

Save VictorHugoBatista/5988bcc087cfea0038aeca25ff540dd9 to your computer and use it in GitHub Desktop.
Classe responsável por converter um select para lista de botões, com comportamento de radiobuttons. Mantém o select intacto e oculto, alterando seu valor selecionado à cada click nos botões.
<select class="my-select">
<option selected disabled value="">Placeholder (não é gerado como botão)</option>
<option value="1">1</option>
<option value="2">2</option>
<option value="3">3</option>
</select>
import SelectButtons from '../components/select-buttons';
$(() => {
new SelectButtons($('.my-select'));
});
/**
* Responsável por converter um select para lista de botões.
* Mantém o select intacto e oculto, alterando seu valor selecionado à cada click nos botões.
*/
export default class SelectButtons {
constructor($select) {
if (! this.initializeElements($select)) {
return;
}
this.selectHiddenClass = 'd-none';
this.textsToReplace = {
'from': 'to',
};
this.buildButtonsBySelectOptions();
this.addButtonClickSelectEvent();
this.markFirstButton();
}
/**
* Inicializa propriedades relacionadas aos elementos jQuery do componente.
* Recebe elemento jQuery do elemento à ser convertido para botões.
* @param JQuery $select
*/
initializeElements($select) {
if (! $select.length) {
return false;
}
this.elements = {
$select: $select,
$selectOptions: $select.find('option').not(':eq(0)'),
};
this.selectId = $select.attr('id');
this.buttonsSelector = `.button-select[data-id="${this.selectId}"]`;
return true;
}
/**
* Constrói os botões com base nos selects, ignora
* a primeira option por ser o valor default sem valor.
* @see initializeElements
*/
buildButtonsBySelectOptions() {
const buttonsToRender = [];
this.elements.$selectOptions.each((_, option) => {
const $option = $(option),
buttonLabel = this.replaceTexts($option.text()),
buttonHTML =
`<button class="button-select btn btn-pill" data-id="${this.selectId}" data-value="${$option.val()}">
${buttonLabel}
</button>`;
buttonsToRender.push(buttonHTML);
});
this.elements.$select.after(`<div class="button-select-wrapper">${buttonsToRender.join('')}</div>`);
this.elements.$select.addClass(this.selectHiddenClass);
}
/**
* Adiciona o evento de click aos botões gerados, troca
* option selecionado no select e as cores dos botões.
*/
addButtonClickSelectEvent() {
$(document).on('click', this.buttonsSelector, event => {
event.preventDefault();
const $buttonClicked = $(event.currentTarget),
value = $buttonClicked.data('value'),
$optionToSelect = $(`#${this.selectId} [value="${value}"]`);
this.markOptionItem($optionToSelect, $buttonClicked);
});
}
/**
* Marca o primeiro botão do grupo.
*/
markFirstButton() {
const $buttonToMark = $(`${this.buttonsSelector}:eq(0)`);
$buttonToMark.trigger('click');
}
/**
* Marca um botão específico do grupo.
* @param JQuery $optionToSelect Opção do select à ser marcada
* @param JQuery $buttonToMark Botão mo grupo à ser marcado.
*/
markOptionItem($optionToSelect, $buttonToMark) {
if (! $optionToSelect.length) {
return;
}
this.elements.$selectOptions.removeAttr('selected');
$optionToSelect.attr('selected', 'selected');
$optionToSelect.trigger('change');
const $allButtons = $(this.buttonsSelector);
if (! $allButtons.length) {
return;
}
$allButtons.removeClass('active');
$buttonToMark.addClass('active');
}
/**
* Texto à substituir usando chaves e valores da propriedade 'textsToReplace'.
* @param strong textToChange
* @see constructor
*/
replaceTexts(textToChange) {
let changedText = textToChange;
for (let textFrom in this.textsToReplace) {
const textTo = this.textsToReplace[textFrom];
changedText = changedText.replace(textFrom, textTo);
}
return changedText;
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment