MediaWiki:Gadget-md5hasher.js: Difference between revisions

m Typo
m Parameterize StatsGraph for target container
 
(13 intermediate revisions by 2 users not shown)
Line 30: Line 30:


window.gfUtils.createWikiPathPart = function createPathPart(filename) {
window.gfUtils.createWikiPathPart = function createPathPart(filename) {
   var hash = md5(encodeURIComponent(filename));
   var hash = window.gfUtils.md5(decodeURIComponent(filename));
   return hash[0] + "/" + hash[0] + hash[1] + "/";
   return hash[0] + "/" + hash[0] + hash[1] + "/";
}
};
 
var createSliderButtonCounter = 0;
window.gfUtils.createSliderButton = function createSliderButton(iconUrl, eventHandler) {
 
 
  var idForThisButton = "dormSliderIdent" + createSliderButtonCounter;
  createSliderButtonCounter = createSliderButtonCounter + 1;
 
  var dormInput = $('<input></input>');
  dormInput.attr('type', "checkbox");
  dormInput.attr('value', "None");
  dormInput.attr('name', "check");
  dormInput.attr('id', idForThisButton);
  dormInput.change(eventHandler);
               
  var dormSpanOn = $('<span></span >');
  dormSpanOn.addClass('texton');
  dormSpanOn.text('ON');
               
  var dormLabel = $('<label></label>');
  dormLabel.attr('for', idForThisButton);
               
  var dormSpanOff = $('<span></span >');
  dormSpanOff.addClass('textoff');
  dormSpanOff.text('OFF');
               
  var dormSlidebutton = $('<div></div>');
  dormSlidebutton.addClass('slideButton');
  dormSlidebutton.append(dormSpanOn);
  dormSlidebutton.append(dormLabel);
  dormSlidebutton.append(dormSpanOff);
               
  var dormSwitcher = $('<div></div>');
  dormSwitcher.addClass('chibiDormSwitcher');
  dormSwitcher.append(dormInput);
  dormSwitcher.append(dormSlidebutton);
 
  return dormSwitcher;
};
 
window.gfUtils.base64ArrayBuffer = function base64ArrayBuffer(arrayBuffer) {
  var base64    = '';
  var encodings = 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/';
 
  var bytes        = new Uint8Array(arrayBuffer);
  var byteLength    = bytes.byteLength;
  var byteRemainder = byteLength % 3;
  var mainLength    = byteLength - byteRemainder;
 
  var a, b, c, d;
  var chunk;
 
  var i;
  // Main loop deals with bytes in chunks of 3
  for (i = 0; i < mainLength; i = i + 3) {
    // Combine the three bytes into a single integer
    chunk = (bytes[i] << 16) | (bytes[i + 1] << 8) | bytes[i + 2];
 
    // Use bitmasks to extract 6-bit segments from the triplet
    a = (chunk & 16515072) >> 18; // 16515072 = (2^6 - 1) << 18;
    b = (chunk & 258048)  >> 12; // 258048  = (2^6 - 1) << 12;
    c = (chunk & 4032)    >>  6; // 4032    = (2^6 - 1) << 6;
    d = chunk & 63              ; // 63      = 2^6 - 1;
 
    // Convert the raw binary segments to the appropriate ASCII encoding
    base64 += encodings[a] + encodings[b] + encodings[c] + encodings[d];
  }
 
  // Deal with the remaining bytes and padding
  if (byteRemainder == 1) {
    chunk = bytes[mainLength];
 
    a = (chunk & 252) >> 2; // 252 = (2^6 - 1) << 2;
 
    // Set the 4 least significant bits to zero
    b = (chunk & 3)  << 4; // 3  = 2^2 - 1;
 
    base64 += encodings[a] + encodings[b] + '==';
  } else if (byteRemainder == 2) {
    chunk = (bytes[mainLength] << 8) | bytes[mainLength + 1];
 
    a = (chunk & 64512) >> 10; // 64512 = (2^6 - 1) << 10;
    b = (chunk & 1008)  >>  4; // 1008  = (2^6 - 1) << 4;
 
    // Set the 2 least significant bits to zero
    c = (chunk & 15)    <<  2; // 15    = 2^4 - 1;
 
    base64 += encodings[a] + encodings[b] + encodings[c] + '=';
  }
 
  return base64;
};
 
/* =========== Widget functions */
window.iopwidgets = window.iopwidgets || {};
 
