Difference between revisions of "MediaWiki:Common.js"

From Game Logs
Jump to: navigation, search
(Add support for dynamic Right-to-Left positioning for Grimoire tooltips.)
(Better Grimoire support)
 
Line 5: Line 5:
  
 
$(function() {
 
$(function() {
 +
 
     // Activate only on 5ed pages.
 
     // Activate only on 5ed pages.
     if ((wgCategories || []).indexOf("DnD 5") === -1)
+
     // if ((wgCategories || []).indexOf("DnD 5") === -1)
         return;
+
    //    return;
 +
 
 +
    var instanceId = 0,
 +
         timeout = null;
  
 
     // Convert readable spell name into a Grimoire link.
 
     // Convert readable spell name into a Grimoire link.
Line 17: Line 21:
 
     };
 
     };
  
     var alignPopup = function(contents) {
+
    // RTL alignment support depending on popup position.
         var popup = contents.parent(),
+
     var alignPopup = function(popup) {
 +
         var container = popup.parent(),
 
             width = $(window).width(),
 
             width = $(window).width(),
             threshold = popup.offset().left + popup.outerWidth();
+
             threshold = container.offset().left + popup.outerWidth();
 
         popup.toggleClass("rtl", threshold > width);
 
         popup.toggleClass("rtl", threshold > width);
 
     };
 
     };
       
 
  
     $(".dnd5-grimoire").off("mouseover").on("mouseover", function(e) {
+
    // Activation event
 +
     $(".dnd5-grimoire").off("mouseenter").on("mouseenter", function(e) {
 +
        var currentId = this.getAttribute("data-instance-id");
  
         // Only one popup allowed.
+
         if (!currentId)
        $(".dnd5-grimoire .dnd5-grimoire-wrapper").hide();
+
            return;
  
         var link = $(e.target).closest(".dnd5-grimoire"),
+
         // Hide active popup at once if it's from another source.
 +
        if (instanceId && instanceId != currentId) {
 +
            var current = document.querySelector("[data-instance-id='" + instanceId + "']");
 +
            $(current).find(".dnd5-grimoire-wrapper").hide();
 +
        }
 +
 
 +
        instanceId = currentId;
 +
        window.clearTimeout(timeout);
 +
        timeout = null;
 +
 
 +
        var link = $(e.currentTarget),
 
             embed = link.find(".dnd5-grimoire-embed"),
 
             embed = link.find(".dnd5-grimoire-embed"),
 +
            wrapper = embed.closest(".dnd5-grimoire-wrapper"),
 
             spellURL = grimTextToURL(link.text());
 
             spellURL = grimTextToURL(link.text());
  
        // Toggle visibility of the info div if it's already been populated.
 
        if (embed.length) {
 
            if (embed.not(":visible"))
 
                embed.parent().show();
 
            alignPopup(embed);
 
            return;
 
        }
 
  
 
         if (!spellURL.length)
 
         if (!spellURL.length)
 
             return;
 
             return;
  
         var wrapper = $("<div></div>").addClass("dnd5-grimoire-wrapper").appendTo(link),
+
         // Instantiate on first occurence.
        embed = $("<div></div>").addClass("dnd5-grimoire-embed dnd5-grimoire-loader").appendTo(wrapper);
+
        if (!wrapper.length) {
 +
            wrapper = $("<div></div>")
 +
                .addClass("dnd5-grimoire-wrapper")
 +
                .appendTo(link);
 +
 
 +
            embed = $("<div></div>").addClass("dnd5-grimoire-embed dnd5-grimoire-loader").appendTo(wrapper);
 +
 
 +
            // Show the block first, better with loader.
  
        // Show the block first, better with loader.
+
            // no Promises, damn.
 +
            $.ajax({
 +
                "url": spellURL,
 +
                "type": "get",
 +
                "cache": true
 +
            })
 +
            .then(function(data) {
 +
                var doc = $(data);
 +
                var article = doc.find("article");
 +
                if (!article.length)
 +
                    return console.log("Failed to find the DOM chunk with spell description");
 +
                embed.removeClass("dnd5-grimoire-loader").append(article);
 +
                alignPopup(wrapper);
 +
            })
 +
            .fail(function() {
 +
                embed.removeClass("loading").html("<p>Failed to look up this spell :(</p>");
 +
            });
 +
        }
  
         // no Promises, damn.
+
         if (!wrapper.is(":visible")) {
        $.ajax({
+
             wrapper.show();
            "url": spellURL,
+
             alignPopup(wrapper);
            "type": "get",
+
         }
            "cache": true
 
        })
 
        .then(function(data) {
 
             var doc = $(data);
 
            var article = doc.find("article");
 
            if (!article.length)
 
                return console.log("Failed to find the DOM chunk with spell description");
 
            embed.removeClass("dnd5-grimoire-loader").append(article);
 
             alignPopup(embed);
 
        })
 
        .fail(function() {
 
            embed.removeClass("loading").html("<p>Failed to look up this spell :(</p>");
 
         });
 
 
     });
 
     });
  
     $(".dnd5-grimoire").off("mouseout").on("mouseout", function(e) {
+
    // Deactivation event
         var target = $(e.target).closest(".dnd5-grimoire-wrapper");
+
     $(".dnd5-grimoire").off("mouseleave").on("mouseleave", function(e) {
         if (!target.length)
+
         var link = $(e.currentTarget),
             return;
+
            wrapper = link.find(".dnd5-grimoire-wrapper"),
        target.hide();
+
            leaveId = this.getAttribute("data-instance-id");
 +
         if (leaveId == instanceId && !timeout) {
 +
             timeout = window.setTimeout(function() {
 +
                wrapper.hide();
 +
                timeout = instanceId = 0;
 +
            }, 150);
 +
        }
 
     });
 
     });
  
 
     // Swap captions for ext-anchors to the Grim URL.
 
     // Swap captions for ext-anchors to the Grim URL.
     $(".dnd5-grimoire").each(function() {
+
     $(".dnd5-grimoire").each(function(idx) {
 +
        this.setAttribute("data-instance-id", ++idx);
 
         var link = $(this);
 
         var link = $(this);
 
         // Insert an external link to the Grimoire page on first hover.
 
         // Insert an external link to the Grimoire page on first hover.

Latest revision as of 04:34, 6 January 2019

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


/* TEMPLATE:GRIMOIRE STARTS */

$(function() {

    // Activate only on 5ed pages.
    // if ((wgCategories || []).indexOf("DnD 5") === -1)
    //     return;

    var instanceId = 0,
        timeout = null;

    // Convert readable spell name into a Grimoire link.
    var grimTextToURL = function(text) {
        var spell = text.trim().toLowerCase()
            .replace(/[^\w\d\ \-]/g, '')
            .replace(/\ +/g, '-');
        return spell ? ("//thebombzen.com/grimoire/spells/" + spell) : false
    };

    // RTL alignment support depending on popup position.
    var alignPopup = function(popup) {
        var container = popup.parent(),
            width = $(window).width(),
            threshold = container.offset().left + popup.outerWidth();
        popup.toggleClass("rtl", threshold > width);
    };

    // Activation event
    $(".dnd5-grimoire").off("mouseenter").on("mouseenter", function(e) {
        var currentId = this.getAttribute("data-instance-id");

        if (!currentId)
            return;

        // Hide active popup at once if it's from another source.
        if (instanceId && instanceId != currentId) {
            var current = document.querySelector("[data-instance-id='" + instanceId + "']");
            $(current).find(".dnd5-grimoire-wrapper").hide();
        }

        instanceId = currentId;
        window.clearTimeout(timeout);
        timeout = null;

        var link = $(e.currentTarget),
            embed = link.find(".dnd5-grimoire-embed"),
            wrapper = embed.closest(".dnd5-grimoire-wrapper"),
            spellURL = grimTextToURL(link.text());


        if (!spellURL.length)
            return;

        // Instantiate on first occurence.
        if (!wrapper.length) {
            wrapper = $("<div></div>")
                .addClass("dnd5-grimoire-wrapper")
                .appendTo(link);

            embed = $("<div></div>").addClass("dnd5-grimoire-embed dnd5-grimoire-loader").appendTo(wrapper);

            // Show the block first, better with loader.

            // no Promises, damn.
            $.ajax({
                "url": spellURL,
                "type": "get",
                "cache": true
            })
            .then(function(data) {
                var doc = $(data);
                var article = doc.find("article");
                if (!article.length)
                    return console.log("Failed to find the DOM chunk with spell description");
                embed.removeClass("dnd5-grimoire-loader").append(article);
                alignPopup(wrapper);
            })
            .fail(function() {
                embed.removeClass("loading").html("<p>Failed to look up this spell :(</p>");
            });
        }

        if (!wrapper.is(":visible")) {
            wrapper.show();
            alignPopup(wrapper);
        }
    });

    // Deactivation event
    $(".dnd5-grimoire").off("mouseleave").on("mouseleave", function(e) {
        var link = $(e.currentTarget),
            wrapper = link.find(".dnd5-grimoire-wrapper"),
            leaveId = this.getAttribute("data-instance-id");
        if (leaveId == instanceId && !timeout) {
            timeout = window.setTimeout(function() {
                wrapper.hide();
                timeout = instanceId = 0;
            }, 150);
        }
    });

    // Swap captions for ext-anchors to the Grim URL.
    $(".dnd5-grimoire").each(function(idx) {
        this.setAttribute("data-instance-id", ++idx);
        var link = $(this);
        // Insert an external link to the Grimoire page on first hover.
        if (link.find("a").length)
            return;
        link.html(
            $("<a></a>").text(link.text())
            .prop("href", "https:" + grimTextToURL(link.text()))
            .prop("target", "_blank")
        );
    });
});

/* TEMPLATE:GRIMOIRE ENDS */


/* COLUMN-HOVER TABLE ACTUATOR STARTS */

$(function() {

    // Given a jQ pointer to a table cell, get a list of all cells at that pos.
    // Note: ignores rows that have merged cells.
    var getColumnCells = function(cell) {
        var items = [],
            targetPos = cell.index();
        if (parseInt(cell.prop("colspan") || 1, 10) != 1)
            return items;

        cell.closest("table").find("tr").each(function() {
            // Make this work only on rows with no merged cells.
            if (parseInt($(this).find("[colspan]").prop("colspan") || 1, 10) != 1)
                return;
            var row = $(this).find("td:eq(" + targetPos + "), th:eq(" + targetPos + ")"); // either
            row.each(function() {
                items.push($(this));
            });
        });

        return items;
    };

    $("table.columns").on("mouseenter mouseleave", "td, th", function(e) {
        var cell = $(e.target).closest("td, th"),
            vertSiblings = getColumnCells(cell),
            method = e.type == "mouseenter" ? "addClass" : "removeClass";

        vertSiblings.forEach(function(el) { $(el)[method]("hovered"); });
    });
});

/* COLUMN-HOVER TABLE ACTUATOR ENDS */