firefox addon store bullshit

This commit is contained in:
Zan
2025-12-10 15:51:37 +01:00
parent 75d6cc4676
commit f6a52b73de
15 changed files with 451 additions and 551 deletions

View File

@@ -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);
}

View File

@@ -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);
}

View File

@@ -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;
}

View File

@@ -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(`
<div class="forgot-container">
<link rel="preconnect" href="https://fonts.googleapis.com">
<link rel="preconnect" href="https://fonts.gstatic.com" crossorigin>
<link href="https://fonts.googleapis.com/css2?family=Montserrat:ital,wght@0,100..900;1,100..900&display=swap" rel="stylesheet">
<link href="https://fonts.googleapis.com/icon?family=Material+Icons+Round" rel="stylesheet">
<style>
.g-recaptcha {
margin-top: 5px;
display: flex;
justify-content: center;
}
</style>
<div class="forgot-card">
<header class="forgot-header">
<p class="logo-text">
<img src="${chrome.runtime.getURL("images/firka_logo.png")}" alt="Firka" class="logo">
Firka
</p>
</header>
<h1 class="forgot-title" data-i18n="forgotpassword.title">Elfelejtett jelszó</h1>
<form id="forgotForm" novalidate>
<div class="form-group">
<label class="form-label" for="BejelentkezesiNev" data-i18n="forgotpassword.om_id_label">OM azonosító</label>
<input type="text" id="BejelentkezesiNev" name="BejelentkezesiNev" class="form-control"
data-i18n-attr="placeholder" data-i18n="forgotpassword.om_id_placeholder"
placeholder="Adja meg az OM azonosítóját" required>
<div class="error-message" data-i18n="forgotpassword.om_id_required">Az OM azonosító megadása kötelező</div>
</div>
<div class="form-group">
<label class="form-label" for="EmailCim" data-i18n="forgotpassword.email_label">E-mail cím</label>
<input type="email" id="EmailCim" name="EmailCim" class="form-control"
data-i18n-attr="placeholder" data-i18n="forgotpassword.email_placeholder"
placeholder="Adja meg az e-mail címét" required>
<div class="error-message" data-i18n="forgotpassword.email_required">Az e-mail cím megadása kötelező</div>
</div>
<!-- reCAPTCHA container removed for security compliance -->
<div class="form-actions">
<a href="/Adminisztracio/Login" class="help-link" data-i18n="forgotpassword.back_to_login">
Vissza a bejelentkezéshez
</a>
<button type="submit" class="btn-submit" data-i18n="forgotpassword.reset_button">
Jelszó visszaállítása
</button>
</div>
</form>
</div>
</div>
`, '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);
}
})();

View File

@@ -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");

View File

@@ -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();

View File