/* ----------- ICSGenerator*/
window.iopwidgets.ICSGenerator = {
/* Hashing as seen on https://stackoverflow.com/a/52171480 */
cyrb53: function(str, seedRaw) {
    var seed = seedRaw || 0;
    var h1 = 0xdeadbeef ^ seed, h2 = 0x41c6ce57 ^ seed;
    for (var i = 0, ch; i < str.length; i++) {
        ch = str.charCodeAt(i);
        h1 = Math.imul(h1 ^ ch, 2654435761);
        h2 = Math.imul(h2 ^ ch, 1597334677);
    }
    h1 = Math.imul(h1 ^ (h1>>>16), 2246822507) ^ Math.imul(h2 ^ (h2>>>13), 3266489909);
    h2 = Math.imul(h2 ^ (h2>>>16), 2246822507) ^ Math.imul(h1 ^ (h1>>>13), 3266489909);
    return 4294967296 * (2097151 & h2) + (h1>>>0);
},
 
buildIcsLink: function(name, start, end, destContainer) {
var d= new Date();
var currentDateString = d.getFullYear() + ("0"+(d.getMonth()+1)).slice(-2) + ("0" + d.getDate()).slice(-2) + "T"
+ ("0" + d.getHours()).slice(-2) + ("0" + d.getMinutes()).slice(-2) + ("0" + d.getSeconds()).slice(-2);
var hash = window.iopwidgets.ICSGenerator.cyrb53("" + name + start + end);
var icsContent = "BEGIN:VCALENDAR\r\n";
icsContent += "VERSION:2.0\r\n";
icsContent += "PRODID:-//iopwiki.com//ICS Widget\r\n";
icsContent += "CALSCALE:GREGORIAN\r\n";
icsContent += "BEGIN:VEVENT\r\n";
icsContent += "DTSTAMP:" + currentDateString + "\r\n";
icsContent += "UID:" + hash + "\r\n";
icsContent += "DTSTART;TZID=Etc/UTC:" + start + "\r\n";
icsContent += "DTEND;TZID=Etc/UTC:" + end + "\r\n";
icsContent += "SUMMARY:" + name + "\r\n";
icsContent += "END:VEVENT\r\n";
icsContent += "END:VCALENDAR\r\n";
var icsLink = document.createElement("a");
icsLink.classList.add('ics-link');
icsLink.setAttribute("href", "javascript:void(0);");
icsLink.setAttribute("target", "_blank");
icsLink.setAttribute("rel", "noopener");
icsLink.setAttribute("tooltip", "Download iCal file");
icsLink.setAttribute("download", "event.ics");
icsLink.addEventListener('click', function(e) {
var uriContent = "data:text/calendar," + encodeURIComponent(icsContent);
e.target.href = uriContent;
});
var visibleText = document.createTextNode("Download iCal file");
icsLink.appendChild(visibleText);
destContainer.appendChild(icsLink);
}
};
 
/* ---------- NavboxPopulizer*/
window.iopwidgets.NavboxPopulizer = {
handlePopulize: function(e, targetList, server) {
      e.preventDefault();
     
      var element = $(e.target);
      var table = element.closest('table');
     
      var addresstocall = "/api.php?action=parse&page=Template:Navbox/" + targetList + "&format=json";
      // for old navbox calls
      if (server != "") {
        addresstocall = "/api.php?action=parse&page=Template:" + targetList + "/list/" + server + "&format=json";
      }
     
      $.getJSON(addresstocall)
        .done(function( json ) {
          table.find(".navboxlist").remove();
 
          var dataToInsert = json.parse.text["*"];
         
          var cell = $("<td></td>");
          cell.append(dataToInsert);
         
          var row = $("<tr></tr>");
          row.addClass('navboxlist');
          row.append(cell);
         
          table.find("tbody").append(row);
          table.removeClass("loading");
        })
        .fail(function( jqxhr, textStatus, error ) {
          table.removeClass("loading");
          console.log("Request Failed", textStatus, error);
        });
    }
};
 
/* ---------- StatTable*/
window.iopwidgets.StatTable = {
swap_costume: function() {
        costumeSelection = document.getElementById("costumeSelection").value;
 
        $("#fullart a").attr("href", costumeSelection);
        $("#fullart a img").attr("src", costumeSelection);
        $("#fullart a img").attr("alt", costumeSelection);
        //$("#fullart a img").attr("srcset", "/wiki/Special:Redirect/file/Springfield" + costumeSelection + ".png 1.5x, /wiki/Special:Redirect/file/Springfield" + costumeSelection + ".png 2x");
        $(".tdoll_chibi").attr("src", "/wiki/Special:Redirect/file/Springfield" + costumeSelection + "_S.png");
       
        // As we change the link, we have to update the Thumb-Cache of the Media Viewer
        // Clear up the thumbs cache
        if (mv && mv.mmv && mv.mmv.bootstrap && mv.mmv.bootstrap.viewer) {
          mw.mmv.bootstrap.thumbs = [];
          // Search for all thumbs
          mw.mmv.bootstrap.processThumbs($("#content"));
          // Re-Init the viewer with the new thumbs
          mw.mmv.bootstrap.viewer.initWithThumbs(mw.mmv.bootstrap.thumbs);
        }
}
};
 
