2206
редагувань
Admin (обговорення | внесок) (Back-лінк: над титульним блоком окремим рядком) |
Admin (обговорення | внесок) (Віджет «Повідомити про правку» (krai-feedback)) |
||
| Рядок 358: | Рядок 358: | ||
}); | }); | ||
}); | }); | ||
/* === Країнопедія: віджет «Повідомити про правку» (krai-feedback) === */ | |||
mw.loader.using(["mediawiki.util"], function () { | |||
$(function () { | |||
if (mw.config.get("wgNamespaceNumber") !== 0) return; // тільки статті | |||
if (mw.config.get("wgAction") !== "view") return; // тільки читання | |||
if (document.getElementById("krai-fb-btn")) return; | |||
var ENDPOINT = "/feedback.php"; | |||
var loadedAt = Math.floor(Date.now() / 1000); // ts фіксуємо на завантаженні (>3с завжди) | |||
var overlay = null; | |||
var btn = document.createElement("button"); | |||
btn.id = "krai-fb-btn"; | |||
btn.type = "button"; | |||
btn.className = "krai-fb-btn"; | |||
btn.textContent = "✏️ Повідомити про правку"; | |||
document.body.appendChild(btn); | |||
function buildModal() { | |||
overlay = document.createElement("div"); | |||
overlay.className = "krai-fb-overlay"; | |||
overlay.innerHTML = | |||
'<div class="krai-fb-modal" role="dialog" aria-modal="true" aria-labelledby="krai-fb-title">' + | |||
'<button type="button" class="krai-fb-close" aria-label="Закрити">×</button>' + | |||
'<h2 id="krai-fb-title" class="krai-fb-title">Повідомити про правку</h2>' + | |||
'<p class="krai-fb-sub">Помітили неточність або застарілі дані? Напишіть — ми перевіримо й оновимо. Дякуємо 💛</p>' + | |||
'<form class="krai-fb-form">' + | |||
'<div class="krai-fb-row krai-fb-kind">' + | |||
'<label><input type="radio" name="kind" value="fix" checked> Виправлення</label>' + | |||
'<label><input type="radio" name="kind" value="doubt"> Маю сумнів</label>' + | |||
'</div>' + | |||
'<label class="krai-fb-label">Цитата / фрагмент <span>(необов’язково)</span>' + | |||
'<textarea name="fragment" rows="2" placeholder="Місце, якого стосується правка"></textarea>' + | |||
'</label>' + | |||
'<label class="krai-fb-label">Що не так або що виправити?' + | |||
'<textarea name="comment" rows="4" placeholder="Опишіть коротко"></textarea>' + | |||
'</label>' + | |||
'<label class="krai-fb-label">Контакт <span>(необов’язково, якщо треба відповідь)</span>' + | |||
'<input type="text" name="contact" placeholder="Email або @Telegram"></label>' + | |||
'<input type="text" name="website" class="krai-fb-hp" tabindex="-1" autocomplete="off" aria-hidden="true">' + | |||
'<div class="krai-fb-actions">' + | |||
'<button type="button" class="krai-fb-cancel">Скасувати</button>' + | |||
'<button type="submit" class="krai-fb-submit">Надіслати</button>' + | |||
'</div>' + | |||
'<div class="krai-fb-msg" aria-live="polite"></div>' + | |||
'</form>' + | |||
'</div>'; | |||
document.body.appendChild(overlay); | |||
overlay.addEventListener("click", function (e) { if (e.target === overlay) closeModal(); }); | |||
overlay.querySelector(".krai-fb-close").addEventListener("click", closeModal); | |||
overlay.querySelector(".krai-fb-cancel").addEventListener("click", closeModal); | |||
overlay.querySelector(".krai-fb-form").addEventListener("submit", onSubmit); | |||
} | |||
function openModal() { | |||
if (!overlay) buildModal(); | |||
var sel = ((window.getSelection && window.getSelection().toString()) || "").trim(); | |||
if (sel) { | |||
var f = overlay.querySelector('textarea[name="fragment"]'); | |||
if (f && !f.value) f.value = sel.slice(0, 1000); | |||
} | |||
overlay.classList.add("is-open"); | |||
document.addEventListener("keydown", onEsc); | |||
var c = overlay.querySelector('textarea[name="comment"]'); | |||
if (c) c.focus(); | |||
} | |||
function closeModal() { | |||
if (overlay) overlay.classList.remove("is-open"); | |||
document.removeEventListener("keydown", onEsc); | |||
} | |||
function onEsc(e) { if (e.key === "Escape") closeModal(); } | |||
function onSubmit(e) { | |||
e.preventDefault(); | |||
var form = e.target; | |||
var msg = form.querySelector(".krai-fb-msg"); | |||
var comment = form.comment.value.trim(); | |||
var fragment = form.fragment.value.trim(); | |||
if (comment.length < 5 && !fragment) { | |||
msg.className = "krai-fb-msg is-err"; | |||
msg.textContent = "Напишіть, будь ласка, кілька слів про правку."; | |||
return; | |||
} | |||
var submitBtn = form.querySelector(".krai-fb-submit"); | |||
submitBtn.disabled = true; | |||
msg.className = "krai-fb-msg"; | |||
msg.textContent = "Надсилаю…"; | |||
var data = new FormData(); | |||
data.append("page", mw.config.get("wgPageName") || ""); | |||
data.append("url", location.href); | |||
data.append("kind", (form.kind.value === "doubt") ? "doubt" : "fix"); | |||
data.append("fragment", fragment); | |||
data.append("comment", comment); | |||
data.append("contact", form.contact.value.trim()); | |||
data.append("website", form.website.value); | |||
data.append("ts", String(loadedAt)); | |||
fetch(ENDPOINT, { method: "POST", body: data, credentials: "same-origin" }) | |||
.then(function (r) { return r.json().catch(function () { return { ok: r.ok }; }); }) | |||
.then(function (res) { | |||
if (res && res.ok) { | |||
form.reset(); | |||
msg.className = "krai-fb-msg is-ok"; | |||
msg.textContent = "Дякуємо! Ми перевіримо й оновимо. 💛"; | |||
setTimeout(closeModal, 1800); | |||
} else { | |||
throw new Error((res && res.error) || "err"); | |||
} | |||
}) | |||
.catch(function () { | |||
msg.className = "krai-fb-msg is-err"; | |||
msg.textContent = "Не вдалося надіслати. Спробуйте ще раз трохи згодом."; | |||
}) | |||
.then(function () { submitBtn.disabled = false; }); | |||
} | |||
btn.addEventListener("click", openModal); | |||
}); | |||
}); | |||
/* === /krai-feedback === */ | |||