Difference between revisions of "MediaWiki:Common.js"
From Game Logs
m (don't self-close tags) |
(Better Grimoire support) |
||
| (8 intermediate revisions by the same user not shown) | |||
| 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; | |
| − | + | ||
| + | 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 ( | + | if (instanceId && instanceId != currentId) { |
| − | + | var current = document.querySelector("[data-instance-id='" + instanceId + "']"); | |
| − | + | $(current).find(".dnd5-grimoire-wrapper").hide(); | |
| − | |||
} | } | ||
| − | + | instanceId = currentId; | |
| − | var | + | 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 (! | + | if (!spellURL.length) |
return; | 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); | |
| − | + | } | |
| − | |||
| − | |||
| − | |||
| − | |||
| − | } | ||
}); | }); | ||
| − | + | ||
| − | $(".dnd5-grimoire"). | + | // Swap captions for ext-anchors to the Grim URL. |
| − | + | $(".dnd5-grimoire").each(function(idx) { | |
| − | if ( | + | 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; | return; | ||
| − | + | link.html( | |
| + | $("<a></a>").text(link.text()) | ||
| + | .prop("href", "https:" + grimTextToURL(link.text())) | ||
| + | .prop("target", "_blank") | ||
| + | ); | ||
}); | }); | ||
}); | }); | ||
/* TEMPLATE:GRIMOIRE ENDS */ | /* 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 */ | ||
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 */