MediaWiki:Common.js: Difference between revisions
mNo edit summary Tag: Reverted |
No edit summary |
||
| (51 intermediate revisions by 3 users not shown) | |||
| Line 1: | Line 1: | ||
/* Any JavaScript here will be loaded for all users on every page load. */ | /* Any JavaScript here will be loaded for all users on every page load. */ | ||
// stolen from Lajos Mészáros on this post https://stackoverflow.com/questions/13358292/capture-tap-event-with-pure-javascript | |||
const onClickOrTap = (element, handler) => { | |||
let touchMoveHappened = false; | |||
element.addEventListener('touchstart', () => { | |||
// on mobile this is the 1st event that happens | |||
touchMoveHappened = false; | |||
}); | |||
element.addEventListener('touchmove', () => { | |||
// on mobile this might get triggered in which case the | |||
// click or tap will get cancelled | |||
// we'll keep a track of it | |||
touchMoveHappened = true; | |||
}); | |||
element.addEventListener('touchend', (e) => { | |||
// happens after touchstart, but before click | |||
// if touch happened then we'll exit | |||
if (touchMoveHappened) { | |||
return; | |||
} | |||
// calling preventDefault() will make sure the | |||
// subsequent click will not get triggered | |||
e.preventDefault(); | |||
// at this point we are ready to call our original handler | |||
handler(e); | |||
}); | |||
element.addEventListener('click', (e) => { | |||
// this will only get triggered on desktopg | |||
// because we call preventDefault for the "touchend" event | |||
handler(e); | |||
}); | |||
} | |||
/* | /* Create Page */ | ||
const createPageTargetIdDataSetString = "[data-create-page-target-id]"; | |||
if (document.querySelector(createPageTargetIdDataSetString)) { | |||
/** | |||
* @type {HTMLElement[]} | |||
*/ | |||
let itemsCreateInputPageGrid = []; | |||
let itemsCreatePageGrid = []; | |||
const createPageTargetId = "createPageTargetId"; | |||
const createPageInputHiddenClass = "hidden"; | |||
const createPageInputActiveClass = "pageInputActive"; | |||
/* | /** | ||
* @param {HTMLElement} element | |||
*/ | |||
function getGridTarget(element) { | |||
const targetId = element.dataset[createPageTargetId]; | |||
document.getElementById( | return document.getElementById(targetId); | ||
} | |||
/** | |||
* @this {HTMLDivElement} | |||
document. | */ | ||
function toggleGridTarget(element, targetElement) { | |||
for (let index = 0; index < itemsCreateInputPageGrid.length; index += 1) { | |||
const target = itemsCreateInputPageGrid[index]; | |||
target.classList.add(createPageInputHiddenClass); | |||
if (target === targetElement) { | |||
target.classList.remove(createPageInputHiddenClass); | |||
} | |||
const clickedElement = itemsCreatePageGrid[index]; | |||
clickedElement.classList.remove(createPageInputActiveClass); | |||
if (clickedElement === element) { | |||
clickedElement.classList.add(createPageInputActiveClass); | |||
} | |||
} | |||
} | |||
/** | |||
* @param {HTMLElement} element | |||
* @param {HTMLElement} targetElement | |||
*/ | |||
function addToggleGridTargetEvent(element, targetElement) { | |||
itemsCreatePageGrid.push(element); | |||
itemsCreateInputPageGrid.push(targetElement); | |||
onClickOrTap(element, (e) => { | |||
toggleGridTarget(element, targetElement) | |||
}); | |||
//element.addEventListener("click", () => | |||
// toggleGridTarget(element, targetElement) | |||
//); | |||
} | |||
const createPageTargetElements = document.querySelectorAll( | |||
createPageTargetIdDataSetString | |||
); | |||
for (let index = 0; index < createPageTargetElements.length; index += 1) { | |||
const element = createPageTargetElements[index]; | |||
const targetElement = getGridTarget(element); | |||
if (targetElement) { | |||
addToggleGridTargetEvent(element, targetElement); | |||
} | |||
} | |||
} | } | ||
/* Jakes Recent Changes Portlet */ | |||
(function () { | |||
function jakeTimeAgo(date) { | |||
var s = Math.floor((Date.now() - date.getTime()) / 1000); | |||
if (s < 60) return s + "s ago"; | |||
var m = Math.floor(s / 60); | |||
if (m < 60) return m + "m ago"; | |||
var h = Math.floor(m / 60); | |||
if (h < 24) return h + "h ago"; | |||
var d = Math.floor(h / 24); | |||
return d + "d ago"; | |||
} | |||
function jakeInjectStyles() { | |||
if (document.getElementById("jake-rc-style")) return; | |||
var style = document.createElement("style"); | |||
style.id = "jake-rc-style"; | |||
style.textContent = | |||
"#p-jake-recentchanges .vector-menu-heading{display:flex;align-items:center;justify-content:space-between;}" + | |||
"#p-jake-recentchanges .jake-rc-dot{width:8px;height:8px;border-radius:50%;background:#2da44e;box-shadow:0 0 0 2px rgba(45,164,78,.18);flex:0 0 auto;}" + | |||
"#p-jake-recentchanges .vector-menu-heading{font-size:.95em;}" + | |||
"#p-jake-recentchanges .vector-menu-content{font-size:.92em;}" + | |||
"#p-jake-recentchanges .jake-rc-meta{font-size:.85em;opacity:.85;}"; | |||
document.head.appendChild(style); | |||
} | |||
function jakeBuildPortlet() { | |||
var menu = | |||
document.getElementById("vector-main-menu") || | |||
document.getElementById("mw-panel"); | |||
if (!menu) return null; | |||
if (document.getElementById("p-jake-recentchanges")) return null; | |||
jakeInjectStyles(); | |||
document. | var portlet = document.createElement("div"); | ||
document.getElementById(" | portlet.id = "p-jake-recentchanges"; | ||
portlet.className = "vector-menu mw-portlet"; | |||
document.getElementById(" | var heading = document.createElement("div"); | ||
heading.className = "vector-menu-heading"; | |||
} | |||
var headingText = document.createElement("span"); | |||
headingText.textContent = "Recent changes"; | |||
var dot = document.createElement("span"); | |||
dot.className = "jake-rc-dot"; | |||
dot.setAttribute("aria-hidden", "true"); | |||
dot.title = "Live"; | |||
heading.appendChild(headingText); | |||
heading.appendChild(dot); | |||
var content = document.createElement("div"); | |||
content.className = "vector-menu-content"; | |||
var ul = document.createElement("ul"); | |||
ul.className = "vector-menu-content-list"; | |||
ul.id = "jake-rc-list"; | |||
var moreWrap = document.createElement("div"); | |||
moreWrap.className = "jake-rc-more"; | |||
var moreLink = document.createElement("a"); | |||
moreLink.href = mw.util.getUrl("Special:RecentChanges"); | |||
moreLink.textContent = "Show more…"; | |||
moreWrap.appendChild(moreLink); | |||
content.appendChild(ul); | |||
content.appendChild(moreWrap); | |||
portlet.appendChild(heading); | |||
portlet.appendChild(content); | |||
var discordPortlet = menu.querySelector("#p-Community"); | |||
if (discordPortlet && discordPortlet.parentNode) { | |||
discordPortlet.parentNode.insertBefore(portlet, discordPortlet.nextSibling); | |||
} else { | |||
var navPortlet = menu.querySelector("#p-navigation"); | |||
if (navPortlet && navPortlet.parentNode) { | |||
navPortlet.parentNode.insertBefore(portlet, navPortlet.nextSibling); | |||
} else { | |||
menu.appendChild(portlet); | |||
} | |||
} | |||
return ul; | |||
} | |||
function jakeLoadRecentChanges(ul) { | |||
if (!ul) return; | |||
var api = new mw.Api(); | |||
api | |||
.get({ | |||
action: "query", | |||
list: "recentchanges", | |||
rcnamespace: "0", /* 4 */ | |||
rclimit: 5, | |||
rcprop: "title|timestamp|user", | |||
rcshow: "!bot", | |||
formatversion: 2 | |||
}) | |||
.then(function (data) { | |||
var items = | |||
data && data.query && data.query.recentchanges | |||
? data.query.recentchanges | |||
: []; | |||
ul.textContent = ""; | |||
for (var i = 0; i < items.length; i++) { | |||
var rc = items[i]; | |||
var li = document.createElement("li"); | |||
li.className = "mw-list-item jake-rc-item"; | |||
var a = document.createElement("a"); | |||
a.href = mw.util.getUrl(rc.title); | |||
a.textContent = rc.title; | |||
var meta = document.createElement("div"); | |||
meta.className = "jake-rc-meta"; | |||
meta.textContent = jakeTimeAgo(new Date(rc.timestamp)) + " · " + (rc.user || ""); | |||
li.appendChild(a); | |||
li.appendChild(meta); | |||
ul.appendChild(li); | |||
} | |||
}) | |||
.catch(function () { | |||
ul.textContent = ""; | |||
var li = document.createElement("li"); | |||
li.className = "mw-list-item jake-rc-item"; | |||
var a = document.createElement("a"); | |||
a.href = mw.util.getUrl("Special:RecentChanges"); | |||
a.textContent = "View recent changes"; | |||
li.appendChild(a); | |||
ul.appendChild(li); | |||
}); | |||
} | |||
function jakeInitRecentChanges() { | |||
if (!window.mw || !mw.util || !mw.Api) return; | |||
var ul = jakeBuildPortlet(); | |||
if (!ul) ul = document.getElementById("jake-rc-list"); | |||
if (!ul) return; | |||
jakeLoadRecentChanges(ul); | |||
setInterval(function () { | |||
jakeLoadRecentChanges(ul); | |||
}, 60000); | |||
} | |||
function jakeWaitForMenu() { | |||
var tries = 0; | |||
var timer = setInterval(function () { | |||
var menu = | |||
document.getElementById("vector-main-menu") || | |||
document.getElementById("mw-panel"); | |||
if (menu) { | |||
clearInterval(timer); | |||
jakeInitRecentChanges(); | |||
return; | |||
} | |||
tries++; | |||
if (tries > 50) clearInterval(timer); | |||
}, 200); | |||
} | |||
jakeWaitForMenu(); | |||
})(); | |||
/* */ | |||
/* | |||
(function () { | |||
function jakeAddFeedbackToNamespaces() { | |||
var list = document.querySelector("#p-associated-pages .vector-menu-content-list"); | |||
if (!list) return; | |||
var existing = document.getElementById("jake-feedback-btn"); | |||
if (existing && !existing.closest("#p-associated-pages")) { | |||
var oldLi = existing.closest("li"); | |||
if (oldLi) oldLi.remove(); | |||
else existing.remove(); | |||
} | |||
if (document.getElementById("ca-jake-feedback")) return; | |||
var li = document.createElement("li"); | |||
li.id = "ca-jake-feedback"; | |||
li.className = "vector-tab-noicon mw-list-item"; | |||
var a = document.createElement("a"); | |||
a.id = "jake-feedback-btn"; | |||
a.className = "jake-feedback-btn"; | |||
a.href = mw.util.getUrl("Consumer_Rights_Wiki:Feedback", { | |||
from: mw.config.get("wgPageName") | |||
}); | |||
a.title = "Give feedback"; | |||
var span = document.createElement("span"); | |||
span.textContent = "Give feedback"; | |||
a.appendChild(span); | |||
li.appendChild(a); | |||
list.appendChild(li); | |||
} | |||
function jakeInit() { | |||
if (!window.mw || !mw.util || !mw.config) return; | |||
jakeAddFeedbackToNamespaces(); | |||
} | |||
if (document.readyState === "loading") { | |||
document.addEventListener("DOMContentLoaded", jakeInit); | |||
} else { | |||
jakeInit(); | |||
} | |||
})(); | |||
*/ | |||
/* */ | |||
(function () { | |||
function jakeAddFooterSocialRow() { | |||
var footer = document.getElementById("footer"); | |||
if (!footer) return; | |||
var places = document.getElementById("footer-places"); | |||
if (!places) return; | |||
if (document.getElementById("footer-social")) return; | |||
var ul = document.createElement("ul"); | |||
ul.id = "footer-social"; | |||
ul.className = "noprint crw-footer-social"; | |||
function add(href, label) { | |||
var li = document.createElement("li"); | |||
var a = document.createElement("a"); | |||
a.href = href; | |||
a.textContent = label; | |||
a.setAttribute("aria-label", label); | |||
a.title = label; | |||
li.appendChild(a); | |||
ul.appendChild(li); | |||
} | |||
// add("https://discord.gg/8w5rSNAXRf", "Discord"); | |||
add("https://www.linkedin.com/company/consumer-rights-wiki/", "LinkedIn"); | |||
add("https://www.reddit.com/user/ConsumerRightsWiki/", "Reddit"); | |||
places.parentNode.insertBefore(ul, places.nextSibling); | |||
} | |||
} | |||
document. | if (document.readyState === "loading") { | ||
document.addEventListener("DOMContentLoaded", jakeAddFooterSocialRow); | |||
} else { | |||
jakeAddFooterSocialRow(); | |||
} | |||
})(); | |||
} | |||