@@ -120,13 +120,11 @@ async function transformLoginPage() {
</div>
`;
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) {

View File

@@ -83,13 +83,12 @@ async function transformTwoFactorPage() {
</div>
`;
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');

View File

@@ -34,10 +34,10 @@
</footer>
</div>
`;
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);
}

View File

@@ -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 = `
<div class="modal-header">
<h2>Üzenet részletei</h2>
<button class="modal-close">×</button>
</div>
<div class="modal-body">
<div class="loading-content">
<div class="loading-spinner"></div>
<p>Üzenet betöltése...</p>
</div>
</div>
`;
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 = `
<div class="error-content">
<h3>Hiba történt</h3>
<p>Az üzenet betöltése sikertelen.</p>
<button class="retry-btn" onclick="openMessageModal(${messageId})">Újrapróbálás</button>
</div>
`;
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 = `
<div class="message-details">
<div class="message-info">
<div class="info-row">
<span class="info-label">Feladó:</span>
<span class="info-value">${sanitizeHTML(sender)}</span>
</div>
<div class="info-row">
<span class="info-label">Dátum:</span>
<span class="info-value">${date}</span>
</div>
<div class="info-row">
<span class="info-label">Tárgy:</span>
<span class="info-value">${sanitizeHTML(subject)}</span>
</div>
</div>
<div class="message-content">
<h4>Üzenet tartalma:</h4>
<div class="message-text">${content}</div>
</div>
${message.csatolmanyok && message.csatolmanyok.length > 0 ? `
<div class="message-attachments">
<h4>Mellékletek:</h4>
<ul>
${message.csatolmanyok.map(attachment => `
<li><a href="#" onclick="downloadAttachment('${attachment.azonosito}')">${sanitizeHTML(attachment.nev)}</a></li>
`).join('')}
</ul>
</div>
` : ''}
</div>
`;
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 = `
<div class="loading-content">
<div class="loading-spinner"></div>
<p>${LanguageManager.t('messages.loading', 'Üzenetek betöltése...')}</p>
</div>
`;
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 = `
<div class="error-content">
<h3>${LanguageManager.t('messages.error.title', 'Hiba történt')}</h3>
<p>${LanguageManager.t('messages.error.description', 'Az üzenetek betöltése sikertelen volt.')}</p>
<button class="retry-btn">${LanguageManager.t('messages.error.retry', 'Újrapróbálás')}</button>
</div>
`;
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 = `
<div class="empty-content">
<h3>${LanguageManager.t('messages.empty.title', 'Nincsenek üzenetek')}</h3>
<p>${LanguageManager.t('messages.empty.description', 'Jelenleg nincsenek elérhető üzenetek.')}</p>
</div>
`;
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 = `
<div class="message-card-header">
<div class="sender-info">
<span class="sender-name">${sanitizeHTML(senderName)}</span>
${!message.isElolvasva ? '<span class="unread-indicator"></span>' : ''}
</div>
<div class="message-date">${date}</div>
</div>
<div class="message-subject">${sanitizeHTML(subject)}</div>
${hasAttachment ? '<div class="attachment-indicator">📎</div>' : ''}
`;
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 = `
<div class="bulk-actions-left">
<div class="view-toggle">
<button id="viewInboxBtn" class="${currentView==='inbox'?'active':''}" title="Beérkezett">
<img src="${chrome.runtime.getURL('icons/messages-active.svg')}" alt="Beérkezett">
</button>
<button id="viewTrashBtn" class="${currentView==='trash'?'active':''}" title="Törölt">
<img src="${chrome.runtime.getURL('icons/delete.svg')}" alt="Törölt">
</button>
</div>
<button id="toggleSelectionModeBtn" class="bulk-btn" title="Kijelölés mód">
<img src="${chrome.runtime.getURL('icons/select.svg')}" alt="Kijelölés mód">
</button>
<button id="selectAllBtn" class="bulk-btn" title="Mind kijelöl">
<img src="${chrome.runtime.getURL('icons/select-all.svg')}" alt="Mind kijelöl">
</button>
<button id="clearSelectionBtn" class="bulk-btn" title="Kijelölés törlése">
<img src="${chrome.runtime.getURL('icons/select-none.svg')}" alt="Kijelölés törlése">
</button>
</div>
<div class="bulk-actions-right">
<button id="markReadBtn" class="bulk-btn" title="Olvasott">
<img src="${chrome.runtime.getURL('icons/eye-on.svg')}" alt="Olvasott">
</button>
<button id="markUnreadBtn" class="bulk-btn" title="Olvasatlan">
<img src="${chrome.runtime.getURL('icons/eye-off.svg')}" alt="Olvasatlan">
</button>
<button id="deleteBtn" class="bulk-btn" title="Törlés">
<img src="${chrome.runtime.getURL('icons/trash.svg')}" alt="Törlés">
</button>
<button id="restoreBtn" class="bulk-btn" title="Visszaállítás">
<img src="${chrome.runtime.getURL('icons/undo.svg')}" alt="Visszaállítás">
</button>
</div>
`;
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);
}

View File

@@ -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;

View File

@@ -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);
}

View File

@@ -242,19 +242,30 @@ document.addEventListener("DOMContentLoaded", async () => {
const settings = pageSettings[pageType] || [];
if (settings.length === 0) {
container.innerHTML = `
<div class="no-settings-placeholder">
<span class="material-icons-round">settings_suggest</span>
<p data-i18n="settings.page_settings.no_settings">Ehhez az oldalhoz nincsenek egyéni beállítások.</p>
</div>
`;
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 = `<div class="no-custom-themes" data-i18n="settings.custom_themes.no_themes">Még nincsenek egyéni témák</div>`;
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 => `
<button class="theme-option custom-theme-option" data-theme="custom-${theme.id}">
<div class="theme-preview" style="background: ${theme.colors.background};">
<div class="preview-header" style="background: ${theme.colors.card};"></div>
@@ -393,6 +410,9 @@ document.addEventListener("DOMContentLoaded", async () => {
</div>
</button>
`).join("");
helper.clearElement(grid);
grid.appendChild(template.content);
grid.querySelectorAll(".custom-theme-option").forEach(btn => {
btn.addEventListener("click", (e) => {

View File

@@ -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 = `<strong>Feladat:</strong> ${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 = `<strong>Határidő:</strong> ${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 = `<strong>Tanár:</strong> ${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 = '<strong>Csatolmányok:</strong>';
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 = `<strong>Megnevezés:</strong> ${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 = `<strong>Típus:</strong> ${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 = `<strong>Bejelentés dátuma:</strong> ${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(`<div>${newContent}</div>`, 'text/html');
const tempDiv = doc.querySelector('div');
const template = document.createElement('template');
template.innerHTML = `<div>${newContent}</div>`;
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(`<div>${gridContent}</div>`, 'text/html');
const tempDiv = doc.querySelector('div');
const template3 = document.createElement('template');
template3.innerHTML = `<div>${gridContent}</div>`;
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(`<div>${gridContent}</div>`, 'text/html');
const tempDiv = doc.querySelector('div');
const template2 = document.createElement('template');
template2.innerHTML = `<div>${gridContent}</div>`;
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;

View File

@@ -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);
}
}
};