|
| 1 | +document.addEventListener("DOMContentLoaded", () => { |
| 2 | + const maps = Joomla.getOptions("plgOgMappings", {}); |
| 3 | + |
| 4 | + const selectorFor = (token) => { |
| 5 | + if (token.startsWith("field.")) { |
| 6 | + const n = CSS.escape(token.slice(6)); |
| 7 | + return `[name="jform[com_fields][${n}]"]`; |
| 8 | + } |
| 9 | + if (token.startsWith("image_")) { |
| 10 | + return `[name="jform[images][${CSS.escape(token)}]"]`; |
| 11 | + } |
| 12 | + return `[name="jform[${CSS.escape(token)}]"]`; |
| 13 | + }; |
| 14 | + |
| 15 | + function getSourceName(token) { |
| 16 | + if (token.startsWith("field.")) { |
| 17 | + const fieldKey = token.slice(6).replace(/_/g, " "); |
| 18 | + return `Custom Field: ${fieldKey}`; |
| 19 | + } |
| 20 | + |
| 21 | + const mapCoreNames = { |
| 22 | + title: "Title", |
| 23 | + alias: "Alias", |
| 24 | + metadesc: "Meta Description", |
| 25 | + metakey: "Meta Keywords", |
| 26 | + articletext: "Article Text", |
| 27 | + image_intro: "Intro Image", |
| 28 | + image_intro_alt: "Intro Image Alt", |
| 29 | + image_fulltext: "Fulltext Image", |
| 30 | + image_fulltext_alt: "Fulltext Image Alt", |
| 31 | + created_by_alias: "Author Alias", |
| 32 | + }; |
| 33 | + |
| 34 | + return mapCoreNames[token] || token; |
| 35 | + } |
| 36 | + |
| 37 | + function sanitizeText(input, maxLen = 60) { |
| 38 | + if (typeof input !== "string" || !input.trim()) return ""; |
| 39 | + |
| 40 | + // Remove HTML tags manually (just in case innerText fails) |
| 41 | + const noTags = input.replace(/<[^>]*>/g, " "); |
| 42 | + |
| 43 | + // Decode HTML entities using a temporary div |
| 44 | + const tempDiv = document.createElement("div"); |
| 45 | + tempDiv.innerHTML = noTags; |
| 46 | + const decoded = tempDiv.textContent || tempDiv.innerText || ""; |
| 47 | + |
| 48 | + // Normalize whitespace |
| 49 | + const cleaned = decoded.replace(/\s+/g, " ").trim(); |
| 50 | + |
| 51 | + // Truncate with word boundary safety |
| 52 | + if (cleaned.length <= maxLen) return cleaned; |
| 53 | + |
| 54 | + const cut = cleaned.lastIndexOf(" ", maxLen - 1); |
| 55 | + const safeCut = cut > maxLen * 0.6 ? cut : maxLen - 1; |
| 56 | + return cleaned.slice(0, safeCut).replace(/[.,;:\-\s]+$/, "") + "…"; |
| 57 | + } |
| 58 | + |
| 59 | + const maxLen = { |
| 60 | + og_title: Number(maps.maxTitleLen) || 60, |
| 61 | + og_description: Number(maps.maxDescLen) || 160, |
| 62 | + og_image_alt: Number(maps.maxAltLen) || 125, |
| 63 | + }; |
| 64 | + |
| 65 | + Object.entries(maps).forEach(([ogKey, token]) => { |
| 66 | + const ogInput = document.getElementById(`jform_attribs_${ogKey}`); |
| 67 | + const srcInput = document.querySelector(selectorFor(token)); |
| 68 | + |
| 69 | + if (!ogInput || !srcInput) return; |
| 70 | + |
| 71 | + const originalPh = ogInput.placeholder; |
| 72 | + const inherited = Joomla.Text._("PLG_SYSTEM_OPENGRAPH_INHERITED"); |
| 73 | + const paint = () => { |
| 74 | + if (ogInput.value.trim()) return; // user override |
| 75 | + let v = srcInput.value.trim(); |
| 76 | + |
| 77 | + if (ogKey !== "og_image") { |
| 78 | + v = sanitizeText(v, maxLen[ogKey]); |
| 79 | + } |
| 80 | + const sourceLabel = getSourceName(token); |
| 81 | + ogInput.placeholder = v |
| 82 | + ? `${v} — ${inherited} from ${sourceLabel}` |
| 83 | + : originalPh; |
| 84 | + }; |
| 85 | + |
| 86 | + paint(); // initial |
| 87 | + srcInput.addEventListener("input", paint); |
| 88 | + |
| 89 | + ogInput.addEventListener("input", () => { |
| 90 | + ogInput.placeholder = originalPh; // detach |
| 91 | + srcInput.removeEventListener("input", paint); |
| 92 | + }); |
| 93 | + }); |
| 94 | +}); |
0 commit comments