I’ll build this as a safe, standalone advanced frontend chunk for RX Theme medical cards: filtering, search, tabs, accordion, reading progress, lazy reveal, copy/share, accessibility, and graceful fallback without breaking WordPress.
Friend, create this file:
rx-theme/assets/static-js/static-chunks-js/chunk-041-medical-card.js
Paste this full advanced code:
/*!
* RX Theme - Medical Card Advanced Chunk
* File: assets/static-js/static-chunks-js/chunk-041-medical-card.js
* Version: 1.0.0
*
* Features:
* - Medical card search
* - Category filter
* - Severity filter
* - Sorting
* - Favorite cards with localStorage
* - Compare select
* - Expand/collapse details
* - Accordion support
* - Tabs support
* - Copy card link
* - Native share support
* - Print card
* - Lazy reveal animation
* - Reading progress inside cards
* - Accessibility improvements
* - Safe no-dependency JavaScript
*/
(function () {
'use strict';
const RXMedicalCard = {
config: {
rootSelector: '[data-rx-medical-cards]',
cardSelector: '[data-rx-medical-card]',
searchSelector: '[data-rx-medical-search]',
categorySelector: '[data-rx-medical-category]',
severitySelector: '[data-rx-medical-severity]',
sortSelector: '[data-rx-medical-sort]',
resetSelector: '[data-rx-medical-reset]',
countSelector: '[data-rx-medical-count]',
emptySelector: '[data-rx-medical-empty]',
compareBarSelector: '[data-rx-compare-bar]',
compareCountSelector: '[data-rx-compare-count]',
storagePrefix: 'rx_theme_medical_card_',
maxCompare: 3,
revealClass: 'is-rx-visible',
hiddenClass: 'is-rx-hidden',
activeClass: 'is-rx-active',
favoriteClass: 'is-rx-favorite',
selectedClass: 'is-rx-selected',
animationDelay: 80
},
state: {
roots: [],
favorites: new Set(),
compareItems: new Set(),
reduceMotion: false
},
init() {
this.state.reduceMotion = window.matchMedia &&
window.matchMedia('(prefers-reduced-motion: reduce)').matches;
this.loadFavorites();
this.state.roots = Array.from(document.querySelectorAll(this.config.rootSelector));
if (!this.state.roots.length) return;
this.state.roots.forEach((root) => {
this.prepareRoot(root);
this.bindRootEvents(root);
this.prepareCards(root);
this.applyFilters(root);
});
this.bindGlobalEvents();
this.observeCards();
this.dispatch('rxMedicalCardsReady', {
roots: this.state.roots.length
});
},
prepareRoot(root) {
if (!root.id) {
root.id = 'rx-medical-cards-' + this.randomId();
}
root.setAttribute('data-rx-ready', 'true');
const search = root.querySelector(this.config.searchSelector);
if (search) {
search.setAttribute('autocomplete', 'off');
search.setAttribute('spellcheck', 'false');
search.setAttribute('aria-label', search.getAttribute('aria-label') || 'Search medical cards');
}
const empty = root.querySelector(this.config.emptySelector);
if (empty) {
empty.hidden = true;
empty.setAttribute('role', 'status');
empty.setAttribute('aria-live', 'polite');
}
const count = root.querySelector(this.config.countSelector);
if (count) {
count.setAttribute('role', 'status');
count.setAttribute('aria-live', 'polite');
}
},
prepareCards(root) {
const cards = this.getCards(root);
cards.forEach((card, index) => {
if (!card.id) {
card.id = 'rx-medical-card-' + this.randomId();
}
card.dataset.rxIndex = String(index);
card.setAttribute('tabindex', '0');
this.prepareFavoriteButton(card);
this.prepareCompareButton(card);
this.prepareToggleButton(card);
this.prepareShareButton(card);
this.prepareCopyButton(card);
this.preparePrintButton(card);
this.prepareReadingProgress(card);
this.prepareAccordions(card);
this.prepareTabs(card);
this.restoreFavoriteUI(card);
});
},
bindRootEvents(root) {
const search = root.querySelector(this.config.searchSelector);
const category = root.querySelector(this.config.categorySelector);
const severity = root.querySelector(this.config.severitySelector);
const sort = root.querySelector(this.config.sortSelector);
const reset = root.querySelector(this.config.resetSelector);
if (search) {
search.addEventListener('input', this.debounce(() => {
this.applyFilters(root);
}, 180));
}
if (category) {
category.addEventListener('change', () => this.applyFilters(root));
}
if (severity) {
severity.addEventListener('change', () => this.applyFilters(root));
}
if (sort) {
sort.addEventListener('change', () => this.applySort(root));
}
if (reset) {
reset.addEventListener('click', () => this.resetRoot(root));
}
root.addEventListener('click', (event) => {
const favoriteBtn = event.target.closest('[data-rx-card-favorite]');
const compareBtn = event.target.closest('[data-rx-card-compare]');
const toggleBtn = event.target.closest('[data-rx-card-toggle]');
const shareBtn = event.target.closest('[data-rx-card-share]');
const copyBtn = event.target.closest('[data-rx-card-copy]');
const printBtn = event.target.closest('[data-rx-card-print]');
const accordionBtn = event.target.closest('[data-rx-accordion-button]');
const tabBtn = event.target.closest('[data-rx-tab-button]');
if (favoriteBtn) {
event.preventDefault();
this.toggleFavorite(favoriteBtn.closest(this.config.cardSelector));
}
if (compareBtn) {
event.preventDefault();
this.toggleCompare(compareBtn.closest(this.config.cardSelector));
}
if (toggleBtn) {
event.preventDefault();
this.toggleCardDetails(toggleBtn.closest(this.config.cardSelector), toggleBtn);
}
if (shareBtn) {
event.preventDefault();
this.shareCard(shareBtn.closest(this.config.cardSelector));
}
if (copyBtn) {
event.preventDefault();
this.copyCardLink(copyBtn.closest(this.config.cardSelector), copyBtn);
}
if (printBtn) {
event.preventDefault();
this.printCard(printBtn.closest(this.config.cardSelector));
}
if (accordionBtn) {
event.preventDefault();
this.toggleAccordion(accordionBtn);
}
if (tabBtn) {
event.preventDefault();
this.activateTab(tabBtn);
}
});
root.addEventListener('keydown', (event) => {
if (event.key !== 'Enter' && event.key !== ' ') return;
const card = event.target.closest(this.config.cardSelector);
if (!card || event.target.closest('button, a, input, select, textarea')) return;
event.preventDefault();
const toggleBtn = card.querySelector('[data-rx-card-toggle]');
this.toggleCardDetails(card, toggleBtn);
});
},
bindGlobalEvents() {
document.addEventListener('scroll', this.throttle(() => {
this.updateReadingProgress();
}, 100), { passive: true });
window.addEventListener('resize', this.debounce(() => {
this.equalizeCardHeights();
}, 200));
document.addEventListener('visibilitychange', () => {
if (document.visibilityState === 'visible') {
this.loadFavorites();
this.state.roots.forEach((root) => {
this.getCards(root).forEach((card) => this.restoreFavoriteUI(card));
});
}
});
},
getCards(root) {
return Array.from(root.querySelectorAll(this.config.cardSelector));
},
applyFilters(root) {
const search = root.querySelector(this.config.searchSelector);
const category = root.querySelector(this.config.categorySelector);
const severity = root.querySelector(this.config.severitySelector);
const query = search ? search.value.trim().toLowerCase() : '';
const selectedCategory = category ? category.value.trim().toLowerCase() : '';
const selectedSeverity = severity ? severity.value.trim().toLowerCase() : '';
let visibleCount = 0;
this.getCards(root).forEach((card) => {
const title = this.getText(card, '[data-rx-card-title]');
const summary = this.getText(card, '[data-rx-card-summary]');
const keywords = (card.dataset.rxKeywords || '').toLowerCase();
const cardCategory = (card.dataset.rxCategory || '').toLowerCase();
const cardSeverity = (card.dataset.rxSeverity || '').toLowerCase();
const searchableText = `${title} ${summary} ${keywords} ${cardCategory} ${cardSeverity}`.toLowerCase();
const matchSearch = !query || searchableText.includes(query);
const matchCategory = !selectedCategory || selectedCategory === 'all' || cardCategory === selectedCategory;
const matchSeverity = !selectedSeverity || selectedSeverity === 'all' || cardSeverity === selectedSeverity;
const isVisible = matchSearch && matchCategory && matchSeverity;
card.hidden = !isVisible;
card.classList.toggle(this.config.hiddenClass, !isVisible);
if (isVisible) visibleCount++;
});
this.updateCount(root, visibleCount);
this.updateEmptyState(root, visibleCount);
this.applySort(root);
this.dispatch('rxMedicalCardsFiltered', {
rootId: root.id,
visibleCount
});
},
applySort(root) {
const sort = root.querySelector(this.config.sortSelector);
if (!sort) return;
const sortValue = sort.value || 'default';
const cards = this.getCards(root);
const parent = cards[0] ? cards[0].parentNode : null;
if (!parent) return;
const sortedCards = cards.slice().sort((a, b) => {
if (sortValue === 'title-asc') {
return this.getCardTitle(a).localeCompare(this.getCardTitle(b));
}
if (sortValue === 'title-desc') {
return this.getCardTitle(b).localeCompare(this.getCardTitle(a));
}
if (sortValue === 'severity-high') {
return this.getSeverityScore(b) - this.getSeverityScore(a);
}
if (sortValue === 'severity-low') {
return this.getSeverityScore(a) - this.getSeverityScore(b);
}
if (sortValue === 'newest') {
return this.getDateScore(b) - this.getDateScore(a);
}
if (sortValue === 'oldest') {
return this.getDateScore(a) - this.getDateScore(b);
}
return Number(a.dataset.rxIndex || 0) - Number(b.dataset.rxIndex || 0);
});
sortedCards.forEach((card) => parent.appendChild(card));
},
resetRoot(root) {
const search = root.querySelector(this.config.searchSelector);
const category = root.querySelector(this.config.categorySelector);
const severity = root.querySelector(this.config.severitySelector);
const sort = root.querySelector(this.config.sortSelector);
if (search) search.value = '';
if (category) category.value = 'all';
if (severity) severity.value = 'all';
if (sort) sort.value = 'default';
this.applyFilters(root);
},
updateCount(root, visibleCount) {
const count = root.querySelector(this.config.countSelector);
if (!count) return;
const total = this.getCards(root).length;
count.textContent = `${visibleCount} of ${total} medical cards shown`;
},
updateEmptyState(root, visibleCount) {
const empty = root.querySelector(this.config.emptySelector);
if (!empty) return;
empty.hidden = visibleCount !== 0;
},
prepareFavoriteButton(card) {
let btn = card.querySelector('[data-rx-card-favorite]');
if (!btn) return;
btn.setAttribute('type', 'button');
btn.setAttribute('aria-label', 'Save this medical card');
btn.setAttribute('aria-pressed', 'false');
},
prepareCompareButton(card) {
let btn = card.querySelector('[data-rx-card-compare]');
if (!btn) return;
btn.setAttribute('type', 'button');
btn.setAttribute('aria-label', 'Add this medical card to compare');
btn.setAttribute('aria-pressed', 'false');
},
prepareToggleButton(card) {
const btn = card.querySelector('[data-rx-card-toggle]');
const details = card.querySelector('[data-rx-card-details]');
if (!btn || !details) return;
if (!details.id) {
details.id = 'rx-card-details-' + this.randomId();
}
btn.setAttribute('type', 'button');
btn.setAttribute('aria-expanded', 'false');
btn.setAttribute('aria-controls', details.id);
details.hidden = true;
},
prepareShareButton(card) {
const btn = card.querySelector('[data-rx-card-share]');
if (!btn) return;
btn.setAttribute('type', 'button');
btn.setAttribute('aria-label', 'Share this medical card');
if (!navigator.share) {
btn.dataset.rxFallbackShare = 'true';
}
},
prepareCopyButton(card) {
const btn = card.querySelector('[data-rx-card-copy]');
if (!btn) return;
btn.setAttribute('type', 'button');
btn.setAttribute('aria-label', 'Copy this card link');
},
preparePrintButton(card) {
const btn = card.querySelector('[data-rx-card-print]');
if (!btn) return;
btn.setAttribute('type', 'button');
btn.setAttribute('aria-label', 'Print this medical card');
},
prepareReadingProgress(card) {
const progress = card.querySelector('[data-rx-card-progress]');
if (!progress) return;
progress.setAttribute('role', 'progressbar');
progress.setAttribute('aria-valuemin', '0');
progress.setAttribute('aria-valuemax', '100');
progress.setAttribute('aria-valuenow', '0');
const bar = progress.querySelector('[data-rx-card-progress-bar]');
if (bar) {
bar.style.width = '0%';
}
},
prepareAccordions(card) {
const buttons = Array.from(card.querySelectorAll('[data-rx-accordion-button]'));
buttons.forEach((button) => {
const panel = this.getAccordionPanel(button);
if (!panel) return;
if (!panel.id) {
panel.id = 'rx-accordion-panel-' + this.randomId();
}
button.setAttribute('type', 'button');
button.setAttribute('aria-expanded', 'false');
button.setAttribute('aria-controls', panel.id);
panel.hidden = true;
});
},
prepareTabs(card) {
const tabButtons = Array.from(card.querySelectorAll('[data-rx-tab-button]'));
if (!tabButtons.length) return;
tabButtons.forEach((button, index) => {
const panel = this.getTabPanel(button);
if (!panel) return;
if (!button.id) {
button.id = 'rx-tab-button-' + this.randomId();
}
if (!panel.id) {
panel.id = 'rx-tab-panel-' + this.randomId();
}
button.setAttribute('type', 'button');
button.setAttribute('role', 'tab');
button.setAttribute('aria-controls', panel.id);
button.setAttribute('aria-selected', index === 0 ? 'true' : 'false');
panel.setAttribute('role', 'tabpanel');
panel.setAttribute('aria-labelledby', button.id);
panel.hidden = index !== 0;
button.classList.toggle(this.config.activeClass, index === 0);
panel.classList.toggle(this.config.activeClass, index === 0);
});
},
toggleFavorite(card) {
if (!card) return;
const key = this.getCardKey(card);
if (this.state.favorites.has(key)) {
this.state.favorites.delete(key);
} else {
this.state.favorites.add(key);
}
this.saveFavorites();
this.restoreFavoriteUI(card);
this.dispatch('rxMedicalCardFavoriteChanged', {
cardId: card.id,
favorite: this.state.favorites.has(key)
});
},
restoreFavoriteUI(card) {
const btn = card.querySelector('[data-rx-card-favorite]');
if (!btn) return;
const key = this.getCardKey(card);
const isFavorite = this.state.favorites.has(key);
card.classList.toggle(this.config.favoriteClass, isFavorite);
btn.setAttribute('aria-pressed', String(isFavorite));
btn.dataset.rxFavoriteState = isFavorite ? 'saved' : 'unsaved';
const label = btn.querySelector('[data-rx-card-favorite-label]');
if (label) {
label.textContent = isFavorite ? 'Saved' : 'Save';
}
},
toggleCompare(card) {
if (!card) return;
const key = this.getCardKey(card);
const btn = card.querySelector('[data-rx-card-compare]');
if (this.state.compareItems.has(key)) {
this.state.compareItems.delete(key);
} else {
if (this.state.compareItems.size >= this.config.maxCompare) {
this.showNotice(card, `You can compare up to ${this.config.maxCompare} cards.`);
return;
}
this.state.compareItems.add(key);
}
const selected = this.state.compareItems.has(key);
card.classList.toggle(this.config.selectedClass, selected);
if (btn) {
btn.setAttribute('aria-pressed', String(selected));
}
this.updateCompareBar();
this.dispatch('rxMedicalCardCompareChanged', {
cardId: card.id,
selected
});
},
updateCompareBar() {
const bars = Array.from(document.querySelectorAll(this.config.compareBarSelector));
bars.forEach((bar) => {
const count = bar.querySelector(this.config.compareCountSelector);
const number = this.state.compareItems.size;
bar.hidden = number === 0;
if (count) {
count.textContent = String(number);
}
});
},
toggleCardDetails(card, btn) {
if (!card) return;
const details = card.querySelector('[data-rx-card-details]');
if (!details) return;
const isOpen = !details.hidden;
details.hidden = isOpen;
card.classList.toggle(this.config.activeClass, !isOpen);
if (btn) {
btn.setAttribute('aria-expanded', String(!isOpen));
const label = btn.querySelector('[data-rx-card-toggle-label]');
if (label) {
label.textContent = isOpen ? 'Read more' : 'Show less';
}
}
if (!isOpen) {
this.smoothFocus(details);
}
this.dispatch('rxMedicalCardToggle', {
cardId: card.id,
open: !isOpen
});
},
toggleAccordion(button) {
const panel = this.getAccordionPanel(button);
if (!panel) return;
const isOpen = !panel.hidden;
panel.hidden = isOpen;
button.setAttribute('aria-expanded', String(!isOpen));
button.classList.toggle(this.config.activeClass, !isOpen);
panel.classList.toggle(this.config.activeClass, !isOpen);
},
activateTab(button) {
const card = button.closest(this.config.cardSelector);
if (!card) return;
const group = button.closest('[data-rx-tabs]');
if (!group) return;
const buttons = Array.from(group.querySelectorAll('[data-rx-tab-button]'));
buttons.forEach((btn) => {
const panel = this.getTabPanel(btn);
const active = btn === button;
btn.setAttribute('aria-selected', String(active));
btn.classList.toggle(this.config.activeClass, active);
if (panel) {
panel.hidden = !active;
panel.classList.toggle(this.config.activeClass, active);
}
});
},
async shareCard(card) {
if (!card) return;
const title = this.getCardTitle(card);
const text = this.getText(card, '[data-rx-card-summary]');
const url = this.getCardUrl(card);
if (navigator.share) {
try {
await navigator.share({ title, text, url });
this.dispatch('rxMedicalCardShared', { cardId: card.id });
return;
} catch (error) {
if (error && error.name === 'AbortError') return;
}
}
this.copyText(url);
this.showNotice(card, 'Card link copied.');
},
copyCardLink(card, button) {
if (!card) return;
const url = this.getCardUrl(card);
this.copyText(url).then(() => {
this.showButtonFeedback(button, 'Copied');
this.showNotice(card, 'Card link copied.');
});
},
printCard(card) {
if (!card) return;
const printWindow = window.open('', '_blank', 'noopener,noreferrer,width=900,height=700');
if (!printWindow) {
window.print();
return;
}
const title = this.escapeHtml(this.getCardTitle(card));
const content = card.cloneNode(true);
content.querySelectorAll('button, [data-rx-card-actions]').forEach((element) => {
element.remove();
});
printWindow.document.write(`
<!doctype html>
<html>
<head>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1">
<title>${title}</title>
<style>
body {
font-family: Arial, sans-serif;
line-height: 1.6;
color: #111;
padding: 24px;
}
h1, h2, h3 {
line-height: 1.3;
}
.rx-print-note {
margin-top: 24px;
font-size: 13px;
color: #555;
border-top: 1px solid #ddd;
padding-top: 12px;
}
</style>
</head>
<body>
${content.outerHTML}
<div class="rx-print-note">
Medical information is for education only. Always follow a qualified clinician’s advice.
</div>
</body>
</html>
`);
printWindow.document.close();
printWindow.focus();
printWindow.print();
},
updateReadingProgress() {
const cards = Array.from(document.querySelectorAll(this.config.cardSelector));
cards.forEach((card) => {
const progress = card.querySelector('[data-rx-card-progress]');
const bar = card.querySelector('[data-rx-card-progress-bar]');
if (!progress || !bar) return;
const rect = card.getBoundingClientRect();
const viewportHeight = window.innerHeight || document.documentElement.clientHeight;
const total = rect.height + viewportHeight;
const passed = viewportHeight - rect.top;
const percent = Math.max(0, Math.min(100, Math.round((passed / total) * 100)));
bar.style.width = percent + '%';
progress.setAttribute('aria-valuenow', String(percent));
});
},
observeCards() {
const cards = Array.from(document.querySelectorAll(this.config.cardSelector));
if (this.state.reduceMotion) {
cards.forEach((card) => card.classList.add(this.config.revealClass));
return;
}
if (!('IntersectionObserver' in window)) {
cards.forEach((card) => card.classList.add(this.config.revealClass));
return;
}
const observer = new IntersectionObserver((entries) => {
entries.forEach((entry) => {
if (!entry.isIntersecting) return;
const card = entry.target;
const index = Number(card.dataset.rxIndex || 0);
window.setTimeout(() => {
card.classList.add(this.config.revealClass);
}, Math.min(index * this.config.animationDelay, 500));
observer.unobserve(card);
});
}, {
root: null,
threshold: 0.12
});
cards.forEach((card) => observer.observe(card));
},
equalizeCardHeights() {
this.state.roots.forEach((root) => {
const cards = this.getCards(root).filter((card) => !card.hidden);
const titles = cards.map((card) => card.querySelector('[data-rx-card-title]')).filter(Boolean);
titles.forEach((title) => {
title.style.minHeight = '';
});
if (window.innerWidth < 768) return;
let maxHeight = 0;
titles.forEach((title) => {
maxHeight = Math.max(maxHeight, title.offsetHeight);
});
titles.forEach((title) => {
title.style.minHeight = maxHeight + 'px';
});
});
},
getAccordionPanel(button) {
const id = button.getAttribute('aria-controls') || button.dataset.rxAccordionTarget;
if (id) {
return document.getElementById(id.replace('#', ''));
}
return button.nextElementSibling;
},
getTabPanel(button) {
const id = button.getAttribute('aria-controls') || button.dataset.rxTabTarget;
if (id) {
return document.getElementById(id.replace('#', ''));
}
const group = button.closest('[data-rx-tabs]');
if (!group) return null;
const index = Array.from(group.querySelectorAll('[data-rx-tab-button]')).indexOf(button);
return group.querySelectorAll('[data-rx-tab-panel]')[index] || null;
},
getText(parent, selector) {
const element = parent.querySelector(selector);
return element ? element.textContent.trim() : '';
},
getCardTitle(card) {
return this.getText(card, '[data-rx-card-title]') ||
card.getAttribute('aria-label') ||
'Medical Card';
},
getSeverityScore(card) {
const severity = (card.dataset.rxSeverity || '').toLowerCase();
const scores = {
critical: 5,
severe: 4,
moderate: 3,
mild: 2,
low: 1,
normal: 0
};
return scores[severity] || 0;
},
getDateScore(card) {
const rawDate = card.dataset.rxDate || card.getAttribute('datetime') || '';
const time = Date.parse(rawDate);
return Number.isNaN(time) ? 0 : time;
},
getCardKey(card) {
return card.dataset.rxCardId || card.id || this.getCardTitle(card).toLowerCase().replace(/\s+/g, '-');
},
getCardUrl(card) {
const base = window.location.href.split('#')[0];
return `${base}#${card.id}`;
},
loadFavorites() {
try {
const raw = localStorage.getItem(this.config.storagePrefix + 'favorites');
const list = raw ? JSON.parse(raw) : [];
this.state.favorites = new Set(Array.isArray(list) ? list : []);
} catch (error) {
this.state.favorites = new Set();
}
},
saveFavorites() {
try {
localStorage.setItem(
this.config.storagePrefix + 'favorites',
JSON.stringify(Array.from(this.state.favorites))
);
} catch (error) {
// localStorage may be blocked. UI will still work during current page load.
}
},
async copyText(text) {
if (navigator.clipboard && window.isSecureContext) {
return navigator.clipboard.writeText(text);
}
const textarea = document.createElement('textarea');
textarea.value = text;
textarea.setAttribute('readonly', '');
textarea.style.position = 'fixed';
textarea.style.left = '-9999px';
textarea.style.top = '-9999px';
document.body.appendChild(textarea);
textarea.select();
try {
document.execCommand('copy');
} finally {
textarea.remove();
}
},
showButtonFeedback(button, text) {
if (!button) return;
const oldText = button.textContent;
button.textContent = text;
window.setTimeout(() => {
button.textContent = oldText;
}, 1200);
},
showNotice(card, message) {
let notice = card.querySelector('[data-rx-card-notice]');
if (!notice) {
notice = document.createElement('div');
notice.setAttribute('data-rx-card-notice', '');
notice.setAttribute('role', 'status');
notice.setAttribute('aria-live', 'polite');
notice.className = 'rx-card-notice';
card.appendChild(notice);
}
notice.textContent = message;
notice.hidden = false;
window.clearTimeout(notice.rxNoticeTimer);
notice.rxNoticeTimer = window.setTimeout(() => {
notice.hidden = true;
}, 2400);
},
smoothFocus(element) {
if (!element) return;
if (!this.state.reduceMotion && typeof element.scrollIntoView === 'function') {
element.scrollIntoView({
behavior: 'smooth',
block: 'nearest'
});
}
element.setAttribute('tabindex', '-1');
element.focus({ preventScroll: true });
},
debounce(callback, wait) {
let timeout;
return function debounced(...args) {
window.clearTimeout(timeout);
timeout = window.setTimeout(() => callback.apply(this, args), wait);
};
},
throttle(callback, wait) {
let waiting = false;
return function throttled(...args) {
if (waiting) return;
waiting = true;
window.setTimeout(() => {
callback.apply(this, args);
waiting = false;
}, wait);
};
},
randomId() {
return Math.random().toString(36).slice(2, 10);
},
escapeHtml(value) {
return String(value)
.replace(/&/g, '&')
.replace(/</g, '<')
.replace(/>/g, '>')
.replace(/"/g, '"')
.replace(/'/g, ''');
},
dispatch(name, detail) {
document.dispatchEvent(new CustomEvent(name, {
bubbles: true,
detail
}));
}
};
window.RXMedicalCard = RXMedicalCard;
if (document.readyState === 'loading') {
document.addEventListener('DOMContentLoaded', () => RXMedicalCard.init());
} else {
RXMedicalCard.init();
}
})();
Use this kind of HTML structure so the JS can work:
<div data-rx-medical-cards>
<input data-rx-medical-search type="search" placeholder="Search disease, symptom, test..." />
<select data-rx-medical-category>
<option value="all">All Categories</option>
<option value="orthopedic">Orthopedic</option>
<option value="blood">Blood</option>
<option value="eye">Eye</option>
</select>
<select data-rx-medical-severity>
<option value="all">All Severity</option>
<option value="mild">Mild</option>
<option value="moderate">Moderate</option>
<option value="severe">Severe</option>
</select>
<select data-rx-medical-sort>
<option value="default">Default</option>
<option value="title-asc">Title A-Z</option>
<option value="title-desc">Title Z-A</option>
<option value="severity-high">Severity High</option>
<option value="severity-low">Severity Low</option>
<option value="newest">Newest</option>
<option value="oldest">Oldest</option>
</select>
<button data-rx-medical-reset type="button">Reset</button>
<p data-rx-medical-count></p>
<p data-rx-medical-empty>No medical card found.</p>
<article
data-rx-medical-card
data-rx-card-id="card-001"
data-rx-category="orthopedic"
data-rx-severity="moderate"
data-rx-date="2026-05-18"
data-rx-keywords="disc pain spine nerve"
>
<div data-rx-card-progress>
<span data-rx-card-progress-bar></span>
</div>
<h2 data-rx-card-title>Thoracic Disc Problem</h2>
<p data-rx-card-summary>Simple educational summary for patients.</p>
<div data-rx-card-actions>
<button data-rx-card-favorite>
<span data-rx-card-favorite-label>Save</span>
</button>
<button data-rx-card-compare>Compare</button>
<button data-rx-card-share>Share</button>
<button data-rx-card-copy>Copy Link</button>
<button data-rx-card-print>Print</button>
<button data-rx-card-toggle>
<span data-rx-card-toggle-label>Read more</span>
</button>
</div>
<div data-rx-card-details>
<p>This section contains more medical education details.</p>
<button data-rx-accordion-button>Symptoms</button>
<div>
<p>Symptoms explanation here.</p>
</div>
<div data-rx-tabs>
<button data-rx-tab-button>Overview</button>
<button data-rx-tab-button>Tests</button>
<div data-rx-tab-panel>
<p>Overview content.</p>
</div>
<div data-rx-tab-panel>
<p>Diagnostic test content.</p>
</div>
</div>
</div>
</article>
</div>
Then enqueue it in RX Theme:
wp_enqueue_script(
'rx-chunk-041-medical-card',
get_template_directory_uri() . '/assets/static-js/static-chunks-js/chunk-041-medical-card.js',
array(),
wp_get_theme()->get('Version'),
true
);
This file is safe as a frontend chunk because it uses no jQuery, no external library, no API call, and no blocking code.