From f6a52b73def2e8fe7438a4faacdf7ae594923d45 Mon Sep 17 00:00:00 2001 From: Zan <62830223+Zan1456@users.noreply.github.com> Date: Wed, 10 Dec 2025 15:51:37 +0100 Subject: [PATCH] firefox addon store bullshit --- absences/absences.js | 6 +- dashboard/dashboard.js | 14 +- forgotpassword/forgotpassword.css | 57 ---- forgotpassword/forgotpassword.js | 290 -------------------- global/maintenance.js | 2 +- grades/grades.js | 17 +- login/login.js | 12 +- login/twofactor.js | 15 +- logout/logout.js | 8 +- messages/messages.js | 428 +++++++++++++++++++++--------- profile/profile.js | 2 +- roleselect/roleselect.js | 10 +- settings/index.js | 38 ++- timetable/timetable.js | 79 ++++-- tools/helper.js | 24 ++ 15 files changed, 451 insertions(+), 551 deletions(-) delete mode 100644 forgotpassword/forgotpassword.css delete mode 100644 forgotpassword/forgotpassword.js diff --git a/absences/absences.js b/absences/absences.js index 5bf0443..c72686e 100644 --- a/absences/absences.js +++ b/absences/absences.js @@ -402,9 +402,9 @@ async function transformAbsencesPage() { container.className = 'kreta-container'; const headerDiv = document.createElement('div'); - const parser = new DOMParser(); - const doc = parser.parseFromString(await createTemplate.header(), 'text/html'); - const tempDiv = doc.body; + const template = document.createElement('template'); + template.innerHTML = await createTemplate.header(); + const tempDiv = template.content; while (tempDiv.firstChild) { headerDiv.appendChild(tempDiv.firstChild); } diff --git a/dashboard/dashboard.js b/dashboard/dashboard.js index 5631c24..115fad3 100644 --- a/dashboard/dashboard.js +++ b/dashboard/dashboard.js @@ -499,22 +499,22 @@ class DashboardRenderer { async render() { await this.init(); - document.body.innerHTML = ''; + helper.clearElement(document.body); const kretaContainer = document.createElement('div'); kretaContainer.className = 'kreta-container'; const headerDiv = document.createElement('div'); - const parser = new DOMParser(); - const headerDoc = parser.parseFromString(await createTemplate.header(), 'text/html'); - const headerContent = headerDoc.body; + const template = document.createElement('template'); + template.innerHTML = await createTemplate.header(); + const headerContent = template.content; while (headerContent.firstChild) { headerDiv.appendChild(headerContent.firstChild); } kretaContainer.appendChild(headerDiv); const mainContentDiv = document.createElement('div'); - const parser2 = new DOMParser(); - const mainDoc = parser2.parseFromString(this.generateMainContent(), 'text/html'); - const mainContent = mainDoc.body; + const template2 = document.createElement('template'); + template2.innerHTML = this.generateMainContent(); + const mainContent = template2.content; while (mainContent.firstChild) { mainContentDiv.appendChild(mainContent.firstChild); } diff --git a/forgotpassword/forgotpassword.css b/forgotpassword/forgotpassword.css deleted file mode 100644 index 33e629f..0000000 --- a/forgotpassword/forgotpassword.css +++ /dev/null @@ -1,57 +0,0 @@ -body.maintenance-mode { - margin:0; - padding:0; - height:100vh; - display:flex; - align-items:center; - justify-content:center; - background-color:var(--background); - color:var(--text-primary); - font-family:'Figtree',sans-serif; -} -body { - background-color:var(--background) !important; -} -.maintenance-container { - text-align:center; - padding:2rem; - border-radius:8px; - background-color:var(--card-card); - box-shadow:0 var(--shadow-blur) 6px var(--accent-shadow); - max-width:600px; - width:90%; -} -.maintenance-logo { - width:128px; - height:128px; - margin:0 auto 2rem; -} -.maintenance-title { - font-size:1.5rem; - font-weight:600; - margin-bottom:1rem; - color:var(--accent-accent); - font-family:'Montserrat',sans-serif; -} -.maintenance-message { - font-size:1rem; - line-height:1.5; - margin-bottom:1.5rem; - color:var(--text-primary); - font-family:'Figtree',sans-serif; -} -.maintenance-footer { - font-size:0.875rem; - color:var(--text-secondary); - margin-top:2rem; - font-family:'Figtree',sans-serif; -} -.maintenance-cactus { - position:fixed; - bottom:0px; - right:20px; - width:120px; - height:120px; - opacity:1; - z-index:1000; -} diff --git a/forgotpassword/forgotpassword.js b/forgotpassword/forgotpassword.js deleted file mode 100644 index 5ab9ab6..0000000 --- a/forgotpassword/forgotpassword.js +++ /dev/null @@ -1,290 +0,0 @@ -(() => { - // reCAPTCHA functionality removed for security compliance - - const loadDependencies = async () => { - // reCAPTCHA functionality removed for security compliance - // Extension now works without external script dependencies - }; - - const createPageStructure = () => { - // Biztonságos DOM létrehozás innerHTML helyett - document.body.innerHTML = ''; - // Biztonságos HTML parsing DOMParser használatával - const parser = new DOMParser(); - const doc = parser.parseFromString(` -
- - - - - - -
-
-

- - Firka -

-
- -

Elfelejtett jelszó

- -
-
- - -
Az OM azonosító megadása kötelező
-
- -
- - -
Az e-mail cím megadása kötelező
-
- - - -
- - Vissza a bejelentkezéshez - - -
-
-
-
- `, 'text/html'); - const tempDiv = doc.body; - - // Biztonságos DOM hozzáadás - while (tempDiv.firstChild) { - document.body.appendChild(tempDiv.firstChild); - } - }; - - const transformForgotPasswordPage = async () => { - await loadDependencies(); - - const isDarkMode = localStorage.getItem("darkMode") === "true"; - document.documentElement.setAttribute( - "data-theme", - isDarkMode ? "dark" : "light", - ); - - chrome.runtime.onMessage.addListener((message) => { - if (message.action === "toggleTheme") { - document.documentElement.setAttribute( - "data-theme", - message.darkMode ? "dark" : "light", - ); - localStorage.setItem("darkMode", message.darkMode); - } - }); - - createPageStructure(); - - let attempts = 0; - const maxAttempts = 50; - - const waitForLanguageManager = () => { - return new Promise((resolve) => { - const checkLanguageManager = () => { - attempts++; - if (typeof LanguageManager !== "undefined" && LanguageManager.t) { - setTimeout(resolve, 200); - } else if (attempts < maxAttempts) { - setTimeout(checkLanguageManager, 100); - } else { - console.warn("LanguageManager not available, using fallback texts"); - resolve(); - } - }; - checkLanguageManager(); - }); - }; - - await waitForLanguageManager(); - - if (typeof LanguageManager !== "undefined" && LanguageManager.t) { - const elements = document.querySelectorAll("[data-i18n]"); - elements.forEach((element) => { - const key = element.getAttribute("data-i18n"); - const translation = LanguageManager.t(key); - - if (translation && translation !== key) { - const attr = element.getAttribute("data-i18n-attr"); - if (attr) { - element.setAttribute(attr, translation); - } else { - element.textContent = translation; - } - } - }); - } - - // reCAPTCHA rendering removed for security compliance - - setupFormValidation(); - }; - - const setupFormValidation = () => { - const form = document.getElementById("forgotForm"); - const inputs = form.querySelectorAll(".form-control"); - - inputs.forEach((input) => { - input.addEventListener("input", () => { - validateInput(input); - }); - - input.addEventListener("blur", () => { - validateInput(input, true); - }); - }); - - form.addEventListener("submit", handleSubmit); - }; - - const validateInput = (input, showError = false) => { - const isValid = input.value.trim().length > 0; - const errorElement = input.nextElementSibling; - - if (!isValid && showError) { - input.classList.add("error"); - errorElement?.classList.add("show"); - } else { - input.classList.remove("error"); - errorElement?.classList.remove("show"); - } - - return isValid; - }; - - const showMessage = (message, isError = false) => { - const existingMessage = document.querySelector(".message"); - if (existingMessage) { - existingMessage.remove(); - } - - const messageDiv = document.createElement("div"); - messageDiv.className = `message ${isError ? "error" : "success"}`; - messageDiv.textContent = message; - - const form = document.getElementById("forgotForm"); - form.insertBefore(messageDiv, form.firstChild); - - setTimeout(() => { - if (messageDiv.parentNode) { - messageDiv.remove(); - } - }, 5000); - }; - - const validateEmail = (email) => { - const emailRegex = /^[^\s@]+@[^\s@]+\.[^\s@]+$/; - return emailRegex.test(email); - }; - - const handleSubmit = async (event) => { - event.preventDefault(); - - const form = event.target; - const inputs = form.querySelectorAll(".form-control[required]"); - let isValid = true; - - inputs.forEach((input) => { - if (!validateInput(input, true)) { - isValid = false; - } - }); - - const emailInput = form.querySelector("#EmailCim"); - if (emailInput.value && !validateEmail(emailInput.value)) { - emailInput.classList.add("error"); - const errorElement = emailInput.nextElementSibling; - if (errorElement) { - errorElement.textContent = LanguageManager.t( - "forgotpassword.invalid_email", - ); - errorElement.classList.add("show"); - } - isValid = false; - } - - // reCAPTCHA validation removed for security compliance - - if (!isValid) { - return; - } - - const submitButton = form.querySelector(".btn-submit"); - const originalText = submitButton.textContent; - submitButton.disabled = true; - submitButton.textContent = LanguageManager.t("loading.text") || "Küldés..."; - - try { - const formData = new FormData(form); - - // reCAPTCHA data removed for security compliance - - const response = await fetch( - "/Adminisztracio/ElfelejtettJelszo/LinkKuldes", - { - method: "POST", - body: formData, - headers: { - "X-Requested-With": "XMLHttpRequest", - }, - }, - ); - - if (!response.ok) { - throw new Error(`HTTP error! status: ${response.status}`); - } - - const result = await response.json(); - - if (result.Success) { - showMessage(LanguageManager.t("forgotpassword.success_message")); - - form.reset(); - - // reCAPTCHA reset removed - - setTimeout(() => { - window.location.href = "/Adminisztracio/Login"; - }, 3000); - } else { - showMessage( - result.Message || LanguageManager.t("forgotpassword.error_message"), - true, - ); - - // reCAPTCHA reset removed - } - } catch (error) { - console.error("Password reset error:", error); - showMessage(LanguageManager.t("forgotpassword.error_message"), true); - - // reCAPTCHA reset removed - } finally { - submitButton.disabled = false; - submitButton.textContent = originalText; - } - }; - - if (window.location.href.includes("/Adminisztracio/ElfelejtettJelszo")) { - transformForgotPasswordPage().catch(console.error); - } -})(); diff --git a/global/maintenance.js b/global/maintenance.js index 9f5ef33..adaa7d0 100644 --- a/global/maintenance.js +++ b/global/maintenance.js @@ -45,7 +45,7 @@ function checkMaintenancePage() { ); existingStyles.forEach((style) => style.remove()); - body.innerHTML = ""; + helper.clearElement(body); body.classList.add("maintenance-mode"); body.classList.add("theme-enabled"); body.classList.add("loaded"); diff --git a/grades/grades.js b/grades/grades.js index 94e1c16..fcee35a 100644 --- a/grades/grades.js +++ b/grades/grades.js @@ -28,17 +28,18 @@ const classAverage = calculateOverallClassAverage(gradesData.subjects); window.currentGradesData = gradesData; - document.body.innerHTML = ''; - const parser = new DOMParser(); - const doc = parser.parseFromString(await generatePageHTML( + + const htmlString = await generatePageHTML( gradesData, studentAverage, classAverage, - ), 'text/html'); - const tempDiv = doc.body; - while (tempDiv.firstChild) { - document.body.appendChild(tempDiv.firstChild); - } + ); + + const template = document.createElement('template'); + template.innerHTML = htmlString; + + helper.clearElement(document.body); + document.body.appendChild(template.content); setupUserDropdown(); diff --git a/login/login.js b/login/login.js index 044c925..3fa2e7b 100644 --- a/login/login.js +++ b/login/login.js @@ -120,13 +120,11 @@ async function transformLoginPage() { `; - document.body.innerHTML = ''; - const parser = new DOMParser(); - const doc = parser.parseFromString(newHTML, 'text/html'); - const tempDiv = doc.body; - while (tempDiv.firstChild) { - document.body.appendChild(tempDiv.firstChild); - } + const template = document.createElement('template'); + template.innerHTML = newHTML; + + helper.clearElement(document.body); + document.body.appendChild(template.content); setupEventListeners(); } catch (error) { diff --git a/login/twofactor.js b/login/twofactor.js index b925b07..32e9ed9 100644 --- a/login/twofactor.js +++ b/login/twofactor.js @@ -83,13 +83,12 @@ async function transformTwoFactorPage() { `; - document.body.innerHTML = ''; - const parser = new DOMParser(); - const doc = parser.parseFromString(newHTML, 'text/html'); - const tempDiv = doc.body; - while (tempDiv.firstChild) { - document.body.appendChild(tempDiv.firstChild); - } + const template = document.createElement('template'); + template.innerHTML = newHTML; + + helper.clearElement(document.body); + document.body.appendChild(template.content); + applyTheme(); setupEventListeners(); if (typeof loadingScreen !== "undefined") { @@ -170,7 +169,7 @@ function handleSubmit(event) { const submitButton = form.querySelector(".btn-kreta"); if (submitButton) { submitButton.disabled = true; - submitButton.innerHTML = ''; + helper.clearElement(submitButton); const spinnerSpan = document.createElement('span'); spinnerSpan.className = 'spinner'; const textSpan = document.createElement('span'); diff --git a/logout/logout.js b/logout/logout.js index 7d4adf9..c0d47fc 100644 --- a/logout/logout.js +++ b/logout/logout.js @@ -34,10 +34,10 @@ `; - document.body.innerHTML = ''; - const parser = new DOMParser(); - const doc = parser.parseFromString(newHTML, 'text/html'); - const tempDiv = doc.body; + helper.clearElement(document.body); + const template = document.createElement('template'); + template.innerHTML = newHTML; + const tempDiv = template.content; while (tempDiv.firstChild) { document.body.appendChild(tempDiv.firstChild); } diff --git a/messages/messages.js b/messages/messages.js index fce3b8d..9bd3350 100644 --- a/messages/messages.js +++ b/messages/messages.js @@ -42,7 +42,7 @@ function sanitizeHTML(html) { const div = document.createElement('div'); div.textContent = html; - return div.innerHTML; + return div.textContent; } class APIManager { @@ -159,18 +159,32 @@ const modalContent = document.createElement('div'); modalContent.className = 'modal-content'; - modalContent.innerHTML = ` - - - `; + + const modalHeader = document.createElement('div'); + modalHeader.className = 'modal-header'; + const modalTitle = document.createElement('h2'); + modalTitle.textContent = 'Üzenet részletei'; + const modalClose = document.createElement('button'); + modalClose.className = 'modal-close'; + modalClose.textContent = '×'; + modalHeader.appendChild(modalTitle); + modalHeader.appendChild(modalClose); + + const modalBody = document.createElement('div'); + modalBody.className = 'modal-body'; + const loadingContent = document.createElement('div'); + loadingContent.className = 'loading-content'; + const loadingSpinner = document.createElement('div'); + loadingSpinner.className = 'loading-spinner'; + const loadingText = document.createElement('p'); + loadingText.textContent = 'Üzenet betöltése...'; + loadingContent.appendChild(loadingSpinner); + loadingContent.appendChild(loadingText); + modalBody.appendChild(loadingContent); + + modalContent.appendChild(modalHeader); + modalContent.appendChild(modalBody); + modalOverlay.appendChild(modalContent); document.body.appendChild(modalOverlay); @@ -213,13 +227,24 @@ console.error('Error loading message details:', error); const modalContent = document.querySelector('.modal-content'); if (modalContent) { - modalContent.querySelector('.modal-body').innerHTML = ` -
-

Hiba történt

-

Az üzenet betöltése sikertelen.

- -
- `; + const modalBody = modalContent.querySelector('.modal-body'); + helper.clearElement(modalBody); + + const errorContent = document.createElement('div'); + errorContent.className = 'error-content'; + const errorTitle = document.createElement('h3'); + errorTitle.textContent = 'Hiba történt'; + const errorText = document.createElement('p'); + errorText.textContent = 'Az üzenet betöltése sikertelen.'; + const retryBtn = document.createElement('button'); + retryBtn.className = 'retry-btn'; + retryBtn.textContent = 'Újrapróbálás'; + retryBtn.onclick = () => openMessageModal(messageId); + + errorContent.appendChild(errorTitle); + errorContent.appendChild(errorText); + errorContent.appendChild(retryBtn); + modalBody.appendChild(errorContent); } } } @@ -231,38 +256,86 @@ const subject = message.targy || 'Nincs tárgy'; const content = message.szoveg || 'Nincs tartalom'; - modalContent.querySelector('.modal-body').innerHTML = ` -
-
-
- Feladó: - ${sanitizeHTML(sender)} -
-
- Dátum: - ${date} -
-
- Tárgy: - ${sanitizeHTML(subject)} -
-
-
-

Üzenet tartalma:

-
${content}
-
- ${message.csatolmanyok && message.csatolmanyok.length > 0 ? ` -
-

Mellékletek:

- -
- ` : ''} -
- `; + const modalBody = modalContent.querySelector('.modal-body'); + helper.clearElement(modalBody); + + const messageDetails = document.createElement('div'); + messageDetails.className = 'message-details'; + + const messageInfo = document.createElement('div'); + messageInfo.className = 'message-info'; + + const senderRow = document.createElement('div'); + senderRow.className = 'info-row'; + const senderLabel = document.createElement('span'); + senderLabel.className = 'info-label'; + senderLabel.textContent = 'Feladó:'; + const senderValue = document.createElement('span'); + senderValue.className = 'info-value'; + senderValue.textContent = sanitizeHTML(sender); + senderRow.appendChild(senderLabel); + senderRow.appendChild(senderValue); + messageInfo.appendChild(senderRow); + + const dateRow = document.createElement('div'); + dateRow.className = 'info-row'; + const dateLabel = document.createElement('span'); + dateLabel.className = 'info-label'; + dateLabel.textContent = 'Dátum:'; + const dateValue = document.createElement('span'); + dateValue.className = 'info-value'; + dateValue.textContent = date; + dateRow.appendChild(dateLabel); + dateRow.appendChild(dateValue); + messageInfo.appendChild(dateRow); + + const subjectRow = document.createElement('div'); + subjectRow.className = 'info-row'; + const subjectLabel = document.createElement('span'); + subjectLabel.className = 'info-label'; + subjectLabel.textContent = 'Tárgy:'; + const subjectValue = document.createElement('span'); + subjectValue.className = 'info-value'; + subjectValue.textContent = sanitizeHTML(subject); + subjectRow.appendChild(subjectLabel); + subjectRow.appendChild(subjectValue); + messageInfo.appendChild(subjectRow); + + messageDetails.appendChild(messageInfo); + + const messageContent = document.createElement('div'); + messageContent.className = 'message-content'; + const contentTitle = document.createElement('h4'); + contentTitle.textContent = 'Üzenet tartalma:'; + messageContent.appendChild(contentTitle); + const messageText = document.createElement('div'); + messageText.className = 'message-text'; + messageText.textContent = content; + messageContent.appendChild(messageText); + messageDetails.appendChild(messageContent); + + if (message.csatolmanyok && message.csatolmanyok.length > 0) { + const messageAttachments = document.createElement('div'); + messageAttachments.className = 'message-attachments'; + const attachTitle = document.createElement('h4'); + attachTitle.textContent = 'Mellékletek:'; + messageAttachments.appendChild(attachTitle); + + const attachList = document.createElement('ul'); + message.csatolmanyok.forEach(attachment => { + const li = document.createElement('li'); + const a = document.createElement('a'); + a.href = '#'; + a.textContent = sanitizeHTML(attachment.nev); + a.onclick = () => downloadAttachment(attachment.azonosito); + li.appendChild(a); + attachList.appendChild(li); + }); + messageAttachments.appendChild(attachList); + messageDetails.appendChild(messageAttachments); + } + + modalBody.appendChild(messageDetails); } function closeMessageModal() { @@ -278,41 +351,58 @@ function createLoadingState() { const loadingDiv = document.createElement('div'); loadingDiv.className = 'loading-state'; - loadingDiv.innerHTML = ` -
-
-

${LanguageManager.t('messages.loading', 'Üzenetek betöltése...')}

-
- `; + + const loadingContent = document.createElement('div'); + loadingContent.className = 'loading-content'; + const spinner = document.createElement('div'); + spinner.className = 'loading-spinner'; + const text = document.createElement('p'); + text.textContent = LanguageManager.t('messages.loading', 'Üzenetek betöltése...'); + loadingContent.appendChild(spinner); + loadingContent.appendChild(text); + loadingDiv.appendChild(loadingContent); + return loadingDiv; } function createErrorState(onRetry) { const errorDiv = document.createElement('div'); errorDiv.className = 'error-state'; - errorDiv.innerHTML = ` -
-

${LanguageManager.t('messages.error.title', 'Hiba történt')}

-

${LanguageManager.t('messages.error.description', 'Az üzenetek betöltése sikertelen volt.')}

- -
- `; - const retryBtn = errorDiv.querySelector('.retry-btn'); + const errorContent = document.createElement('div'); + errorContent.className = 'error-content'; + const title = document.createElement('h3'); + title.textContent = LanguageManager.t('messages.error.title', 'Hiba történt'); + const desc = document.createElement('p'); + desc.textContent = LanguageManager.t('messages.error.description', 'Az üzenetek betöltése sikertelen volt.'); + const retryBtn = document.createElement('button'); + retryBtn.className = 'retry-btn'; + retryBtn.textContent = LanguageManager.t('messages.error.retry', 'Újrapróbálás'); retryBtn.addEventListener('click', onRetry); + errorContent.appendChild(title); + errorContent.appendChild(desc); + errorContent.appendChild(retryBtn); + errorDiv.appendChild(errorContent); + return errorDiv; } function createEmptyState() { const emptyDiv = document.createElement('div'); emptyDiv.className = 'empty-state'; - emptyDiv.innerHTML = ` -
-

${LanguageManager.t('messages.empty.title', 'Nincsenek üzenetek')}

-

${LanguageManager.t('messages.empty.description', 'Jelenleg nincsenek elérhető üzenetek.')}

-
- `; + + const emptyContent = document.createElement('div'); + emptyContent.className = 'empty-content'; + const title = document.createElement('h3'); + title.textContent = LanguageManager.t('messages.empty.title', 'Nincsenek üzenetek'); + const desc = document.createElement('p'); + desc.textContent = LanguageManager.t('messages.empty.description', 'Jelenleg nincsenek elérhető üzenetek.'); + + emptyContent.appendChild(title); + emptyContent.appendChild(desc); + emptyDiv.appendChild(emptyContent); + return emptyDiv; } @@ -332,18 +422,42 @@ const subject = message.uzenetTargy || 'Nincs tárgy'; const date = formatDate(message.uzenetKuldesDatum); const hasAttachment = message.hasCsatolmany; + + const cardHeader = document.createElement('div'); + cardHeader.className = 'message-card-header'; - card.innerHTML = ` -
-
- ${sanitizeHTML(senderName)} - ${!message.isElolvasva ? '' : ''} -
-
${date}
-
-
${sanitizeHTML(subject)}
- ${hasAttachment ? '
📎
' : ''} - `; + const senderInfo = document.createElement('div'); + senderInfo.className = 'sender-info'; + const senderNameSpan = document.createElement('span'); + senderNameSpan.className = 'sender-name'; + senderNameSpan.textContent = sanitizeHTML(senderName); + senderInfo.appendChild(senderNameSpan); + + if (!message.isElolvasva) { + const unreadIndicator = document.createElement('span'); + unreadIndicator.className = 'unread-indicator'; + senderInfo.appendChild(unreadIndicator); + } + + const messageDate = document.createElement('div'); + messageDate.className = 'message-date'; + messageDate.textContent = date; + + cardHeader.appendChild(senderInfo); + cardHeader.appendChild(messageDate); + card.appendChild(cardHeader); + + const messageSubject = document.createElement('div'); + messageSubject.className = 'message-subject'; + messageSubject.textContent = sanitizeHTML(subject); + card.appendChild(messageSubject); + + if (hasAttachment) { + const attachmentIndicator = document.createElement('div'); + attachmentIndicator.className = 'attachment-indicator'; + attachmentIndicator.textContent = '📎'; + card.appendChild(attachmentIndicator); + } return card; @@ -397,41 +511,111 @@ function renderBulkActions(container) { const bulk = document.createElement('div'); bulk.className = 'bulk-actions-card'; - bulk.innerHTML = ` -
-
- - -
- - - -
-
- - - - -
- `; + + const bulkActionsLeft = document.createElement('div'); + bulkActionsLeft.className = 'bulk-actions-left'; + + const viewToggle = document.createElement('div'); + viewToggle.className = 'view-toggle'; + + const viewInboxBtn = document.createElement('button'); + viewInboxBtn.id = 'viewInboxBtn'; + viewInboxBtn.className = currentView === 'inbox' ? 'active' : ''; + viewInboxBtn.title = 'Beérkezett'; + const inboxImg = document.createElement('img'); + inboxImg.src = chrome.runtime.getURL('icons/messages-active.svg'); + inboxImg.alt = 'Beérkezett'; + viewInboxBtn.appendChild(inboxImg); + + const viewTrashBtn = document.createElement('button'); + viewTrashBtn.id = 'viewTrashBtn'; + viewTrashBtn.className = currentView === 'trash' ? 'active' : ''; + viewTrashBtn.title = 'Törölt'; + const trashImg = document.createElement('img'); + trashImg.src = chrome.runtime.getURL('icons/delete.svg'); + trashImg.alt = 'Törölt'; + viewTrashBtn.appendChild(trashImg); + + viewToggle.appendChild(viewInboxBtn); + viewToggle.appendChild(viewTrashBtn); + bulkActionsLeft.appendChild(viewToggle); + + const toggleSelBtn = document.createElement('button'); + toggleSelBtn.id = 'toggleSelectionModeBtn'; + toggleSelBtn.className = 'bulk-btn'; + toggleSelBtn.title = 'Kijelölés mód'; + const selectImg = document.createElement('img'); + selectImg.src = chrome.runtime.getURL('icons/select.svg'); + selectImg.alt = 'Kijelölés mód'; + toggleSelBtn.appendChild(selectImg); + bulkActionsLeft.appendChild(toggleSelBtn); + + const selectAllBtn = document.createElement('button'); + selectAllBtn.id = 'selectAllBtn'; + selectAllBtn.className = 'bulk-btn'; + selectAllBtn.title = 'Mind kijelöl'; + const selectAllImg = document.createElement('img'); + selectAllImg.src = chrome.runtime.getURL('icons/select-all.svg'); + selectAllImg.alt = 'Mind kijelöl'; + selectAllBtn.appendChild(selectAllImg); + bulkActionsLeft.appendChild(selectAllBtn); + + const clearSelBtn = document.createElement('button'); + clearSelBtn.id = 'clearSelectionBtn'; + clearSelBtn.className = 'bulk-btn'; + clearSelBtn.title = 'Kijelölés törlése'; + const clearSelImg = document.createElement('img'); + clearSelImg.src = chrome.runtime.getURL('icons/select-none.svg'); + clearSelImg.alt = 'Kijelölés törlése'; + clearSelBtn.appendChild(clearSelImg); + bulkActionsLeft.appendChild(clearSelBtn); + + bulk.appendChild(bulkActionsLeft); + + const bulkActionsRight = document.createElement('div'); + bulkActionsRight.className = 'bulk-actions-right'; + + const markReadBtn = document.createElement('button'); + markReadBtn.id = 'markReadBtn'; + markReadBtn.className = 'bulk-btn'; + markReadBtn.title = 'Olvasott'; + const markReadImg = document.createElement('img'); + markReadImg.src = chrome.runtime.getURL('icons/eye-on.svg'); + markReadImg.alt = 'Olvasott'; + markReadBtn.appendChild(markReadImg); + bulkActionsRight.appendChild(markReadBtn); + + const markUnreadBtn = document.createElement('button'); + markUnreadBtn.id = 'markUnreadBtn'; + markUnreadBtn.className = 'bulk-btn'; + markUnreadBtn.title = 'Olvasatlan'; + const markUnreadImg = document.createElement('img'); + markUnreadImg.src = chrome.runtime.getURL('icons/eye-off.svg'); + markUnreadImg.alt = 'Olvasatlan'; + markUnreadBtn.appendChild(markUnreadImg); + bulkActionsRight.appendChild(markUnreadBtn); + + const deleteBtn = document.createElement('button'); + deleteBtn.id = 'deleteBtn'; + deleteBtn.className = 'bulk-btn'; + deleteBtn.title = 'Törlés'; + const deleteImg = document.createElement('img'); + deleteImg.src = chrome.runtime.getURL('icons/trash.svg'); + deleteImg.alt = 'Törlés'; + deleteBtn.appendChild(deleteImg); + bulkActionsRight.appendChild(deleteBtn); + + const restoreBtn = document.createElement('button'); + restoreBtn.id = 'restoreBtn'; + restoreBtn.className = 'bulk-btn'; + restoreBtn.title = 'Visszaállítás'; + const restoreImg = document.createElement('img'); + restoreImg.src = chrome.runtime.getURL('icons/undo.svg'); + restoreImg.alt = 'Visszaállítás'; + restoreBtn.appendChild(restoreImg); + bulkActionsRight.appendChild(restoreBtn); + + bulk.appendChild(bulkActionsRight); container.appendChild(bulk); bulk.querySelector('#viewInboxBtn').addEventListener('click', () => switchView('inbox')); @@ -568,13 +752,13 @@ async function switchView(view) { async function transformMessagesPage() { try { await waitForTranslations(); - document.body.innerHTML = ''; + helper.clearElement(document.body); const kretaContainer = document.createElement('div'); kretaContainer.className = 'kreta-container'; const headerDiv = document.createElement('div'); - const parser = new DOMParser(); - const headerDoc = parser.parseFromString(await createTemplate.header(), 'text/html'); - const headerContent = headerDoc.body; + const template = document.createElement('template'); + template.innerHTML = await createTemplate.header(); + const headerContent = template.content; while (headerContent.firstChild) { headerDiv.appendChild(headerContent.firstChild); } diff --git a/profile/profile.js b/profile/profile.js index 6a79716..b976e42 100644 --- a/profile/profile.js +++ b/profile/profile.js @@ -30,7 +30,7 @@ const backButton = document.createElement('button'); backButton.id = 'firka-back-button'; - backButton.innerHTML = '← Vissza'; + backButton.textContent = '← Vissza'; backButton.style.cssText = ` position: static; margin: 20px; diff --git a/roleselect/roleselect.js b/roleselect/roleselect.js index 38a6508..2b7f5d3 100644 --- a/roleselect/roleselect.js +++ b/roleselect/roleselect.js @@ -154,15 +154,15 @@ if (userName) { await storageManager.set("userName", userName); } - document.body.innerHTML = ''; - const parser = new DOMParser(); - const doc = parser.parseFromString(createHTML( + helper.clearElement(document.body); + const template = document.createElement('template'); + template.innerHTML = createHTML( schoolCode, fullSchoolName, userName, settings, - ), 'text/html'); - const tempDiv = doc.body; + ); + const tempDiv = template.content; while (tempDiv.firstChild) { document.body.appendChild(tempDiv.firstChild); } diff --git a/settings/index.js b/settings/index.js index 4e5fa4b..71347e8 100644 --- a/settings/index.js +++ b/settings/index.js @@ -242,19 +242,30 @@ document.addEventListener("DOMContentLoaded", async () => { const settings = pageSettings[pageType] || []; if (settings.length === 0) { - container.innerHTML = ` -
- settings_suggest -

Ehhez az oldalhoz nincsenek egyéni beállítások.

-
- `; + helper.clearElement(container); + + const placeholder = document.createElement('div'); + placeholder.className = 'no-settings-placeholder'; + const icon = document.createElement('span'); + icon.className = 'material-icons-round'; + icon.textContent = 'settings_suggest'; + const text = document.createElement('p'); + text.setAttribute('data-i18n', 'settings.page_settings.no_settings'); + text.textContent = 'Ehhez az oldalhoz nincsenek egyéni beállítások.'; + placeholder.appendChild(icon); + placeholder.appendChild(text); + container.appendChild(placeholder); + if (window.LanguageManager) { window.LanguageManager.loadTranslationsForPage(); } return; } - container.innerHTML = settings.map(setting => renderSettingItem(setting)).join(""); + const template = document.createElement('template'); + template.innerHTML = settings.map(setting => renderSettingItem(setting)).join(""); + helper.clearElement(container); + container.appendChild(template.content); initSettingItems(container); if (window.LanguageManager) { @@ -362,14 +373,20 @@ document.addEventListener("DOMContentLoaded", async () => { if (!grid) return; if (customThemes.length === 0) { - grid.innerHTML = `
Még nincsenek egyéni témák
`; + helper.clearElement(grid); + const noThemes = document.createElement('div'); + noThemes.className = 'no-custom-themes'; + noThemes.setAttribute('data-i18n', 'settings.custom_themes.no_themes'); + noThemes.textContent = 'Még nincsenek egyéni témák'; + grid.appendChild(noThemes); if (window.LanguageManager) { window.LanguageManager.loadTranslationsForPage(); } return; } - grid.innerHTML = customThemes.map(theme => ` + const template = document.createElement('template'); + template.innerHTML = customThemes.map(theme => ` `).join(""); + + helper.clearElement(grid); + grid.appendChild(template.content); grid.querySelectorAll(".custom-theme-option").forEach(btn => { btn.addEventListener("click", (e) => { diff --git a/timetable/timetable.js b/timetable/timetable.js index 4dee498..bb5322a 100644 --- a/timetable/timetable.js +++ b/timetable/timetable.js @@ -197,8 +197,9 @@ } const htmlText = await response.text(); - const parser = new DOMParser(); - const doc = parser.parseFromString(htmlText, 'text/html'); + const template = document.createElement('template'); + template.innerHTML = htmlText; + const doc = template.content; const panelBody = doc.querySelector('.panel-body'); const panelFooter = doc.querySelector('.panel-footer'); const teacherInfo = doc.querySelector('.panel-heading'); @@ -887,18 +888,27 @@ detailsDiv.className = 'homework-details'; const contentP = document.createElement('p'); - contentP.innerHTML = `Feladat: ${homeworkDetails.content}`; + const contentStrong = document.createElement('strong'); + contentStrong.textContent = 'Feladat: '; + contentP.appendChild(contentStrong); + contentP.appendChild(document.createTextNode(homeworkDetails.content)); detailsDiv.appendChild(contentP); if (homeworkDetails.deadline) { const deadlineP = document.createElement('p'); - deadlineP.innerHTML = `Határidő: ${homeworkDetails.deadline}`; + const deadlineStrong = document.createElement('strong'); + deadlineStrong.textContent = 'Határidő: '; + deadlineP.appendChild(deadlineStrong); + deadlineP.appendChild(document.createTextNode(homeworkDetails.deadline)); detailsDiv.appendChild(deadlineP); } if (homeworkDetails.teacher) { const teacherP = document.createElement('p'); - teacherP.innerHTML = `Tanár: ${homeworkDetails.teacher}`; + const teacherStrong = document.createElement('strong'); + teacherStrong.textContent = 'Tanár: '; + teacherP.appendChild(teacherStrong); + teacherP.appendChild(document.createTextNode(homeworkDetails.teacher)); detailsDiv.appendChild(teacherP); } @@ -908,7 +918,9 @@ attachmentsDiv.style.marginTop = '1rem'; const attachmentsTitle = document.createElement('p'); - attachmentsTitle.innerHTML = 'Csatolmányok:'; + const attachStrong = document.createElement('strong'); + attachStrong.textContent = 'Csatolmányok:'; + attachmentsTitle.appendChild(attachStrong); attachmentsTitle.style.marginBottom = '0.5rem'; attachmentsDiv.appendChild(attachmentsTitle); @@ -1213,15 +1225,24 @@ detailsDiv.className = 'test-details'; const nameP = document.createElement('p'); - nameP.innerHTML = `Megnevezés: ${testDetails.name}`; + const nameStrong = document.createElement('strong'); + nameStrong.textContent = 'Megnevezés: '; + nameP.appendChild(nameStrong); + nameP.appendChild(document.createTextNode(testDetails.name)); detailsDiv.appendChild(nameP); const typeP = document.createElement('p'); - typeP.innerHTML = `Típus: ${testDetails.type}`; + const typeStrong = document.createElement('strong'); + typeStrong.textContent = 'Típus: '; + typeP.appendChild(typeStrong); + typeP.appendChild(document.createTextNode(testDetails.type)); detailsDiv.appendChild(typeP); const dateP = document.createElement('p'); - dateP.innerHTML = `Bejelentés dátuma: ${testDetails.announceDate}`; + const dateStrong = document.createElement('strong'); + dateStrong.textContent = 'Bejelentés dátuma: '; + dateP.appendChild(dateStrong); + dateP.appendChild(document.createTextNode(testDetails.announceDate)); detailsDiv.appendChild(dateP); testContent.appendChild(detailsDiv); @@ -1632,7 +1653,7 @@ modalContent.appendChild(header); modalContent.appendChild(body); - modal.innerHTML = ''; + helper.clearElement(modal); modal.appendChild(modalContent); document.body.appendChild(modal); @@ -1703,11 +1724,11 @@ if (timetableGrid) { const newContent = await generateTimeGrid(allLessons, weekDates); - timetableGrid.innerHTML = ''; + helper.clearElement(timetableGrid); - const parser1 = new DOMParser(); - const doc = parser1.parseFromString(`
${newContent}
`, 'text/html'); - const tempDiv = doc.querySelector('div'); + const template = document.createElement('template'); + template.innerHTML = `
${newContent}
`; + const tempDiv = template.content.querySelector('div'); while (tempDiv.firstChild) { timetableGrid.appendChild(tempDiv.firstChild); } @@ -2186,7 +2207,7 @@ } - modalGrid.innerHTML = ''; + helper.clearElement(modalGrid); allWeeks.forEach((week) => { const weekCell = document.createElement('div'); weekCell.className = `week-cell ${week.selected ? 'selected' : ''} ${week.selected ? 'current-week' : ''}`; @@ -2274,7 +2295,7 @@ const weekGrid = document.getElementById("week-grid"); if (weekGrid) { - weekGrid.innerHTML = ''; + helper.clearElement(weekGrid); newWeekOptions.forEach((opt) => { const weekCell = document.createElement('div'); weekCell.className = `week-cell ${opt.selected ? 'selected' : ''}`; @@ -2321,7 +2342,7 @@ }; - document.body.innerHTML = ''; + helper.clearElement(document.body); const kretaContainer = document.createElement('div'); @@ -2330,9 +2351,9 @@ const headerDiv = document.createElement('div'); - const parser2 = new DOMParser(); - const headerDoc = parser2.parseFromString(await createTemplate.header(), 'text/html'); - const headerContent = headerDoc.body; + const template = document.createElement('template'); + template.innerHTML = await createTemplate.header(); + const headerContent = template.content; while (headerContent.firstChild) { headerDiv.appendChild(headerContent.firstChild); } @@ -2480,9 +2501,9 @@ const gridContent = await generateTimeGrid(data.lessons, data.weekDates); - const parser3 = new DOMParser(); - const doc = parser3.parseFromString(`
${gridContent}
`, 'text/html'); - const tempDiv = doc.querySelector('div'); + const template3 = document.createElement('template'); + template3.innerHTML = `
${gridContent}
`; + const tempDiv = template3.content.querySelector('div'); while (tempDiv.firstChild) { timetableGrid.appendChild(tempDiv.firstChild); } @@ -2541,7 +2562,7 @@ } - weekDisplay.innerHTML = ''; + helper.clearElement(weekDisplay); visibleWeeks.forEach((weekNum, index) => { const isSelected = index === 2; const isCurrent = weekNum === currentWeekNumber; @@ -2637,12 +2658,12 @@ const timetableContainer = document.querySelector(".timetable-grid"); if (timetableContainer) { - timetableContainer.innerHTML = ''; + helper.clearElement(timetableContainer); const gridContent = await generateTimeGrid(lessons, weekDates); - const parser2 = new DOMParser(); - const doc = parser2.parseFromString(`
${gridContent}
`, 'text/html'); - const tempDiv = doc.querySelector('div'); + const template2 = document.createElement('template'); + template2.innerHTML = `
${gridContent}
`; + const tempDiv = template2.content.querySelector('div'); while (tempDiv.firstChild) { timetableContainer.appendChild(tempDiv.firstChild); } @@ -2670,7 +2691,7 @@ } - modalGrid.innerHTML = ''; + helper.clearElement(modalGrid); allWeeks.forEach((weekNumber) => { const isSelected = weekNumber === selectedWeekNumber; const isCurrent = weekNumber === currentWeekNumber; diff --git a/tools/helper.js b/tools/helper.js index 2b33dd9..190547d 100644 --- a/tools/helper.js +++ b/tools/helper.js @@ -37,4 +37,28 @@ const helper = { const [hours, minutes] = timeStr.split(":").map(Number); return hours * 60 + minutes; }, + + createElementFromHTML(htmlString) { + const template = document.createElement('template'); + template.innerHTML = htmlString.trim(); + return template.content; + }, + + setTextContent(element, text) { + element.textContent = text; + }, + + clearElement(element) { + while (element.firstChild) { + element.removeChild(element.firstChild); + } + }, + + appendChildren(parent, children) { + if (Array.isArray(children)) { + children.forEach(child => parent.appendChild(child)); + } else { + parent.appendChild(children); + } + } }; \ No newline at end of file