Last active
November 6, 2018 18:20
-
-
Save andrewgremlich/b89be9c8a03851b1c6bf1d6e51dad1d6 to your computer and use it in GitHub Desktop.
Detailed Dropdown. When some dropdowns aren't just enough, here's a detailed component dropdown for those dropdown needs
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
class DetailedDropDownStyles { | |
constructor() { | |
this.themeRed = '#ef4545'; | |
this.themeRedBorder = '#c13636'; | |
} | |
setStyles() { | |
this.searchBar.style.cssText = ` | |
padding: 10px; | |
font-size: 20px; | |
height: 40px; | |
width: 200px; | |
border-radius: 10px; | |
border: 1px solid ${this.themeRed}; | |
outline: none;`; | |
this.searchBar.parentElement.style.cssText = ` | |
display: flex; | |
flex-direction: row; | |
align-items: center;`; | |
this.output.style.cssText = ` | |
display: flex; | |
flex-wrap: wrap; | |
padding: 10px; | |
overflow: scroll;`; | |
this.aside.style.cssText = ` | |
display: flex; | |
flex-direction: row; | |
justify-content: center; | |
align-items: center; | |
position: absolute; | |
left: 15%; | |
background: ${this.themeRed}; | |
border: 1px solid ${this.themeRedBorder}; | |
border-radius: 20px;`; | |
} | |
} | |
export default class DetailedDropDown extends DetailedDropDownStyles { | |
constructor(inputSelector, src, dataCallback, presetId = undefined) { | |
super(); | |
this.fetchSrc = src; | |
this.searchBar = document.getElementById(inputSelector); | |
this.aside = document.createElement('aside'); | |
this.output = document.createElement('div'); | |
this.madeReferenceCards = []; | |
this.dataCallback = dataCallback; | |
this.presetId = presetId; | |
this.initComponent(); | |
} | |
initComponent() { | |
this.setStyles(); | |
this.aside.appendChild(this.output); | |
this.searchBar.setAttribute('incremental', '') | |
this.searchBar.setAttribute('type', 'search') | |
this.searchBar.parentNode.insertBefore(this.aside, this.searchBar.nextSibling); | |
this.attachEventListeners(); | |
this.presetId && this.fetchPreSelected(this.presetId); | |
} | |
getPeopleByName(fetchSrc, name) { | |
return new Promise(async resolve => { | |
const data = await fetch(`${fetchSrc.queryAll}${name}`); | |
const resultNames = await data.json(); | |
resolve(resultNames); | |
}); | |
} | |
getSetId(fetchSrc, presetId) { | |
return new Promise(async resolve => { | |
const data = await fetch(`${fetchSrc.getOne}${presetId}`); | |
const resultName = await data.json(); | |
resolve(resultName); | |
}); | |
} | |
render() { | |
const maxWidth = window.innerWidth / 1.5; | |
const maxHeight = window.innerHeight / 1.4; | |
this.output.style.maxWidth = maxWidth + 'px'; | |
this.output.style.maxHeight = maxHeight + 'px'; | |
this.madeReferenceCards.forEach(element => { | |
this.output.appendChild(element); | |
}); | |
} | |
fetchPreSelected(presetId) { | |
this.searchBar.setAttribute('data-form-id', presetId); | |
this.getSetId(this.fetchSrc, presetId).then(data => { | |
this.makeReferenceCards(data); | |
this.render(); | |
}); | |
} | |
attachEventListeners() { | |
this.searchBar.addEventListener('search', async () => { | |
const typed = this.searchBar.value; | |
this.output.innerHTML = ''; | |
if (typed.length >= 2) { | |
this.makeReferenceCards(await this.getPeopleByName(this.fetchSrc, typed)); | |
this.render(); | |
} else if (typed.length < 2) { | |
this.searchBar.setAttribute('data-form-id', ''); | |
} | |
}); | |
} | |
attachCard(name) { | |
return evt => { | |
let { id } = evt.currentTarget; | |
this.searchBar.setAttribute('data-form-id', id); | |
this.searchBar.value = name; | |
this.output.innerHTML = ''; | |
this.output.appendChild(evt.currentTarget); | |
}; | |
} | |
makeReferenceCards(persons) { | |
this.madeReferenceCards.length = 0; | |
for (let person of persons) { | |
this.dataCallback(this.madeReferenceCards, this.attachCard(person.name), person); | |
} | |
} | |
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
import _ from './modules/_.js'; | |
import DetailedDropDown from './modules/DetailedDropDown.js'; | |
/* | |
#params | |
1. inputSelector = html ID of input[type="search"] | |
2. src = remote source URL | |
queryAll -> base URL for searching which src to get. the search term will be appended. | |
getOne -> base URL for searching one src. the uuid will be appended. | |
3. dataCallback = method to handle incoming data from src. give | |
cards inside the detailed dropdown. | |
madeCardsStash = where all the made DOM nodes will go. | |
attachToCard = event function handler. | |
Attaches a 'data-form-id' attribute to search bar element. | |
fills in name with name of clicked | |
clears output div | |
fills selected person to output | |
adds selected styling. | |
4. presetId = UUID of data item that has been already selected. | |
*/ | |
function makeInteractiveCard(strings) { | |
let base = ` | |
border-radius: 7.5px; | |
border: 1px solid #c13636; | |
margin: 10px; | |
padding: 10px; | |
${strings[0]}`; | |
return base; | |
} | |
const detailedDropDown = new DetailedDropDown( | |
'search', | |
{ | |
queryAll: 'http://localhost:3000/api/get/peopleByName/', | |
getOne: 'http://localhost:3000/api/get/personById/' | |
}, | |
(madeCardsStash, attachToCard, { name, birthDate, deathDate, email, username, profile, uuid }) => { | |
const referenceDiv = _.create('div'), | |
nameH2 = _.attachText('h2', name), | |
birthDateTitle = _.attachText('p', birthDate), | |
deathDateTitle = _.attachText('p', deathDate), | |
emailTitle = _.attachText('p', email), | |
usernameTitle = _.attachText('p', username), | |
profileImg = _.image(profile); | |
profileImg.style.cssText = ` | |
border-radius: 7.5px; | |
float: left; | |
width: 80px; | |
margin-right: 10px; | |
margin-bottom: 5px;`; | |
referenceDiv.style.cssText = makeInteractiveCard``; | |
referenceDiv.id = uuid; | |
referenceDiv.addEventListener('click', attachToCard); | |
referenceDiv.addEventListener('mouseenter', evt => evt.currentTarget.style.cssText = makeInteractiveCard`cursor: pointer;`); | |
referenceDiv.addEventListener('mouseleave', evt => evt.currentTarget.style.cssText = makeInteractiveCard`cursor: none;`); | |
_.appendAll(referenceDiv, [profileImg, nameH2, birthDateTitle, deathDateTitle, emailTitle, usernameTitle]); | |
madeCardsStash.push(referenceDiv); | |
}, | |
undefined | |
); |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment