henry-search 1.0.8 → 1.0.10
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/HenrySearch.js +26928 -27056
- package/dist/HenrySearch.umd.cjs +114 -111
- package/package.json +1 -1
- package/src/components/AudioLinks.vue +29 -0
- package/src/components/EventLinks.vue +93 -0
- package/src/components/Search.vue +37 -528
- package/src/components/SearchDetail.vue +32 -33
- package/src/components/SearchHistory.vue +13 -14
- package/src/components/SearchTab.vue +30 -45
|
@@ -1,15 +1,10 @@
|
|
|
1
1
|
<script setup>
|
|
2
2
|
|
|
3
|
-
import { ref, onMounted
|
|
4
|
-
|
|
5
|
-
import VueDatePicker from '@vuepic/vue-datepicker';
|
|
3
|
+
import { ref, onMounted } from 'vue'
|
|
6
4
|
import '@vuepic/vue-datepicker/dist/main.css'
|
|
7
|
-
|
|
8
|
-
import Typesense from 'typesense'
|
|
9
|
-
|
|
10
|
-
|
|
11
5
|
import PTabs from './PTabs.vue'
|
|
12
6
|
import SearchTab from "./SearchTab.vue"
|
|
7
|
+
import EventLinks from "./EventLinks.vue"
|
|
13
8
|
|
|
14
9
|
import formatDate from '../composables/formatDate'
|
|
15
10
|
|
|
@@ -29,38 +24,38 @@
|
|
|
29
24
|
})
|
|
30
25
|
|
|
31
26
|
const displayDate = ref(null)
|
|
32
|
-
const datepicker = ref(null)
|
|
33
|
-
const rangeInput = ref(null)
|
|
34
|
-
const venueOptions = ref([])
|
|
35
|
-
const ensembleOptions = ref([])
|
|
36
27
|
|
|
37
28
|
const today = Date.now()
|
|
38
29
|
const date = ref([today, today])
|
|
39
30
|
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
31
|
+
onMounted(() => {
|
|
32
|
+
document.addEventListener("click", function(){
|
|
33
|
+
document.querySelectorAll(".audioLinkBox").forEach((el) => {
|
|
34
|
+
el.classList.remove("-open")
|
|
35
|
+
})
|
|
36
|
+
})
|
|
37
|
+
})
|
|
43
38
|
|
|
44
39
|
const mainRefinements = [
|
|
45
40
|
{attribute: 'works.composers', title: 'Composer', placeholder: 'Search Composers'},
|
|
46
41
|
{attribute: 'works.title', title: 'Work', placeholder: 'Search Works'},
|
|
47
|
-
{attribute: 'conductors', title: 'Conductor', placeholder: 'Search Conductors'},
|
|
48
|
-
{attribute: 'ensembles', title: 'Orchestra/Ensemble', placeholder: 'Search Orchestras/Ensembles'},
|
|
42
|
+
{attribute: 'works.conductors', title: 'Conductor', placeholder: 'Search Conductors'},
|
|
43
|
+
{attribute: 'works.ensembles', title: 'Orchestra/Ensemble', placeholder: 'Search Orchestras/Ensembles'},
|
|
49
44
|
{attribute: 'works.artists.name', title: 'Artist', placeholder: 'Search Artists'},
|
|
50
45
|
]
|
|
51
46
|
|
|
52
47
|
const addlRefinements = [
|
|
53
|
-
{attribute: 'works.artists.role', title: 'Instrument', placeholder: 'Search Instruments', type: 'list'},
|
|
48
|
+
{attribute: 'works.artists.role', title: 'Instrument', placeholder: 'Search Instruments', type: 'list', hideSearch: 'true'},
|
|
54
49
|
// {attribute: 'works.additional_creators.creator_name', title: 'Additional Creator', placeholder: 'Search Creators', type: 'list'},
|
|
55
50
|
// {attribute: 'works.additional_creators.creator_role', title: 'Additional Creator Role', placeholder: 'Search Creator Roles', type: 'list'},
|
|
56
51
|
{attribute: 'season', title: 'Season', placeholder: 'Search Seasons', type: 'list'},
|
|
57
52
|
{attribute: 'event_title', title: 'Event Title', placeholder: 'Search Event Titles', type: 'list'},
|
|
58
53
|
{attribute: 'event_types', title: 'Series', placeholder: 'Search Event Types', type: 'list'},
|
|
59
|
-
{attribute: 'venue', title: 'Venue', placeholder: 'Search Venues', type: 'list'},
|
|
54
|
+
{attribute: 'venue', title: 'Venue', placeholder: 'Search Venues', type: 'list', hideSearch: 'true'},
|
|
60
55
|
{attribute: 'location', title: 'Location', type: 'location'},
|
|
61
|
-
{attribute: 'media', title: 'Media', placeholder: 'Select Media', type: 'list', hideSearch: '
|
|
62
|
-
{attribute: 'premiere', title: 'Premiere', placeholder: 'Select Premiere', type: 'list', hideSearch: '
|
|
63
|
-
{attribute: 'works.commission', title: 'Commission', placeholder: 'Select Premiere', type: 'list', hideSearch: '
|
|
56
|
+
{attribute: 'media', title: 'Media', placeholder: 'Select Media', type: 'list', hideSearch: 'true'},
|
|
57
|
+
{attribute: 'works.premiere', title: 'Premiere', placeholder: 'Select Premiere', type: 'list', hideSearch: 'true'},
|
|
58
|
+
{attribute: 'works.commission', title: 'Commission', placeholder: 'Select Premiere', type: 'list', hideSearch: 'true'}
|
|
64
59
|
]
|
|
65
60
|
|
|
66
61
|
const artistRefinements = [
|
|
@@ -79,108 +74,6 @@
|
|
|
79
74
|
{attribute: 'commission', title: 'Commission', placeholder: 'Search Commissions'}
|
|
80
75
|
]
|
|
81
76
|
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
// Check if we're on mobile
|
|
85
|
-
const isMobile = ref(false)
|
|
86
|
-
|
|
87
|
-
// Function to check mobile status
|
|
88
|
-
function checkMobile() {
|
|
89
|
-
if (typeof window !== 'undefined') {
|
|
90
|
-
isMobile.value = window.innerWidth <= 767
|
|
91
|
-
}
|
|
92
|
-
}
|
|
93
|
-
|
|
94
|
-
onMounted(() => {
|
|
95
|
-
|
|
96
|
-
console.log("props.workIndex", props.workIndex)
|
|
97
|
-
|
|
98
|
-
// Disable browser scroll restoration
|
|
99
|
-
if ('scrollRestoration' in history) {
|
|
100
|
-
history.scrollRestoration = 'manual'
|
|
101
|
-
}
|
|
102
|
-
|
|
103
|
-
// Listen for clicks on pagination and scroll after a delay
|
|
104
|
-
setupPaginationScrollFix()
|
|
105
|
-
|
|
106
|
-
// Check mobile status and add resize listener
|
|
107
|
-
checkMobile()
|
|
108
|
-
if (typeof window !== 'undefined') {
|
|
109
|
-
window.addEventListener('resize', checkMobile)
|
|
110
|
-
}
|
|
111
|
-
|
|
112
|
-
// // Fallback: Watch for date picker menu to appear/disappear using MutationObserver
|
|
113
|
-
// const observer = new MutationObserver((mutations) => {
|
|
114
|
-
// mutations.forEach((mutation) => {
|
|
115
|
-
// // Watch for added nodes (menu opening)
|
|
116
|
-
// mutation.addedNodes.forEach((node) => {
|
|
117
|
-
// if (node.nodeType === 1 && node.classList) {
|
|
118
|
-
// // Only trigger for the main menu, not wrapper elements or our modal
|
|
119
|
-
// if (node.classList.contains('dp__menu') &&
|
|
120
|
-
// !node.classList.contains('dp__mobile_modal') &&
|
|
121
|
-
// !modalCreated && !isCreatingModal) {
|
|
122
|
-
// if (typeof window !== 'undefined' && window.innerWidth <= 767) {
|
|
123
|
-
// onDatePickerOpened()
|
|
124
|
-
// }
|
|
125
|
-
// }
|
|
126
|
-
// }
|
|
127
|
-
// })
|
|
128
|
-
// })
|
|
129
|
-
// })
|
|
130
|
-
|
|
131
|
-
// observer.observe(document.body, {
|
|
132
|
-
// childList: true,
|
|
133
|
-
// subtree: true
|
|
134
|
-
// })
|
|
135
|
-
|
|
136
|
-
})
|
|
137
|
-
|
|
138
|
-
|
|
139
|
-
onUnmounted(() => {
|
|
140
|
-
// Restore browser scroll restoration
|
|
141
|
-
if ('scrollRestoration' in history) {
|
|
142
|
-
history.scrollRestoration = 'auto'
|
|
143
|
-
}
|
|
144
|
-
|
|
145
|
-
// Remove resize listener
|
|
146
|
-
if (typeof window !== 'undefined') {
|
|
147
|
-
window.removeEventListener('resize', checkMobile)
|
|
148
|
-
}
|
|
149
|
-
})
|
|
150
|
-
|
|
151
|
-
|
|
152
|
-
function setupPaginationScrollFix() {
|
|
153
|
-
// Use event delegation to catch pagination clicks
|
|
154
|
-
document.addEventListener('click', (event) => {
|
|
155
|
-
const paginationLink = event.target.closest('.ais-Pagination-link')
|
|
156
|
-
|
|
157
|
-
if (paginationLink) {
|
|
158
|
-
// Don't prevent default - let InstantSearch handle navigation normally
|
|
159
|
-
// Schedule a scroll after InstantSearch updates
|
|
160
|
-
setTimeout(() => {
|
|
161
|
-
scrollToResults()
|
|
162
|
-
}, 200)
|
|
163
|
-
}
|
|
164
|
-
})
|
|
165
|
-
}
|
|
166
|
-
|
|
167
|
-
function scrollToResults() {
|
|
168
|
-
const resultsSection = document.querySelector('.eventsSearch__results')
|
|
169
|
-
if (resultsSection) {
|
|
170
|
-
const rect = resultsSection.getBoundingClientRect()
|
|
171
|
-
const scrollTop = window.pageYOffset + rect.top - 20 // 20px offset from top
|
|
172
|
-
|
|
173
|
-
window.scrollTo({
|
|
174
|
-
top: scrollTop,
|
|
175
|
-
behavior: 'smooth'
|
|
176
|
-
})
|
|
177
|
-
}
|
|
178
|
-
}
|
|
179
|
-
|
|
180
|
-
const setDate = (value) => {
|
|
181
|
-
date.value = value
|
|
182
|
-
displayDate.value = value
|
|
183
|
-
}
|
|
184
77
|
|
|
185
78
|
function createURL(facets) {
|
|
186
79
|
let returnUrl = "/?"
|
|
@@ -229,332 +122,10 @@
|
|
|
229
122
|
returnLocation += location.country
|
|
230
123
|
}
|
|
231
124
|
}
|
|
232
|
-
return returnLocation
|
|
233
|
-
|
|
234
|
-
|
|
125
|
+
return returnLocation
|
|
235
126
|
}
|
|
236
127
|
|
|
237
|
-
// Generic mobile filter modal function
|
|
238
|
-
function createMobileFilterModal(filterType, displayName, items, refineFunction) {
|
|
239
|
-
const modalHTML = createMultiSelectModalHTML({
|
|
240
|
-
modalId: `${filterType}__mobile_modal`,
|
|
241
|
-
title: `Select ${displayName}`,
|
|
242
|
-
description: `Choose your ${displayName.toLowerCase()}`,
|
|
243
|
-
cancelText: 'Cancel',
|
|
244
|
-
selectText: 'Apply',
|
|
245
|
-
cancelButtonClass: `js-${filterType}-cancel`,
|
|
246
|
-
selectButtonClass: `js-${filterType}-select`,
|
|
247
|
-
contentContainerClass: `eventsModal__${filterType}Container`
|
|
248
|
-
})
|
|
249
|
-
|
|
250
|
-
// Insert modal into body
|
|
251
|
-
document.body.insertAdjacentHTML('beforeend', modalHTML)
|
|
252
|
-
|
|
253
|
-
const modal = document.querySelector(`.${filterType}__mobile_modal`)
|
|
254
|
-
const container = modal.querySelector(`.eventsModal__${filterType}Container`)
|
|
255
|
-
|
|
256
|
-
if (modal && container) {
|
|
257
|
-
// Generate filter options HTML
|
|
258
|
-
let optionsHTML = '<div class="filterModal__items">'
|
|
259
|
-
|
|
260
|
-
items.forEach((item) => {
|
|
261
|
-
const isChecked = item.isRefined ? 'checked' : ''
|
|
262
|
-
const cleanLabel = item.value.replace(/<[^>]*>/g, '') // Remove HTML tags
|
|
263
|
-
|
|
264
|
-
// For venue, split venue name from city
|
|
265
|
-
let itemTextHTML = `<span class="filterModal__itemText">${cleanLabel}</span>`
|
|
266
|
-
if (filterType === 'venue') {
|
|
267
|
-
// Split on common patterns: ", City" or " | City" or similar
|
|
268
|
-
const parts = cleanLabel.split(/,\s*(?=[A-Z])|(?:\s*\|\s*[^|]*,\s*)/);
|
|
269
|
-
if (parts.length >= 2) {
|
|
270
|
-
const venueName = parts[0].trim();
|
|
271
|
-
const cityInfo = parts.slice(1).join(', ').trim();
|
|
272
|
-
itemTextHTML = `
|
|
273
|
-
<span class="filterModal__itemText">
|
|
274
|
-
<span class="filterModal__venueName">${venueName}</span>
|
|
275
|
-
<span class="filterModal__venueCity">${cityInfo}</span>
|
|
276
|
-
</span>
|
|
277
|
-
`
|
|
278
|
-
}
|
|
279
|
-
}
|
|
280
|
-
|
|
281
|
-
optionsHTML += `
|
|
282
|
-
<div class="filterModal__item">
|
|
283
|
-
<label class="filterModal__itemLabel">
|
|
284
|
-
<input type="checkbox"
|
|
285
|
-
class="${filterType}-checkbox"
|
|
286
|
-
value="${item.value.replace(/"/g, '"')}"
|
|
287
|
-
${isChecked}
|
|
288
|
-
data-count="${item.count}"
|
|
289
|
-
style="display: block !important; width: 20px !important; height: 20px !important; margin: 0 !important; opacity: 1 !important; visibility: visible !important;">
|
|
290
|
-
${itemTextHTML}
|
|
291
|
-
</label>
|
|
292
|
-
</div>
|
|
293
|
-
`
|
|
294
|
-
})
|
|
295
|
-
|
|
296
|
-
optionsHTML += '</div>'
|
|
297
|
-
container.innerHTML = optionsHTML
|
|
298
|
-
|
|
299
|
-
// Add body class for modal
|
|
300
|
-
document.body.classList.add('menu-is-open')
|
|
301
|
-
|
|
302
|
-
// Add close functionality
|
|
303
|
-
const closeBtn = modal.querySelector('.js--modal-close')
|
|
304
|
-
if (closeBtn) {
|
|
305
|
-
closeBtn.addEventListener('click', (e) => {
|
|
306
|
-
e.preventDefault()
|
|
307
|
-
closeMobileFilterModal(filterType)
|
|
308
|
-
})
|
|
309
|
-
}
|
|
310
|
-
|
|
311
|
-
// Add escape key handler
|
|
312
|
-
const escapeHandler = (evt) => {
|
|
313
|
-
if (evt.keyCode === 27) { // ESC key
|
|
314
|
-
closeMobileFilterModal(filterType)
|
|
315
|
-
}
|
|
316
|
-
}
|
|
317
|
-
document.addEventListener('keydown', escapeHandler)
|
|
318
|
-
|
|
319
|
-
// Add click listeners to buttons
|
|
320
|
-
const selectBtn = modal.querySelector(`.js-${filterType}-select`)
|
|
321
|
-
const cancelBtn = modal.querySelector(`.js-${filterType}-cancel`)
|
|
322
|
-
|
|
323
|
-
if (selectBtn) {
|
|
324
|
-
selectBtn.addEventListener('click', () => {
|
|
325
|
-
// Get all checkboxes
|
|
326
|
-
const checkboxes = modal.querySelectorAll(`.${filterType}-checkbox`)
|
|
327
|
-
|
|
328
|
-
// Get currently selected values from checkboxes
|
|
329
|
-
const selectedValues = []
|
|
330
|
-
checkboxes.forEach(checkbox => {
|
|
331
|
-
if (checkbox.checked) {
|
|
332
|
-
selectedValues.push(checkbox.value)
|
|
333
|
-
}
|
|
334
|
-
})
|
|
335
|
-
|
|
336
|
-
// First, clear all existing refinements
|
|
337
|
-
items.forEach(item => {
|
|
338
|
-
if (item.isRefined) {
|
|
339
|
-
refineFunction(item.value)
|
|
340
|
-
}
|
|
341
|
-
})
|
|
342
128
|
|
|
343
|
-
// Then apply new selections
|
|
344
|
-
selectedValues.forEach(value => {
|
|
345
|
-
refineFunction(value)
|
|
346
|
-
})
|
|
347
|
-
|
|
348
|
-
closeMobileFilterModal(filterType)
|
|
349
|
-
})
|
|
350
|
-
}
|
|
351
|
-
|
|
352
|
-
if (cancelBtn) {
|
|
353
|
-
cancelBtn.addEventListener('click', () => {
|
|
354
|
-
closeMobileFilterModal(filterType)
|
|
355
|
-
})
|
|
356
|
-
|
|
357
|
-
// Add hover effects for secondary button
|
|
358
|
-
cancelBtn.addEventListener('mouseenter', () => {
|
|
359
|
-
cancelBtn.style.background = '#e5e5e5'
|
|
360
|
-
})
|
|
361
|
-
|
|
362
|
-
cancelBtn.addEventListener('mouseleave', () => {
|
|
363
|
-
cancelBtn.style.background = '#F5F5F5'
|
|
364
|
-
})
|
|
365
|
-
}
|
|
366
|
-
}
|
|
367
|
-
}
|
|
368
|
-
|
|
369
|
-
function closeMobileFilterModal(filterType) {
|
|
370
|
-
const modal = document.querySelector(`.${filterType}__mobile_modal`)
|
|
371
|
-
if (modal) {
|
|
372
|
-
modal.remove()
|
|
373
|
-
document.body.classList.remove('menu-is-open')
|
|
374
|
-
}
|
|
375
|
-
}
|
|
376
|
-
|
|
377
|
-
// Generic click handler for filter dropdowns
|
|
378
|
-
function handleFilterDropdownClick(event, filterType, displayName, items, refine) {
|
|
379
|
-
let windowWidth = 1024; // Default to desktop
|
|
380
|
-
|
|
381
|
-
try {
|
|
382
|
-
if (typeof window !== 'undefined' && window) {
|
|
383
|
-
windowWidth = window.innerWidth || 1024;
|
|
384
|
-
}
|
|
385
|
-
} catch (e) {
|
|
386
|
-
// Window not available, use default
|
|
387
|
-
}
|
|
388
|
-
|
|
389
|
-
// Show modal on mobile only
|
|
390
|
-
const shouldShowModal = windowWidth <= 767;
|
|
391
|
-
|
|
392
|
-
if (shouldShowModal) {
|
|
393
|
-
event.preventDefault();
|
|
394
|
-
event.stopPropagation();
|
|
395
|
-
createMobileFilterModal(filterType, displayName, items, refine);
|
|
396
|
-
return false;
|
|
397
|
-
} else {
|
|
398
|
-
// console.log('Desktop - allowing normal dropdown');
|
|
399
|
-
}
|
|
400
|
-
}
|
|
401
|
-
|
|
402
|
-
function createMobileDatePickerModal() {
|
|
403
|
-
const menu = document.querySelector('.dp__menu')
|
|
404
|
-
if (!menu) {
|
|
405
|
-
setTimeout(() => {
|
|
406
|
-
const retryMenu = document.querySelector('.dp__menu')
|
|
407
|
-
if (retryMenu) {
|
|
408
|
-
createMobileDatePickerModal()
|
|
409
|
-
}
|
|
410
|
-
}, 50)
|
|
411
|
-
return
|
|
412
|
-
}
|
|
413
|
-
|
|
414
|
-
// Create modal structure using reusable template function
|
|
415
|
-
const modalHTML = createMultiSelectModalHTML({
|
|
416
|
-
modalId: 'dp__mobile_modal',
|
|
417
|
-
title: 'Select Date Range',
|
|
418
|
-
description: 'Choose your date range',
|
|
419
|
-
cancelText: 'Cancel',
|
|
420
|
-
selectText: 'Select',
|
|
421
|
-
cancelButtonClass: 'js-datepicker-cancel',
|
|
422
|
-
selectButtonClass: 'js-datepicker-select',
|
|
423
|
-
contentContainerClass: 'eventsModal__datePickerContainer'
|
|
424
|
-
})
|
|
425
|
-
|
|
426
|
-
// Insert modal into body
|
|
427
|
-
document.body.insertAdjacentHTML('beforeend', modalHTML)
|
|
428
|
-
|
|
429
|
-
// Move the date picker menu into the modal
|
|
430
|
-
const modal = document.querySelector('.dp__mobile_modal')
|
|
431
|
-
const datePickerContainer = modal.querySelector('.eventsModal__datePickerContainer')
|
|
432
|
-
|
|
433
|
-
if (modal && datePickerContainer && menu) {
|
|
434
|
-
datePickerContainer.appendChild(menu)
|
|
435
|
-
|
|
436
|
-
// Hide the original VueDatePicker buttons since we have modal buttons
|
|
437
|
-
const originalActionRow = menu.querySelector('.dp__action_row')
|
|
438
|
-
if (originalActionRow) {
|
|
439
|
-
originalActionRow.style.display = 'none'
|
|
440
|
-
}
|
|
441
|
-
|
|
442
|
-
// Add body class for modal
|
|
443
|
-
document.body.classList.add('menu-is-open')
|
|
444
|
-
|
|
445
|
-
// Track selected range manually
|
|
446
|
-
let selectedRange = null
|
|
447
|
-
|
|
448
|
-
// Add close functionality
|
|
449
|
-
const closeBtn = modal.querySelector('.js--modal-close')
|
|
450
|
-
if (closeBtn) {
|
|
451
|
-
closeBtn.addEventListener('click', (e) => {
|
|
452
|
-
e.preventDefault()
|
|
453
|
-
closeMobileDatePickerModal()
|
|
454
|
-
})
|
|
455
|
-
}
|
|
456
|
-
|
|
457
|
-
// Add escape key handler
|
|
458
|
-
document.addEventListener('keydown', handleModalEscape)
|
|
459
|
-
|
|
460
|
-
// Add click listeners to our custom buttons
|
|
461
|
-
const selectBtn = modal.querySelector('.js-datepicker-select')
|
|
462
|
-
const cancelBtn = modal.querySelector('.js-datepicker-cancel')
|
|
463
|
-
|
|
464
|
-
if (selectBtn) {
|
|
465
|
-
selectBtn.addEventListener('click', () => {
|
|
466
|
-
|
|
467
|
-
// Get currently selected dates from the calendar
|
|
468
|
-
const selectedDates = menu.querySelectorAll('.dp__calendar_item[aria-selected="true"]')
|
|
469
|
-
|
|
470
|
-
if (selectedDates.length >= 2) {
|
|
471
|
-
const dateRange = []
|
|
472
|
-
selectedDates.forEach((dateEl) => {
|
|
473
|
-
const dateId = dateEl.id // Format: "2025-11-01"
|
|
474
|
-
if (dateId) {
|
|
475
|
-
const dateObj = new Date(dateId + 'T00:00:00')
|
|
476
|
-
dateRange.push(dateObj)
|
|
477
|
-
}
|
|
478
|
-
})
|
|
479
|
-
|
|
480
|
-
// Sort dates to ensure proper range
|
|
481
|
-
dateRange.sort((a, b) => a - b)
|
|
482
|
-
|
|
483
|
-
// Set the date range
|
|
484
|
-
setDate(dateRange)
|
|
485
|
-
displayDate.value = [...dateRange]
|
|
486
|
-
|
|
487
|
-
} else if (selectedDates.length === 1) {
|
|
488
|
-
// Single date selected - create a single day range
|
|
489
|
-
const dateId = selectedDates[0].id
|
|
490
|
-
const singleDate = new Date(dateId + 'T00:00:00')
|
|
491
|
-
const endDate = new Date(singleDate)
|
|
492
|
-
endDate.setDate(endDate.getDate() + 1)
|
|
493
|
-
|
|
494
|
-
const range = [singleDate, endDate]
|
|
495
|
-
setDate(range)
|
|
496
|
-
displayDate.value = [...range]
|
|
497
|
-
|
|
498
|
-
} else {
|
|
499
|
-
console.log('No dates selected')
|
|
500
|
-
}
|
|
501
|
-
|
|
502
|
-
// Close modal
|
|
503
|
-
setTimeout(() => {
|
|
504
|
-
closeMobileDatePickerModal()
|
|
505
|
-
}, 100)
|
|
506
|
-
})
|
|
507
|
-
}
|
|
508
|
-
|
|
509
|
-
if (cancelBtn) {
|
|
510
|
-
cancelBtn.addEventListener('click', () => {
|
|
511
|
-
closeMobileDatePickerModal()
|
|
512
|
-
})
|
|
513
|
-
|
|
514
|
-
// Add hover effects for secondary button
|
|
515
|
-
cancelBtn.addEventListener('mouseenter', () => {
|
|
516
|
-
cancelBtn.style.background = '#e5e5e5'
|
|
517
|
-
})
|
|
518
|
-
|
|
519
|
-
cancelBtn.addEventListener('mouseleave', () => {
|
|
520
|
-
cancelBtn.style.background = '#F5F5F5'
|
|
521
|
-
})
|
|
522
|
-
}
|
|
523
|
-
|
|
524
|
-
modalCreated = true
|
|
525
|
-
} else {
|
|
526
|
-
console.error('Failed to find modal elements after creation')
|
|
527
|
-
}
|
|
528
|
-
}
|
|
529
|
-
|
|
530
|
-
function closeMobileDatePickerModal() {
|
|
531
|
-
|
|
532
|
-
// Close the VueDatePicker directly
|
|
533
|
-
if (datepicker.value && datepicker.value.closeMenu) {
|
|
534
|
-
datepicker.value.closeMenu()
|
|
535
|
-
}
|
|
536
|
-
|
|
537
|
-
const modal = document.querySelector('.dp__mobile_modal')
|
|
538
|
-
if (modal) {
|
|
539
|
-
modal.remove()
|
|
540
|
-
document.body.classList.remove('menu-is-open')
|
|
541
|
-
document.removeEventListener('keydown', handleModalEscape)
|
|
542
|
-
modalCreated = false // Reset the flag
|
|
543
|
-
} else {
|
|
544
|
-
console.log('No modal found to remove')
|
|
545
|
-
}
|
|
546
|
-
// Always reset the flag, even if no modal was found
|
|
547
|
-
modalCreated = false
|
|
548
|
-
}
|
|
549
|
-
|
|
550
|
-
function handleModalEscape(evt) {
|
|
551
|
-
if (evt.keyCode === 27) { // ESC key
|
|
552
|
-
closeMobileDatePickerModal()
|
|
553
|
-
if (datepicker.value && datepicker.value.closeMenu) {
|
|
554
|
-
datepicker.value.closeMenu()
|
|
555
|
-
}
|
|
556
|
-
}
|
|
557
|
-
}
|
|
558
129
|
</script>
|
|
559
130
|
|
|
560
131
|
<template>
|
|
@@ -567,16 +138,16 @@
|
|
|
567
138
|
:addl-refinements="addlRefinements"
|
|
568
139
|
:sort-field="'performance_date'"
|
|
569
140
|
:query-by-fields="'works, works.composers, works.title, works.artists, season, venue, event_types, notes, event_title, ensembles, conductors'"
|
|
570
|
-
:include-fields="'works, works.composers, works.title, works.artists, season, venue, event_types, notes, event_title, ensembles, conductors, id, performance_date'"
|
|
141
|
+
:include-fields="'works, works.composers, works.title, works.artists, season, venue, event_types, notes, event_title, ensembles, conductors, id, performance_date, program_book_link, media, bso_audio_id'"
|
|
571
142
|
search-placeholder="Search by composer, works, conductor, orchestra, and more"
|
|
572
143
|
results-title="Performances"
|
|
573
144
|
>
|
|
574
|
-
<template v-slot="{ items
|
|
145
|
+
<template v-slot="{ items }">
|
|
575
146
|
<div class="eventsSearch__resultsGrid" v-if="items && items.length">
|
|
576
147
|
<!-- Header Row -->
|
|
577
148
|
<div class="eventsSearch__resultCell -header -first">Date/Season/Title</div>
|
|
578
149
|
<div class="eventsSearch__resultCell -header">Venue</div>
|
|
579
|
-
<div class="eventsSearch__resultCell -header">
|
|
150
|
+
<div class="eventsSearch__resultCell -header">Ensemble</div>
|
|
580
151
|
<div class="eventsSearch__resultCell -header">Conductor</div>
|
|
581
152
|
<div class="eventsSearch__resultCell -header">Composer/Work</div>
|
|
582
153
|
<div class="eventsSearch__resultCell -header">Artist/Role</div>
|
|
@@ -624,31 +195,7 @@
|
|
|
624
195
|
${item.works.length > 1 ? '-details' : '' }
|
|
625
196
|
${index % 2 == 0 ? '-even' : '-odd'}
|
|
626
197
|
${(index + 1 == items.length && (i + 1 == item.works.length || i == 5)) ? '-last -lastMobile' : ''}`">
|
|
627
|
-
<
|
|
628
|
-
<svg width="18" height="18" viewBox="0 0 18 18" fill="none" xmlns="http://www.w3.org/2000/svg">
|
|
629
|
-
<circle cx="9" cy="9" r="9" fill="#01ABE6"/>
|
|
630
|
-
<path d="M5 9H13" stroke="white" stroke-width="1.5"/>
|
|
631
|
-
<path d="M9 5L13 9L9 13" stroke="white" stroke-width="1.5"/>
|
|
632
|
-
</svg>
|
|
633
|
-
<a class="detailsLink" :href="`/details?performanceId=${item.id}`">Details</a>
|
|
634
|
-
</div>
|
|
635
|
-
<div v-if="item.program_link" class="eventsSearch__perfDetails">
|
|
636
|
-
<svg width="18" height="18" viewBox="0 0 18 18" fill="none" xmlns="http://www.w3.org/2000/svg">
|
|
637
|
-
<circle cx="9" cy="9" r="8.25" fill="white" stroke="#01ABE6" stroke-width="1.5"/>
|
|
638
|
-
<path d="M6.22876 12.0713L11.8854 6.41469" stroke="#01ABE6" stroke-width="1.5"/>
|
|
639
|
-
<path d="M6.22864 6.41382L11.8854 6.41395L11.8855 12.0707" stroke="#01ABE6" stroke-width="1.5"/>
|
|
640
|
-
</svg>
|
|
641
|
-
<a class="detailsLink" :href="item.program_link">Program</a>
|
|
642
|
-
</div>
|
|
643
|
-
<div v-if="item.media && item.media.includes('audio')" class="eventsSearch__perfDetails">
|
|
644
|
-
<svg width="18" height="18" viewBox="0 0 18 18" fill="none" xmlns="http://www.w3.org/2000/svg">
|
|
645
|
-
<circle cx="9" cy="9" r="8.25" fill="white" stroke="#01ABE6" stroke-width="1.5"/>
|
|
646
|
-
<path d="M9.81086 5L6.92983 7.30483H4.625V10.7621H6.92983L9.81086 13.0669V5Z" fill="white" stroke="#01ABE6" stroke-width="1.5" stroke-linecap="round" stroke-linejoin="round"/>
|
|
647
|
-
<path d="M12.4268 6.99219C12.9669 7.53246 13.2703 8.26513 13.2703 9.02908C13.2703 9.79302 12.9669 10.5257 12.4268 11.066" fill="white"/>
|
|
648
|
-
<path d="M12.4268 6.99219C12.9669 7.53246 13.2703 8.26513 13.2703 9.02908C13.2703 9.79302 12.9669 10.5257 12.4268 11.066" stroke="#01ABE6" stroke-width="1.5" stroke-linecap="round" stroke-linejoin="round"/>
|
|
649
|
-
</svg>
|
|
650
|
-
<a class="detailsLink">Audio</a>
|
|
651
|
-
</div>
|
|
198
|
+
<event-links :item="item" />
|
|
652
199
|
</div>
|
|
653
200
|
</template>
|
|
654
201
|
<!-- Additional event rows -->
|
|
@@ -689,34 +236,10 @@
|
|
|
689
236
|
</div>
|
|
690
237
|
<div :class="`eventsSearch__resultCell -detailsMobile
|
|
691
238
|
${index % 2 == 0 ? '-even' : '-odd'}
|
|
692
|
-
${(index + 1 == items.length && (i + 1 == item.works.length || i ==
|
|
239
|
+
${(index + 1 == items.length && (i + 1 == item.works.length || i == 4)) ? '-last -lastMobile' : ''}
|
|
693
240
|
${ !(i + 1 == item.works.length || i == 5) ? '-empty' : ''}`">
|
|
694
241
|
<template v-if="(i + 1 == item.works.length || i == 5)">
|
|
695
|
-
<
|
|
696
|
-
<svg width="18" height="18" viewBox="0 0 18 18" fill="none" xmlns="http://www.w3.org/2000/svg">
|
|
697
|
-
<circle cx="9" cy="9" r="9" fill="#01ABE6"/>
|
|
698
|
-
<path d="M5 9H13" stroke="white" stroke-width="1.5"/>
|
|
699
|
-
<path d="M9 5L13 9L9 13" stroke="white" stroke-width="1.5"/>
|
|
700
|
-
</svg>
|
|
701
|
-
<a class="detailsLink" :href="`/details?performanceId=${item.id}`">Details</a>
|
|
702
|
-
</div>
|
|
703
|
-
<div v-if="item.program_link" class="eventsSearch__perfDetails -detailsMobile">
|
|
704
|
-
<svg width="18" height="18" viewBox="0 0 18 18" fill="none" xmlns="http://www.w3.org/2000/svg">
|
|
705
|
-
<circle cx="9" cy="9" r="8.25" fill="white" stroke="#01ABE6" stroke-width="1.5"/>
|
|
706
|
-
<path d="M6.22876 12.0713L11.8854 6.41469" stroke="#01ABE6" stroke-width="1.5"/>
|
|
707
|
-
<path d="M6.22864 6.41382L11.8854 6.41395L11.8855 12.0707" stroke="#01ABE6" stroke-width="1.5"/>
|
|
708
|
-
</svg>
|
|
709
|
-
<a class="detailsLink" :href="item.program_link">Program</a>
|
|
710
|
-
</div>
|
|
711
|
-
<div v-if="item.media && item.media.includes('audio')" class="eventsSearch__perfDetails -detailsMobile">
|
|
712
|
-
<svg width="18" height="18" viewBox="0 0 18 18" fill="none" xmlns="http://www.w3.org/2000/svg">
|
|
713
|
-
<circle cx="9" cy="9" r="8.25" fill="white" stroke="#01ABE6" stroke-width="1.5"/>
|
|
714
|
-
<path d="M9.81086 5L6.92983 7.30483H4.625V10.7621H6.92983L9.81086 13.0669V5Z" fill="white" stroke="#01ABE6" stroke-width="1.5" stroke-linecap="round" stroke-linejoin="round"/>
|
|
715
|
-
<path d="M12.4268 6.99219C12.9669 7.53246 13.2703 8.26513 13.2703 9.02908C13.2703 9.79302 12.9669 10.5257 12.4268 11.066" fill="white"/>
|
|
716
|
-
<path d="M12.4268 6.99219C12.9669 7.53246 13.2703 8.26513 13.2703 9.02908C13.2703 9.79302 12.9669 10.5257 12.4268 11.066" stroke="#01ABE6" stroke-width="1.5" stroke-linecap="round" stroke-linejoin="round"/>
|
|
717
|
-
</svg>
|
|
718
|
-
<a class="detailsLink">Audio</a>
|
|
719
|
-
</div>
|
|
242
|
+
<event-links :item="item" extra-classes="-detailsMobile" />
|
|
720
243
|
</template>
|
|
721
244
|
</div>
|
|
722
245
|
</template>
|
|
@@ -725,11 +248,20 @@
|
|
|
725
248
|
<div :class="`eventsSearch__resultCell -empty ${index % 2 == 0 ? '-even' : '-odd'} ${(index + 1 == items.length && (i + 1 == item.works.length || i == 5)) ? '-last' : ''}`"></div>
|
|
726
249
|
<div :class="`eventsSearch__resultCell -empty ${index % 2 == 0 ? '-even' : '-odd'} ${(index + 1 == items.length && (i + 1 == item.works.length || i == 5)) ? '-last' : ''}`"></div>
|
|
727
250
|
<div :class="`eventsSearch__resultCell -empty ${index % 2 == 0 ? '-even' : '-odd'} ${(index + 1 == items.length && (i + 1 == item.works.length || i == 5)) ? '-last' : ''}`"></div>
|
|
251
|
+
<div :class="`eventsSearch__resultCell -work -right -emptyMobile ${index % 2 == 0 ? '-even' : '-odd'} ${(index + 1 == items.length && (i + 1 == item.works.length || i == 5)) ? '-last' : ''}`"></div>
|
|
728
252
|
<div :class="`eventsSearch__resultCell ${index % 2 == 0 ? '-even' : '-odd'} ${(index + 1 == items.length && (i + 1 == item.works.length || i == 5)) ? '-last' : ''}`">
|
|
729
253
|
<a :href="`/details?performanceId=${item.id}`">More...</a>
|
|
730
254
|
</div>
|
|
255
|
+
|
|
731
256
|
<div :class="`eventsSearch__resultCell -empty ${index % 2 == 0 ? '-even' : '-odd'} ${(index + 1 == items.length && (i + 1 == item.works.length || i == 5)) ? '-last' : ''}`"></div>
|
|
732
|
-
<div :class="`eventsSearch__resultCell -
|
|
257
|
+
<div :class="`eventsSearch__resultCell -detailsMobile
|
|
258
|
+
${index % 2 == 0 ? '-even' : '-odd'}
|
|
259
|
+
${(index + 1 == items.length && (i + 1 == item.works.length || i == 5)) ? '-last -lastMobile' : ''}
|
|
260
|
+
${ !(i + 1 == item.works.length || i == 5) ? '-empty' : ''}`">
|
|
261
|
+
<template v-if="(i + 1 == item.works.length || i == 5)">
|
|
262
|
+
<event-links :item="item" extra-classes="-detailsMobile" />
|
|
263
|
+
</template>
|
|
264
|
+
</div>
|
|
733
265
|
</template>
|
|
734
266
|
</template>
|
|
735
267
|
<template v-if="!item.works || item.works.length == 0">
|
|
@@ -754,31 +286,8 @@
|
|
|
754
286
|
<div :class="`eventsSearch__resultCell ${index % 2 == 0 ? '-even' : '-odd'} ${(index + 1 == items.length) ? '-last' : ''}`"><span class="mobileHeader">Composer/Work</span></div>
|
|
755
287
|
<div :class="`eventsSearch__resultCell -hideMobile ${index % 2 == 0 ? '-even' : '-odd'} ${(index + 1 == items.length) ? '-last' : ''}`"></div>
|
|
756
288
|
<div :class="`eventsSearch__resultCell -detailsMobile ${index % 2 == 0 ? '-even' : '-odd'} ${(index + 1 == items.length) ? '-last' : ''}`">
|
|
757
|
-
<
|
|
758
|
-
|
|
759
|
-
<circle cx="9" cy="9" r="9" fill="#01ABE6"/>
|
|
760
|
-
<path d="M5 9H13" stroke="white" stroke-width="1.5"/>
|
|
761
|
-
<path d="M9 5L13 9L9 13" stroke="white" stroke-width="1.5"/>
|
|
762
|
-
</svg>
|
|
763
|
-
<a class="detailsLink" :href="`/details?performanceId=${item.id}`">Details</a>
|
|
764
|
-
</div>
|
|
765
|
-
<div v-if="item.program_link" class="eventsSearch__perfDetails">
|
|
766
|
-
<svg width="18" height="18" viewBox="0 0 18 18" fill="none" xmlns="http://www.w3.org/2000/svg">
|
|
767
|
-
<circle cx="9" cy="9" r="8.25" fill="white" stroke="#01ABE6" stroke-width="1.5"/>
|
|
768
|
-
<path d="M6.22876 12.0713L11.8854 6.41469" stroke="#01ABE6" stroke-width="1.5"/>
|
|
769
|
-
<path d="M6.22864 6.41382L11.8854 6.41395L11.8855 12.0707" stroke="#01ABE6" stroke-width="1.5"/>
|
|
770
|
-
</svg>
|
|
771
|
-
<a class="detailsLink" :href="item.program_link">Program</a>
|
|
772
|
-
</div>
|
|
773
|
-
<div v-if="item.media && item.media.includes('audio')" class="eventsSearch__perfDetails">
|
|
774
|
-
<svg width="18" height="18" viewBox="0 0 18 18" fill="none" xmlns="http://www.w3.org/2000/svg">
|
|
775
|
-
<circle cx="9" cy="9" r="8.25" fill="white" stroke="#01ABE6" stroke-width="1.5"/>
|
|
776
|
-
<path d="M9.81086 5L6.92983 7.30483H4.625V10.7621H6.92983L9.81086 13.0669V5Z" fill="white" stroke="#01ABE6" stroke-width="1.5" stroke-linecap="round" stroke-linejoin="round"/>
|
|
777
|
-
<path d="M12.4268 6.99219C12.9669 7.53246 13.2703 8.26513 13.2703 9.02908C13.2703 9.79302 12.9669 10.5257 12.4268 11.066" fill="white"/>
|
|
778
|
-
<path d="M12.4268 6.99219C12.9669 7.53246 13.2703 8.26513 13.2703 9.02908C13.2703 9.79302 12.9669 10.5257 12.4268 11.066" stroke="#01ABE6" stroke-width="1.5" stroke-linecap="round" stroke-linejoin="round"/>
|
|
779
|
-
</svg>
|
|
780
|
-
<a class="detailsLink">Audio</a>
|
|
781
|
-
</div>
|
|
289
|
+
<event-links :item="item" />
|
|
290
|
+
|
|
782
291
|
</div>
|
|
783
292
|
</template>
|
|
784
293
|
</template>
|
|
@@ -824,7 +333,7 @@
|
|
|
824
333
|
{{ item.composer }} / {{ item.work_title }}
|
|
825
334
|
</a>
|
|
826
335
|
</div>
|
|
827
|
-
<div :class="`eventsSearch__resultCell ${index % 2 == 0 ? '-even' : '-odd'} ${(index + 1 == items.length) ? '-last' : ''}`">
|
|
336
|
+
<div :class="`eventsSearch__resultCell -perfs ${index % 2 == 0 ? '-even' : '-odd'} ${(index + 1 == items.length) ? '-last' : ''}`">
|
|
828
337
|
<span class="mobileHeader"># of Performances</span>
|
|
829
338
|
<a :href="createURL([{ facet: 'works.artists.name', value: item.artist_name},
|
|
830
339
|
{ facet: 'works.artists.role', value: item.artist_role },
|
|
@@ -881,7 +390,7 @@
|
|
|
881
390
|
</template>
|
|
882
391
|
</a>
|
|
883
392
|
</div>
|
|
884
|
-
<div :class="`eventsSearch__resultCell ${index % 2 == 0 ? '-even' : '-odd'} ${(index + 1 == items.length) ? '-last' : ''}`">
|
|
393
|
+
<div :class="`eventsSearch__resultCell -perfs ${index % 2 == 0 ? '-even' : '-odd'} ${(index + 1 == items.length) ? '-last' : ''}`">
|
|
885
394
|
<span class="mobileHeader"># of times Performed</span>
|
|
886
395
|
<a :href="createURL([{ facet: 'works.composers', value: item.composers},
|
|
887
396
|
{ facet: 'works.creators', value: item.creators},
|