Register
Login
Resources
Docs Blog Datasets Glossary Case Studies Tutorials & Webinars
Product
Data Engine LLMs Platform Enterprise
Pricing Explore
Connect to our Discord channel

filter-cards.js 4.4 KB

You have to be logged in to leave a comment. Sign In
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
  1. function matchCardBySearch (card, searchString) {
  2. const matchReg = new RegExp(searchString, 'i')
  3. // Check if this card matches - any `data-*` attribute contains the string
  4. return Object.keys(card.dataset).some(key => matchReg.test(card.dataset[key]))
  5. }
  6. function matchCardByAttribute (card, attribute, value) {
  7. if (attribute in card.dataset) {
  8. const allValues = card.dataset[attribute].split(',')
  9. return allValues.some(key => key === value)
  10. }
  11. return false
  12. }
  13. export default function cardsFilter () {
  14. const inputFilter = document.querySelector('.js-filter-card-filter')
  15. const dropdownFilters = document.querySelectorAll('.js-filter-card-filter-dropdown')
  16. const cards = Array.from(document.querySelectorAll('.js-filter-card'))
  17. const showMoreButton = document.querySelector('.js-filter-card-show-more')
  18. const noResults = document.querySelector('.js-filter-card-no-results')
  19. // if jsFilterCardMax not set, assume no limit (well, at 99)
  20. // some landing pages don't include the button because the number of
  21. // guides is less than the max defined in includes/article-cards.html
  22. const maxCards = showMoreButton ? parseInt(showMoreButton.dataset.jsFilterCardMax || 99) : 99
  23. const noFilter = () => {
  24. if (showMoreButton) showMoreButton.classList.remove('d-none')
  25. for (let index = 0; index < cards.length; index++) {
  26. const card = cards[index]
  27. // Hide all but the first n number of cards
  28. if (index > maxCards - 1) {
  29. card.classList.add('d-none')
  30. } else {
  31. card.classList.remove('d-none')
  32. }
  33. }
  34. }
  35. const filterEventHandler = (evt) => {
  36. const { currentTarget } = evt
  37. const value = currentTarget.value
  38. if (showMoreButton) showMoreButton.classList.add('d-none')
  39. // Track whether or not we had at least one match
  40. let hasMatches = false
  41. for (let index = 0; index < cards.length; index++) {
  42. const card = cards[index]
  43. let cardMatches = false
  44. if (currentTarget.tagName === 'INPUT') {
  45. // Filter was emptied
  46. if (!value) {
  47. noFilter()
  48. // return hasMatches = true, so we don't show the "No results" blurb
  49. hasMatches = true
  50. continue
  51. }
  52. cardMatches = matchCardBySearch(card, value)
  53. }
  54. if (currentTarget.tagName === 'SELECT' && currentTarget.name) {
  55. const matches = []
  56. // check all the other dropdowns
  57. dropdownFilters.forEach(({ name, value }) => {
  58. if (!name || !value) return
  59. matches.push(matchCardByAttribute(card, name, value))
  60. })
  61. // if none of the filters is selected
  62. if (matches.length === 0) {
  63. noFilter()
  64. // return hasMatches = true, so we don't show the "No results" blurb
  65. hasMatches = true
  66. continue
  67. }
  68. cardMatches = matches.every(value => value)
  69. }
  70. if (cardMatches) {
  71. card.classList.remove('d-none')
  72. hasMatches = true
  73. } else {
  74. card.classList.add('d-none')
  75. }
  76. }
  77. // If there wasn't at least one match, show the "no results" text
  78. if (!hasMatches) {
  79. noResults.classList.remove('d-none')
  80. } else {
  81. noResults.classList.add('d-none')
  82. }
  83. return hasMatches
  84. }
  85. if (inputFilter) {
  86. inputFilter.addEventListener('keyup', (evt) => {
  87. const hasMatches = filterEventHandler(evt)
  88. if (!hasMatches) {
  89. document.querySelector('.js-filter-card-value').textContent = evt.currentTarget.value
  90. }
  91. })
  92. }
  93. if (dropdownFilters) {
  94. dropdownFilters.forEach(filter => filter.addEventListener('change', filterEventHandler))
  95. }
  96. if (showMoreButton) {
  97. showMoreButton.addEventListener('click', evt => {
  98. // Number of cards that are currently visible
  99. const numShown = cards.filter(card => !card.classList.contains('d-none')).length
  100. // We want to show n more cards
  101. const totalToShow = numShown + maxCards
  102. for (let index = numShown; index < cards.length; index++) {
  103. const card = cards[index]
  104. // If the card we're at is less than the total number of cards
  105. // we should show, show this one
  106. if (index < totalToShow) {
  107. card.classList.remove('d-none')
  108. } else {
  109. // Otherwise, we've shown the ones we intend to so exit the loop
  110. break
  111. }
  112. }
  113. // They're all shown now, we should hide the button
  114. if (totalToShow >= cards.length) {
  115. evt.currentTarget.classList.add('d-none')
  116. }
  117. })
  118. }
  119. }
Tip!

Press p or to see the previous file or, n or to see the next file

Comments

Loading...