Jump to content

MediaWiki:Common.js: Difference between revisions

From Consumer Rights Wiki
Kostas (talk | contribs)
m super special considerations for iPad...(I hope)
No edit summary
 
(41 intermediate revisions by 2 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
function onClickOrTap(element, target, handler){
const onClickOrTap = (element, handler) => {
   let touchMoveHappened = false;
   let touchMoveHappened = false;
   element.addEventListener('touchstart', () => {
   element.addEventListener('touchstart', () => {
     // on mobile this is the 1st event that happens
     // on mobile this is the 1st event that happens
     touchMoveHappened = false;
     touchMoveHappened = false;
   })
   });
   element.addEventListener('touchmove', () => {
   element.addEventListener('touchmove', () => {
     // on mobile this might get triggered in which case the
     // on mobile this might get triggered in which case the
Line 12: Line 12:
     // we'll keep a track of it
     // we'll keep a track of it
     touchMoveHappened = true;
     touchMoveHappened = true;
   })
   });
   element.addEventListener('touchend', () => {
   element.addEventListener('touchend', (e) => {
     // happens after touchstart, but before click
     // happens after touchstart, but before click
     // if touch happened then we'll exit
     // if touch happened then we'll exit
Line 23: Line 23:
     e.preventDefault();
     e.preventDefault();
     // at this point we are ready to call our original handler
     // at this point we are ready to call our original handler
     toggleGridTarget(element, targetElement);
     handler(e);
   }
   });
  )
   element.addEventListener('click', (e) => {
   element.addEventListener('click', () => {
     // this will only get triggered on desktopg
     // this will only get triggered on desktop
     // because we call preventDefault for the "touchend" event
     // because we call preventDefault for the "touchend" event
     toggleGridTarget(element, targetElement);
     handler(e);
   })
   });
}
}
/* Create Page */
/* Create Page */
const createPageTargetIdDataSetString = "[data-create-page-target-id]";
const createPageTargetIdDataSetString = "[data-create-page-target-id]";
Line 85: Line 85:
     itemsCreateInputPageGrid.push(targetElement);
     itemsCreateInputPageGrid.push(targetElement);
      
      
     onClickOrTap(element,targetElement,toggleGridTarget(element, targetElement));
     onClickOrTap(element, (e) => {
   
    toggleGridTarget(element, targetElement)
     // element.addEventListener("click", () =>
    });
     //   toggleGridTarget(element, targetElement)
     //element.addEventListener("click", () =>
     // );
     //   toggleGridTarget(element, targetElement)
     //);
   }
   }


Line 106: Line 107:
   }
   }
}
}
/* 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();
    var portlet = document.createElement("div");
    portlet.id = "p-jake-recentchanges";
    portlet.className = "vector-menu mw-portlet";
    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);
  }
  if (document.readyState === "loading") {
    document.addEventListener("DOMContentLoaded", jakeAddFooterSocialRow);
  } else {
    jakeAddFooterSocialRow();
  }
})();

Latest revision as of 21:26, 1 February 2026

/* 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];

    return document.getElementById(targetId);
  }

  /**
   * @this {HTMLDivElement}
   */
  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();

    var portlet = document.createElement("div");
    portlet.id = "p-jake-recentchanges";
    portlet.className = "vector-menu mw-portlet";

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

  if (document.readyState === "loading") {
    document.addEventListener("DOMContentLoaded", jakeAddFooterSocialRow);
  } else {
    jakeAddFooterSocialRow();
  }
})();