```javascript
document.addEventListener('DOMContentLoaded', function() {
const isMobile = /Android|webOS|iPhone|iPad|iPod|BlackBerry|IEMobile|Opera Mini/i.test(navigator.userAgent);
// Highlight glossary terms in page text
function highlightGlossaryTerms() {
const cachedTerms = localStorage.getItem('glossary_terms');
if (cachedTerms) {
applyHighlights(JSON.parse(cachedTerms));
return;
}
fetch(tocData.ajaxurl, {
method: 'POST',
headers: {
'Content-Type': 'application/x-www-form-urlencoded',
},
body: 'action=get_glossary_terms'
})
.then(response => response.json())
.then(data => {
if (data.success) {
localStorage.setItem('glossary_terms', JSON.stringify(data.data));
applyHighlights(data.data);
}
})
.catch(error => {
console.error('Error fetching glossary terms:', error);
});
}
function applyHighlights(terms) {
const contentContainer = document.querySelector('.entry-content') || document.body;
const textNodes = document.createTreeWalker(
contentContainer,
NodeFilter.SHOW_TEXT,
{
acceptNode: node => {
const parent = node.parentElement;
if (parent.closest('h1,h2,h3,h4,h5,h6,a,.archive,.category,#user-dictionary')) {
return NodeFilter.FILTER_REJECT;
}
return NodeFilter.FILTER_ACCEPT;
}
}
);
const nodesToProcess = [];
while (textNodes.nextNode()) {
nodesToProcess.push(textNodes.currentNode);
}
nodesToProcess.forEach(node => {
const text = node.textContent;
let newContent = text;
terms.forEach(term => {
if (/^[a-zA-Z]+$/.test(term)) {
const regex = new RegExp(`\\b${term}\\b`, 'gi');
newContent = newContent.replace(regex, `${term}`);
}
});
if (newContent !== text) {
const span = document.createElement('span');
span.innerHTML = newContent;
node.parentNode.replaceChild(span, node);
}
});
// Add click/touch listeners to highlighted terms
document.querySelectorAll('.glossary-term').forEach(term => {
term.addEventListener('click', handleTermClick);
if (isMobile) {
term.addEventListener('touchend', handleTermClick, { passive: true });
}
});
}
function showTooltip(word, translation, url, notFound = false) {
let tooltip = document.querySelector('.toc-tooltip');
if (tooltip) tooltip.remove();
tooltip = document.createElement('div');
tooltip.className = 'toc-tooltip liquid-glass';
tooltip.innerHTML = `
${translation}
`;
if (!notFound) {
const addBtn = document.createElement('button');
addBtn.className = 'toc-add-btn';
addBtn.innerText = 'Додати до словника';
addBtn.dataset.term = word;
addBtn.dataset.translation = translation;
tooltip.appendChild(addBtn);
addBtn.addEventListener('click', function(e) {
e.stopPropagation();
const term = this.dataset.term;
const translation = this.dataset.translation;
if (!tocData.isLoggedIn) {
let localDict = localStorage.getItem('user_dictionary');
localDict = localDict ? JSON.parse(localDict) : {};
if (localDict[term]) {
alert('Це слово вже додано');
return;
}
localDict[term] = translation;
localStorage.setItem('user_dictionary', JSON.stringify(localDict));
this.innerText = 'Додано до словника';
closeTooltipWithAnimation(tooltip);
} else {
fetch(tocData.ajaxurl, {
method: 'POST',
headers: {
'Content-Type': 'application/x-www-form-urlencoded',
},
body: `action=toc_add_to_dict&term=${encodeURIComponent(term)}&translation=${encodeURIComponent(translation)}`
})
.then(response => response.json())
.then(data => {
if (data.success) {
addBtn.innerText = 'Додано до словника';
closeTooltipWithAnimation(tooltip);
} else {
alert('Помилка: ' + data.data);
}
});
}
});
}
document.body.appendChild(tooltip);
if (isMobile) {
tooltip.style.bottom = '0';
tooltip.style.left = '0';
tooltip.style.right = '0';
} else {
const rect = document.querySelector(`.glossary-term[data-term="${word}"]`).getBoundingClientRect();
tooltip.style.top = `${rect.bottom + window.scrollY + 5}px`;
tooltip.style.left = `${rect.left + window.scrollX}px`;
}
tooltip.classList.add('show'); // Trigger slide-up animation
function closeTooltip(e) {
if (!tooltip.contains(e.target)) {
closeTooltipWithAnimation(tooltip);
document.removeEventListener('click', closeTooltip);
document.removeEventListener('touchend', closeTooltip);
}
}
setTimeout(() => {
document.addEventListener('click', closeTooltip);
document.addEventListener('touchend', closeTooltip);
}, 0);
}
function closeTooltipWithAnimation(tooltip) {
tooltip.classList.add('closing');
setTimeout(() => {
tooltip.remove();
}, 300); // Duration of animation
}
function handleTermClick(event) {
event.preventDefault();
const word = event.target.dataset.term;
if (word && /^[a-zA-Z]+$/.test(word)) {
fetch(tocData.ajaxurl, {
method: 'POST',
headers: {
'Content-Type': 'application/x-www-form-urlencoded',
},
body: `action=get_translation&word=${encodeURIComponent(word)}`
})
.then(response => response.json())
.then(data => {
if (data.success) {
showTooltip(word, data.data.translation, data.data.url);
} else {
showTooltip(word, data.data.message || 'Переклад не знайдено', null, true);
}
})
.catch(error => {
console.error('Error:', error);
showTooltip(word, 'Помилка при отриманні перекладу', null, true);
});
}
}
// Start highlighting after page load
if (window.requestIdleCallback) {
requestIdleCallback(highlightGlossaryTerms);
} else {
setTimeout(highlightGlossaryTerms, 0);
}
});
```css
/* translate-on-click.css (версія 1.5) */
.toc-tooltip {
position: absolute;
background: rgba(255, 255, 255, 0.15);
backdrop-filter: blur(10px) brightness(1.1);
border: 1px solid rgba(255, 255, 255, 0.5);
padding: 10px;
z-index: 1000;
box-shadow: 0 8px 32px rgba(31, 38, 135, 0.2), inset 0 4px 20px rgba(255, 255, 255, 0.3);
font-size: 16px;
color: #333333;
max-width: 300px;
border-radius: 20px;
overflow-y: auto;
max-height: 200px;
opacity: 0;
transform: translateY(20px);
transition: opacity 0.3s ease, transform 0.3s ease;
}
.toc-tooltip.show {
opacity: 1;
transform: translateY(0);
}
.toc-tooltip.closing {
opacity: 0;
transform: translateY(20px);
}
@media (max-width: 768px) {
.toc-tooltip {
position: fixed !important;
bottom: 0 !important;
left: 0 !important;
right: 0 !important;
max-width: none !important;
}
}
.toc-content {
cursor: pointer;
}
.toc-add-btn {
display: block;
width: 100%;
margin-top: 10px;
padding: 8px;
background-color: #007bff;
color: white;
border: none;
border-radius: 4px;
font-size: 16px;
cursor: pointer;
transition: background-color 0.3s;
}
.toc-add-btn:hover {
background-color: #0056b3;
}
.toc-add-btn.success {
background-color: green;
color: white;
}
.remove-term {
width: 40px;
height: 40px;
font-size: 18px;
margin-left: 10px;
background-color: #dc3545;
color: white;
border: none;
border-radius: 4px;
cursor: pointer;
transition: background-color 0.3s;
}
.remove-term:hover {
background-color: #c82333;
}
.game-option {
display: inline-block;
margin: 10px;
padding: 10px 20px;
background-color: #f8f9fa;
border: 1px solid #ccc;
border-radius: 4px;
cursor: pointer;
transition: background-color 0.3s;
}
.game-option:hover {
background-color: #e9ecef;
}
.glossary-term {
background: rgba(255, 255, 255, 0.15);
backdrop-filter: blur(5px) brightness(1.1);
cursor: pointer;
padding: 2px 4px;
border-radius: 10px;
box-shadow: inset 0 1px 3px rgba(255, 255, 255, 0.3);
}
#user-dictionary, #game-container {
background: rgba(255, 255, 255, 0.15);
backdrop-filter: blur(10px) brightness(1.1);
border: 1px solid rgba(255, 255, 255, 0.5);
padding: 20px;
border-radius: 20px;
box-shadow: 0 8px 32px rgba(31, 38, 135, 0.2), inset 0 4px 20px rgba(255, 255, 255, 0.3);
}
#user-dictionary ul li, #game-container .game-option {
background: rgba(255, 255, 255, 0.2);
backdrop-filter: blur(5px);
border-radius: 10px;
padding: 10px;
margin-bottom: 10px;
}
Сторінку не знайдено - Cryeng
Перейти до вмісту