/* ---------- StatsGraph*/
window.iopwidgets.StatsGraph = {
calcCoordinate: function(degree, min, max, val) {
  var oldX = 0;
  var oldY = (max-min) == 0 ? 0 : -(300 / (max-min)) * (val - min);
 
  if (degree == 0) {
    return [oldX, Math.floor(oldY)];
  }
 
  var rotate = (-degree * Math.PI) / 180;
 
  var newX = oldX*Math.cos(rotate)+oldY*Math.sin(rotate);
  var newY = oldY*Math.cos(rotate)+oldX*Math.sin(rotate);
  return [Math.floor(newX), Math.round(newY)];
},
buildPolygonString: function(data) {
  var ret = "";
  var degreeSpacing = 360 / data.length;
  for (var i=0;i<data.length;i++) {
    var coord = this.calcCoordinate(degreeSpacing*i, data[i].min, data[i].max, data[i].value);
    ret += coord[0] + "," + coord[1] + " ";
  }
  ret = ret.trim();
  return ret;
},
buildGraph: function(dataComplete, container) {
  var svg = document.createElementNS("http://www.w3.org/2000/svg", "svg");
  var svgNS = svg.namespaceURI;
  var svgLinkNS = "http://www.w3.org/1999/xlink";
  svg.setAttributeNS("http://www.w3.org/2000/xmlns/", "xmlns:xlink", svgLinkNS);
  svg.setAttribute('viewBox', "0 0 800 800");
  svg.setAttribute('preserveAspectRatio', "xMidyMid meet");
  svg.setAttribute('width', "300px");
  svg.setAttribute('height', "auto");
  svg.setAttribute('version', "1.1");
 
  /* This pretty much defines the base net lines */
  var defs = document.createElementNS(svgNS, 'defs');
 
  /* Wedge id has to be unique */
  var wedgeId = "wedge-" + 'xxxxxxxx-xxxx-4xxx-yxxx-xxxxxxxxxxxx'.replace(/[xy]/g, function(c) {
    var r = Math.random() * 16 | 0, v = c == 'x' ? r : (r & 0x3 | 0x8);
    return v.toString(16);
  });
 
  var wedge = document.createElementNS(svgNS, 'g');
  wedge.setAttribute('id', wedgeId);
 
  var directionCount = dataComplete[0].data.length;
  var degreeSpacing = 360 / directionCount;
 
  var radialLine = document.createElementNS(svgNS, 'line');
  radialLine.setAttribute('class', 'radial');
  radialLine.setAttribute('y2', -325);
  wedge.appendChild(radialLine);
 
  for (var lineIdx=1;lineIdx<5;lineIdx++) {
    var orientationLine = document.createElementNS(svgNS, 'line');
    var lineDistance = lineIdx * -75;
    var rotate = (degreeSpacing * Math.PI) / 180;
    orientationLine.setAttribute('y1', lineDistance);
    orientationLine.setAttribute('x2', lineDistance*Math.sin(rotate));
    orientationLine.setAttribute('y2', lineDistance*Math.cos(rotate));
    if (lineIdx % 2 == 0) {
      orientationLine.setAttribute('class', 'emphased');
    }
    wedge.appendChild(orientationLine);
  }
  defs.appendChild(wedge);
  svg.appendChild(defs);
 
  // Now start drawing
  var gDrawing = document.createElementNS(svgNS, 'g');
  gDrawing.setAttribute('transform', 'translate(400 400)');
 
  for (var dataIdx=0; dataIdx<directionCount; dataIdx++) {
    var propertyLine = document.createElementNS(svgNS, 'use');
    propertyLine.setAttributeNS(svgLinkNS, "href", "#" + wedgeId);
    propertyLine.setAttribute('transform', "rotate(" + (degreeSpacing * dataIdx) + ")");
    gDrawing.appendChild(propertyLine );
  }
 
  for (var dataIdx=0; dataIdx<dataComplete.length; dataIdx++) {
    var polygonParams = dataComplete[dataIdx];
    var datapresentation = document.createElementNS(svgNS, 'polygon');
   
    if ('title' in polygonParams) {
      var title = document.createElementNS(svgNS, 'title');
      title.appendChild(document.createTextNode(polygonParams.title));
      datapresentation.appendChild(title);
    }
   
    if (('fill' in polygonParams) || ('stroke' in polygonParams)) {
      if ('fill' in polygonParams) datapresentation.setAttribute('fill', polygonParams.fill);
      if ('stroke' in polygonParams) datapresentation.setAttribute('stroke', polygonParams.stroke);
    } else {
      datapresentation.setAttribute('class', polygonParams.class ? polygonParams.class : "graph-orange");
    }
    datapresentation.setAttribute('points', this.buildPolygonString(polygonParams.data));
    gDrawing.appendChild(datapresentation);
   
    for (var labelIdx=0; labelIdx<polygonParams.data.length; labelIdx++) {
      var polygonCornerData = polygonParams.data[labelIdx];
      var rotate = (-degreeSpacing * labelIdx * Math.PI) / 180;
     
      var label = document.createElementNS(svgNS, 'text');
      label.setAttribute('x', -340*Math.sin(rotate));
      label.setAttribute('y', -340*Math.cos(rotate));
      label.setAttribute('title', titleText);
      label.appendChild(document.createTextNode(polygonCornerData.label));
      var titleText = "" + polygonCornerData.min + " <= " + polygonCornerData.value + " <= " + polygonCornerData.max;
      var title = document.createElementNS(svgNS, 'title');
      title.appendChild(document.createTextNode(titleText));
      label.appendChild(title);
     
      gDrawing.appendChild(label);
    }
  }
 
  svg.appendChild(gDrawing);
 
  container.appendChild(svg);
}
};