Skip to content

Commit

Permalink
feat: create custom select dropdown component
Browse files Browse the repository at this point in the history
  • Loading branch information
cdrani committed May 28, 2024
1 parent ec22795 commit 9ab0b4c
Show file tree
Hide file tree
Showing 2 changed files with 95 additions and 35 deletions.
36 changes: 25 additions & 11 deletions src/components/effects/effects-selector.js
Original file line number Diff line number Diff line change
@@ -1,20 +1,34 @@
const btnStyles =
'text-align:end;cursor:pointer;background:#171717;padding:2px;padding-right:16px;color:#fff;font-size:1rem;'

const createOptions = (optionNames) =>
optionNames.map((name) => `<option name="${name}" value="${name}">${name}</option>`).join('')
optionNames
.map(
(name) => `<button style="${btnStyles}" name="${name}" value="${name}">${name}</button>`
)
.join('')

export const createEffectsSelector = ({ labelName, name, optionNames }) => `
<div style="display:flex;justify-content:space-between">
<div id="${name}-presets" style="display:flex;position:relative;justify-content:space-between;">
<label style="color:#b3b3b3;font-size:">${labelName}</label>
<form id="select-container" class="selector">
<select
class="select"
id="${name}-presets"
name="${name}-presets"
style="color:#fff;font-size:1rem;text-align:end"
<form id="select-container" class="selector" style="overflow-y:auto;max-height:100px;">
<button id="${name}-btn" style="display:flex;align-content:center;border:solid 1px #fff;background:transparent;color:#b3b3b3;width:100px;justify-content:end;">
<span id="${name}-selected" style="color:#fff;font-size:1rem;margin-right: 4px">none</span>
<svg style="width:1rem;height:1rem;margin-top:4px;" viewBox="0 0 256 256" fill="#fff" xmlns="http://www.w3.org/2000/svg">
<path
stroke-width="4px"
d="m128 182a5.98159 5.98159 0 0 1 -4.24268-1.75732l-80-80a6.00006 6.00006 0 0 1 8.48536-8.48536l75.75732 75.75733 75.75732-75.75733a6.00006 6.00006 0 0 1 8.48536 8.48536l-80 80a5.98159 5.98159 0 0 1 -4.24268 1.75732z"
/>
</svg>
</button>
<div
id="${name}-list"
style="min-width:100px;border:1px solid #b3b3b3;border-radius:4px;right:0;overflow-y:auto;background:#171717;flex-direction:column;max-height:110px;z-index:100;position:absolute;display:none"
>
<option name="none" value="none">-----</option>
${createOptions(optionNames)}
</select>
${createOptions(['none', ...optionNames])}
</div>
</form>
</div>
`
94 changes: 70 additions & 24 deletions src/models/reverb/reverb-controller.js
Original file line number Diff line number Diff line change
Expand Up @@ -13,57 +13,103 @@ export default class ReverbController {
this.#setupEvents(effect)
}

#setupButtonListeners(button) {
button.addEventListener('click', (e) => this.#handleSelection(e))
button.addEventListener('mouseover', () => (button.style.background = '#3e3d3d'))
button.addEventListener('mouseleave', () => (button.style.background = '#171717'))
}

#highlightFirstVisibleBtn({ isRoom, effectList }) {
const { roomEffect, convolverEffect } = this.elements
const selectedEffect = isRoom ? roomEffect.textContent : convolverEffect.textContent
const selectedBtn = effectList.querySelector(`button[value="${selectedEffect}"]`)

effectList.scrollTop = selectedBtn.offsetTop - effectList.offsetTop
selectedBtn.style.background = '#3e3d3d'
}

#toggleListView(e) {
e.preventDefault()
const { roomList, convolverList } = this.elements

const isRoom = e.currentTarget.id.startsWith('room')
const list = isRoom ? roomList : convolverList
const otherList = isRoom ? convolverList : roomList

const isShowing = list.style.display == 'flex'
list.style.display = isShowing ? 'none' : 'flex'
otherList.style.display = 'none'

if (list.style.display !== 'flex') return

this.#highlightFirstVisibleBtn({ isRoom, effectList: list })
}

#setupSelectEvents() {
const { roomBtn, roomList, convolverBtn, convolverList } = this.elements

roomBtn.addEventListener('click', (e) => this.#toggleListView(e))
;[...roomList.children].forEach((btn) => this.#setupButtonListeners(btn))

convolverBtn.addEventListener('click', (e) => this.#toggleListView(e))
;[...convolverList.children].forEach((btn) => this.#setupButtonListeners(btn))
}

#setupEvents(effect) {
const { roomEffectSelect, convolverEffectSelect, presetSelection } = this.elements
const { roomEffect, convolverEffect, presetSelection } = this.elements

if (effect == 'none') {
this.setValuesToNone()
} else {
presetSelection.textContent = effect
const selectedElement = roomPresets.includes(effect)
? roomEffectSelect
: convolverEffectSelect
selectedElement.value = effect
const selectedElement = roomPresets.includes(effect) ? roomEffect : convolverEffect
selectedElement.textContent = effect
}

roomEffectSelect.onchange = async (e) => {
await this.handleSelection(e)
}
convolverEffectSelect.onchange = async (e) => {
await this.handleSelection(e)
}
this.#setupSelectEvents()
}

get elements() {
return {
presetSelection: document.getElementById('preset-selection'),
roomEffectSelect: document.getElementById('room-effect-presets'),
convolverEffectSelect: document.getElementById('convolver-effect-presets')
roomBtn: document.getElementById('room-effect-btn'),
roomList: document.getElementById('room-effect-list'),
roomEffect: document.getElementById('room-effect-selected'),

convolverBtn: document.getElementById('convolver-effect-btn'),
convolverList: document.getElementById('convolver-effect-list'),
convolverEffect: document.getElementById('convolver-effect-selected'),

presetSelection: document.getElementById('preset-selection')
}
}

async handleSelection(e) {
const {
target: { value, id }
} = e
async #handleSelection(e) {
e.preventDefault()

const value = e.target.value
await this._reverb.setReverbEffect(value)

const { convolverEffectSelect, roomEffectSelect } = this.elements
const nonSelectedElement = id?.startsWith('room') ? convolverEffectSelect : roomEffectSelect
nonSelectedElement.value = 'none'
const { roomList, convolverList, convolverEffect, roomEffect } = this.elements
const roomPresetUpdate = e.target?.parentElement?.id?.startsWith('room')

convolverEffect.textContent = roomPresetUpdate ? 'none' : value
roomEffect.textContent = roomPresetUpdate ? value : 'none'

this.elements.presetSelection.textContent = value

roomList.style.display = 'none'
convolverList.style.display = 'none'
}

async saveSelection() {
await this._store.saveReverb(this.elements.presetSelection.textContent)
}

setValuesToNone() {
const { presetSelection, roomEffectSelect, convolverEffectSelect } = this.elements
const { presetSelection, roomEffect, convolverEffect } = this.elements
presetSelection.textContent = 'none'
roomEffectSelect.value = 'none'
convolverEffectSelect.value = 'none'
roomEffect.textContent = 'none'
convolverEffect.textContent = 'none'
}

async clearReverb() {
Expand Down

0 comments on commit 9ab0b4c

Please sign in to comment.