FFlogs XIVAnalysis Button
@match: https://www.fflogs.com/reports/*
Adds a button linking to XIVAnalysis based on the current fight parameter in FFLogs reports. Generated by AI so don't judge it too hard.
// ==UserScript==
// @name FFLogs → XIVAnalysis Fight Button
// @namespace http://tampermonkey.net/
// @version 1.1
// @description Adds a button linking to XIVAnalysis based on the current fight parameter in FFLogs reports.
// @match https://www.fflogs.com/reports/*
// @grant none
// @run-at document-idle
// ==/UserScript==
(() => {
'use strict'
const BUTTON_ID = 'xivanalysis-button'
function getFightParam() {
const url = new URL(window.location.href)
return url.searchParams.get('fight')
}
function getReportID() {
// /reports/{reportID}...
const m = window.location.pathname.match(/\/reports\/([^/]+)/)
return m?.[1] ?? null
}
function ensureButton(container) {
let button = document.getElementById(BUTTON_ID)
if (!button) {
button = document.createElement('a')
button.id = BUTTON_ID
button.className = 'big-tab view-type-tab'
button.innerHTML = \`
<span class="zmdi zmdi-search-in-file"></span>
<span class="big-tab-text"><br>XIVAnalysis</span>
\`
container.appendChild(button)
} else if (button.parentElement !== container) {
// If FFLogs re-rendered tabs, move our button back into the right container
container.appendChild(button)
}
return button
}
function updateButton() {
const fight = getFightParam()
const reportID = getReportID()
const existing = document.getElementById(BUTTON_ID)
// If we can't build a valid link, remove the button if it exists
if (!fight || !reportID) {
if (existing) existing.remove()
return
}
const container = document.getElementById('top-level-view-tabs')
if (!container) return // wait for SPA to render
const button = ensureButton(container)
button.href = \`https://xivanalysis.com/fflogs/\${reportID}/\${fight}\`
button.target = '_blank'
button.rel = 'noopener noreferrer'
}
// Fire update when history changes (SPA navigation)
;(history => {
const pushState = history.pushState
const replaceState = history.replaceState
history.pushState = function () {
const ret = pushState.apply(this, arguments)
window.dispatchEvent(new Event('locationchange'))
return ret
}
history.replaceState = function () {
const ret = replaceState.apply(this, arguments)
window.dispatchEvent(new Event('locationchange'))
return ret
}
})(window.history)
window.addEventListener('popstate', () => window.dispatchEvent(new Event('locationchange')))
window.addEventListener('locationchange', updateButton)
// Observe DOM changes because FFLogs frequently re-renders the tab bar
const obs = new MutationObserver(() => updateButton())
obs.observe(document.documentElement, { childList: true, subtree: true })
// Initial run
updateButton()
})()