774 lines
35 KiB
JavaScript
774 lines
35 KiB
JavaScript
(function () {
|
||
var favoriteCodes = [];
|
||
var codeLinks = {};
|
||
|
||
function getPageId(root) {
|
||
var value = root && root.getAttribute ? root.getAttribute('data-page-id') : '';
|
||
var pageId = parseInt(value || '0', 10);
|
||
|
||
if (!Number.isFinite(pageId) || pageId <= 0) {
|
||
var stateNode = root ? root.querySelector('.ansico-diagnosekoder__page-state') : null;
|
||
if (stateNode) {
|
||
try {
|
||
var state = JSON.parse(stateNode.textContent || '{}');
|
||
pageId = parseInt(state.pageId || '0', 10);
|
||
} catch (error) {}
|
||
}
|
||
}
|
||
|
||
if ((!Number.isFinite(pageId) || pageId <= 0) && typeof AnsicoDiagnosekoderConfig.resultsPageId !== 'undefined') {
|
||
pageId = parseInt(AnsicoDiagnosekoderConfig.resultsPageId || '0', 10);
|
||
}
|
||
|
||
if ((!Number.isFinite(pageId) || pageId <= 0) && document.body) {
|
||
var match = (document.body.className || '').match(/(?:^|\s)page-id-(\d+)(?:\s|$)/);
|
||
if (match) {
|
||
pageId = parseInt(match[1], 10);
|
||
}
|
||
}
|
||
|
||
return Number.isFinite(pageId) && pageId > 0 ? pageId : 0;
|
||
}
|
||
|
||
function preloadPageState(root) {
|
||
if (!root || !root.getAttribute) {
|
||
return;
|
||
}
|
||
|
||
var stateNode = root.querySelector('.ansico-diagnosekoder__page-state');
|
||
if (stateNode) {
|
||
try {
|
||
var state = JSON.parse(stateNode.textContent || '{}');
|
||
if (Array.isArray(state.favorites)) {
|
||
favoriteCodes = state.favorites.map(normalizeCode);
|
||
}
|
||
if (state.links && typeof state.links === 'object') {
|
||
codeLinks = {};
|
||
Object.keys(state.links).forEach(function (code) {
|
||
codeLinks[normalizeCode(code)] = state.links[code];
|
||
});
|
||
}
|
||
if (state.pageId && root.getAttribute('data-page-id') !== String(state.pageId)) {
|
||
root.setAttribute('data-page-id', String(state.pageId));
|
||
}
|
||
return;
|
||
} catch (error) {}
|
||
}
|
||
|
||
var favoritesRaw = root.getAttribute('data-page-favorites') || '[]';
|
||
var linksRaw = root.getAttribute('data-page-links') || '{}';
|
||
|
||
try {
|
||
var parsedFavorites = JSON.parse(favoritesRaw);
|
||
if (Array.isArray(parsedFavorites)) {
|
||
favoriteCodes = parsedFavorites.map(normalizeCode);
|
||
}
|
||
} catch (error) {}
|
||
|
||
try {
|
||
var parsedLinks = JSON.parse(linksRaw);
|
||
if (parsedLinks && typeof parsedLinks === 'object') {
|
||
codeLinks = {};
|
||
Object.keys(parsedLinks).forEach(function (code) {
|
||
codeLinks[normalizeCode(code)] = parsedLinks[code];
|
||
});
|
||
}
|
||
} catch (error) {}
|
||
}
|
||
|
||
function debounce(fn, delay) {
|
||
var timer;
|
||
return function () {
|
||
var context = this;
|
||
var args = arguments;
|
||
clearTimeout(timer);
|
||
timer = setTimeout(function () {
|
||
fn.apply(context, args);
|
||
}, delay);
|
||
};
|
||
}
|
||
|
||
function escapeHtml(str) {
|
||
return String(str)
|
||
.replace(/&/g, '&')
|
||
.replace(/</g, '<')
|
||
.replace(/>/g, '>')
|
||
.replace(/"/g, '"')
|
||
.replace(/'/g, ''');
|
||
}
|
||
|
||
function escapeRegExp(str) {
|
||
return String(str).replace(/[.*+?^${}()|[\]\\]/g, '\\$&');
|
||
}
|
||
|
||
function normalizeCode(code) {
|
||
return String(code || '').replace(/\s+/g, '').toUpperCase();
|
||
}
|
||
|
||
function highlightText(text, query) {
|
||
var safeText = escapeHtml(text);
|
||
var trimmedQuery = String(query || '').trim();
|
||
|
||
if (!trimmedQuery) {
|
||
return safeText;
|
||
}
|
||
|
||
var parts = trimmedQuery.split(/\s+/).filter(Boolean);
|
||
if (!parts.length) {
|
||
return safeText;
|
||
}
|
||
|
||
var pattern = parts.map(escapeRegExp).join('|');
|
||
return safeText.replace(new RegExp('(' + pattern + ')', 'gi'), '<mark class="ansico-diagnosekoder__highlight">$1</mark>');
|
||
}
|
||
|
||
function getCopyIcon() {
|
||
return '<svg viewBox="0 0 24 24" aria-hidden="true" focusable="false"><path d="M16 1H6c-1.1 0-2 .9-2 2v12h2V3h10V1zm3 4H10c-1.1 0-2 .9-2 2v14c0 1.1.9 2 2 2h9c1.1 0 2-.9 2-2V7c0-1.1-.9-2-2-2zm0 16H10V7h9v14z"></path></svg>';
|
||
}
|
||
|
||
function getStarIcon(isActive) {
|
||
if (isActive) {
|
||
return '<svg viewBox="0 0 24 24" aria-hidden="true" focusable="false"><path d="M12 17.27 18.18 21l-1.64-7.03L22 9.24l-7.19-.61L12 2 9.19 8.63 2 9.24l5.46 4.73L5.82 21z" fill="currentColor"></path></svg>';
|
||
}
|
||
|
||
return '<svg viewBox="0 0 24 24" aria-hidden="true" focusable="false" fill="none"><path d="M12 17.27 18.18 21l-1.64-7.03L22 9.24l-7.19-.61L12 2 9.19 8.63 2 9.24l5.46 4.73L5.82 21z" fill="none" stroke="currentColor" stroke-width="1.8" stroke-linecap="round" stroke-linejoin="round"></path></svg>';
|
||
}
|
||
|
||
function getPlusIcon() {
|
||
return '<svg viewBox="0 0 24 24" aria-hidden="true" focusable="false"><path d="M19 11H13V5h-2v6H5v2h6v6h2v-6h6z"></path></svg>';
|
||
}
|
||
|
||
function getMinusIcon() {
|
||
return '<svg viewBox="0 0 24 24" aria-hidden="true" focusable="false"><path d="M19 11H5v2h14z"></path></svg>';
|
||
}
|
||
|
||
function isFavorite(code) {
|
||
return favoriteCodes.indexOf(normalizeCode(code)) !== -1;
|
||
}
|
||
|
||
function getLinkedUrl(code, fallback) {
|
||
var normalized = normalizeCode(code);
|
||
if (normalized && typeof codeLinks[normalized] === 'string' && codeLinks[normalized]) {
|
||
return codeLinks[normalized];
|
||
}
|
||
return fallback || '';
|
||
}
|
||
|
||
function setTemporaryLabel(button, label, duration) {
|
||
var originalLabel = button.getAttribute('data-label-default') || button.getAttribute('aria-label') || '';
|
||
button.setAttribute('aria-label', label);
|
||
button.classList.add('is-feedback-visible');
|
||
window.setTimeout(function () {
|
||
button.setAttribute('aria-label', originalLabel);
|
||
button.classList.remove('is-feedback-visible');
|
||
}, duration || 1400);
|
||
}
|
||
|
||
function pulseButton(button) {
|
||
button.classList.remove('is-pressed');
|
||
void button.offsetWidth;
|
||
button.classList.add('is-pressed');
|
||
window.setTimeout(function () {
|
||
button.classList.remove('is-pressed');
|
||
}, 220);
|
||
}
|
||
|
||
function copyText(value, button) {
|
||
var successLabel = button.getAttribute('data-label-success') || button.getAttribute('aria-label') || '';
|
||
var errorLabel = button.getAttribute('data-label-error') || button.getAttribute('aria-label') || '';
|
||
pulseButton(button);
|
||
|
||
if (navigator.clipboard && navigator.clipboard.writeText) {
|
||
navigator.clipboard.writeText(value).then(function () {
|
||
setTemporaryLabel(button, successLabel, 1400);
|
||
}).catch(function () {
|
||
setTemporaryLabel(button, errorLabel, 1400);
|
||
});
|
||
return;
|
||
}
|
||
|
||
try {
|
||
var temp = document.createElement('textarea');
|
||
temp.value = value;
|
||
temp.setAttribute('readonly', 'readonly');
|
||
temp.style.position = 'absolute';
|
||
temp.style.left = '-9999px';
|
||
document.body.appendChild(temp);
|
||
temp.select();
|
||
document.execCommand('copy');
|
||
document.body.removeChild(temp);
|
||
setTemporaryLabel(button, successLabel, 1400);
|
||
} catch (error) {
|
||
setTemporaryLabel(button, errorLabel, 1400);
|
||
}
|
||
}
|
||
|
||
|
||
|
||
|
||
|
||
function searchInternalContent(query) {
|
||
if (!AnsicoDiagnosekoderConfig.contentSearchUrl) {
|
||
return Promise.resolve([]);
|
||
}
|
||
|
||
var url = AnsicoDiagnosekoderConfig.contentSearchUrl + '?q=' + encodeURIComponent(query) + '&limit=8';
|
||
return fetch(url, {
|
||
credentials: 'same-origin',
|
||
headers: {
|
||
'X-WP-Nonce': AnsicoDiagnosekoderConfig.nonce
|
||
},
|
||
cache: 'no-store'
|
||
}).then(function (response) {
|
||
if (!response.ok) {
|
||
throw new Error('Internal content search failed');
|
||
}
|
||
return response.json();
|
||
}).then(function (data) {
|
||
return Array.isArray(data.results) ? data.results : [];
|
||
});
|
||
}
|
||
|
||
function ensureLinkModal() {
|
||
var existing = document.getElementById('ansico-diagnosekoder-link-modal');
|
||
if (existing) {
|
||
return existing;
|
||
}
|
||
|
||
var wrapper = document.createElement('div');
|
||
wrapper.id = 'ansico-diagnosekoder-link-modal';
|
||
wrapper.className = 'ansico-diagnosekoder__modal';
|
||
wrapper.setAttribute('hidden', 'hidden');
|
||
wrapper.innerHTML = '' +
|
||
'<div class="ansico-diagnosekoder__modal-backdrop" data-modal-close="1"></div>' +
|
||
'<div class="ansico-diagnosekoder__modal-dialog" role="dialog" aria-modal="true" aria-labelledby="ansico-diagnosekoder-link-modal-title">' +
|
||
'<div class="ansico-diagnosekoder__modal-header">' +
|
||
'<h3 id="ansico-diagnosekoder-link-modal-title" class="ansico-diagnosekoder__modal-title"></h3>' +
|
||
'<button type="button" class="ansico-diagnosekoder__modal-close" data-modal-close="1" aria-label="Luk">×</button>' +
|
||
'</div>' +
|
||
'<div class="ansico-diagnosekoder__modal-body">' +
|
||
'<div class="ansico-diagnosekoder__modal-field">' +
|
||
'<label class="ansico-diagnosekoder__modal-label" for="ansico-diagnosekoder-link-modal-code"></label>' +
|
||
'<input id="ansico-diagnosekoder-link-modal-code" class="ansico-diagnosekoder__modal-input" type="text" readonly />' +
|
||
'</div>' +
|
||
'<p class="ansico-diagnosekoder__modal-hint"></p>' +
|
||
'<div class="ansico-diagnosekoder__modal-field">' +
|
||
'<label class="ansico-diagnosekoder__modal-label" for="ansico-diagnosekoder-link-modal-url"></label>' +
|
||
'<input id="ansico-diagnosekoder-link-modal-url" class="ansico-diagnosekoder__modal-input" type="url" />' +
|
||
'</div>' +
|
||
'<div class="ansico-diagnosekoder__modal-field">' +
|
||
'<label class="ansico-diagnosekoder__modal-label" for="ansico-diagnosekoder-link-modal-search"></label>' +
|
||
'<input id="ansico-diagnosekoder-link-modal-search" class="ansico-diagnosekoder__modal-input" type="search" />' +
|
||
'</div>' +
|
||
'<div class="ansico-diagnosekoder__modal-search-results"></div>' +
|
||
'</div>' +
|
||
'<div class="ansico-diagnosekoder__modal-footer">' +
|
||
'<button type="button" class="ansico-diagnosekoder__modal-button ansico-diagnosekoder__modal-button--secondary" data-modal-cancel="1"></button>' +
|
||
'<button type="button" class="ansico-diagnosekoder__modal-button ansico-diagnosekoder__modal-button--primary" data-modal-save="1"></button>' +
|
||
'</div>' +
|
||
'</div>';
|
||
document.body.appendChild(wrapper);
|
||
return wrapper;
|
||
}
|
||
|
||
function openLinkModal(code, currentUrl) {
|
||
var modal = ensureLinkModal();
|
||
var titleNode = modal.querySelector('.ansico-diagnosekoder__modal-title');
|
||
var labels = modal.querySelectorAll('.ansico-diagnosekoder__modal-label');
|
||
var hintNode = modal.querySelector('.ansico-diagnosekoder__modal-hint');
|
||
var codeInput = modal.querySelector('#ansico-diagnosekoder-link-modal-code');
|
||
var urlInput = modal.querySelector('#ansico-diagnosekoder-link-modal-url');
|
||
var searchInput = modal.querySelector('#ansico-diagnosekoder-link-modal-search');
|
||
var resultsNode = modal.querySelector('.ansico-diagnosekoder__modal-search-results');
|
||
var cancelButton = modal.querySelector('[data-modal-cancel="1"]');
|
||
var saveButton = modal.querySelector('[data-modal-save="1"]');
|
||
var closeButtons = modal.querySelectorAll('[data-modal-close="1"]');
|
||
var activeSearchToken = 0;
|
||
|
||
titleNode.textContent = currentUrl ? AnsicoDiagnosekoderConfig.strings.linkModalTitleEdit : AnsicoDiagnosekoderConfig.strings.linkModalTitleAdd;
|
||
labels[0].textContent = AnsicoDiagnosekoderConfig.strings.linkModalCodeLabel;
|
||
labels[1].textContent = AnsicoDiagnosekoderConfig.strings.linkModalUrlLabel;
|
||
labels[2].textContent = AnsicoDiagnosekoderConfig.strings.linkModalSearchLabel;
|
||
hintNode.textContent = AnsicoDiagnosekoderConfig.strings.linkModalHint;
|
||
cancelButton.textContent = AnsicoDiagnosekoderConfig.strings.linkModalCancel;
|
||
saveButton.textContent = AnsicoDiagnosekoderConfig.strings.linkModalSave;
|
||
codeInput.value = code || '';
|
||
urlInput.value = currentUrl || '';
|
||
urlInput.placeholder = AnsicoDiagnosekoderConfig.strings.linkPromptDefault || 'https://';
|
||
searchInput.value = '';
|
||
searchInput.placeholder = AnsicoDiagnosekoderConfig.strings.linkModalSearchPlaceholder;
|
||
resultsNode.innerHTML = '<p class="ansico-diagnosekoder__modal-message">' + escapeHtml(AnsicoDiagnosekoderConfig.strings.linkModalSearchEmpty) + '</p>';
|
||
modal.removeAttribute('hidden');
|
||
document.body.classList.add('ansico-diagnosekoder-modal-open');
|
||
|
||
function closeModal() {
|
||
modal.setAttribute('hidden', 'hidden');
|
||
document.body.classList.remove('ansico-diagnosekoder-modal-open');
|
||
saveButton.onclick = null;
|
||
cancelButton.onclick = null;
|
||
closeButtons.forEach(function (button) { button.onclick = null; });
|
||
searchInput.oninput = null;
|
||
document.removeEventListener('keydown', onKeyDown);
|
||
}
|
||
|
||
function onKeyDown(event) {
|
||
if (event.key === 'Escape') {
|
||
closeModal();
|
||
}
|
||
}
|
||
|
||
function renderSearchResults(items) {
|
||
if (!items.length) {
|
||
resultsNode.innerHTML = '<p class="ansico-diagnosekoder__modal-message">' + escapeHtml(AnsicoDiagnosekoderConfig.strings.linkModalSearchNone) + '</p>';
|
||
return;
|
||
}
|
||
|
||
var html = '<ul class="ansico-diagnosekoder__modal-result-list">';
|
||
items.forEach(function (item) {
|
||
html += '<li class="ansico-diagnosekoder__modal-result-item">';
|
||
html += '<button type="button" class="ansico-diagnosekoder__modal-result-button" data-url="' + escapeHtml(item.url || '') + '">';
|
||
html += '<span class="ansico-diagnosekoder__modal-result-title">' + escapeHtml(item.title || item.url || '') + '</span>';
|
||
html += '<span class="ansico-diagnosekoder__modal-result-meta">' + escapeHtml(item.url || '') + '</span>';
|
||
html += '</button></li>';
|
||
});
|
||
html += '</ul>';
|
||
resultsNode.innerHTML = html;
|
||
resultsNode.querySelectorAll('.ansico-diagnosekoder__modal-result-button').forEach(function (button) {
|
||
button.addEventListener('click', function () {
|
||
urlInput.value = button.getAttribute('data-url') || '';
|
||
});
|
||
});
|
||
}
|
||
|
||
searchInput.oninput = debounce(function () {
|
||
var query = searchInput.value.trim();
|
||
activeSearchToken += 1;
|
||
var token = activeSearchToken;
|
||
|
||
if (!query) {
|
||
resultsNode.innerHTML = '<p class="ansico-diagnosekoder__modal-message">' + escapeHtml(AnsicoDiagnosekoderConfig.strings.linkModalSearchEmpty) + '</p>';
|
||
return;
|
||
}
|
||
|
||
resultsNode.innerHTML = '<p class="ansico-diagnosekoder__modal-message">' + escapeHtml(AnsicoDiagnosekoderConfig.strings.loading) + '</p>';
|
||
searchInternalContent(query).then(function (items) {
|
||
if (token !== activeSearchToken) {
|
||
return;
|
||
}
|
||
renderSearchResults(items);
|
||
}).catch(function () {
|
||
resultsNode.innerHTML = '<p class="ansico-diagnosekoder__modal-message">' + escapeHtml(AnsicoDiagnosekoderConfig.strings.linkSearchError) + '</p>';
|
||
});
|
||
}, 180);
|
||
|
||
var resolver;
|
||
var promise = new Promise(function (resolve) {
|
||
resolver = resolve;
|
||
});
|
||
|
||
saveButton.onclick = function () {
|
||
resolver(String(urlInput.value || '').trim());
|
||
closeModal();
|
||
};
|
||
cancelButton.onclick = function () {
|
||
resolver(null);
|
||
closeModal();
|
||
};
|
||
closeButtons.forEach(function (button) {
|
||
button.onclick = function () {
|
||
resolver(null);
|
||
closeModal();
|
||
};
|
||
});
|
||
|
||
document.addEventListener('keydown', onKeyDown);
|
||
window.setTimeout(function () { urlInput.focus(); urlInput.select(); }, 0);
|
||
return promise;
|
||
}
|
||
|
||
function fetchPageState(pageId) {
|
||
if (!pageId || !AnsicoDiagnosekoderConfig.pageStateUrl) {
|
||
return Promise.resolve({ favorites: favoriteCodes, links: codeLinks, page_id: pageId || 0 });
|
||
}
|
||
|
||
var url = AnsicoDiagnosekoderConfig.pageStateUrl + '?page_id=' + encodeURIComponent(pageId) + '&_ansico_ts=' + Date.now();
|
||
return fetch(url, {
|
||
credentials: 'same-origin',
|
||
cache: 'no-store'
|
||
}).then(function (response) {
|
||
if (!response.ok) {
|
||
throw new Error('Page state failed');
|
||
}
|
||
return response.json();
|
||
}).then(function (data) {
|
||
syncClientCollections(data || {});
|
||
return data || {};
|
||
}).catch(function () {
|
||
return { favorites: favoriteCodes, links: codeLinks, page_id: pageId || 0 };
|
||
});
|
||
}
|
||
|
||
function mergeAndSortResults(results) {
|
||
var merged = (Array.isArray(results) ? results : []).map(function (item, index) {
|
||
var normalizedCode = normalizeCode(item.code);
|
||
var favorite = isFavorite(normalizedCode) || !!item.is_favorite;
|
||
var linkedUrl = getLinkedUrl(normalizedCode, item.linked_url || '');
|
||
return Object.assign({}, item, {
|
||
is_favorite: favorite,
|
||
linked_url: linkedUrl,
|
||
_normalized_code: normalizedCode,
|
||
_render_index: index
|
||
});
|
||
});
|
||
|
||
merged.sort(function (a, b) {
|
||
if (!!a.is_favorite !== !!b.is_favorite) {
|
||
return a.is_favorite ? -1 : 1;
|
||
}
|
||
return a._render_index - b._render_index;
|
||
});
|
||
|
||
return merged;
|
||
}
|
||
|
||
function renderResults(container, results, query) {
|
||
if (!results.length) {
|
||
container.innerHTML = '<p class="ansico-diagnosekoder__message">' + escapeHtml(AnsicoDiagnosekoderConfig.strings.noResults) + '</p>';
|
||
return;
|
||
}
|
||
|
||
var sortedResults = mergeAndSortResults(results);
|
||
var html = '<ul class="ansico-diagnosekoder__list">';
|
||
sortedResults.forEach(function (item) {
|
||
var normalizedCode = item._normalized_code || normalizeCode(item.code);
|
||
var favorite = !!item.is_favorite;
|
||
var linkedUrl = item.linked_url || '';
|
||
var hasLink = !!linkedUrl;
|
||
var copyValue = item.code + ' - ' + item.text;
|
||
var copyAria = AnsicoDiagnosekoderConfig.strings.copyCodeAria.replace('%s', copyValue);
|
||
var favoriteAria = favorite ? AnsicoDiagnosekoderConfig.strings.removeFavorite : AnsicoDiagnosekoderConfig.strings.addFavorite;
|
||
var linkAria = hasLink ? AnsicoDiagnosekoderConfig.strings.removeLink : AnsicoDiagnosekoderConfig.strings.addLink;
|
||
var entryTagStart = hasLink ? '<a class="ansico-diagnosekoder__entry-link" href="' + escapeHtml(linkedUrl) + '">' : '';
|
||
var entryTagEnd = hasLink ? '</a>' : '';
|
||
|
||
html += '<li class="ansico-diagnosekoder__item' + (favorite ? ' is-favorite' : '') + (hasLink ? ' has-link' : '') + '" data-code="' + escapeHtml(normalizedCode) + '" data-is-favorite="' + (favorite ? '1' : '0') + '" data-has-link="' + (hasLink ? '1' : '0') + '">';
|
||
html += '<div class="ansico-diagnosekoder__row">';
|
||
html += entryTagStart + '<div class="ansico-diagnosekoder__entry">';
|
||
html += '<span class="ansico-diagnosekoder__code">' + highlightText(item.code, query) + '</span>';
|
||
html += '<span class="ansico-diagnosekoder__separator"> – </span>';
|
||
html += '<span class="ansico-diagnosekoder__text">' + highlightText(item.text, query) + '</span>';
|
||
if (hasLink) {
|
||
html += '<span class="ansico-diagnosekoder__linked-badge">' + escapeHtml(AnsicoDiagnosekoderConfig.strings.openLink) + '</span>';
|
||
}
|
||
html += '</div>' + entryTagEnd;
|
||
html += '<div class="ansico-diagnosekoder__actions">';
|
||
html += '<button type="button" class="ansico-diagnosekoder__icon-button ansico-diagnosekoder__copy-button" data-copy-value="' + escapeHtml(copyValue) + '"';
|
||
html += ' data-label-default="' + escapeHtml(copyAria) + '"';
|
||
html += ' data-label-success="' + escapeHtml(AnsicoDiagnosekoderConfig.strings.copied) + '"';
|
||
html += ' data-label-error="' + escapeHtml(AnsicoDiagnosekoderConfig.strings.copyError) + '"';
|
||
html += ' aria-label="' + escapeHtml(copyAria) + '" title="' + escapeHtml(AnsicoDiagnosekoderConfig.strings.copyIcon) + '">';
|
||
html += getCopyIcon() + '</button>';
|
||
|
||
if (AnsicoDiagnosekoderConfig.isLoggedIn) {
|
||
html += '<button type="button" class="ansico-diagnosekoder__icon-button ansico-diagnosekoder__favorite-button' + (favorite ? ' is-active' : '') + '" data-code="' + escapeHtml(normalizedCode) + '" aria-pressed="' + (favorite ? 'true' : 'false') + '" data-label-default="' + escapeHtml(favoriteAria) + '" aria-label="' + escapeHtml(favoriteAria) + '" title="' + escapeHtml(AnsicoDiagnosekoderConfig.strings.favoriteIcon) + '">';
|
||
html += getStarIcon(favorite) + '</button>';
|
||
html += '<button type="button" class="ansico-diagnosekoder__icon-button ansico-diagnosekoder__link-button' + (hasLink ? ' is-active' : '') + '" data-code="' + escapeHtml(normalizedCode) + '" data-current-url="' + escapeHtml(linkedUrl) + '" data-label-default="' + escapeHtml(linkAria) + '" aria-label="' + escapeHtml(linkAria) + '" title="' + escapeHtml(hasLink ? AnsicoDiagnosekoderConfig.strings.removeLinkIcon : AnsicoDiagnosekoderConfig.strings.addLinkIcon) + '">';
|
||
html += hasLink ? getMinusIcon() : getPlusIcon();
|
||
html += '</button>';
|
||
}
|
||
|
||
html += '</div></div></li>';
|
||
});
|
||
html += '</ul>';
|
||
container.innerHTML = html;
|
||
}
|
||
|
||
function getQueryParam(name) {
|
||
var params = new URLSearchParams(window.location.search);
|
||
return params.get(name) || '';
|
||
}
|
||
|
||
function getSelectorEscaped(value) {
|
||
if (window.CSS && typeof window.CSS.escape === 'function') {
|
||
return window.CSS.escape(value);
|
||
}
|
||
return String(value).replace(/"/g, '\\"');
|
||
}
|
||
|
||
function updateFavoriteButtons(code, isFav, pageId) {
|
||
var normalizedCode = normalizeCode(code);
|
||
var selector = '.ansico-diagnosekoder__favorite-button[data-code="' + getSelectorEscaped(normalizedCode) + '"]';
|
||
if (pageId) {
|
||
selector = '.ansico-diagnosekoder[data-page-id="' + getSelectorEscaped(String(pageId)) + '"] ' + selector;
|
||
}
|
||
var buttons = document.querySelectorAll(selector);
|
||
buttons.forEach(function (button) {
|
||
var label = isFav ? AnsicoDiagnosekoderConfig.strings.removeFavorite : AnsicoDiagnosekoderConfig.strings.addFavorite;
|
||
button.classList.toggle('is-active', isFav);
|
||
button.setAttribute('aria-pressed', isFav ? 'true' : 'false');
|
||
button.setAttribute('aria-label', label);
|
||
button.setAttribute('data-label-default', label);
|
||
button.innerHTML = getStarIcon(isFav);
|
||
var item = button.closest('.ansico-diagnosekoder__item');
|
||
if (item) {
|
||
item.classList.toggle('is-favorite', isFav);
|
||
item.setAttribute('data-is-favorite', isFav ? '1' : '0');
|
||
}
|
||
});
|
||
}
|
||
|
||
function updateLinkButtons(code, url) {
|
||
var normalizedCode = normalizeCode(code);
|
||
var buttons = document.querySelectorAll('.ansico-diagnosekoder__link-button[data-code="' + getSelectorEscaped(normalizedCode) + '"]');
|
||
var hasLink = !!url;
|
||
buttons.forEach(function (button) {
|
||
var label = hasLink ? AnsicoDiagnosekoderConfig.strings.removeLink : AnsicoDiagnosekoderConfig.strings.addLink;
|
||
button.classList.toggle('is-active', hasLink);
|
||
button.setAttribute('aria-label', label);
|
||
button.setAttribute('data-label-default', label);
|
||
button.setAttribute('data-current-url', url || '');
|
||
button.setAttribute('title', hasLink ? AnsicoDiagnosekoderConfig.strings.removeLinkIcon : AnsicoDiagnosekoderConfig.strings.addLinkIcon);
|
||
button.innerHTML = hasLink ? getMinusIcon() : getPlusIcon();
|
||
var item = button.closest('.ansico-diagnosekoder__item');
|
||
if (item) {
|
||
item.classList.toggle('has-link', hasLink);
|
||
item.setAttribute('data-has-link', hasLink ? '1' : '0');
|
||
}
|
||
});
|
||
}
|
||
|
||
function syncClientCollections(data) {
|
||
if (Array.isArray(data.favorites)) {
|
||
favoriteCodes = data.favorites.map(normalizeCode);
|
||
}
|
||
if (data.links && typeof data.links === 'object') {
|
||
codeLinks = {};
|
||
Object.keys(data.links).forEach(function (code) {
|
||
codeLinks[normalizeCode(code)] = data.links[code];
|
||
});
|
||
}
|
||
}
|
||
|
||
function toggleFavorite(code, button, refreshCallback, pageId) {
|
||
fetch(AnsicoDiagnosekoderConfig.favoritesUrl, {
|
||
method: 'POST',
|
||
credentials: 'same-origin',
|
||
headers: {
|
||
'Content-Type': 'application/json',
|
||
'X-WP-Nonce': AnsicoDiagnosekoderConfig.nonce
|
||
},
|
||
body: JSON.stringify({ code: normalizeCode(code), page_id: pageId || 0 })
|
||
}).then(function (response) {
|
||
if (!response.ok) {
|
||
throw new Error('Favorite toggle failed');
|
||
}
|
||
return response.json();
|
||
}).then(function (data) {
|
||
syncClientCollections(data);
|
||
pulseButton(button);
|
||
updateFavoriteButtons(code, !!data.is_favorite, pageId || 0);
|
||
if (typeof refreshCallback === 'function') {
|
||
refreshCallback();
|
||
}
|
||
}).catch(function () {
|
||
setTemporaryLabel(button, AnsicoDiagnosekoderConfig.strings.favoriteError, 1400);
|
||
});
|
||
}
|
||
|
||
function saveCodeLink(code, url, button, refreshCallback, pageId) {
|
||
fetch(AnsicoDiagnosekoderConfig.linksUrl, {
|
||
method: 'POST',
|
||
credentials: 'same-origin',
|
||
headers: {
|
||
'Content-Type': 'application/json',
|
||
'X-WP-Nonce': AnsicoDiagnosekoderConfig.nonce
|
||
},
|
||
body: JSON.stringify({ code: normalizeCode(code), url: url, page_id: pageId || 0 })
|
||
}).then(function (response) {
|
||
if (!response.ok) {
|
||
throw new Error('Link save failed');
|
||
}
|
||
return response.json();
|
||
}).then(function (data) {
|
||
syncClientCollections(data);
|
||
pulseButton(button);
|
||
updateLinkButtons(code, data.url || '');
|
||
setTemporaryLabel(button, AnsicoDiagnosekoderConfig.strings.linkSaved, 1200);
|
||
if (typeof refreshCallback === 'function') {
|
||
refreshCallback();
|
||
}
|
||
}).catch(function () {
|
||
setTemporaryLabel(button, AnsicoDiagnosekoderConfig.strings.linkError, 1400);
|
||
});
|
||
}
|
||
|
||
function removeCodeLink(code, button, refreshCallback, pageId) {
|
||
var url = AnsicoDiagnosekoderConfig.linksUrl + '?code=' + encodeURIComponent(normalizeCode(code)) + '&page_id=' + encodeURIComponent(pageId || 0);
|
||
fetch(url, {
|
||
method: 'DELETE',
|
||
credentials: 'same-origin',
|
||
headers: {
|
||
'X-WP-Nonce': AnsicoDiagnosekoderConfig.nonce
|
||
}
|
||
}).then(function (response) {
|
||
if (!response.ok) {
|
||
throw new Error('Link removal failed');
|
||
}
|
||
return response.json();
|
||
}).then(function (data) {
|
||
syncClientCollections(data);
|
||
pulseButton(button);
|
||
updateLinkButtons(code, '');
|
||
setTemporaryLabel(button, AnsicoDiagnosekoderConfig.strings.linkRemoved, 1200);
|
||
if (typeof refreshCallback === 'function') {
|
||
refreshCallback();
|
||
}
|
||
}).catch(function () {
|
||
setTemporaryLabel(button, AnsicoDiagnosekoderConfig.strings.linkError, 1400);
|
||
});
|
||
}
|
||
|
||
|
||
function initResultsBlock(root) {
|
||
preloadPageState(root);
|
||
var input = root.querySelector('.ansico-diagnosekoder__input');
|
||
var results = root.querySelector('.ansico-diagnosekoder__results');
|
||
var hasData = root.getAttribute('data-has-data') === '1';
|
||
|
||
if (!input || !results || !hasData) {
|
||
return;
|
||
}
|
||
|
||
var runSearch = function () {
|
||
var query = input.value.trim();
|
||
|
||
if (!query) {
|
||
results.innerHTML = '<p class="ansico-diagnosekoder__message">' + escapeHtml(AnsicoDiagnosekoderConfig.strings.empty) + '</p>';
|
||
return;
|
||
}
|
||
|
||
results.innerHTML = '<p class="ansico-diagnosekoder__message">' + escapeHtml(AnsicoDiagnosekoderConfig.strings.loading) + '</p>';
|
||
var pageId = getPageId(root);
|
||
var url = AnsicoDiagnosekoderConfig.restUrl + '?q=' + encodeURIComponent(query) + '&limit=50&page_id=' + encodeURIComponent(pageId) + '&_ansico_ts=' + Date.now();
|
||
|
||
fetchPageState(pageId).then(function () {
|
||
return fetch(url, {
|
||
credentials: 'same-origin',
|
||
cache: 'no-store'
|
||
});
|
||
})
|
||
.then(function (response) {
|
||
if (!response.ok) {
|
||
throw new Error('Request failed');
|
||
}
|
||
return response.json();
|
||
})
|
||
.then(function (data) {
|
||
syncClientCollections(data);
|
||
if (
|
||
(!Array.isArray(data.favorites) || !data.favorites.length) &&
|
||
(!data.links || !Object.keys(data.links).length) &&
|
||
(!favoriteCodes.length && !Object.keys(codeLinks).length)
|
||
) {
|
||
preloadPageState(root);
|
||
}
|
||
renderResults(results, data.results || [], query);
|
||
})
|
||
.catch(function () {
|
||
results.innerHTML = '<p class="ansico-diagnosekoder__message">' + escapeHtml(AnsicoDiagnosekoderConfig.strings.error) + '</p>';
|
||
});
|
||
};
|
||
|
||
var debouncedSearch = debounce(runSearch, 200);
|
||
input.addEventListener('input', debouncedSearch);
|
||
|
||
results.addEventListener('click', function (event) {
|
||
var copyButton = event.target.closest('.ansico-diagnosekoder__copy-button');
|
||
if (copyButton) {
|
||
copyText(copyButton.getAttribute('data-copy-value') || '', copyButton);
|
||
return;
|
||
}
|
||
|
||
var favoriteButton = event.target.closest('.ansico-diagnosekoder__favorite-button');
|
||
if (favoriteButton) {
|
||
toggleFavorite(favoriteButton.getAttribute('data-code') || '', favoriteButton, runSearch, getPageId(root));
|
||
return;
|
||
}
|
||
|
||
var linkButton = event.target.closest('.ansico-diagnosekoder__link-button');
|
||
if (linkButton) {
|
||
var code = linkButton.getAttribute('data-code') || '';
|
||
var currentUrl = linkButton.getAttribute('data-current-url') || '';
|
||
if (currentUrl) {
|
||
removeCodeLink(code, linkButton, runSearch, getPageId(root));
|
||
return;
|
||
}
|
||
openLinkModal(code, currentUrl).then(function (enteredUrl) {
|
||
if (enteredUrl === null) {
|
||
return;
|
||
}
|
||
enteredUrl = String(enteredUrl).trim();
|
||
if (!enteredUrl) {
|
||
return;
|
||
}
|
||
saveCodeLink(code, enteredUrl, linkButton, runSearch, getPageId(root));
|
||
});
|
||
}
|
||
});
|
||
|
||
var stateNode = root.querySelector('.ansico-diagnosekoder__page-state');
|
||
var hasServerRenderedResults = false;
|
||
|
||
if (stateNode) {
|
||
try {
|
||
var initialState = JSON.parse(stateNode.textContent || '{}');
|
||
hasServerRenderedResults = !!(initialState && initialState.hasInitialResults);
|
||
} catch (error) {}
|
||
}
|
||
|
||
fetchPageState(getPageId(root)).then(function () {
|
||
var presetQuery = getQueryParam('q');
|
||
if (presetQuery) {
|
||
input.value = presetQuery;
|
||
if (!hasServerRenderedResults) {
|
||
runSearch();
|
||
}
|
||
}
|
||
});
|
||
}
|
||
|
||
function initSearchOnlyBlock(form) {
|
||
form.addEventListener('submit', function (event) {
|
||
var input = form.querySelector('.ansico-diagnosekoder__input');
|
||
var query = input ? input.value.trim() : '';
|
||
var resultsUrl = form.getAttribute('data-results-url') || AnsicoDiagnosekoderConfig.resultsUrl || '';
|
||
|
||
if (!resultsUrl) {
|
||
event.preventDefault();
|
||
var message = form.querySelector('.ansico-diagnosekoder__message');
|
||
if (message) {
|
||
message.textContent = AnsicoDiagnosekoderConfig.strings.missingResultsUrl;
|
||
}
|
||
return;
|
||
}
|
||
|
||
if (!query) {
|
||
event.preventDefault();
|
||
return;
|
||
}
|
||
|
||
event.preventDefault();
|
||
var url = new URL(resultsUrl, window.location.origin);
|
||
url.searchParams.set('q', query);
|
||
window.location.href = url.toString();
|
||
});
|
||
}
|
||
|
||
document.addEventListener('DOMContentLoaded', function () {
|
||
var resultsBlocks = document.querySelectorAll('.wp-block-ansico-diagnosekoder.ansico-diagnosekoder');
|
||
resultsBlocks.forEach(initResultsBlock);
|
||
|
||
var searchOnlyBlocks = document.querySelectorAll('.wp-block-ansico-diagnosekoder-soegefelt.ansico-diagnosekoder--search-only');
|
||
searchOnlyBlocks.forEach(initSearchOnlyBlock);
|
||
});
|
||
})();
|