MediaWiki:Common.js: Difference between revisions

From Dune: Awakening Community Wiki
Jump to navigation Jump to search
(test new code to ensure that specific anchors targeted by redirect pages will still be highlighted)
(tweak code to work hand-in-hand with the buitl-in :target handler, and to remove itself when :target appears again)
Tag: Reverted
Line 229: Line 229:


$(document).ready(function () {
$(document).ready(function () {
   if (window.location.hash) {
   if (!window.location.hash) return;
    const el = document.querySelector(window.location.hash);


    if (el) {
  const el = document.querySelector(window.location.hash);
      el.classList.add("target-highlight");
  if (!el) return;
    }
 
  // Check if browser already applied :target
  const isTargetApplied = el.matches(':target');
 
  if (!isTargetApplied) {
    el.classList.add('target-highlight');
   }
   }
});
window.addEventListener("hashchange", function () {
  document.querySelectorAll(".target-highlight").forEach(el => {
    el.classList.remove("target-highlight");
  });
});
});

Revision as of 14:13, 27 March 2026

// Any JavaScript here will be loaded for all users on every page load.

// Display fullscreen map if the URL param display = content
function displayContent() {
  const content = document.querySelector(".mw-body-content");
  document.body.innerHTML = "";
  document.body.appendChild(content);
  setTimeout( function () {
    const mapFullscreen = document.querySelector(".oo-ui-icon-fullScreen");
    if (mapFullscreen) { mapFullscreen.click() }  
  }, 500)
}

const contentOnlyPages = ['/Landing'];
const urlParams = new URLSearchParams(window.location.search);
const display = urlParams.get("display");

if (display === "content") {
 displayContent();
}

// Some pages are content-only by default. Allow the param to override it instead
if (contentOnlyPages.includes(window.location.pathname) && display != "full") {
 displayContent();
}

var mainPageLinks = document.getElementsByClassName("mainpage-link");
Array.from(mainPageLinks).forEach(function(element) {
  element.addEventListener('click', goToMainPage, true);
});

function goToMainPage() {
  window.location = '/';
}

// Add Kofi widget script
// So long as we're not just dusplaying content, show the kofi button!
if (display != "content") {
  var kofiWidgetScript = document.createElement("script");

  kofiWidgetScript.onload = function () {
    kofiWidgetOverlay.draw('awakeningwiki', {
      'type': 'floating-chat',
      'floating-chat.donateButton.text': 'Support Us',
      'floating-chat.donateButton.background-color': '#323842',
      'floating-chat.donateButton.text-color': '#fff'
    });
  };

  kofiWidgetScript.src = "https://storage.ko-fi.com/cdn/scripts/overlay-widget.js";
  document.head.appendChild(kofiWidgetScript);
}

// Add Plausible js header to create global plausible instance
var plausibleWidgetScript = document.createElement("script");
plausibleWidgetScript.innerHTML = "window.plausible = window.plausible || function() { (window.plausible.q = window.plausible.q || []).push(arguments) }"
document.head.appendChild(plausibleWidgetScript);

// Copyable Elements (with tooltips)
function copyText(event) {
  event.stopPropagation();
  event.preventDefault();
  var copyText = event.currentTarget.querySelectorAll(":scope > .copy-text")[0]
  navigator.clipboard.writeText(copyText.dataset.value)
  
  var tooltip = event.currentTarget.querySelectorAll(":scope > .tooltiptext")[0]
  tooltip.innerHTML = "Copied: " + copyText.dataset.value
}

function hideTooltip(event) {
  event.stopPropagation();
  event.preventDefault();
  var tooltip = event.currentTarget.querySelectorAll(":scope > .tooltiptext")[0]
  tooltip.innerHTML = "Copy to clipboard";
}

// Add listener on all copyable elements to copy them to clipboard (with tooltip!)
var copyableElements = document.getElementsByClassName("copyable");
Array.from(copyableElements).forEach(function(element) {
  element.addEventListener('click', copyText, true);
  element.addEventListener('mouseout', hideTooltip);
});

// Allow map to be accessed via JS

function translateCoords(latlng) {
 x = parseFloat((100000 - (latlng['lat'] * 1000)).toFixed(2));
 y = parseFloat((latlng['lng'] * 1000).toFixed(2));

 return [x,y]
}


function removePin() {
  if (!window.droppedPin) { return }
  map = window.dataMaps[0];
  map.layerManager.removeMember(window.droppedPin);
  window.droppedPin = null;
}

function loadPin() {
  param = new URLSearchParams(window.location.search).get('marker');
  if (!param || !param.startsWith('Custom@')) { return }
  map = window.dataMaps[0];
  positions = param.replace('Custom@','').split(':');
  x = parseFloat(positions[0]);
  y = parseFloat(positions[1]); 
  removePin();
  marker = map.createMarker(['Custom'], [x,y]);
  window.droppedPin = marker;
}

