* Move article from github directory as a top-level product * Update article titles * Remove old -ing article titles * Use older format for this PR * Finish updating links for retitled articles * Remove sponsors topic * Add sponsors to index.md * Create folder for map topic for sponsors * Add integrating folder/category with super basic graphql article * Add get started category/folder * Update index.md * Add articles to category folders and update all the links and check it out locally 🙏 * Fix space * Fix set of broken links * Update link in resuable * Add the quickstart * Add USD * Add matching donations caveat * fix ci failures * Bringing back `-ing` to Sponsors titles, categories, & links (#18817) * Bringing back -ing * The one that got away * Apply @ethanpalm's input Co-authored-by: Ethan Palm <56270045+ethanpalm@users.noreply.github.com> Co-authored-by: Ethan Palm <56270045+ethanpalm@users.noreply.github.com> * Apply product input * Apply suggestions from code review Co-authored-by: Emily Gould <4822039+emilyistoofunky@users.noreply.github.com> * Apply @emilyistoofunky's input * Sponsors landing page design (#18774) * Add sponsors to index.md as a top-level product * Revamp the GitHub Sponsors landing page with article links * remove merge tags * add community section * add sponsor descriptions * swap repo for user * remove prefix tag * lint * remove topic fix landing page * Tweak articles on landing page * Drop "account" * Add quickstart * Bigger, brighter, and shorter intro * Possibly too long of an intro? * fix quickstart link * add guides page * fix error for mismatch between title and filename * use link over guid * remove HTML from layout file (aligns to #18811) * use variable for section title * Add intro * Remove beta * Apply suggestions from code review Co-authored-by: Emily Gould <4822039+emilyistoofunky@users.noreply.github.com> * Apply suggestions from code review * Integrate article changes and remove old TOC * Fixing the commented out text to match other landing pages 👓 * Apply suggestions from code review Co-authored-by: Emily Gould <4822039+emilyistoofunky@users.noreply.github.com> * Switch up order of sidebar categories * Add new text to landing page button * Add topics and types * Add the underscore * Add some more topics * fix `type:` * Fix topics * plural ftw * hide learning paths when not defined * lint * Add quickstart to guides page * remove unused sidebar links * hide subsection title when learning tracks are not present * Apply @emilyistoofunky's topics input * Remove duplicated topics * Events ftw * typo * Remove obsolete topics for now * add some temporary duplicate topics * Resolve Linter error Co-authored-by: Rachael Sewell <rachmari@github.com> Co-authored-by: Emily Gould <4822039+emilyistoofunky@users.noreply.github.com> Co-authored-by: Rachael Sewell <rachmari@github.com> Co-authored-by: Ethan Palm <56270045+ethanpalm@users.noreply.github.com> Co-authored-by: Kevin Heis <heiskr@users.noreply.github.com> Co-authored-by: Emily Gould <4822039+emilyistoofunky@users.noreply.github.com>
139 lines
4.4 KiB
JavaScript
139 lines
4.4 KiB
JavaScript
function matchCardBySearch (card, searchString) {
|
|
const matchReg = new RegExp(searchString, 'i')
|
|
// Check if this card matches - any `data-*` attribute contains the string
|
|
return Object.keys(card.dataset).some(key => matchReg.test(card.dataset[key]))
|
|
}
|
|
|
|
function matchCardByAttribute (card, attribute, value) {
|
|
if (attribute in card.dataset) {
|
|
const allValues = card.dataset[attribute].split(',')
|
|
return allValues.some(key => key === value)
|
|
}
|
|
return false
|
|
}
|
|
|
|
export default function cardsFilter () {
|
|
const inputFilter = document.querySelector('.js-filter-card-filter')
|
|
const dropdownFilters = document.querySelectorAll('.js-filter-card-filter-dropdown')
|
|
const cards = Array.from(document.querySelectorAll('.js-filter-card'))
|
|
const showMoreButton = document.querySelector('.js-filter-card-show-more')
|
|
const noResults = document.querySelector('.js-filter-card-no-results')
|
|
// if jsFilterCardMax not set, assume no limit (well, at 99)
|
|
// some landing pages don't include the button because the number of
|
|
// guides is less than the max defined in includes/article-cards.html
|
|
const maxCards = showMoreButton ? parseInt(showMoreButton.dataset.jsFilterCardMax || 99) : 99
|
|
|
|
const noFilter = () => {
|
|
if (showMoreButton) showMoreButton.classList.remove('d-none')
|
|
for (let index = 0; index < cards.length; index++) {
|
|
const card = cards[index]
|
|
// Hide all but the first n number of cards
|
|
if (index > maxCards - 1) {
|
|
card.classList.add('d-none')
|
|
} else {
|
|
card.classList.remove('d-none')
|
|
}
|
|
}
|
|
}
|
|
|
|
const filterEventHandler = (evt) => {
|
|
const { currentTarget } = evt
|
|
const value = currentTarget.value
|
|
|
|
if (showMoreButton) showMoreButton.classList.add('d-none')
|
|
|
|
// Track whether or not we had at least one match
|
|
let hasMatches = false
|
|
|
|
for (let index = 0; index < cards.length; index++) {
|
|
const card = cards[index]
|
|
|
|
let cardMatches = false
|
|
|
|
if (currentTarget.tagName === 'INPUT') {
|
|
// Filter was emptied
|
|
if (!value) {
|
|
noFilter()
|
|
// return hasMatches = true, so we don't show the "No results" blurb
|
|
hasMatches = true
|
|
continue
|
|
}
|
|
cardMatches = matchCardBySearch(card, value)
|
|
}
|
|
|
|
if (currentTarget.tagName === 'SELECT' && currentTarget.name) {
|
|
const matches = []
|
|
// check all the other dropdowns
|
|
dropdownFilters.forEach(({ name, value }) => {
|
|
if (!name || !value) return
|
|
matches.push(matchCardByAttribute(card, name, value))
|
|
})
|
|
// if none of the filters is selected
|
|
if (matches.length === 0) {
|
|
noFilter()
|
|
// return hasMatches = true, so we don't show the "No results" blurb
|
|
hasMatches = true
|
|
continue
|
|
}
|
|
cardMatches = matches.every(value => value)
|
|
}
|
|
|
|
if (cardMatches) {
|
|
card.classList.remove('d-none')
|
|
hasMatches = true
|
|
} else {
|
|
card.classList.add('d-none')
|
|
}
|
|
}
|
|
|
|
// If there wasn't at least one match, show the "no results" text
|
|
if (!hasMatches) {
|
|
noResults.classList.remove('d-none')
|
|
} else {
|
|
noResults.classList.add('d-none')
|
|
}
|
|
|
|
return hasMatches
|
|
}
|
|
|
|
if (inputFilter) {
|
|
inputFilter.addEventListener('keyup', (evt) => {
|
|
const hasMatches = filterEventHandler(evt)
|
|
if (!hasMatches) {
|
|
document.querySelector('.js-filter-card-value').textContent = evt.currentTarget.value
|
|
}
|
|
})
|
|
}
|
|
|
|
if (dropdownFilters) {
|
|
dropdownFilters.forEach(filter => filter.addEventListener('change', filterEventHandler))
|
|
}
|
|
|
|
if (showMoreButton) {
|
|
showMoreButton.addEventListener('click', evt => {
|
|
// Number of cards that are currently visible
|
|
const numShown = cards.filter(card => !card.classList.contains('d-none')).length
|
|
// We want to show n more cards
|
|
const totalToShow = numShown + maxCards
|
|
|
|
for (let index = numShown; index < cards.length; index++) {
|
|
const card = cards[index]
|
|
|
|
// If the card we're at is less than the total number of cards
|
|
// we should show, show this one
|
|
if (index < totalToShow) {
|
|
card.classList.remove('d-none')
|
|
} else {
|
|
// Otherwise, we've shown the ones we intend to so exit the loop
|
|
break
|
|
}
|
|
}
|
|
|
|
// They're all shown now, we should hide the button
|
|
if (totalToShow >= cards.length) {
|
|
evt.currentTarget.classList.add('d-none')
|
|
}
|
|
})
|
|
}
|
|
}
|