1
0
mirror of synced 2025-12-21 10:57:10 -05:00
Files
docs/javascripts/filter-cards.js
jmarlena 1fc4c3f68b Article restructuring for Sponsors landing page (#18772)
* 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>
2021-04-21 11:48:19 -07:00

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')
}
})
}
}