function clearPins() {
  if (!window.droppedPins) { return; }
  map = window.dataMaps[0];
  window.droppedPins.forEach(function(pin) { map.layerManager.removeMember(pin)});
  window.droppedPins = [];
}

function addPin(coords) {
  map = window.dataMaps[0];
  window.droppedPins = window.droppedPins || [];
  marker = map.createMarker(['Custom'], coords);
  window.droppedPins.push(marker);
};

function loadCollection() {
  clearPins()
  param = new URLSearchParams(window.location.search).get('collection');
  if (!param) { return };
  fetch('https://api.awakening.wiki/markers/'+ param).
    then(function(response) { return response.json() }).
    then(function(body) { 
      if (!body.markers || body.markers == 0) { return; }
      for(i = 0; i < body.markers; i++) {
        addPin([body.x_coords[i], body.y_coords[i]])
      }
    });
}

function saveCollection() {
  if (!window.droppedPins || window.droppedPins.length == 0) { return; }
  markers = [];
  window.droppedPins.forEach(function(marker) { markers.push({x: marker.apiInstance[0], y: marker.apiInstance[1]}) })
  collectionAttributes = { user: mw.user.getName(), markers: markers }
  fetch('https://api.awakening.wiki/markers', { method: 'POST', body: JSON.stringify(collectionAttributes)}).
    then(function(response) { return response.json() }).
    then(function(body) { 
      if (!body.item_id) { 
        console.log("Something went wrong "+body)
      } else {
        collectionUrl = "https://awakening.wiki/Interactive_Map?collection=" + body.item_id
        navigator.clipboard.writeText(collectionUrl)
        window.location = collectionUrl
      }
    });
}

var saveCollectionLinks = document.getElementsByClassName("save-collection");
Array.from(saveCollectionLinks).forEach(function(element) {
  element.addEventListener('click', saveCollection, true);
});

function dropPin(event) {
  map = window.dataMaps[0];
  param = new URLSearchParams(window.location.search).get('mode');
  if (!param || param != 'multiple') {
    removePin(map);
    marker = map.createMarker(['Custom'], translateCoords(event.latlng));
    window.droppedPin = marker;
  } else {
    addPin(translateCoords(event.latlng));
  }
}

window.enabledMapPages = ['/Interactive_Map', '/Deep_Desert', '/Map:Deep_Desert'];

mw.loader.using( [ 'ext.datamaps.leaflet', 'ext.datamaps.bootstrap' ], function(require) {
  window.leaflet = require( 'ext.datamaps.leaflet' );
  if (window.enabledMapPages.includes(window.location.pathname)) {
    mw.dataMaps.registerMapAddedHandler(
      function(map) {
        window.dataMaps = window.dataMaps || [];
        window.dataMaps.push(map);
        map.on('leafletLoaded', function () {
          leafletMap = map.viewport.getLeafletMap();
          // When the map is clicked, the leaflet coords (0-100 xy from bottom left) are in the event
          leafletMap.on('click', dropPin);
          loadPin();
          loadCollection();
        });
      }
    );
  }
});

// Place collapsible toggle below sibling header if present
mw.hook('wikipage.content').add(function ($content) {
  $content.find('.mw-collapsible').each(function () {
    var collapsible = this;

    new MutationObserver(function (mutations, obs) {
      var $toggle = $(collapsible).find('> .mw-collapsible-toggle');
      var $heading = $(collapsible).find('> h1, > h2, > h3, > h4, > h5, > h6').first();

      if ($toggle.length && $heading.length) {
        $toggle.insertAfter($heading);
        obs.disconnect();
      }
    }).observe(collapsible, { childList: true });
  });
});

// Process <time> tags to display timestamps in readers' local timezone
mw.loader.using(['mediawiki.util']).then(function () {
  $(document).ready(function () {
    document.querySelectorAll('time[datetime]').forEach(function (el) {
      var date = new Date(el.getAttribute("datetime"));

      if (isNaN(date.getTime())) return;

      el.textContent = date.toLocaleString(undefined, {
        dateStyle: 'full',
        timeStyle: 'long'
      });
    });
  });
});

$(document).ready(function () {
  if (!window.location.hash) return;

  const el = document.querySelector(window.location.hash);
  if (!el) return;

  // Check if browser already applied :target
  const isTargetApplied = el.matches(':target');

  if (!isTargetApplied) {
    el.classList.add('target-highlight');
  }
});

window.addEventListener("hashchange", function () {
  document.querySelectorAll(".target-highlight").forEach(el => {
    el.classList.remove("target-highlight");
  });
});