`;
}).join('');
preview.querySelectorAll('[data-remove-upload]').forEach(btn => {
btn.addEventListener('click', function(){
const index = parseInt(this.dataset.removeUpload, 10);
const files = getInputFiles(input).slice();
files.splice(index, 1);
setInputFiles(input, files);
renderPreview(preview, input);
});
});
preview.querySelectorAll('[data-move-upload]').forEach(btn => {
btn.addEventListener('click', function(){
const dir = this.dataset.moveUpload;
const index = parseInt(this.dataset.index, 10);
const target = dir === 'up' ? index - 1 : index + 1;
const files = moveItem(getInputFiles(input), index, target);
setInputFiles(input, files);
renderPreview(preview, input);
});
});
if (isGallery) {
let dragIndex = null;
preview.querySelectorAll('.ld-upload-file[draggable="true"]').forEach(item => {
item.addEventListener('dragstart', function(){
dragIndex = parseInt(this.dataset.index, 10);
});
item.addEventListener('dragover', function(e){
e.preventDefault();
});
item.addEventListener('drop', function(e){
e.preventDefault();
const dropIndex = parseInt(this.dataset.index, 10);
if (dragIndex === null || dragIndex === dropIndex) return;
const files = moveItem(getInputFiles(input), dragIndex, dropIndex);
setInputFiles(input, files);
renderPreview(preview, input);
});
});
}
}
zones.forEach(zone => {
const targetId = zone.dataset.target || '';
const input = targetId ? form.querySelector('#' + targetId) : null;
const preview = targetId ? form.querySelector('[data-preview-for="' + targetId + '"]') : null;
const multiple = !!(input && input.hasAttribute('multiple'));
const maxFiles = parseInt(zone.dataset.max || (multiple ? '10' : '1'), 10);
if (!input) return;
setInputFiles(input, Array.from(input.files || []));
function refresh() {
const files = getInputFiles(input);
renderPreview(preview, input);
zone.classList.toggle('is-filled', files.length > 0);
}
function setFiles(newFiles, merge = false) {
let files = Array.from(newFiles || []);
if (multiple && merge) {
files = getInputFiles(input).concat(files);
}
files = uniqueFiles(files);
files = multiple ? files.slice(0, maxFiles) : files.slice(0, 1);
setInputFiles(input, files);
refresh();
}
zone.addEventListener('click', function(e){
if (e.target === input) return;
input.click();
});
input.addEventListener('change', function(){
setInputFiles(input, Array.from(input.files || []));
refresh();
});
['dragenter', 'dragover'].forEach(evt => {
zone.addEventListener(evt, function(e){
e.preventDefault();
e.stopPropagation();
zone.classList.add('is-dragover');
});
});
['dragleave', 'dragend', 'drop'].forEach(evt => {
zone.addEventListener(evt, function(e){
e.preventDefault();
e.stopPropagation();
zone.classList.remove('is-dragover');
});
});
zone.addEventListener('drop', function(e){
const files = e.dataTransfer && e.dataTransfer.files ? e.dataTransfer.files : [];
if (!files.length) return;
setFiles(files, multiple);
});
refresh();
});
form.querySelectorAll('[data-existing-toggle]').forEach(btn => {
btn.addEventListener('click', function(){
const inputSelector = this.dataset.existingToggle;
const targetInput = inputSelector ? form.querySelector(inputSelector) : null;
const wrapper = this.closest('.ld-existing-media-item');
if (!targetInput) return;
const willRemove = targetInput.value !== '1';
targetInput.value = willRemove ? '1' : '0';
if (wrapper) {
wrapper.classList.toggle('is-removed', willRemove);
}
this.textContent = willRemove
? (this.dataset.restoreLabel || 'Przywróć')
: (this.dataset.removeLabel || 'Usuń');
});
});
form.querySelectorAll('.ld-existing-gallery').forEach(gallery => {
const orderInputSelector = gallery.dataset.orderInput || '';
const orderInput = orderInputSelector ? form.querySelector(orderInputSelector) : null;
function syncExistingOrder() {
if (!orderInput) return;
const ids = Array.from(
gallery.querySelectorAll('.ld-existing-gallery-item:not(.is-removed)')
).map(item => item.dataset.id);
orderInput.value = ids.join(',');
}
function moveExisting(item, direction) {
if (!item || item.classList.contains('is-removed')) return;
let sibling = direction === 'up' ? item.previousElementSibling : item.nextElementSibling;
while (sibling && sibling.classList.contains('is-removed')) {
sibling = direction === 'up' ? sibling.previousElementSibling : sibling.nextElementSibling;
}
if (!sibling) return;
if (direction === 'up') {
gallery.insertBefore(item, sibling);
} else {
gallery.insertBefore(sibling, item);
}
syncExistingOrder();
}
let dragItem = null;
gallery.querySelectorAll('.ld-existing-gallery-item').forEach(item => {
item.addEventListener('dragstart', function(){
if (this.classList.contains('is-removed')) return;
dragItem = this;
});
item.addEventListener('dragover', function(e){
e.preventDefault();
});
item.addEventListener('drop', function(e){
e.preventDefault();
if (!dragItem || dragItem === this || this.classList.contains('is-removed')) return;
const rect = this.getBoundingClientRect();
const before = (e.clientY - rect.top) {
btn.addEventListener('click', function(){
const item = this.closest('.ld-existing-gallery-item');
if (!item) return;
const willRemove = !item.classList.contains('is-removed');
item.classList.toggle('is-removed', willRemove);
this.textContent = willRemove ? 'Przywróć' : 'Usuń';
syncExistingOrder();
});
});
gallery.querySelectorAll('[data-move-existing]').forEach(btn => {
btn.addEventListener('click', function(){
const item = this.closest('.ld-existing-gallery-item');
if (!item) return;
moveExisting(item, this.dataset.moveExisting);
});
});
syncExistingOrder();
});
function dynlistRowHtml(name, value) {
return `
`;
}
form.querySelectorAll('[data-dynlist]').forEach(list => {
const items = list.querySelector('[data-dynlist-items]');
const addBtn = list.querySelector('[data-dynlist-add]');
const name = list.dataset.name || 'ld_offer_points[]';
if (!items) return;
function rows() {
return Array.from(items.querySelectorAll('[data-dynlist-row]'));
}
function ensureRow() {
if (!rows().length) {
items.insertAdjacentHTML('beforeend', dynlistRowHtml(name, ''));
}
}
function refresh() {
const currentRows = rows();
currentRows.forEach((row, index) => {
const upBtn = row.querySelector('[data-dynlist-action="up"]');
const downBtn = row.querySelector('[data-dynlist-action="down"]');
if (upBtn) upBtn.disabled = index === 0;
if (downBtn) downBtn.disabled = index === currentRows.length - 1;
});
}
if (addBtn) {
addBtn.addEventListener('click', function(){
items.insertAdjacentHTML('beforeend', dynlistRowHtml(name, ''));
refresh();
const currentRows = rows();
const lastInput = currentRows.length ? currentRows[currentRows.length - 1].querySelector('input') : null;
if (lastInput) {
lastInput.focus();
}
});
}
items.addEventListener('click', function(e){
const btn = e.target.closest('[data-dynlist-action]');
if (!btn) return;
const row = btn.closest('[data-dynlist-row]');
if (!row) return;
const action = btn.dataset.dynlistAction;
const currentRows = rows();
const index = currentRows.indexOf(row);
if (action === 'remove') {
if (currentRows.length 0) {
items.insertBefore(row, currentRows[index - 1]);
refresh();
return;
}
if (action === 'down' && index >= 0 && index {
defaultSubmitLabels.set(
btn,
btn.tagName === 'INPUT' ? btn.value : btn.textContent
);
btn.addEventListener('click', function(){
clickedSubmit = btn;
});
});
function setButtonLabel(btn, label) {
if (!btn) return;
if (btn.tagName === 'INPUT') {
btn.value = label;
} else {
btn.textContent = label;
}
}
function setSavingState(isSaving, activeBtn) {
submitBtns.forEach(btn => {
btn.disabled = isSaving;
if (isSaving && btn === activeBtn) {
setButtonLabel(btn, 'Zapisywanie...');
}
if (!isSaving) {
setButtonLabel(btn, defaultSubmitLabels.get(btn) || 'Zapisz zmiany');
}
});
}
function clearToastTimers() {
if (toastHideTimer) window.clearTimeout(toastHideTimer);
if (toastReloadTimer) window.clearTimeout(toastReloadTimer);
toastHideTimer = null;
toastReloadTimer = null;
}
function showSaveToast(message, redirectUrl = '') {
if (!saveToast) {
alert(message);
if (redirectUrl) {
window.location.href = redirectUrl;
} else {
window.location.reload();
}
return;
}
clearToastTimers();
if (saveMsg) {
saveMsg.textContent = message;
}
saveToast.classList.remove('is-leaving');
saveToast.classList.add('is-mounted');
window.requestAnimationFrame(function(){
saveToast.classList.add('is-visible');
});
toastHideTimer = window.setTimeout(function(){
saveToast.classList.add('is-leaving');
saveToast.classList.remove('is-visible');
}, 1850);
toastReloadTimer = window.setTimeout(function(){
if (redirectUrl) {
window.location.href = redirectUrl;
} else {
window.location.reload();
}
}, 2450);
}
form.addEventListener('submit', async function(e){
e.preventDefault();
const submitter = e.submitter && submitBtns.includes(e.submitter)
? e.submitter
: (clickedSubmit || submitBtns[0] || null);
const afterSave = submitter ? (submitter.dataset.afterSave || 'reload') : 'reload';
if (!ajaxUrl || !pid || !token) {
alert('Brak danych do zapisu AJAX.');
return;
}
if (form.dataset.ldSaving === '1') return;
form.dataset.ldSaving = '1';
setSavingState(true, submitter);
try {
const fd = new FormData(form);
fd.set('action', 'ld_frontend_edit');
fd.set('pid', pid);
fd.set('token', token);
const response = await fetch(ajaxUrl, {
method: 'POST',
body: fd,
credentials: 'same-origin',
headers: {
'X-Requested-With': 'XMLHttpRequest'
}
});
const raw = await response.text();
let json = null;
try {
json = JSON.parse(raw);
} catch (parseErr) {
throw new Error(
raw && raw.trim()
? raw.replace(/]*>/g, ' ').trim().slice(0, 300)
: 'Wystąpił błąd podczas zapisu.'
);
}
if (!json || typeof json.success === 'undefined') {
throw new Error('Nieprawidłowa odpowiedź serwera.');
}
if (!json.success) {
throw new Error(
(json.data && json.data.message)
? json.data.message
: 'Nie udało się zapisać zmian.'
);
}
const message = (json.data && json.data.message)
? json.data.message
: 'Zapisano. Zmiany trafiły do moderacji.';
const serverRedirectUrl = (json.data && json.data.redirect_url)
? json.data.redirect_url
: '';
const redirectUrl = afterSave === 'view'
? (serverRedirectUrl || previewUrl)
: '';
showSaveToast(message, redirectUrl);
} catch (err) {
alert(err && err.message ? err.message : 'Wystąpił błąd podczas zapisu.');
} finally {
form.dataset.ldSaving = '0';
setSavingState(false, submitter);
clickedSubmit = null;
}
});
if (deleteBtn) {
const defaultDeleteLabel = deleteBtn.textContent || 'Usuń profil';
deleteBtn.addEventListener('click', async function(){
if (!ajaxUrl || !pid || !token) {
alert('Brak danych do usunięcia wpisu.');
return;
}
if (form.dataset.ldDeleting === '1') return;
const confirmed = window.confirm('Czy na pewno chcesz usunąć ten profil? Tej operacji nie można łatwo cofnąć.');
if (!confirmed) return;
form.dataset.ldDeleting = '1';
deleteBtn.disabled = true;
deleteBtn.textContent = 'Usuwanie...';
try {
const fd = new FormData();
fd.set('action', 'ld_frontend_delete');
fd.set('pid', pid);
fd.set('token', token);
const nonceInput = form.querySelector('input[name="ld_nonce"]');
if (nonceInput && nonceInput.value) {
fd.set('ld_nonce', nonceInput.value);
}
const response = await fetch(ajaxUrl, {
method: 'POST',
body: fd,
credentials: 'same-origin',
headers: {
'X-Requested-With': 'XMLHttpRequest'
}
});
const raw = await response.text();
let json = null;
try {
json = JSON.parse(raw);
} catch (parseErr) {
throw new Error(
raw && raw.trim()
? raw.replace(/]*>/g, ' ').trim().slice(0, 300)
: 'Wystąpił błąd podczas usuwania profilu.'
);
}
if (!json || typeof json.success === 'undefined') {
throw new Error('Nieprawidłowa odpowiedź serwera.');
}
if (!json.success) {
throw new Error(
(json.data && json.data.message)
? json.data.message
: 'Nie udało się usunąć profilu.'
);
}
const message = (json.data && json.data.message)
? json.data.message
: 'Profil został usunięty.';
const redirectUrl = (json.data && json.data.redirect_url)
? json.data.redirect_url
: window.location.origin;
showSaveToast(message, redirectUrl);
} catch (err) {
alert(err && err.message ? err.message : 'Wystąpił błąd podczas usuwania profilu.');
deleteBtn.disabled = false;
deleteBtn.textContent = defaultDeleteLabel;
} finally {
form.dataset.ldDeleting = '0';
}
});
}
}
})();