function openTab(evt, tabName) {
// Declare all variables
let i, tabcontent, tablinks;
// Get all elements with class="tabcontent" and hide them
tabcontent = document.getElementsByClassName("tabcontent");
for (i = 0; i < tabcontent.length; i++) {
tabcontent[i].style.display = "none";
}
// Get all elements with class="tablinks" and remove the class "active"
tablinks = document.getElementsByClassName("tablinks");
for (i = 0; i < tablinks.length; i++) {
tablinks[i].className = tablinks[i].className.replace(" active", "");
}
// Show the current tab, and add an "active" class to the button that opened the tab
document.getElementById(tabName).style.display = "block";
evt.currentTarget.className += " active";
// Kiểm tra nếu tab "4 Kĩ Năng" được nhấn, gọi hàm loadCoverImages() từ masonry.js
if (tabName === "4KiNang" && !evt.currentTarget.classList.contains('loaded')) {
loadCoverImages(); // Gọi hàm từ masonry.js
evt.currentTarget.classList.add('loaded'); // Đánh dấu là tab này đã load
}
// Cập nhật URL mà không tải lại trang
let basePath = window.location.pathname;
// Loại bỏ tabName cũ nếu có
const validTabs = ['DichPhienAm', 'KhoaPhatAm', 'KhoaGiaoTiep', '4KiNang', 'BaiTapLuyen'];
validTabs.forEach(validTab => {
if (basePath.endsWith('/' + validTab)) {
basePath = basePath.slice(0, -validTab.length - 1);
} else if (basePath.endsWith(validTab)) {
basePath = basePath.slice(0, -validTab.length);
}
});
// Loại bỏ dấu gạch chéo ở cuối nếu có
if (basePath.endsWith('/')) {
basePath = basePath.slice(0, -1);
}
// Cập nhật URL mới
if (tabName !== 'DichPhienAm') {
const newUrl = basePath + '/' + tabName;
history.pushState(null, '', newUrl);
} else {
// Trở về link gốc khi là tab mặc định (DichPhienAm)
history.pushState(null, '', basePath);
}
}
// Open the tab based on URL or default to the first tab
document.addEventListener("DOMContentLoaded", function() {
// Hide avatar container initially
document.getElementById("avatarContainer").style.display = "none";
let path = window.location.pathname;
// Loại bỏ dấu gạch chéo ở cuối nếu có
if (path.endsWith('/')) {
path = path.slice(0, -1);
}
let tabName = path.substring(path.lastIndexOf('/') + 1) || 'DichPhienAm';
const validTabs = ['DichPhienAm', 'KhoaPhatAm', 'KhoaGiaoTiep', '4KiNang', 'BaiTapLuyen'];
if (validTabs.includes(tabName)) {
const tabButton = document.querySelector(`.tablinks[onclick*='${tabName}']`);
if (tabButton) {
tabButton.click();
}
} else {
document.querySelector(".tablinks").click();
}
});
// Lắng nghe sự kiện popstate
window.addEventListener('popstate', function(event) {
let path = window.location.pathname;
// Loại bỏ dấu gạch chéo ở cuối nếu có
if (path.endsWith('/')) {
path = path.slice(0, -1);
}
let tabName = path.substring(path.lastIndexOf('/') + 1) || 'DichPhienAm';
const validTabs = ['DichPhienAm', 'KhoaPhatAm', 'KhoaGiaoTiep', '4KiNang', 'BaiTapLuyen'];
if (validTabs.includes(tabName)) {
const tabButton = document.querySelector(`.tablinks[onclick*='${tabName}']`);
if (tabButton) {
tabButton.click();
}
} else {
document.querySelector(".tablinks").click();
}
});
// Lấy phần tử div có thể chỉnh sửa và phần tử để hiển thị IPA và dịch tiếng Việt
const editableDiv = document.getElementById('editableDiv');
const ipaResultDiv = document.getElementById('ipaResult');
const translationResultDiv = document.getElementById('translationResult');
// Hàm dịch tiếng Việt sử dụng endpoint PHP
function translateText(lines) {
const url = `/DICH-IPA/translate.php?text=` + encodeURIComponent(lines.join('\n'));
return fetch(url)
.then(response => {
if (!response.ok) {
throw new Error(`HTTP error! status: ${response.status}`);
}
return response.json();
})
.then(data => {
if (Array.isArray(data) && data[0] && Array.isArray(data[0])) {
// Tách kết quả dịch thành các dòng tương ứng
const translatedText = data[0].map(item => item[0]).join(' ');
const translatedLines = translatedText.split('\n');
// Đảm bảo rằng số lượng dòng dịch khớp với số lượng dòng gốc
if (translatedLines.length === lines.length) {
return translatedLines;
} else {
return lines.map((line, index) => translatedLines[index] || line);
}
} else {
throw new Error('Invalid response structure');
}
})
.catch(error => {
// Xử lý lỗi một cách im lặng và trả về các dòng gốc nếu có lỗi
return lines;
});
}
// Hàm hiển thị kết quả dịch
function displayTranslation() {
const text = editableDiv.innerText;
const lines = text.split('\n');
translateText(lines)
.then(translatedLines => {
// Ghép các dòng dịch lại với nhau, thêm thẻ
giữa các dòng
const formattedText = translatedLines.join('
');
const translationCopyButton = translationResultDiv.querySelector('.translation-copy');
translationResultDiv.innerHTML = formattedText;
translationResultDiv.appendChild(translationCopyButton);
})
.catch(error => console.error('Error displaying translation:', error));
}
// Hàm lưu vị trí con trỏ
function saveCaretPosition(context) {
const selection = window.getSelection();
if (selection.rangeCount === 0) return 0;
const range = selection.getRangeAt(0);
const preCaretRange = range.cloneRange();
preCaretRange.selectNodeContents(context);
preCaretRange.setEnd(range.endContainer, range.endOffset);
return preCaretRange.toString().length;
}
// Hàm khôi phục vị trí con trỏ
function restoreCaretPosition(context, pos) {
const selection = window.getSelection();
const range = document.createRange();
range.selectNodeContents(context);
range.collapse(true);
let charIndex = 0;
// Hàm duyệt qua các nút để tìm vị trí con trỏ
function traverseNodes(node) {
if (node.nodeType === 3) { // Nếu là text node
const nextCharIndex = charIndex + node.length;
if (nextCharIndex >= pos) {
range.setStart(node, pos - charIndex);
range.setEnd(node, pos - charIndex);
return true;
}
charIndex = nextCharIndex;
} else {
for (let i = 0; i < node.childNodes.length; i++) {
if (traverseNodes(node.childNodes[i])) return true;
}
}
return false;
}
traverseNodes(context);
selection.removeAllRanges();
selection.addRange(range);
}
// Thêm và bỏ lớp highlight cho các từ trong editableDiv
function addHighlight(wordIndex) {
const editableSpan = editableDiv.querySelector(`span[data-index='${wordIndex}']`);
const ipaSpan = ipaResultDiv.querySelector(`span[data-index='${wordIndex}']`);
if (editableSpan) editableSpan.classList.add('highlight');
if (ipaSpan) {
ipaSpan.classList.remove('highlight'); // Để reset animation
void ipaSpan.offsetWidth; // Kích hoạt lại DOM để reset animation
ipaSpan.classList.add('highlight');
}
}
function removeHighlight(wordIndex) {
const editableSpan = editableDiv.querySelector(`span[data-index='${wordIndex}']`);
const ipaSpan = ipaResultDiv.querySelector(`span[data-index='${wordIndex}']`);
if (editableSpan) editableSpan.classList.remove('highlight');
if (ipaSpan) ipaSpan.classList.remove('highlight');
}
// Thêm lớp highlight khi di chuột qua từ trong editableDiv
editableDiv.addEventListener('mouseover', function(event) {
if (event.target.tagName === 'SPAN' && !event.target.classList.contains('no-ipa')) {
const wordIndex = event.target.dataset.index;
addHighlight(wordIndex);
}
});
editableDiv.addEventListener('mouseout', function(event) {
if (event.target.tagName === 'SPAN' && !event.target.classList.contains('no-ipa')) {
const wordIndex = event.target.dataset.index;
removeHighlight(wordIndex);
}
});
// Thêm lớp highlight khi di chuột qua từ trong ipaResultDiv
ipaResultDiv.addEventListener('mouseover', function(event) {
if (event.target.tagName === 'SPAN' && !event.target.classList.contains('no-ipa')) {
const wordIndex = event.target.dataset.index;
addHighlight(wordIndex);
}
});
ipaResultDiv.addEventListener('mouseout', function(event) {
if (event.target.tagName === 'SPAN' && !event.target.classList.contains('no-ipa')) {
const wordIndex = event.target.dataset.index;
removeHighlight(wordIndex);
}
});
// Khởi tạo Web Worker
const ipaWorker = new Worker('ipaWorker.js');
// Gửi dữ liệu từ chính đến Worker và nhận phản hồi
async function getIPABatchFromServer(words) {
return new Promise((resolve, reject) => {
ipaWorker.postMessage(words);
ipaWorker.onmessage = (event) => {
const base64String = event.data;
const uint8Array = new Uint8Array(atob(base64String).split('').map(char => char.charCodeAt(0)));
const jsonStr = new TextDecoder().decode(uint8Array);
const data = JSON.parse(jsonStr);
resolve(data);
};
ipaWorker.onerror = (error) => {
console.error('Error in Web Worker:', error);
reject(error);
};
});
}
// Cập nhật hàm displayIPA để gọi dữ liệu IPA từ server và thêm lớp 'no-ipa' cho các từ không có IPA
async function displayIPA() {
let text = editableDiv.innerText.toLowerCase(); // Chuyển văn bản thành chữ thường
// Chuẩn hóa tất cả các dấu nháy thành dấu nháy thẳng
text = text.replace(/[\u2018\u2019\u201A\u201B\u2039\u203A\u0027]/g, "'");
const words = text.split(/(\s+)/); // Chia nhỏ văn bản thành các từ và khoảng trắng
// Tách riêng các từ cần tìm IPA và giữ nguyên các từ đặc biệt
let uniqueWords = new Set();
let wordsData = words.map(word => {
let cleanWord = word.trim(); // Trim để loại bỏ khoảng trắng ở đầu và cuối
let punctuation = null;
// Kiểm tra xem từ có kết thúc bằng dấu nháy hay không
const match = cleanWord.match(/([a-zA-Z']+)([^a-zA-Z']*)$/);
if (match) {
cleanWord = match[1]; // Lấy phần từ sạch (bao gồm cả dấu nháy nếu có)
punctuation = match[2]; // Lấy phần dấu câu nằm sau từ (nếu có)
}
if (cleanWord !== '') {
uniqueWords.add(cleanWord);
}
return {
original: word,
clean: cleanWord,
punctuation: punctuation
};
});
// Gọi dữ liệu IPA từ server cho tất cả các từ ngoại trừ "the"
let ipaData = await getIPABatchFromServer([...uniqueWords].filter(word => word !== 'the'));
// Lưu trữ các vị trí cần thay thế
let replacements = [];
// Xử lý dữ liệu IPA nhận được từ server
for (let i = 0; i < wordsData.length; i++) {
const wordObj = wordsData[i];
if (wordObj.clean === 'the' && i < wordsData.length - 1) {
let j = i + 1;
// Bỏ qua các phần tử không phải từ (khoảng trắng, dấu câu)
while (j < wordsData.length && !/^[a-zA-Z]/.test(wordsData[j].clean)) {
j++;
}
if (j < wordsData.length) {
const nextWord = wordsData[j].clean.replace(/[^a-zA-Z]/g, ''); // Loại bỏ khoảng trắng và dấu câu trước khi kiểm tra
// Chỉ thay thế nếu từ tiếp theo bắt đầu bằng nguyên âm
if (/^[aeiou]/i.test(nextWord)) {
replacements.push({ index: i, ipa: 'ðiː' });
} else {
replacements.push({ index: i, ipa: 'ðə' });
}
}
} else if (wordObj.clean !== '') {
// Nếu không phải từ "the", vẫn tiến hành dịch sang IPA
let ipaWord = ipaData[wordObj.clean] || wordObj.clean;
if (wordObj.punctuation) { // Nếu có dấu câu
ipaWord += `${wordObj.punctuation}`;
}
if (ipaWord !== wordObj.clean) { // Nếu từ có trong từ điển
words[i] = `${ipaWord}`; // Thay thế bằng IPA và thêm chỉ số từ
} else { // Nếu từ không có trong từ điển
words[i] = `${wordObj.original}`; // Bao quanh từ không tìm thấy bằng thẻ span, thêm lớp highlight và chỉ số từ
}
} else {
words[i] = wordObj.original; // Giữ nguyên khoảng trắng
}
}
// Áp dụng các thay thế cho từ "the"
replacements.forEach(({ index, ipa }) => {
words[index] = `${ipa}`;
});
// Kết hợp các từ IPA đã xử lý thành chuỗi cuối cùng và hiển thị
const formattedWords = words.join(''); // Không thêm khoảng cách giữa các từ IPA để giữ nguyên định dạng gốc
// Thay thế ký tự xuống dòng bằng thẻ
const finalFormattedWords = formattedWords.replace(/\n/g, '
');
const ipaCopyButton = ipaResultDiv.querySelector('.ipa-copy');
ipaResultDiv.innerHTML = finalFormattedWords;
ipaResultDiv.appendChild(ipaCopyButton);
// Dịch và hiển thị nội dung trong ô dịch tiếng Việt
displayTranslation();
}
// Hàm tách văn bản thành từng câu dựa theo chấm cuối câu và xuống dòng
function splitTextIntoSentences(text) {
const sentences = text.split(/(?<=\.)\s*/); // Chia văn bản thành từng câu dựa vào dấu chấm
return sentences.join('\n\n'); // Nối lại các câu bằng hai ký tự xuống dòng
}
// Kiểm tra việc chia văn bản thành các câu và hiển thị chúng
function displaySentencesWithTranslations(sentences, translations) {
editableDiv.innerHTML = sentences.map((sentence, index) =>
`
${sentence}
`
).join('
');
translationResultDiv.innerHTML = translations.map((translation, index) =>
`${translation}
`
).join('
');
}
// Xử lý sự kiện khi nội dung thay đổi
editableDiv.addEventListener('paste', function(event) {
event.preventDefault();
const text = (event.clipboardData || window.clipboardData).getData('text');
const formattedText = splitTextIntoSentences(text).replace(/\n/g, '
'); // Thay thế \n bằng
document.execCommand('insertHTML', false, formattedText);
setTimeout(() => {
const selection = window.getSelection();
const range = document.createRange();
range.selectNodeContents(editableDiv);
range.collapse(false); // Collapse the range to the end point
selection.removeAllRanges();
selection.addRange(range);
}, 0);
});
editableDiv.addEventListener('input', function() {
const savedPosition = saveCaretPosition(editableDiv); // Lưu vị trí con trỏ
// Lấy văn bản thô và chia thành các từ để bao quanh chúng bằng thẻ span
const text = editableDiv.innerText;
const words = text.split(/(\s+)/).map((word, index) => {
if (word.trim() === '') return word; // Giữ nguyên khoảng trắng và newline
if (word === '\n') return '
'; // Giữ nguyên newline
return `${word}`; // Thêm chỉ số từ
}).join('');
// Thay thế nội dung của editableDiv bằng nội dung mới với các thẻ span
editableDiv.innerHTML = words;
// Khôi phục vị trí con trỏ
restoreCaretPosition(editableDiv, savedPosition);
// Hiển thị IPA và dịch tiếng Việt
displayIPA();
});
// Xử lý sự kiện khi nhấn phím Enter
editableDiv.addEventListener('keydown', function(event) {
if (event.key === 'Enter') {
event.preventDefault();
document.execCommand('insertLineBreak'); // Chèn một dòng mới
}
});
// Đặt tiêu điểm vào editableDiv khi trang tải
window.addEventListener('DOMContentLoaded', function() {
editableDiv.focus();
});
// Định nghĩa hàm copyToClipboard
function copyToClipboard() {
const translatedText = document.getElementById('translationResult');
const tempElement = document.createElement('div');
tempElement.style.position = 'fixed';
tempElement.style.left = '-9999px';
// Tạo bản sao nội dung mà không bao gồm nút sao chép
Array.from(translatedText.childNodes).forEach(node => {
if (!node.classList || !node.classList.contains('translation-copy')) {
tempElement.appendChild(node.cloneNode(true));
}
});
document.body.appendChild(tempElement);
const range = document.createRange();
range.selectNodeContents(tempElement);
const selection = window.getSelection();
selection.removeAllRanges();
selection.addRange(range);
document.execCommand('copy');
selection.removeAllRanges();
document.body.removeChild(tempElement);
// Thay đổi icon và text
const copyIcon = document.getElementById('translation-copy-icon');
const copyText = document.getElementById('translation-copy-text');
copyIcon.src = 'file-E8hDSmHTudVYHsk3xrSpnqjo.png'; // Đường dẫn đến icon đã sao chép
copyText.textContent = 'Copied!';
// Đặt lại icon và text sau 2,5 giây
setTimeout(() => {
copyIcon.src = 'file-OHmcKVxPhS1eZ1OisXdc7mKM.png'; // Đường dẫn đến icon sao chép ban đầu
copyText.textContent = 'Copy';
}, 2500);
}
function copyIPAToClipboard() {
const ipaText = document.getElementById('ipaResult');
const tempElement = document.createElement('div');
tempElement.style.position = 'fixed';
tempElement.style.left = '-9999px';
// Tạo bản sao nội dung mà không bao gồm nút sao chép
Array.from(ipaText.childNodes).forEach(node => {
if (!node.classList || !node.classList.contains('ipa-copy')) {
tempElement.appendChild(node.cloneNode(true));
}
});
document.body.appendChild(tempElement);
const range = document.createRange();
range.selectNodeContents(tempElement);
const selection = window.getSelection();
selection.removeAllRanges();
selection.addRange(range);
document.execCommand('copy');
selection.removeAllRanges();
document.body.removeChild(tempElement);
// Thay đổi icon và text
const copyIcon = document.getElementById('ipa-copy-icon');
const copyText = document.getElementById('ipa-copy-text');
copyIcon.src = 'file-E8hDSmHTudVYHsk3xrSpnqjo.png'; // Đường dẫn đến icon đã sao chép
copyText.textContent = 'Copied!';
// Đặt lại icon và text sau 2,5 giây
setTimeout(() => {
copyIcon.src = 'file-OHmcKVxPhS1eZ1OisXdc7mKM.png'; // Đường dẫn đến icon sao chép ban đầu
copyText.textContent = 'Copy';
}, 2500);
}
// Hàm phát âm thanh cho văn bản
function textToSpeech(text) {
const speech = new SpeechSynthesisUtterance();
speech.text = text;
speech.lang = 'en-US';
speech.volume = 1;
speech.rate = 1;
speech.pitch = 1;
window.speechSynthesis.speak(speech);
}
// Ngăn chặn phát âm thanh khi quét khối ở ô IPA và ô dịch tiếng Việt
ipaResultDiv.addEventListener('mouseup', function(event) {
const selection = window.getSelection();
if (selection.toString().length > 0) {
// Bỏ qua phát âm thanh cho ô IPA
event.stopPropagation();
}
});
translationResultDiv.addEventListener('mouseup', function(event) {
const selection = window.getSelection();
if (selection.toString().length > 0) {
// Bỏ qua phát âm thanh cho ô dịch tiếng Việt
event.stopPropagation();
}
});
// Event listener for the clear button
document.getElementById('clearEditable').addEventListener('click', function() {
// Select all text
const range = document.createRange();
range.selectNodeContents(editableDiv);
const selection = window.getSelection();
selection.removeAllRanges();
selection.addRange(range);
// Clear the selected text
document.execCommand('delete');
});
// Function to update clear button visibility
function updateClearButton() {
const clearButton = document.getElementById('clearEditable');
if (editableDiv.innerText.trim().length > 0) {
clearButton.classList.remove('hidden');
} else {
clearButton.classList.add('hidden');
}
}
// Event listener for the clear button
document.getElementById('clearEditable').addEventListener('click', function() {
editableDiv.innerHTML = '';
updateClearButton();
});
// Add event listener to the editable div
editableDiv.addEventListener('input', updateClearButton);
// Initial call to set the correct state of the clear button
updateClearButton();
const playAudioIcon = document.getElementById('playAudio');
const stopAudioIcon = document.getElementById('stopAudio');
let speechSynthesisUtterance = null;
// Hàm phát âm thanh
function textToSpeech(text) {
if (speechSynthesisUtterance) {
window.speechSynthesis.cancel();
}
speechSynthesisUtterance = new SpeechSynthesisUtterance(text);
speechSynthesisUtterance.lang = 'en-US';
speechSynthesisUtterance.volume = 1;
speechSynthesisUtterance.rate = 1;
speechSynthesisUtterance.pitch = 1;
speechSynthesisUtterance.onend = function () {
playAudioIcon.classList.remove('hidden');
stopAudioIcon.classList.add('hidden');
};
window.speechSynthesis.speak(speechSynthesisUtterance);
playAudioIcon.classList.add('hidden');
stopAudioIcon.classList.remove('hidden');
}
// Hàm dừng phát âm thanh
function stopAudio() {
if (speechSynthesisUtterance) {
window.speechSynthesis.cancel();
}
playAudioIcon.classList.remove('hidden');
stopAudioIcon.classList.add('hidden');
}
// Sự kiện nhấp vào biểu tượng phát âm thanh
playAudioIcon.addEventListener('click', function() {
const text = editableDiv.innerText; // Lấy nội dung văn bản từ ô nhập liệu
textToSpeech(text);
});
// Sự kiện nhấp vào biểu tượng dừng phát âm thanh
stopAudioIcon.addEventListener('click', stopAudio);
// Lắng nghe sự kiện chuột kéo để phát âm thanh chỉ khi quét khối ở ô nhập liệu
editableDiv.addEventListener('mouseup', function(event) {
// Kiểm tra xem có phải là chọn văn bản hay không
const selection = window.getSelection();
if (selection.toString().length > 0 && event.target.closest('#editableDiv')) {
// Phát âm thanh cho văn bản được chọn trong ô nhập liệu
textToSpeech(selection.toString());
}
});
// QUÉT KHỐI VÀ HIỆN ICON REPEAT (LÀM LỆCH BỐ CỤC SANG TRÁI, LỖI CŨNG NHỎ, CHƯA TÌM RA ĐƯỢC GIẢI PHÁP SẼ ĐỂ SAU)
const repeatIcon = document.getElementById('repeatIcon');
// Chức năng hiển thị biểu tượng lặp lại bên cạnh văn bản đã chọn
function showRepeatIcon(text, rect) {
repeatIcon.style.display = 'block';
repeatIcon.style.left = `${rect.right + 10}px`;
repeatIcon.style.top = `${rect.top + window.scrollY}px`;
repeatIcon.onclick = function() {
textToSpeech(text);
document.body.style.overflow = ''; // Khôi phục trạng thái ban đầu
};
}
// Sửa đổi trình lắng nghe sự kiện để hiển thị biểu tượng lặp lại khi người dùng chọn văn bản
editableDiv.addEventListener('mouseup', function(event) {
const selection = window.getSelection();
const selectedText = selection.toString().trim();
if (selectedText.length > 0 && event.target.closest('#editableDiv')) {
const range = selection.getRangeAt(0);
const rect = range.getBoundingClientRect();
// Hiển thị icon tại vị trí phù hợp
showRepeatIcon(selectedText, rect);
// Phát âm thanh văn bản được chọn
textToSpeech(selectedText);
} else {
repeatIcon.style.display = 'none'; // Ẩn icon nếu không có văn bản được chọn
}
});
// Ẩn icon nếu không có văn bản được chọn hoặc khi nút Clear được bấm
repeatIcon.style.display = 'none';
// Sự kiện click vào nút "Clear"
const clearButton = document.getElementById('clearEditable');
clearButton.addEventListener('click', function() {
editableDiv.innerHTML = '';
updateClearButton();
repeatIcon.style.display = 'none'; // Ẩn icon khi bấm nút Clear
});
//**********************************************************************************************************************//
// THEO DÕI HÀNH VI CỦA USER
document.addEventListener("DOMContentLoaded", function() {
let hasInputOccurred = false; // Biến cờ để theo dõi lần đầu nhập
// Bắt sự kiện khi người dùng nhập chữ vào editableDiv
document.getElementById("editableDiv").addEventListener("input", function() {
if (!hasInputOccurred) { // Chỉ xử lý nếu chưa có input trước đó
console.log("User đã nhập chữ vào editableDiv lần đầu");
hasInputOccurred = true; // Đánh dấu là đã có input
var xhr = new XMLHttpRequest();
xhr.open("POST", "input.php", true);
xhr.setRequestHeader("Content-Type", "application/x-www-form-urlencoded");
xhr.send("action=use_translate_ipa");
}
});
// Lắng nghe sự kiện chuột kéo để phát âm thanh khi quét khối ở ô nhập liệu
document.getElementById("editableDiv").addEventListener("mouseup", function() {
let selectedText = window.getSelection().toString();
if (selectedText) { // Kiểm tra nếu có văn bản được chọn
console.log("User đã quét chọn đoạn văn bản: " + selectedText);
// Có thể thêm logic để phát âm thanh tại đây, ví dụ:
// playAudio(selectedText);
// Nếu cần gửi dữ liệu về server
var xhr = new XMLHttpRequest();
xhr.open("POST", "input.php", true);
xhr.setRequestHeader("Content-Type", "application/x-www-form-urlencoded");
xhr.send("action=selection&text=" + encodeURIComponent(selectedText));
}
});
// Bắt sự kiện khi người dùng nhấp vào nút "Khóa Phát Âm"
document.querySelector(".tablinks[onclick*='KhoaPhatAm']").addEventListener("click", function() {
console.log("User đã nhấp vào tab Khóa Phát Âm");
var xhr = new XMLHttpRequest();
xhr.open("POST", "input.php", true);
xhr.setRequestHeader("Content-Type", "application/x-www-form-urlencoded");
xhr.send("action=khoa_phat_am");
});
// Bắt sự kiện khi người dùng nhấp vào nút "Khóa Giao Tiếp"
document.querySelector(".tablinks[onclick*='KhoaGiaoTiep']").addEventListener("click", function() {
console.log("User đã nhấp vào tab Khóa Giao Tiếp");
var xhr = new XMLHttpRequest();
xhr.open("POST", "input.php", true);
xhr.setRequestHeader("Content-Type", "application/x-www-form-urlencoded");
xhr.send("action=khoa_giao_tiep");
});
// Bắt sự kiện khi người dùng nhấp vào nút "Bài Tập Luyện"
document.querySelector(".tablinks[onclick*='BaiTapLuyen']").addEventListener("click", function() {
console.log("User đã nhấp vào tab Bài Tập Luyện");
var xhr = new XMLHttpRequest();
xhr.open("POST", "input.php", true);
xhr.setRequestHeader("Content-Type", "application/x-www-form-urlencoded");
xhr.send("action=bai_tap_luyen");
});
});
//****************************** begin login modal ************************************************************************//
document.addEventListener('DOMContentLoaded', function() {
var loginModal = document.getElementById("loginModal");
var loginButton = document.getElementById("loginButton");
var signupButton = document.getElementById("signupButton");
var loginClose = document.getElementsByClassName("login-close")[0];
var signInContent = document.getElementById("signInContent");
var signUpContent = document.getElementById("signUpContent");
var modalImage = document.getElementById("modalImageSection").getElementsByTagName('img')[0];
var showSignup = document.getElementById("showSignup");
var showSignin = document.getElementById("showSignin");
if (!loginModal || !loginButton || !loginClose || !signInContent || !signUpContent || !modalImage) {
console.error("Không tìm thấy một trong những phần tử modal.");
return;
}
// Hàm hiển thị modal với hiệu ứng
function showModal() {
loginModal.classList.remove('hide');
loginModal.style.display = "flex"; // Đảm bảo modal được hiển thị
setTimeout(function() {
loginModal.classList.add('show');
}, 10); // Thời gian trễ nhỏ để chắc chắn rằng `opacity` có sự thay đổi
}
// Hàm ẩn modal với hiệu ứng
function hideModal() {
loginModal.classList.remove('show');
loginModal.classList.add('hide');
setTimeout(function() {
loginModal.style.display = "none";
}, 500); // Thời gian trễ phù hợp với transition trong CSS (0.5s)
}
// Khi người dùng nhấn vào nút "Login"
if (loginButton) {
loginButton.onclick = function() {
showModal();
signInContent.style.display = "block";
signUpContent.style.display = "none";
modalImage.src = "/DICH-IPA/tranh_mau.jpg"; // Hình ảnh cho đăng nhập
}
}
// Khi người dùng nhấn vào nút "Sign Up"
if (signupButton) {
signupButton.onclick = function() {
showModal();
signInContent.style.display = "none";
signUpContent.style.display = "block";
modalImage.src = "/DICH-IPA/tranh_mau_signup.jpg"; // Hình ảnh cho đăng ký
}
}
// Khi người dùng nhấn vào dấu "x" để đóng modal
if (loginClose) {
loginClose.onclick = function() {
hideModal();
}
}
// Chuyển từ Sign In sang Sign Up và ngược lại
if (showSignup) {
showSignup.onclick = function() {
signInContent.style.display = "none";
signUpContent.style.display = "block";
modalImage.src = "/DICH-IPA/tranh_mau_signup.jpg"; // Hình ảnh cho đăng ký
}
}
if (showSignin) {
showSignin.onclick = function() {
signInContent.style.display = "block";
signUpContent.style.display = "none";
modalImage.src = "/DICH-IPA/tranh_mau.jpg"; // Hình ảnh cho đăng nhập
}
}
});
//************************************* end login modal *****************************************************************//
document.addEventListener('DOMContentLoaded', function() {
var avatarContainer = document.getElementById("avatarContainer");
var userAvatar = document.getElementById("userAvatar");
// Giả định kiểm tra trạng thái đăng nhập
var isLoggedIn = false; // Đặt là true khi user đã đăng nhập
if (isLoggedIn) {
// Nếu đã đăng nhập và có avatar của người dùng
let userAvatarUrl = "/DICH-IPA/user_uploaded_avatar.png"; // URL ảnh avatar của người dùng
if (userAvatarUrl) {
userAvatar.src = userAvatarUrl; // Thay thế bằng avatar người dùng
} else {
// Nếu không có ảnh avatar, thay bằng chữ cái đầu của tên
let userName = "John Doe"; // Ví dụ tên người dùng
let initial = userName.charAt(0).toUpperCase(); // Lấy chữ cái đầu và chuyển thành viết hoa
userAvatar.style.display = "none"; // Ẩn hình ảnh
let initialElement = document.createElement('div');
initialElement.classList.add('user-initial');
initialElement.textContent = initial;
avatarContainer.appendChild(initialElement);
}
} else {
// Người dùng chưa đăng nhập, hiển thị avatar mặc định (default_avatar.png)
userAvatar.src = "/DICH-IPA/sample_avatar.png";
}
});
//************************************* begin hình avartar *****************************************************************//
document.addEventListener('DOMContentLoaded', function() {
var avatarInput = document.getElementById('avatarInput');
var avatarPreview = document.getElementById('avatarPreview');
if (avatarInput && avatarPreview) {
avatarInput.addEventListener('change', function() {
var file = avatarInput.files[0];
if (file) {
var reader = new FileReader();
reader.onload = function(e) {
avatarPreview.src = e.target.result; // Cập nhật ảnh đại diện
};
reader.readAsDataURL(file); // Đọc file và chuyển thành URL để hiển thị
}
});
}
});
//************************************* end hình avartar *****************************************************************//
//pricing//
document.addEventListener('DOMContentLoaded', function() {
// Các phần tử Modal và nút liên quan
var pricingButton = document.getElementById("pricingButton");
var pricingModal = document.getElementById("pricingModal");
var pricingClose = document.getElementsByClassName("pricing-close")[0];
// Hàm hiển thị modal với hiệu ứng
function showModal(modal) {
modal.classList.remove('hide');
modal.style.display = "flex"; // Đảm bảo modal được hiển thị
setTimeout(function() {
modal.classList.add('show');
}, 10); // Thời gian trễ nhỏ để chắc chắn rằng `opacity` có sự thay đổi
}
// Hàm ẩn modal với hiệu ứng
function hideModal(modal) {
modal.classList.remove('show');
modal.classList.add('hide');
setTimeout(function() {
modal.style.display = "none";
}, 500); // Thời gian trễ phù hợp với transition trong CSS (0.5s)
}
// Khi người dùng nhấn vào nút "Pricing"
if (pricingButton) {
pricingButton.onclick = function() {
showModal(pricingModal); // Hiển thị modal với hiệu ứng
}
}
// Khi người dùng nhấn vào dấu "x" để đóng modal
if (pricingClose) {
pricingClose.onclick = function() {
hideModal(pricingModal); // Đóng modal với hiệu ứng
}
}
// Khi người dùng nhấn bất kỳ đâu ngoài phần nội dung modal, đóng modal
//bên mansory ah, đã gộp vào//
});
//pricing//
//**************************************************************************************************//
document.addEventListener('DOMContentLoaded', function() {
// Lấy tất cả các nút upgrade
const upgradeButtons = document.querySelectorAll('.subscribe-button');
upgradeButtons.forEach(button => {
button.addEventListener('click', function(event) {
// Ngăn chặn hành động mặc định để tránh cuộn không mong muốn
event.preventDefault();
// Lưu lại vị trí hiện tại của trang
const currentScrollPosition = window.pageYOffset;
// Tìm card chứa nút bấm này
const card = button.closest('.pricing-card');
const qrContainer = card.querySelector('.qr-container');
if (qrContainer.classList.contains('qr-visible')) {
// Nếu QR đang hiện, thì ẩn đi
qrContainer.classList.remove('qr-visible');
} else {
// Nếu QR đang ẩn, thì hiện ra
qrContainer.classList.add('qr-visible');
// Cuộn đến phần QR code để đảm bảo người dùng nhìn thấy
qrContainer.scrollIntoView({
behavior: 'smooth',
block: 'nearest'
});
}
// Giữ nguyên vị trí của trang sau khi hiển thị hoặc ẩn QR code
window.scrollTo({
top: currentScrollPosition,
behavior: 'auto'
});
});
});
});
//**********************************************************************************************//
// ===========================================================================================================
// 1. HÀM CALLBACK KHI GOOGLE API TRẢ VỀ KẾT QUẢ ĐĂNG NHẬP HOẶC ĐĂNG KÝ
// ===========================================================================================================
function handleCredentialResponse(response) {
// Lấy JWT từ Google
const jwt = response.credential;
// Gửi JWT đến server để xử lý đăng ký hoặc đăng nhập
fetch('/DICH-IPA/verify_google.php', {
method: 'POST',
headers: {
'Content-Type': 'application/json',
},
body: JSON.stringify({ idToken: jwt }),
})
.then(response => response.json())
.then(data => {
if (data.success) {
alert(data.message); // Đăng ký hoặc đăng nhập thành công
// Tạo phiên đăng nhập sau khi đăng ký/đăng nhập thành công
createSession(data.userId);
} else {
alert('Đăng ký/Đăng nhập thất bại: ' + data.message);
}
})
.catch(error => {
console.error('Đã xảy ra lỗi:', error);
alert('Đăng ký/Đăng nhập thất bại.');
});
}
// ===========================================================================================================
// 2. HÀM TẠO PHIÊN ĐĂNG NHẬP
// ===========================================================================================================
function createSession(userId) {
fetch('/DICH-IPA/session_manager.php', {
method: 'POST',
headers: {
'Content-Type': 'application/json',
},
body: JSON.stringify({ userId: userId }),
})
.then(response => response.json())
.then(data => {
console.log("Server Response:", data); // Kiểm tra phản hồi từ server
if (data.success === true) {
console.log('Phiên đăng nhập đã được tạo thành công');
// Ẩn nút Đăng Nhập và Đăng Ký
document.getElementById('loginButton').style.display = 'none';
document.getElementById('signupButton').style.display = 'none';
// Hiển thị avatar và menu sổ xuống
document.getElementById('avatarContainer').style.display = 'inline-block';
// Đặt lại số lần gọi hàm kiểm tra lỗi
localStorage.setItem('checkErrorsCallCount', 0);
// Đóng modal đăng nhập hoặc đăng ký
const loginModal = document.getElementById("loginModal");
if (loginModal) {
function hideModal(modal) {
modal.classList.remove('show');
setTimeout(function() {
modal.style.display = "none";
}, 500); // Thời gian trễ phù hợp với transition trong CSS
}
hideModal(loginModal);
}
// Nếu modal bài học đang mở, focus lại
const lessonModal = document.getElementById("lessonModal");
if (lessonModal && lessonModal.classList.contains('show')) {
console.log("Focus lại vào modal bài học sau khi đăng nhập thành công.");
// Focus vào englishInput trong modal bài học (nếu tồn tại)
const iframe = document.getElementById('modal-iframe');
if (iframe) {
const iframeDocument = iframe.contentWindow.document;
const englishInput = iframeDocument.getElementById('english-input');
if (englishInput) {
englishInput.focus({ preventScroll: true });
console.log("Đã focus vào englishInput trong modal bài học");
} else {
console.error("Không tìm thấy phần tử english-input trong iframe.");
}
}
}
// (*) Cập nhật lại các phần tử Standard/Premium (hiển thị ID)
updatePlanParagraphs();
} else {
alert('Có lỗi xảy ra khi tạo phiên đăng nhập: ' + data.message);
}
})
.catch(error => {
console.error('Đã xảy ra lỗi:', error);
alert('Không thể tạo phiên đăng nhập.');
});
}
// ===========================================================================================================
// 3. HÀM (CŨ) KIỂM TRA XEM USER ĐÃ ĐĂNG NHẬP CHƯA (CHỈ TRẢ VỀ true/false)
// ===========================================================================================================
async function isUserLoggedIn_OLD() {
try {
const response = await fetch('/DICH-IPA/check_login_status.php', {
method: 'GET',
credentials: 'include' // Gửi cookie/session tới server
});
const data = await response.json();
return data.loggedIn; // Server trả về trạng thái loggedIn
} catch (error) {
console.error('Đã xảy ra lỗi khi kiểm tra trạng thái đăng nhập:', error);
return false;
}
}
// ===========================================================================================================
// 4. HÀM CẬP NHẬT GIAO DIỆN DỰA TRÊN TRẠNG THÁI ĐĂNG NHẬP (SỬ DỤNG isUserLoggedIn_OLD)
// ===========================================================================================================
async function updateUIBasedOnLoginStatus() {
const loggedIn = await isUserLoggedIn_OLD(); // Kiểm tra xem user đã đăng nhập hay chưa
if (loggedIn) {
console.log("Người dùng đã đăng nhập, cập nhật giao diện.");
// Ẩn nút Đăng Nhập và Đăng Ký
const loginButton = document.getElementById('loginButton');
const signupButton = document.getElementById('signupButton');
if (loginButton) loginButton.style.display = 'none';
if (signupButton) signupButton.style.display = 'none';
// Hiển thị avatar và menu sổ xuống
const avatarContainer = document.getElementById('avatarContainer');
if (avatarContainer) avatarContainer.style.display = 'inline-block';
} else {
console.log("Người dùng chưa đăng nhập, cập nhật giao diện để hiện Đăng Nhập/Đăng Ký.");
// Hiển thị nút Đăng Nhập và Đăng Ký
const loginButton = document.getElementById('loginButton');
const signupButton = document.getElementById('signupButton');
if (loginButton) loginButton.style.display = 'block';
if (signupButton) signupButton.style.display = 'block';
// Ẩn avatar và menu sổ xuống
const avatarContainer = document.getElementById('avatarContainer');
if (avatarContainer) avatarContainer.style.display = 'none';
}
}
// ===========================================================================================================
// 5. HÀM KHỞI TẠO CHO GOOGLE API
// ===========================================================================================================
window.onload = function () {
// Cập nhật nút đăng nhập / đăng ký
updateUIBasedOnLoginStatus();
// (*) Cập nhật luôn phần ID Standard/Premium
updatePlanParagraphs();
google.accounts.id.initialize({
client_id: '1049105636345-49al5bf5smvoh8t7uiu4v44lk21s2770.apps.googleusercontent.com',
callback: handleCredentialResponse
});
// Render nút Google cho Đăng Ký
google.accounts.id.renderButton(
document.getElementById('googleLoginButtonSignup'),
{
theme: 'outline',
size: 'medium',
text: 'signin_with',
type: 'standard'
}
);
// Render nút Google cho Đăng Nhập
google.accounts.id.renderButton(
document.getElementById('googleLoginButtonSignin'),
{
theme: 'outline',
size: 'medium',
text: 'signin_with',
type: 'standard'
}
);
google.accounts.id.prompt(); // Hiển thị hộp thoại Google nếu cần
};
// ===========================================================================================================
// 6. XỬ LÝ ĐĂNG XUẤT
// ===========================================================================================================
document.getElementById('logoutButton').addEventListener('click', function() {
// Gửi yêu cầu DELETE để đăng xuất
fetch('/DICH-IPA/session_manager.php', {
method: 'DELETE',
headers: {
'Content-Type': 'application/json',
}
})
.then(response => response.json())
.then(data => {
if (data.success) {
alert('Đăng xuất thành công!');
// Cập nhật giao diện sau khi đăng xuất
document.getElementById('loginButton').style.display = 'block';
document.getElementById('signupButton').style.display = 'block';
document.getElementById('avatarContainer').style.display = 'none';
// (*) Cập nhật lại ID Standard/Premium (hiển thị "chưa đăng nhập")
updatePlanParagraphs();
} else {
alert('Đăng xuất thất bại: ' + data.message);
}
})
.catch(error => {
console.error('Đã xảy ra lỗi:', error);
alert('Đăng xuất thất bại.');
});
});
// ===========================================================================================================
// 7. XỬ LÝ MENU SỔ XUỐNG KHI NHẤN AVATAR
// ===========================================================================================================
document.getElementById('avatarContainer').addEventListener('click', function() {
const dropdownMenu = document.getElementById('dropdownMenu');
if (dropdownMenu.classList.contains('show')) {
dropdownMenu.classList.remove('show');
} else {
dropdownMenu.classList.add('show');
}
});
// Đóng menu nếu nhấp ra ngoài khu vực avatar
window.addEventListener('click', function(event) {
const avatarContainer = document.getElementById('avatarContainer');
const dropdownMenu = document.getElementById('dropdownMenu');
if (!avatarContainer.contains(event.target)) {
dropdownMenu.classList.remove('show');
}
});
// ===========================================================================================================
// 8. HÀM LẤY THÔNG TIN USER (ID, subscriptionStatus) TỪ SERVER
// ===========================================================================================================
async function isUserLoggedIn() {
try {
const response = await fetch('/DICH-IPA/check_login_status.php', {
method: 'GET',
credentials: 'include'
});
const data = await response.json();
if (data.loggedIn) {
return {
userId: data.user.user_id,
subscriptionStatus: data.user.subscription_status
};
}
return false;
} catch (error) {
console.error('Đã xảy ra lỗi khi kiểm tra trạng thái đăng nhập:', error);
return false;
}
}
// ===========================================================================================================
// 9. HÀM CẬP NHẬT NỘI DUNG CỦA GÓI STANDARD/PREMIUM DỰA TRÊN ID USER
// ===========================================================================================================
async function updatePlanParagraphs() {
// Gọi hàm lấy loginInfo
const loginInfo = await isUserLoggedIn();
// Lấy hai phần tử trên trang
const transferInfoStandardEl = document.getElementById('transferInfoStandard');
const transferInfoPremiumEl = document.getElementById('transferInfoPremium');
// Phòng trường hợp không tìm thấy ID
if (!transferInfoStandardEl || !transferInfoPremiumEl) {
console.error("Không tìm thấy transferInfoStandard hoặc transferInfoPremium trong DOM.");
return;
}
if (loginInfo) {
// Nếu user đã đăng nhập
const userId = loginInfo.userId;
// Cập nhật nội dung gói Standard
transferInfoStandardEl.innerHTML = `
*** Quan Trọng ***
Nội dung chuyển khoản của bạn là:
id ${userId}
`;
// Cập nhật nội dung gói Premium
transferInfoPremiumEl.innerHTML = `
*** Quan Trọng ***
Nội dung chuyển khoản của bạn là:
id ${userId}
`;
} else {
// Chưa đăng nhập
transferInfoStandardEl.innerHTML = `
Bạn chưa đăng nhập, vui lòng đăng nhập để xem nội dung chuyển khoản (Standard).
`;
transferInfoPremiumEl.innerHTML = `
Bạn chưa đăng nhập, vui lòng đăng nhập để xem nội dung chuyển khoản (Premium).
`;
}
}
// ===========================================================================================================
// 10. HÀM CẬP NHẬT NỘI DUNG TRẠNG THÁI GÓI TRÊN GIAO DIỆN
async function updateSubscriptionStatusParagraph() {
// Gọi hàm lấy loginInfo
const loginInfo = await isUserLoggedIn();
// Lấy phần tử để hiển thị trạng thái đăng ký
const subscriptionStatusEl = document.getElementById('subscriptionStatus');
// Phòng trường hợp phần tử không tồn tại
if (!subscriptionStatusEl) {
console.error("Không tìm thấy phần tử subscriptionStatus trong DOM.");
return;
}
// Nếu user đã đăng nhập và có thông tin trạng thái
if (loginInfo && loginInfo.subscriptionStatus) {
const subscriptionStatus = loginInfo.subscriptionStatus;
if (subscriptionStatus === 'active') {
subscriptionStatusEl.innerHTML = `PAID`;
} else {
subscriptionStatusEl.innerHTML = `FREE`;
}
} else {
// Nếu chưa đăng nhập hoặc không có thông tin trạng thái
subscriptionStatusEl.textContent = "Không xác định.";
}
}
// Gọi hàm sau khi trang tải xong
document.addEventListener('DOMContentLoaded', updateSubscriptionStatusParagraph);
// ===========================================================================================================
//**********************************************************************************************************************//
// Khởi tạo Facebook SDK
window.fbAsyncInit = function() {
FB.init({
appId: 'YOUR_FACEBOOK_APP_ID',
cookie: true,
xfbml: true,
version: 'v10.0'
});
// Xử lý khi người dùng nhấn vào nút Đăng nhập bằng Facebook
document.getElementById('facebookLoginButton').onclick = function() {
FB.login(function(response) {
if (response.authResponse) {
const accessToken = response.authResponse.accessToken;
// Gửi mã Access Token đến server để xác thực
fetch('/DICH-IPA/verify_facebook.php', {
method: 'POST',
headers: {
'Content-Type': 'application/json'
},
body: JSON.stringify({ accessToken: accessToken })
}).then(response => response.json())
.then(data => {
if (data.success) {
alert("Đăng nhập Facebook thành công!");
} else {
alert("Đăng nhập Facebook thất bại!");
}
});
} else {
alert("Người dùng đã hủy đăng nhập.");
}
}, {scope: 'public_profile,email'});
};
};
//**********************************************************************************************************************//