[ Disclaimer, Create new user --- Wiki markup help, Install P99 ]
Difference between revisions of "MediaWiki:Common.js"
From Project 1999 Wiki
| Line 9: | Line 9: | ||
if (onHttp && haveNotTriedAlready) { | if (onHttp && haveNotTriedAlready) { | ||
| − | location = location.origin.replace('http:', 'https:') + | + | location = |
| − | + | location.origin.replace('http:', 'https:') + | |
| − | + | location.pathname + | |
| − | + | location.search + | |
| − | + | (location.search[0] === '?' ? '&' : '?') + | |
| − | + | 'redirected_from_http=1' + | |
| + | location.hash; | ||
} | } | ||
} catch (err) { | } catch (err) { | ||
| Line 25: | Line 26: | ||
// Get all magelos of current user | // Get all magelos of current user | ||
| − | // (currently un-used, but intended for future achievement code, so that | + | // (currently un-used, but intended for future achievement code, so that |
| − | // we can have an "add this achievement to my magelo" drop-down with all | + | // we can have an "add this achievement to my magelo" drop-down with all |
// their magelos listed) | // their magelos listed) | ||
| − | + | var getMagelosForCurrentUser = function () { | |
| − | + | var userName = $('#pt-userpage a').text(); | |
| − | + | var url = | |
| − | + | 'https://wiki.project1999.com/index.php?limit=50&tagfilter=&' + | |
| − | + | 'title=Special%3AContributions&contribs=user&target=' + | |
| − | + | userName + | |
| − | + | '&namespace=500&topOnly=1&year=&month=-1'; | |
| − | + | fetch(url) | |
| − | + | .then(function (response) { | |
| − | + | return response.text(); | |
| − | + | }) | |
| − | + | .then(function (html) { | |
| − | + | var mageloLinks = Array.from($(html).find('li a:contains("Magelo")')); | |
| + | var names = mageloLinks | ||
| + | .filter(function (i, a) { | ||
| + | return !$(a).text().includes('('); | ||
| + | }) | ||
| + | .map(function (i, el) { | ||
| + | return $(el).text(); | ||
| + | }); | ||
| + | console.log(names); | ||
| + | }); | ||
| + | }; | ||
// ********************************** | // ********************************** | ||
| Line 47: | Line 58: | ||
/** | /** | ||
| − | * Basic "state getter": checks localStorage for *stateKey*, then return the | + | * Basic "state getter": checks localStorage for *stateKey*, then return the |
* value for *pageName* (if any) found on that object. | * value for *pageName* (if any) found on that object. | ||
*/ | */ | ||
| − | var getPageState = function(pageName, stateKey) { | + | var getPageState = function (pageName, stateKey) { |
// Get the state for all pages for this key | // Get the state for all pages for this key | ||
var allPageStates = JSON.parse(localStorage.getItem(stateKey) || '{}'); | var allPageStates = JSON.parse(localStorage.getItem(stateKey) || '{}'); | ||
| Line 63: | Line 74: | ||
* status state for the current page. | * status state for the current page. | ||
*/ | */ | ||
| − | window.getStateByPage = function(stateKey) { | + | window.getStateByPage = function (stateKey) { |
var pageName = location.pathname.substr(1); // ditch the leading "/" | var pageName = location.pathname.substr(1); // ditch the leading "/" | ||
return getPageState(pageName, stateKey); | return getPageState(pageName, stateKey); | ||
| Line 73: | Line 84: | ||
* about which page you are on) | * about which page you are on) | ||
*/ | */ | ||
| − | window.getGlobalState = function(stateKey) { | + | window.getGlobalState = function (stateKey) { |
return getPageState('__global', stateKey); | return getPageState('__global', stateKey); | ||
}; | }; | ||
| Line 80: | Line 91: | ||
* Basic "state setter" function | * Basic "state setter" function | ||
*/ | */ | ||
| − | var setPageState = function(pageName, stateKey, state) { | + | var setPageState = function (pageName, stateKey, state) { |
// Get the state for this key (for all pages) out of local storage | // Get the state for this key (for all pages) out of local storage | ||
var allPageStates = JSON.parse(localStorage.getItem(stateKey) || '{}'); | var allPageStates = JSON.parse(localStorage.getItem(stateKey) || '{}'); | ||
| Line 97: | Line 108: | ||
* value of "b". | * value of "b". | ||
*/ | */ | ||
| − | window.setStateByPage = function(stateKey, state) { | + | window.setStateByPage = function (stateKey, state) { |
var pageName = location.pathname.substr(1); // ditch the leading "/" | var pageName = location.pathname.substr(1); // ditch the leading "/" | ||
setPageState(pageName, stateKey, state); | setPageState(pageName, stateKey, state); | ||
}; | }; | ||
| − | window.setGlobalState = function(stateKey, state) { | + | window.setGlobalState = function (stateKey, state) { |
return setPageState('__global', stateKey, state); | return setPageState('__global', stateKey, state); | ||
}; | }; | ||
| − | |||
// ******************************* | // ******************************* | ||
| Line 113: | Line 123: | ||
* last update: 7 January, 2018 by Loramin | * last update: 7 January, 2018 by Loramin | ||
*/ | */ | ||
| − | $(function() { | + | $(function () { |
var hideDelay = 0; | var hideDelay = 0; | ||
var trigDelay = 250; | var trigDelay = 250; | ||
| Line 122: | Line 132: | ||
// One instance that's reused to show info for the current person | // One instance that's reused to show info for the current person | ||
| − | var container = $('<div id="itemHoverContainer">' | + | var container = $( |
| − | + | '<div id="itemHoverContainer">' + '<div id="HoverContent"></div>' + '</div>' | |
| − | + | ); | |
$('body').append(container); | $('body').append(container); | ||
| − | /* --- hoverbox for item/mob, currently only used in magelo --- */ | + | /* --- hoverbox for item/mob, currently only used in magelo --- */ |
// Determine which "a" elements should trigger the item stats mouseover | // Determine which "a" elements should trigger the item stats mouseover | ||
var $mouseoverTargets = $('span.ih a'); | var $mouseoverTargets = $('span.ih a'); | ||
| − | var isItemCategory = document.title.startsWith('Category:') && document.title.includes('Equipment - Project 1999 Wiki') && | + | var isItemCategory = |
| − | + | document.title.startsWith('Category:') && | |
| + | document.title.includes('Equipment - Project 1999 Wiki') && | ||
| + | !document.title.includes('Worshiper Equipment'); | ||
if (isItemCategory) { | if (isItemCategory) { | ||
// Include the category's item list along with ".ih" links | // Include the category's item list along with ".ih" links | ||
| Line 139: | Line 151: | ||
} | } | ||
| − | $mouseoverTargets = $mouseoverTargets.filter(function(i, a) { | + | $mouseoverTargets = $mouseoverTargets.filter(function (i, a) { |
// Don't add hover to links like "next 200" | // Don't add hover to links like "next 200" | ||
| − | return !$(a).attr('href').startsWith('/Special:') && | + | return ( |
| − | + | !$(a).attr('href').startsWith('/Special:') && | |
| + | !$(a).attr('href').includes('title=Category:') | ||
| + | ); | ||
}); | }); | ||
| − | $mouseoverTargets.on('mouseover', function() | + | $mouseoverTargets.on('mouseover', function () { |
| − | + | ||
var $this = $(this); | var $this = $(this); | ||
var itemname = $this.attr('title'); | var itemname = $this.attr('title'); | ||
| − | if (itemname == '' || itemname == 'undefined') | + | if (itemname == '' || itemname == 'undefined') return; |
| − | + | ||
| − | if (hideTimer) | + | if (hideTimer) clearTimeout(hideTimer); |
| − | + | ||
if ($this.parents('div.mw-content-ltr').length) { | if ($this.parents('div.mw-content-ltr').length) { | ||
| Line 161: | Line 172: | ||
container.css({ | container.css({ | ||
| − | + | left: pos.left + 5 + 'px', | |
| − | + | top: pos.top + 5 + 'px', | |
}); | }); | ||
} | } | ||
| − | |||
| − | |||
$(this).trigger('mousemove'); | $(this).trigger('mousemove'); | ||
| Line 177: | Line 186: | ||
// + '<p></p></div></div><div class="itembotbg"></div>'); | // + '<p></p></div></div><div class="itembotbg"></div>'); | ||
| − | if (ajax) | + | if (ajax) { |
| − | + | ||
ajax.abort(); | ajax.abort(); | ||
ajax = null; | ajax = null; | ||
} | } | ||
ajax = $.ajax({ | ajax = $.ajax({ | ||
| − | url: window.location.protocol + | + | url: |
| − | + | window.location.protocol + | |
| + | '//wiki.project1999.com/index.php/Special:AjaxHoverHelper/' + | ||
| + | itemname, | ||
cacheResponse: true, | cacheResponse: true, | ||
| − | success: function(html) | + | success: function (html) { |
| − | + | ||
var $html = $(html); | var $html = $(html); | ||
| − | $('#itemHoverContent').html($html[2]).prepend($html[0]).prepend($html[1]); | + | $('#itemHoverContent') |
| − | } | + | .html($html[2]) |
| + | .prepend($html[0]) | ||
| + | .prepend($html[1]); | ||
| + | }, | ||
}); | }); | ||
container.css('display', 'block'); | container.css('display', 'block'); | ||
//container.fadeIn('fast'); | //container.fadeIn('fast'); | ||
| − | |||
}); //on mouseover | }); //on mouseover | ||
| − | $('span.ih a').on('mouseout', function() | + | $('span.ih a').on('mouseout', function () { |
| − | + | if (hideTimer) clearTimeout(hideTimer); | |
| − | if (hideTimer) | + | hideTimer = setTimeout(function () { |
| − | + | ||
| − | hideTimer = setTimeout(function() | + | |
| − | + | ||
container.css('display', 'none'); | container.css('display', 'none'); | ||
//container.fadeOut('fast'); | //container.fadeOut('fast'); | ||
| Line 209: | Line 217: | ||
}); | }); | ||
| − | $('span.ih a').mousemove(function(e){ | + | $('span.ih a').mousemove(function (e) { |
var mousex = e.pageX + 20; //Get X coodrinates | var mousex = e.pageX + 20; //Get X coodrinates | ||
var mousey = e.pageY + 20; //Get Y coordinates | var mousey = e.pageY + 20; //Get Y coordinates | ||
| Line 220: | Line 228: | ||
var tipVisY = $(window).height() - (mousey + tipHeight); | var tipVisY = $(window).height() - (mousey + tipHeight); | ||
| − | if ( tipVisX < 20 ) { //If tooltip exceeds the X coordinate of viewport | + | if (tipVisX < 20) { |
| + | //If tooltip exceeds the X coordinate of viewport | ||
| − | if( tipWidth > e.pageX - 20 ){ | + | if (tipWidth > e.pageX - 20) { |
mousex = 0; | mousex = 0; | ||
} else { | } else { | ||
mousex = e.pageX - tipWidth - 20; | mousex = e.pageX - tipWidth - 20; | ||
} | } | ||
| − | + | } | |
| − | } if ( tipVisY < 20 ) { //If tooltip exceeds the Y coordinate of viewport | + | if (tipVisY < 20) { |
| + | //If tooltip exceeds the Y coordinate of viewport | ||
mousey = e.pageY - tipHeight - 20; | mousey = e.pageY - tipHeight - 20; | ||
} | } | ||
| − | container.css({ | + | container.css({ top: mousey, left: mousex }); |
}); | }); | ||
// Allow mouse over of details without hiding details | // Allow mouse over of details without hiding details | ||
| − | $('#itemHoverContainer').mouseover(function() | + | $('#itemHoverContainer').mouseover(function () { |
| − | + | if (hideTimer) clearTimeout(hideTimer); | |
| − | if (hideTimer) | + | |
| − | + | ||
}); | }); | ||
// Hide after mouseout | // Hide after mouseout | ||
| − | $('#itemHoverContainer').mouseout(function() | + | $('#itemHoverContainer').mouseout(function () { |
| − | + | if (hideTimer) clearTimeout(hideTimer); | |
| − | if (hideTimer) | + | hideTimer = setTimeout(function () { |
| − | + | ||
| − | hideTimer = setTimeout(function() | + | |
| − | + | ||
container.css('display', 'none'); | container.css('display', 'none'); | ||
//container.fadeOut('fast'); | //container.fadeOut('fast'); | ||
| Line 255: | Line 260: | ||
// magelo non-ajax item hover, but move box with mouse | // magelo non-ajax item hover, but move box with mouse | ||
| − | $('.magelohb').mousemove(function(e){ | + | $('.magelohb').mousemove(function (e) { |
var childContainer = $(this).children('span.hb'); | var childContainer = $(this).children('span.hb'); | ||
| Line 269: | Line 274: | ||
var tipVisY = $(window).height() - (mousey + tipHeight - 20); | var tipVisY = $(window).height() - (mousey + tipHeight - 20); | ||
| − | if ( tipVisX < 20 ) { //If tooltip exceeds the X coordinate of viewport | + | if (tipVisX < 20) { |
| + | //If tooltip exceeds the X coordinate of viewport | ||
| − | if( tipWidth > e.pageX - 20){ | + | if (tipWidth > e.pageX - 20) { |
mousex = 0; | mousex = 0; | ||
} else { | } else { | ||
mousex = e.pageX - tipWidth - 20; | mousex = e.pageX - tipWidth - 20; | ||
} | } | ||
| − | + | } | |
| − | } if ( tipVisY < 20 ) { //If tooltip exceeds the Y coordinate of viewport | + | if (tipVisY < 20) { |
| + | //If tooltip exceeds the Y coordinate of viewport | ||
mousey = e.pageY - tipHeight - 20; | mousey = e.pageY - tipHeight - 20; | ||
} | } | ||
| − | childContainer.css({ top: mousey, left: mousex, 'z-index':'999' }); | + | childContainer.css({ top: mousey, left: mousex, 'z-index': '999' }); |
}); | }); | ||
// change to position:fixed on all hover divs if we have JS active | // change to position:fixed on all hover divs if we have JS active | ||
// otherwise leave as position:absolute so the stationary hovers are near their items | // otherwise leave as position:absolute so the stationary hovers are near their items | ||
| − | $('.magelohb span.hb').each(function(i) { | + | $('.magelohb span.hb').each(function (i) { |
| − | $(this).css({ | + | $(this).css({ position: 'fixed' }); |
}); | }); | ||
| Line 297: | Line 304: | ||
// Fashion for item pages | // Fashion for item pages | ||
| − | var extractFashionHtml = function(html) { | + | var extractFashionHtml = function (html) { |
| − | return $(html).find('.fashion_show, .primary_secondary_show').map(function(i, el) { | + | return $(html) |
| − | + | .find('.fashion_show, .primary_secondary_show') | |
| − | + | .map(function (i, el) { | |
| − | + | var $el = $(el); | |
| − | + | var data = $el.data(); | |
| − | + | data.race = $el.find('.fashion_race').html(); | |
| − | + | if ($el.is('.fashion_show')) { | |
| − | + | data.armor = $el.find('.fashion_armor').html(); | |
| − | + | } | |
| − | + | return data; | |
| − | + | }) | |
| − | var getFashionShows = function(fashionCategory) { | + | .toArray(); |
| + | }; | ||
| + | |||
| + | var getFashionShows = function (fashionCategory) { | ||
var url = '/Category:Fashion: ' + fashionCategory; | var url = '/Category:Fashion: ' + fashionCategory; | ||
return $.get(url).then(extractFashionHtml); | return $.get(url).then(extractFashionHtml); | ||
}; | }; | ||
| − | var getItemPageShows = function() { | + | var getItemPageShows = function () { |
| − | var fashionCategories = | + | var fashionCategories = $('#catlinks li a') |
| − | + | .map(function (i, a) { | |
| − | + | return $(a).text(); | |
| − | + | }) | |
| − | + | .filter(function (i, text) { | |
| + | return text.startsWith('Fashion:'); | ||
| + | }) | ||
| + | .map(function (i, text) { | ||
| + | return text.substr('Fashion: '.length); | ||
| + | }); | ||
var fashion = fashionCategories[0]; | var fashion = fashionCategories[0]; | ||
if (!fashion) return $.when(); | if (!fashion) return $.when(); | ||
var tint = fashionCategories[1]; | var tint = fashionCategories[1]; | ||
| − | return getFashionShows(fashion).then(function(shows) { | + | return getFashionShows(fashion).then(function (shows) { |
var sameTint = []; | var sameTint = []; | ||
var otherTint = []; | var otherTint = []; | ||
| − | shows.forEach(function(show) { | + | shows.forEach(function (show) { |
var isHeld = show.primaryFashion || show.secondaryFashion; | var isHeld = show.primaryFashion || show.secondaryFashion; | ||
var bothHaveSameTint = show.tint === tint; | var bothHaveSameTint = show.tint === tint; | ||
| Line 334: | Line 349: | ||
else otherTint.push(show); | else otherTint.push(show); | ||
}); | }); | ||
| − | return { matches: sameTint, partialMatches: otherTint, fashion: fashion, tint: tint }; | + | return { |
| + | matches: sameTint, | ||
| + | partialMatches: otherTint, | ||
| + | fashion: fashion, | ||
| + | tint: tint, | ||
| + | }; | ||
}); | }); | ||
| − | } | + | }; |
| − | var addFashionSection = function(shows, isFullMatch) { | + | var addFashionSection = function (shows, isFullMatch) { |
var preface = isFullMatch | var preface = isFullMatch | ||
| − | + | ? '<h2>Fashion/Appearance</h2>' | |
| − | + | : '<div>Fashion images with the wrong "tint" (i.e. coloring) which ' + | |
| − | + | "can only be used to get a general sense of the item's " + | |
| − | + | 'appearance:</div>'; | |
// Don't show the explanatory text if there are no shows to explain | // Don't show the explanatory text if there are no shows to explain | ||
if (!shows.length && !isFullMatch) preface = ''; | if (!shows.length && !isFullMatch) preface = ''; | ||
| − | var $ul = $('<ul>').append(shows.map(function(show) { | + | var $ul = $('<ul>').append( |
| − | + | shows.map(function (show) { | |
| − | + | var img = isFullMatch | |
| − | + | ? '<br/><img style="max-height: 100px; max-width: 100px;" src="/images/' + | |
| − | + | show.file.replace(/ /g, '_') + | |
| − | + | '"/>' | |
| − | + | : ''; | |
| − | + | return ( | |
| + | '<li class="fashion-link" data-file="' + | ||
| + | show.file + | ||
| + | '">' + | ||
| + | '<a href="#">' + | ||
| + | show.gender + | ||
| + | ' ' + | ||
| + | show.race + | ||
| + | img + | ||
| + | '</a></li>' | ||
| + | ); | ||
| + | }) | ||
| + | ); | ||
$('#itemfashion').before($('<div>' + preface + '</div>').append($ul)); | $('#itemfashion').before($('<div>' + preface + '</div>').append($ul)); | ||
}; | }; | ||
| − | var addFashionSections = function() { | + | var addFashionSections = function () { |
| − | getItemPageShows().then(function(pageShows) { | + | getItemPageShows().then(function (pageShows) { |
| − | if(!pageShows) return; | + | if (!pageShows) return; |
var matches = pageShows.matches || []; | var matches = pageShows.matches || []; | ||
var partialMatches = pageShows.partialMatches || []; | var partialMatches = pageShows.partialMatches || []; | ||
if (pageShows.matches.length || pageShows.partialMatches.length) | if (pageShows.matches.length || pageShows.partialMatches.length) | ||
addFashionSection(pageShows.matches, true); | addFashionSection(pageShows.matches, true); | ||
| − | if (pageShows.partialMatches.length) | + | if (pageShows.partialMatches.length) |
addFashionSection(pageShows.partialMatches, false); | addFashionSection(pageShows.partialMatches, false); | ||
}); | }); | ||
}; | }; | ||
addFashionSections(); | addFashionSections(); | ||
| − | + | ||
| − | + | ||
//***************************************** | //***************************************** | ||
// Add class-based filtering to item tables | // Add class-based filtering to item tables | ||
//*****************************************w | //*****************************************w | ||
| − | + | ||
| − | // Determine whether or not a provided row should be shown for the provided | + | // Determine whether or not a provided row should be shown for the provided |
// class abbreviation (eg. "BRD") | // class abbreviation (eg. "BRD") | ||
| − | var isRowShown = function($tr, classAbbrev) { | + | var isRowShown = function ($tr, classAbbrev) { |
// Extract classes (and races) | // Extract classes (and races) | ||
| − | var | + | var classText = $tr.find('td').eq(3).text().split('Class:')[1]; |
| − | if (!classText) return true; | + | if (!classText) return true; // Ignore (don't filter) rows without class text |
| − | + | ||
// remove "Race: " part (if any) and upper-case text | // remove "Race: " part (if any) and upper-case text | ||
classText = classText.split('Race:')[0] || classText; | classText = classText.split('Race:')[0] || classText; | ||
classText = classText.toUpperCase(); | classText = classText.toUpperCase(); | ||
| − | + | ||
// determine matching text | // determine matching text | ||
var isMatch = classText.includes(classAbbrev); | var isMatch = classText.includes(classAbbrev); | ||
var isAllMatch = classText.includes('ALL'); | var isAllMatch = classText.includes('ALL'); | ||
var isExcept = classText.includes('ALL EXCEPT'); | var isExcept = classText.includes('ALL EXCEPT'); | ||
| − | + | ||
// determine matches | // determine matches | ||
if (isMatch && !isExcept) return true; // (eg. BRD in "BRD") | if (isMatch && !isExcept) return true; // (eg. BRD in "BRD") | ||
| − | if (!isMatch && isExcept) return true; | + | if (!isMatch && isExcept) return true; // (eg. BRD in "ALL EXCEPT WIZ") |
if (!isExcept && isAllMatch) return true; // (eg. BRD in "ALL") | if (!isExcept && isAllMatch) return true; // (eg. BRD in "ALL") | ||
return false; | return false; | ||
}; | }; | ||
| − | + | ||
| − | var scrollToTable = function($table) { | + | var scrollToTable = function ($table) { |
| − | window.setTimeout(function() { | + | window.setTimeout(function () { |
| − | $('html, body').animate({ scrollTop: | + | $('html, body').animate({ scrollTop: $table.offset().top }, 200); |
}, 100); | }, 100); | ||
}; | }; | ||
| − | + | ||
| − | // Filter the provided table to only display rows for the provided class | + | // Filter the provided table to only display rows for the provided class |
// abbreviation | // abbreviation | ||
| − | var filterTable = function($table, classAbbrev) { | + | var filterTable = function ($table, classAbbrev) { |
$table.find('tr').each(function (i, tr) { | $table.find('tr').each(function (i, tr) { | ||
var $tr = $(tr); | var $tr = $(tr); | ||
| Line 415: | Line 446: | ||
}); | }); | ||
scrollToTable($table); | scrollToTable($table); | ||
| − | + | ||
addFilterLink($table, false); | addFilterLink($table, false); | ||
| − | $('.itemsUnfilterLink').click(function() { | + | $('.itemsUnfilterLink').click(function () { |
unfilterTable($table); | unfilterTable($table); | ||
}); | }); | ||
| − | + | ||
alert('Filtered to only show rows containing ' + classAbbrev + ' gear.'); | alert('Filtered to only show rows containing ' + classAbbrev + ' gear.'); | ||
}; | }; | ||
| − | + | ||
// Restore a table to its previous, un-filtered state | // Restore a table to its previous, un-filtered state | ||
| − | var unfilterTable = function($table) { | + | var unfilterTable = function ($table) { |
$table.find('tr').show(); | $table.find('tr').show(); | ||
addFilterLink($table, true); | addFilterLink($table, true); | ||
scrollToTable($table); | scrollToTable($table); | ||
}; | }; | ||
| − | + | ||
| − | // When a user clicks on a table class filter link, handle it by asking them | + | // When a user clicks on a table class filter link, handle it by asking them |
// which class (and then filtering the table for that class) | // which class (and then filtering the table for that class) | ||
| − | var handleItemFilterLinkClick = function(e) { | + | var handleItemFilterLinkClick = function (e) { |
| − | var promptMessage = 'Please enter the three-letter abbreviation for the ' + | + | var promptMessage = |
| − | + | 'Please enter the three-letter abbreviation for the ' + | |
| − | + | 'class you want to filter by (eg. "brd" for "Bard").'; | |
| + | |||
var $table = $(e.target).closest('table'); | var $table = $(e.target).closest('table'); | ||
var classAbbrev = prompt(promptMessage).toUpperCase(); | var classAbbrev = prompt(promptMessage).toUpperCase(); | ||
if (!classAbbrev || classAbbrev.length !== 3 || classAbbrev === 'ALL') { | if (!classAbbrev || classAbbrev.length !== 3 || classAbbrev === 'ALL') { | ||
| − | alert('A 3-digit abbreviation wasn\'t entered (or "All" was entered); ' + | + | alert( |
| − | 'filtering disabled'); | + | 'A 3-digit abbreviation wasn\'t entered (or "All" was entered); ' + |
| + | 'filtering disabled' | ||
| + | ); | ||
unfilterTable($table); | unfilterTable($table); | ||
return false; | return false; | ||
| Line 447: | Line 481: | ||
filterTable($table, classAbbrev); | filterTable($table, classAbbrev); | ||
}; | }; | ||
| − | + | ||
// Adds either a filter or unfilter link (as determined by showFilter) to the | // Adds either a filter or unfilter link (as determined by showFilter) to the | ||
// provided table | // provided table | ||
| − | var addFilterLink = function($table, showFilter) { | + | var addFilterLink = function ($table, showFilter) { |
var $statsHeaderCells = $table.find('th:contains("Stats")'); | var $statsHeaderCells = $table.find('th:contains("Stats")'); | ||
var filterType = showFilter ? 'Filter' : 'Unfilter'; | var filterType = showFilter ? 'Filter' : 'Unfilter'; | ||
| − | $statsHeaderCells.html('Stats <span style="float:right">' + | + | $statsHeaderCells.html( |
| − | '<a style="text-decoration: underline" class="items' + filterType + 'Link" href="#">' + | + | 'Stats <span style="float:right">' + |
| − | filterType + (showFilter ? ' by Class' : '') + '</a></span>'); | + | '<a style="text-decoration: underline" class="items' + |
| − | + | filterType + | |
| + | 'Link" href="#">' + | ||
| + | filterType + | ||
| + | (showFilter ? ' by Class' : '') + | ||
| + | '</a></span>' | ||
| + | ); | ||
| + | |||
var $link = $statsHeaderCells.find('.items' + filterType + 'Link'); | var $link = $statsHeaderCells.find('.items' + filterType + 'Link'); | ||
if (showFilter) $link.click(handleItemFilterLinkClick); | if (showFilter) $link.click(handleItemFilterLinkClick); | ||
| − | else $link.click(function() { unfilterTable($table); }) | + | else |
| + | $link.click(function () { | ||
| + | unfilterTable($table); | ||
| + | }); | ||
}; | }; | ||
| − | + | ||
// Add class filtering links to all item tables | // Add class filtering links to all item tables | ||
| − | var addItemFilteringLinks = function() { | + | var addItemFilteringLinks = function () { |
var $tables = $('table th:contains("Item Name")').closest('table'); | var $tables = $('table th:contains("Item Name")').closest('table'); | ||
| − | $tables.each(function(i, table) { | + | $tables.each(function (i, table) { |
var $table = $(table); | var $table = $(table); | ||
// Make sure it has both "Item Name" and "Stats" columns | // Make sure it has both "Item Name" and "Stats" columns | ||
if (!$table.has('th:contains("Stats")')) return; | if (!$table.has('th:contains("Stats")')) return; | ||
| − | + | ||
addFilterLink($table, true); | addFilterLink($table, true); | ||
}); | }); | ||
}; | }; | ||
addItemFilteringLinks(); | addItemFilteringLinks(); | ||
| − | + | ||
//***************************************** | //***************************************** | ||
// End class-based filtering to item tables | // End class-based filtering to item tables | ||
| Line 482: | Line 525: | ||
if (window.location.pathname.includes('Special:ClassSlotEquip')) { | if (window.location.pathname.includes('Special:ClassSlotEquip')) { | ||
// Add checkboxes UI to the page | // Add checkboxes UI to the page | ||
| − | $('table') | + | $('table').before( |
| − | + | '<label><input id="showNoDrop" type="checkbox" checked/> Show No Drop</label> ' + | |
| − | + | '<label><input id="showDroppable" type="checkbox" checked/> Show Droppable</label>' /*+ | |
'| <label><input id="showEffect" type="checkbox" checked/> Show With Effects</label>' + | '| <label><input id="showEffect" type="checkbox" checked/> Show With Effects</label>' + | ||
| − | '<label><input id="showNoEffect" type="checkbox" checked/> Show Without Effects</label>'*/); | + | '<label><input id="showNoEffect" type="checkbox" checked/> Show Without Effects</label>'*/ |
| + | ); | ||
// Handle when drop/no drop box is checked | // Handle when drop/no drop box is checked | ||
| − | $('#showNoDrop, #showDroppable').change(function() { | + | $('#showNoDrop, #showDroppable').change(function () { |
var showNoDrop = $('#showNoDrop').is(':checked'); | var showNoDrop = $('#showNoDrop').is(':checked'); | ||
var showDroppable = $('#showDroppable').is(':checked'); | var showDroppable = $('#showDroppable').is(':checked'); | ||
| Line 495: | Line 539: | ||
// .... but those rows do have an old bgcolor="#cccccc" attribute | // .... but those rows do have an old bgcolor="#cccccc" attribute | ||
// that we can use to identify (and not hide) them | // that we can use to identify (and not hide) them | ||
| − | $('tbody tr[bgcolor!=#cccccc]').each(function(i, el) { | + | $('tbody tr[bgcolor!=#cccccc]').each(function (i, el) { |
var text = $(el).find('td:eq(0) .itemdata').text(); | var text = $(el).find('td:eq(0) .itemdata').text(); | ||
var isNoDrop = text.includes('NO DROP'); | var isNoDrop = text.includes('NO DROP'); | ||
| Line 501: | Line 545: | ||
}); | }); | ||
}); | }); | ||
| − | /* | + | /* |
Problem: the event handler needs to be merged so unchecking one box (eg. effect) doesn't undo the other (eg. no drop) | Problem: the event handler needs to be merged so unchecking one box (eg. effect) doesn't undo the other (eg. no drop) | ||
| Line 519: | Line 563: | ||
*/ | */ | ||
} | } | ||
| − | |||
// Generic Table Filtering (for Template:TableFilterCheckbox) | // Generic Table Filtering (for Template:TableFilterCheckbox) | ||
| − | $('.table-filter-checkbox-container').each(function(i, el) { | + | $('.table-filter-checkbox-container').each(function (i, el) { |
var $container = $(el); | var $container = $(el); | ||
var matchSelector = $container.data('match'); | var matchSelector = $container.data('match'); | ||
var text = $container.text(); | var text = $container.text(); | ||
| − | $container.html('<label><input class="table-filter-checkbox" type="checkbox" ' + | + | $container.html( |
| − | + | '<label><input class="table-filter-checkbox" type="checkbox" ' + | |
| + | 'value="' + | ||
| + | matchSelector + | ||
| + | '" checked />' + | ||
| + | text + | ||
| + | '</label>' | ||
| + | ); | ||
}); | }); | ||
| − | var shouldRowBeShown = function(tr) { | + | var shouldRowBeShown = function (tr) { |
var $tr = $(tr); | var $tr = $(tr); | ||
// Check all the checkboxes to see if any given row should appear | // Check all the checkboxes to see if any given row should appear | ||
| Line 536: | Line 585: | ||
return $('.table-filter-checkbox') | return $('.table-filter-checkbox') | ||
.toArray() | .toArray() | ||
| − | .reduce(function(isShown, checkbox) { | + | .reduce(function (isShown, checkbox) { |
var matchSelector = $(checkbox).val(); | var matchSelector = $(checkbox).val(); | ||
| − | var matches = $tr.is(matchSelector) || | + | var matches = $tr.is(matchSelector) || !!$tr.has(matchSelector).length; |
| − | + | ||
var isChecked = $(checkbox).attr('checked'); | var isChecked = $(checkbox).attr('checked'); | ||
return isShown && !!(isChecked || (!isChecked && !matches)); | return isShown && !!(isChecked || (!isChecked && !matches)); | ||
}, true); | }, true); | ||
| − | } | + | }; |
| − | $('body').on('change', '.table-filter-checkbox', function(e) { | + | $('body').on('change', '.table-filter-checkbox', function (e) { |
$('table').show(); | $('table').show(); | ||
| − | $('table:not(.toc) tbody tr:not([bgcolor="#cccccc"])').each(function(i, tr) { | + | $('table:not(.toc) tbody tr:not([bgcolor="#cccccc"])').each(function ( |
| + | i, | ||
| + | tr | ||
| + | ) { | ||
$(tr).toggle(shouldRowBeShown(tr)); | $(tr).toggle(shouldRowBeShown(tr)); | ||
}); | }); | ||
// If all of a table's non-header rows are hidden, hide it | // If all of a table's non-header rows are hidden, hide it | ||
| − | $('table').filter(function(i, table) { | + | $('table') |
| − | + | .filter(function (i, table) { | |
| − | + | return !$(table).has('tr:visible:not([bgcolor="#cccccc"])').length; | |
| + | }) | ||
| + | .hide(); | ||
}); | }); | ||
// Convert youtube template divs into actual iframes | // Convert youtube template divs into actual iframes | ||
| − | $('.youtube-placeholder').each(function(i, placeholder) { | + | $('.youtube-placeholder').each(function (i, placeholder) { |
var $placeholder = $(placeholder); | var $placeholder = $(placeholder); | ||
var data = $placeholder.data(); | var data = $placeholder.data(); | ||
| Line 563: | Line 616: | ||
// @see https://stackoverflow.com/questions/25661182/embed-youtube-video-refused-to-display-in-a-frame-because-it-set-x-frame-opti | // @see https://stackoverflow.com/questions/25661182/embed-youtube-video-refused-to-display-in-a-frame-because-it-set-x-frame-opti | ||
//if (url.includes('/watch?') url = url.replace('/watch?', '/embed?'); | //if (url.includes('/watch?') url = url.replace('/watch?', '/embed?'); | ||
| − | + | ||
// TODO: get height/width from template? | // TODO: get height/width from template? | ||
$placeholder.replaceWith( | $placeholder.replaceWith( | ||
'<iframe ' + | '<iframe ' + | ||
| − | 'width="' + (data.width || '') + '" ' + | + | 'width="' + |
| − | 'height="' + (data.height || '') + '" ' + | + | (data.width || '') + |
| − | 'src="' + url + '" ' + | + | '" ' + |
| + | 'height="' + | ||
| + | (data.height || '') + | ||
| + | '" ' + | ||
| + | 'src="' + | ||
| + | url + | ||
| + | '" ' + | ||
'frameborder="0" ' + | 'frameborder="0" ' + | ||
'allow="accelerometer; autoplay; encrypted-media; gyroscope; picture-in-picture" ' + | 'allow="accelerometer; autoplay; encrypted-media; gyroscope; picture-in-picture" ' + | ||
'allowfullscreen' + | 'allowfullscreen' + | ||
| − | + | '></iframe>' | |
); | ); | ||
}); | }); | ||
| Line 581: | Line 640: | ||
var fullTitle = $('title').text(); | var fullTitle = $('title').text(); | ||
| − | var title = fullTitle.substr(0, fullTitle.length - ' - Project 1999 Wiki'.length); | + | var title = fullTitle.substr( |
| − | switch(title) { | + | 0, |
| + | fullTitle.length - ' - Project 1999 Wiki'.length | ||
| + | ); | ||
| + | switch (title) { | ||
case 'Magelo Blue': | case 'Magelo Blue': | ||
case 'Magelo Green': | case 'Magelo Green': | ||
case 'Magelo Red': | case 'Magelo Red': | ||
| − | $('.createboxInput').on('focus', function() { this.value = ''}); | + | $('.createboxInput').on('focus', function () { |
| + | this.value = ''; | ||
| + | }); | ||
break; | break; | ||
// Give the Per-Level Hunting Guide Page its own JS | // Give the Per-Level Hunting Guide Page its own JS | ||
| Line 611: | Line 675: | ||
case 'Magelo Import': | case 'Magelo Import': | ||
importScript('MediaWiki:MageloImport.js'); | importScript('MediaWiki:MageloImport.js'); | ||
| − | break; | + | break; |
case 'Mobs By Level': | case 'Mobs By Level': | ||
// Basic DOM manipulation (since the wiki won't let us add <input> tags in the wiki text | // Basic DOM manipulation (since the wiki won't let us add <input> tags in the wiki text | ||
| − | $('#placeholder') | + | $('#placeholder').replaceWith( |
| − | + | '<form id="form">' + | |
| − | + | 'Class: <input id="class" style="width: 8em" value="Warrior" /> ' + | |
| − | + | 'Level: <input id="level" style="width: 4em" /> ' + | |
| − | + | '<input type="submit"/>' + | |
| − | + | ||
'</form>' | '</form>' | ||
| − | + | ); | |
| − | $('#form').submit(function() { | + | $('#form').submit(function () { |
| − | var clazz = $('#class').val(); | + | var clazz = $('#class').val(); |
| − | var level = $('#level').val(); | + | var level = $('#level').val(); |
| − | window.location = 'https://wiki.project1999.com/index.php?title=Special:Search&limit=500&offset=0&redirs=0&profile=default&search=%22Level%5C%3A%5C+' + | + | window.location = |
| − | + | 'https://wiki.project1999.com/index.php?title=Special:Search&limit=500&offset=0&redirs=0&profile=default&search=%22Level%5C%3A%5C+' + | |
| + | level + | ||
| + | '%22+-%22Shopkeeper%22+-%22Merchant%22+%22Class%5C%3A%5C+' + | ||
| + | clazz + | ||
| + | '%22+-"startMageloProfile"'; | ||
return false; | return false; | ||
}); | }); | ||
| Line 634: | Line 701: | ||
// the table of contents is shown | // the table of contents is shown | ||
| − | var setNotesColumns = function(cols) { $('#notesWrapper').css('width', cols ? cols + 'em' : ''); }; | + | var setNotesColumns = function (cols) { |
| − | var toggleNotRelevant =function(isChecked) { | + | $('#notesWrapper').css('width', cols ? cols + 'em' : ''); |
| − | $('#notesWrapper').find(':not(:visible)').show() | + | }; |
| + | var toggleNotRelevant = function (isChecked) { | ||
| + | $('#notesWrapper').find(':not(:visible)').show(); | ||
if (isChecked) return; | if (isChecked) return; | ||
| − | $('#notesWrapper').children().filter(function(i, el) { | + | $('#notesWrapper') |
| − | + | .children() | |
| − | + | .filter(function (i, el) { | |
| − | + | var isRelevant = $(el).is('.relevant'); | |
| − | + | $(el).toggle(isRelevant); | |
| − | }) | + | // Show the patch header also |
| + | if (isRelevant) $(el).prevUntil('h3').last().prev().show(); | ||
| + | }); | ||
| + | }; | ||
| + | var toggleTableOfContents = function (isChecked) { | ||
| + | $('#toc').toggle(isChecked); | ||
| + | }; | ||
| + | var togglePatchHeaders = function (isChecked) { | ||
| + | $('.toclevel-4').toggle(isChecked); | ||
}; | }; | ||
| − | |||
| − | |||
var notesWidth = getStateByPage('notes-width') || ''; | var notesWidth = getStateByPage('notes-width') || ''; | ||
| − | var showTableOfContents = getStateByPage('show-table-of-contents') !== false; | + | var showTableOfContents = |
| + | getStateByPage('show-table-of-contents') !== false; | ||
var showPatchHeaders = getStateByPage('show-patch-headers') !== false; | var showPatchHeaders = getStateByPage('show-patch-headers') !== false; | ||
var showNotRelevant = getStateByPage('show-not-relevant') !== false; | var showNotRelevant = getStateByPage('show-not-relevant') !== false; | ||
| Line 660: | Line 736: | ||
$('#patchNoteOptions').html( | $('#patchNoteOptions').html( | ||
| − | + | '<div><label><input ' + | |
| − | + | (showTableOfContents ? 'checked ' : '') + | |
| − | + | 'id="show-table-of-contents" type="checkbox" /> Show Table of Contents?<label><br/>' + | |
| − | + | '<label><input ' + | |
| + | (showPatchHeaders ? 'checked ' : '') + | ||
| + | 'id="show-patch-headers" type="checkbox"/> Show patch headers in Table of Contents?<label><br/>' + | ||
| + | '<label><input ' + | ||
| + | (showNotRelevant ? 'checked ' : '') + | ||
| + | 'id="show-not-relevant" type="checkbox"/> Show content not marked as relevant to P99?<label></div>' + | ||
| + | '<div><label>Limit notes to a width of <input id="notes-width" placeholder="40" style="width: 4em;" value="' + | ||
| + | notesWidth + | ||
| + | '" /> columns (for readability)</label></div>' | ||
); | ); | ||
| − | $('#notes-width').change(function(e) { | + | $('#notes-width').change(function (e) { |
var cols = parseFloat($(e.target).val()); | var cols = parseFloat($(e.target).val()); | ||
setNotesColumns(cols); | setNotesColumns(cols); | ||
setStateByPage('notes-width', cols); | setStateByPage('notes-width', cols); | ||
}); | }); | ||
| − | $('#show-table-of-contents').change(function(e) { | + | $('#show-table-of-contents').change(function (e) { |
| − | var isChecked | + | var isChecked = $(e.target).is(':checked'); |
toggleTableOfContents(isChecked); | toggleTableOfContents(isChecked); | ||
setStateByPage('show-table-of-contents', isChecked); | setStateByPage('show-table-of-contents', isChecked); | ||
}); | }); | ||
| − | $('#show-patch-headers').change(function(e) { | + | $('#show-patch-headers').change(function (e) { |
| − | var isChecked | + | var isChecked = $(e.target).is(':checked'); |
togglePatchHeaders(isChecked); | togglePatchHeaders(isChecked); | ||
setStateByPage('show-patch-headers', isChecked); | setStateByPage('show-patch-headers', isChecked); | ||
}); | }); | ||
| − | $('#show-not-relevant').change(function(e) { | + | $('#show-not-relevant').change(function (e) { |
| − | var isChecked | + | var isChecked = $(e.target).is(':checked'); |
toggleNotRelevant(isChecked); | toggleNotRelevant(isChecked); | ||
setStateByPage('show-not-relevant', isChecked); | setStateByPage('show-not-relevant', isChecked); | ||
| Line 690: | Line 774: | ||
// Warn users who accidentally try to edit a templated section | // Warn users who accidentally try to edit a templated section | ||
| − | if ((window.location + '').includes('title=Template:Namedmobpage&action=edit')) { | + | if ( |
| − | alert( | + | (window.location + '').includes('title=Template:Namedmobpage&action=edit') |
| + | ) { | ||
| + | alert( | ||
| + | "Warning: You are attempting you edit the template for all named mobs. You probably didn't mean to do that: you probably clicked on an edit link somewhere in the page and wound up here. To avoid this simply go back and use the edit *tab* at the top of the page instead." | ||
| + | ); | ||
} | } | ||
| Line 704: | Line 792: | ||
var isUnderTenLines = $('#wpTextbox1').val().split('\n').length < 10; | var isUnderTenLines = $('#wpTextbox1').val().split('\n').length < 10; | ||
var url = '/' + pageName + '#' + (section + extra).replace(/ /g, '_'); | var url = '/' + pageName + '#' + (section + extra).replace(/ /g, '_'); | ||
| − | var message = 'This page uses "transclusion" to show part of another page, specifically the code:\n\n {{#lsth:' + pageName + | + | var message = |
| − | + | 'This page uses "transclusion" to show part of another page, specifically the code:\n\n {{#lsth:' + | |
| − | + | pageName + | |
| + | '|[[' + | ||
| + | section + | ||
| + | ']]' + | ||
| + | extra + | ||
| + | '}}\n\nIf you want to edit the transcluded section, click "Ok": you will be taken to that page.' + | ||
| + | ' If you want to stay on this page, click "Cancel".'; | ||
if (isEdit && isUnderTenLines && confirm(message)) location = url; | if (isEdit && isUnderTenLines && confirm(message)) location = url; | ||
} | } | ||
| Line 713: | Line 807: | ||
var selectedServer = getGlobalState('selectedServer') || 'Blue'; | var selectedServer = getGlobalState('selectedServer') || 'Blue'; | ||
| − | var buildTabHtml = function(serverNames) { | + | var buildTabHtml = function (serverNames) { |
| − | var tabDivs = serverNames.map(function(name, i) { | + | var tabDivs = serverNames.map(function (name, i) { |
| − | return '<div id="' + name + 'Tab" class="tab' + (name === selectedServer ? ' selected' : '') + '">'+ name + '</div>'; | + | return ( |
| + | '<div id="' + | ||
| + | name + | ||
| + | 'Tab" class="tab' + | ||
| + | (name === selectedServer ? ' selected' : '') + | ||
| + | '">' + | ||
| + | name + | ||
| + | '</div>' | ||
| + | ); | ||
}); | }); | ||
| − | return '<div class="tabs">' + tabDivs.join('') + '<div class="clear"></div></div>'; | + | return ( |
| + | '<div class="tabs">' + | ||
| + | tabDivs.join('') + | ||
| + | '<div class="clear"></div></div>' | ||
| + | ); | ||
}; | }; | ||
| − | var selectTab = function(name) { | + | var selectTab = function (name) { |
// show the server's box (and hide the others) | // show the server's box (and hide the others) | ||
$trackers.hide(); | $trackers.hide(); | ||
| Line 730: | Line 836: | ||
// Select the tab for that server (and unselect the others) | // Select the tab for that server (and unselect the others) | ||
$('.auctrackerbox .tab').removeClass('selected'); | $('.auctrackerbox .tab').removeClass('selected'); | ||
| − | var $tab = $('.auctrackerbox .tab:contains("' + name + | + | var $tab = $('.auctrackerbox .tab:contains("' + name + '")'); |
if (!$tab.length) $tab = $('.auctrackerbox .tab:first'); | if (!$tab.length) $tab = $('.auctrackerbox .tab:first'); | ||
$tab.addClass('selected'); | $tab.addClass('selected'); | ||
| Line 740: | Line 846: | ||
if ($trackers.length) { | if ($trackers.length) { | ||
// Convert IDs of "auc_Blue" into an array of ["Blue", "Green", ...] | // Convert IDs of "auc_Blue" into an array of ["Blue", "Green", ...] | ||
| − | var servers = $trackers.toArray().map(function(tracker) { | + | var servers = $trackers.toArray().map(function (tracker) { |
| − | return tracker.id.substr(4); | + | return tracker.id.substr(4); |
}); | }); | ||
$trackers.prepend(buildTabHtml(servers)); | $trackers.prepend(buildTabHtml(servers)); | ||
selectTab(selectedServer); | selectTab(selectedServer); | ||
| − | $trackers.on('click', '.tab', function(e) { | + | $trackers.on('click', '.tab', function (e) { |
selectTab($(e.target).text()); | selectTab($(e.target).text()); | ||
}); | }); | ||
| Line 756: | Line 862: | ||
var forumIds = { blue: 27, green: 77, red: 59, teal: 78 }; | var forumIds = { blue: 27, green: 77, red: 59, teal: 78 }; | ||
| − | + | $('.auctrackerbox span span:contains("Project 1999 Auction Tracker")').each( | |
| − | $('.auctrackerbox span span:contains("Project 1999 Auction Tracker")').each(function(i, el) { | + | function (i, el) { |
| − | + | var $el = $(el); | |
| − | + | var serverName = $el | |
| − | + | .closest('.auctrackerbox') | |
| − | + | .attr('id') | |
| − | + | .substr(4) | |
| − | + | .toLowerCase(); | |
| − | + | const forumSearchUrl = | |
| − | + | 'https://www.project1999.com/forums/search.php?do=process&forumchoice[]=' + | |
| − | + | forumIds[serverName] + | |
| − | + | '&query=%22' + | |
| − | + | $('#firstHeading').text() + | |
| + | '%22'; | ||
| + | $el.append( | ||
| + | '<a ' + | ||
| + | 'style="font-size: 0.5em; float: right" ' + | ||
| + | 'target="_new" ' + | ||
| + | 'href="' + | ||
| + | forumSearchUrl + | ||
| + | '"' + | ||
| + | '>Search Forum</a>' | ||
| + | ); | ||
| + | } | ||
| + | ); | ||
} | } | ||
}); | }); | ||
Revision as of 21:44, 20 December 2020
/* Any JavaScript here will be loaded for all users on every page load. */
importScript('MediaWiki:Polyfills.js');
// HTTP prevents people from logging in now in (some?) Chrome browsers; redirect to HTTPS
try {
var onHttp = location.protocol === 'http:';
var haveNotTriedAlready = !location.search.includes('redirected_from_http');
if (onHttp && haveNotTriedAlready) {
location =
location.origin.replace('http:', 'https:') +
location.pathname +
location.search +
(location.search[0] === '?' ? '&' : '?') +
'redirected_from_http=1' +
location.hash;
}
} catch (err) {
// Give up on trying to redirect
// maybe alert user?
}
importScript('MediaWiki:Simple-lightbox.min.js');
importScript('MediaWiki:Zones.js');
// Get all magelos of current user
// (currently un-used, but intended for future achievement code, so that
// we can have an "add this achievement to my magelo" drop-down with all
// their magelos listed)
var getMagelosForCurrentUser = function () {
var userName = $('#pt-userpage a').text();
var url =
'https://wiki.project1999.com/index.php?limit=50&tagfilter=&' +
'title=Special%3AContributions&contribs=user&target=' +
userName +
'&namespace=500&topOnly=1&year=&month=-1';
fetch(url)
.then(function (response) {
return response.text();
})
.then(function (html) {
var mageloLinks = Array.from($(html).find('li a:contains("Magelo")'));
var names = mageloLinks
.filter(function (i, a) {
return !$(a).text().includes('(');
})
.map(function (i, el) {
return $(el).text();
});
console.log(names);
});
};
// **********************************
// Add localStorage helper functions
// **********************************
/**
* Basic "state getter": checks localStorage for *stateKey*, then return the
* value for *pageName* (if any) found on that object.
*/
var getPageState = function (pageName, stateKey) {
// Get the state for all pages for this key
var allPageStates = JSON.parse(localStorage.getItem(stateKey) || '{}');
// Extract just the state for this page (if any)
return allPageStates[pageName];
};
/**
* Returns the state data stored for the provided stateKey and the current page.
* For instance, getStateByPage('checkbox-status') would return the checkbox\
* status state for the current page.
*/
window.getStateByPage = function (stateKey) {
var pageName = location.pathname.substr(1); // ditch the leading "/"
return getPageState(pageName, stateKey);
};
/**
* Return the global state for a provided state key
* (works just like getStateByPage, but for states that don't care
* about which page you are on)
*/
window.getGlobalState = function (stateKey) {
return getPageState('__global', stateKey);
};
/**
* Basic "state setter" function
*/
var setPageState = function (pageName, stateKey, state) {
// Get the state for this key (for all pages) out of local storage
var allPageStates = JSON.parse(localStorage.getItem(stateKey) || '{}');
// Set the state only for this page
allPageStates[pageName] = state;
// Put the state for the stateKey (for all pages) back into local storage
localStorage.setItem(stateKey, JSON.stringify(allPageStates));
};
/**
* Sets the state data stored for the provided stateKey and the current page.
* For instance, setStateByPage('checkbox-status', {a: 'b'}) would set the
* checkbox status state for the current page to an object with a key of "a" and
* value of "b".
*/
window.setStateByPage = function (stateKey, state) {
var pageName = location.pathname.substr(1); // ditch the leading "/"
setPageState(pageName, stateKey, state);
};
window.setGlobalState = function (stateKey, state) {
return setPageState('__global', stateKey, state);
};
// *******************************
/* p1999wiki.js
* written by http://wiki.project1999.com/User:Ravhin
* last update: 7 January, 2018 by Loramin
*/
$(function () {
var hideDelay = 0;
var trigDelay = 250;
var hideTimer = null;
var ajax = null;
var currentPosition = { left: '0px', top: '0px' };
// One instance that's reused to show info for the current person
var container = $(
'<div id="itemHoverContainer">' + '<div id="HoverContent"></div>' + '</div>'
);
$('body').append(container);
/* --- hoverbox for item/mob, currently only used in magelo --- */
// Determine which "a" elements should trigger the item stats mouseover
var $mouseoverTargets = $('span.ih a');
var isItemCategory =
document.title.startsWith('Category:') &&
document.title.includes('Equipment - Project 1999 Wiki') &&
!document.title.includes('Worshiper Equipment');
if (isItemCategory) {
// Include the category's item list along with ".ih" links
$mouseoverTargets = $mouseoverTargets.add('.mw-content-ltr a');
}
$mouseoverTargets = $mouseoverTargets.filter(function (i, a) {
// Don't add hover to links like "next 200"
return (
!$(a).attr('href').startsWith('/Special:') &&
!$(a).attr('href').includes('title=Category:')
);
});
$mouseoverTargets.on('mouseover', function () {
var $this = $(this);
var itemname = $this.attr('title');
if (itemname == '' || itemname == 'undefined') return;
if (hideTimer) clearTimeout(hideTimer);
if ($this.parents('div.mw-content-ltr').length) {
var pos = $this.offset();
var width = $this.width();
container.css({
left: pos.left + 5 + 'px',
top: pos.top + 5 + 'px',
});
}
$(this).trigger('mousemove');
$('#itemHoverContent').html(' ');
//$('#itemHoverContent').html('<div class="itemtopbg"><div class="itemtitle">Loading...</div></div>'
// + '<div class="itembg" style="min-height:50px;"><div class="itemdata">'
// + '<div class="itemicon" style="float:right;"><img alt="" src="/images/Ajax_loader.gif" border="0"></div>'
// + '<p></p></div></div><div class="itembotbg"></div>');
if (ajax) {
ajax.abort();
ajax = null;
}
ajax = $.ajax({
url:
window.location.protocol +
'//wiki.project1999.com/index.php/Special:AjaxHoverHelper/' +
itemname,
cacheResponse: true,
success: function (html) {
var $html = $(html);
$('#itemHoverContent')
.html($html[2])
.prepend($html[0])
.prepend($html[1]);
},
});
container.css('display', 'block');
//container.fadeIn('fast');
}); //on mouseover
$('span.ih a').on('mouseout', function () {
if (hideTimer) clearTimeout(hideTimer);
hideTimer = setTimeout(function () {
container.css('display', 'none');
//container.fadeOut('fast');
}, hideDelay);
});
$('span.ih a').mousemove(function (e) {
var mousex = e.pageX + 20; //Get X coodrinates
var mousey = e.pageY + 20; //Get Y coordinates
var tipWidth = container.width(); //Find width of tooltip
var tipHeight = container.height(); //Find height of tooltip
//Distance of element from the right edge of viewport
var tipVisX = $(window).width() - (mousex + tipWidth);
//Distance of element from the bottom of viewport
var tipVisY = $(window).height() - (mousey + tipHeight);
if (tipVisX < 20) {
//If tooltip exceeds the X coordinate of viewport
if (tipWidth > e.pageX - 20) {
mousex = 0;
} else {
mousex = e.pageX - tipWidth - 20;
}
}
if (tipVisY < 20) {
//If tooltip exceeds the Y coordinate of viewport
mousey = e.pageY - tipHeight - 20;
}
container.css({ top: mousey, left: mousex });
});
// Allow mouse over of details without hiding details
$('#itemHoverContainer').mouseover(function () {
if (hideTimer) clearTimeout(hideTimer);
});
// Hide after mouseout
$('#itemHoverContainer').mouseout(function () {
if (hideTimer) clearTimeout(hideTimer);
hideTimer = setTimeout(function () {
container.css('display', 'none');
//container.fadeOut('fast');
}, hideDelay);
});
// magelo non-ajax item hover, but move box with mouse
$('.magelohb').mousemove(function (e) {
var childContainer = $(this).children('span.hb');
var tipWidth = childContainer.width(); //Find width of tooltip
var tipHeight = childContainer.height(); //Find height of tooltip
var mousex = e.pageX + 20; //Get X coodrinates
var mousey = e.pageY + 20; //Get Y coordinates
//Distance of element from the right edge of viewport
var tipVisX = $(window).width() - (mousex + tipWidth - 20);
//Distance of element from the bottom of viewport
var tipVisY = $(window).height() - (mousey + tipHeight - 20);
if (tipVisX < 20) {
//If tooltip exceeds the X coordinate of viewport
if (tipWidth > e.pageX - 20) {
mousex = 0;
} else {
mousex = e.pageX - tipWidth - 20;
}
}
if (tipVisY < 20) {
//If tooltip exceeds the Y coordinate of viewport
mousey = e.pageY - tipHeight - 20;
}
childContainer.css({ top: mousey, left: mousex, 'z-index': '999' });
});
// change to position:fixed on all hover divs if we have JS active
// otherwise leave as position:absolute so the stationary hovers are near their items
$('.magelohb span.hb').each(function (i) {
$(this).css({ position: 'fixed' });
});
// Chrome no longer displays alt text when an image is hovered over. However the wiki only has
// alt attributes for images, not titles. This fixes that by converting alt => title
$('img[alt]').each(function (i, img) {
$(img).attr('title', $(img).attr('alt'));
});
// Fashion for item pages
var extractFashionHtml = function (html) {
return $(html)
.find('.fashion_show, .primary_secondary_show')
.map(function (i, el) {
var $el = $(el);
var data = $el.data();
data.race = $el.find('.fashion_race').html();
if ($el.is('.fashion_show')) {
data.armor = $el.find('.fashion_armor').html();
}
return data;
})
.toArray();
};
var getFashionShows = function (fashionCategory) {
var url = '/Category:Fashion: ' + fashionCategory;
return $.get(url).then(extractFashionHtml);
};
var getItemPageShows = function () {
var fashionCategories = $('#catlinks li a')
.map(function (i, a) {
return $(a).text();
})
.filter(function (i, text) {
return text.startsWith('Fashion:');
})
.map(function (i, text) {
return text.substr('Fashion: '.length);
});
var fashion = fashionCategories[0];
if (!fashion) return $.when();
var tint = fashionCategories[1];
return getFashionShows(fashion).then(function (shows) {
var sameTint = [];
var otherTint = [];
shows.forEach(function (show) {
var isHeld = show.primaryFashion || show.secondaryFashion;
var bothHaveSameTint = show.tint === tint;
var bothHaveNoTint = !(show.tint || tint);
if (isHeld || bothHaveSameTint || bothHaveNoTint) sameTint.push(show);
else otherTint.push(show);
});
return {
matches: sameTint,
partialMatches: otherTint,
fashion: fashion,
tint: tint,
};
});
};
var addFashionSection = function (shows, isFullMatch) {
var preface = isFullMatch
? '<h2>Fashion/Appearance</h2>'
: '<div>Fashion images with the wrong "tint" (i.e. coloring) which ' +
"can only be used to get a general sense of the item's " +
'appearance:</div>';
// Don't show the explanatory text if there are no shows to explain
if (!shows.length && !isFullMatch) preface = '';
var $ul = $('<ul>').append(
shows.map(function (show) {
var img = isFullMatch
? '<br/><img style="max-height: 100px; max-width: 100px;" src="/images/' +
show.file.replace(/ /g, '_') +
'"/>'
: '';
return (
'<li class="fashion-link" data-file="' +
show.file +
'">' +
'<a href="#">' +
show.gender +
' ' +
show.race +
img +
'</a></li>'
);
})
);
$('#itemfashion').before($('<div>' + preface + '</div>').append($ul));
};
var addFashionSections = function () {
getItemPageShows().then(function (pageShows) {
if (!pageShows) return;
var matches = pageShows.matches || [];
var partialMatches = pageShows.partialMatches || [];
if (pageShows.matches.length || pageShows.partialMatches.length)
addFashionSection(pageShows.matches, true);
if (pageShows.partialMatches.length)
addFashionSection(pageShows.partialMatches, false);
});
};
addFashionSections();
//*****************************************
// Add class-based filtering to item tables
//*****************************************w
// Determine whether or not a provided row should be shown for the provided
// class abbreviation (eg. "BRD")
var isRowShown = function ($tr, classAbbrev) {
// Extract classes (and races)
var classText = $tr.find('td').eq(3).text().split('Class:')[1];
if (!classText) return true; // Ignore (don't filter) rows without class text
// remove "Race: " part (if any) and upper-case text
classText = classText.split('Race:')[0] || classText;
classText = classText.toUpperCase();
// determine matching text
var isMatch = classText.includes(classAbbrev);
var isAllMatch = classText.includes('ALL');
var isExcept = classText.includes('ALL EXCEPT');
// determine matches
if (isMatch && !isExcept) return true; // (eg. BRD in "BRD")
if (!isMatch && isExcept) return true; // (eg. BRD in "ALL EXCEPT WIZ")
if (!isExcept && isAllMatch) return true; // (eg. BRD in "ALL")
return false;
};
var scrollToTable = function ($table) {
window.setTimeout(function () {
$('html, body').animate({ scrollTop: $table.offset().top }, 200);
}, 100);
};
// Filter the provided table to only display rows for the provided class
// abbreviation
var filterTable = function ($table, classAbbrev) {
$table.find('tr').each(function (i, tr) {
var $tr = $(tr);
var rowIsShown = isRowShown($tr, classAbbrev);
$tr.toggle(rowIsShown);
});
scrollToTable($table);
addFilterLink($table, false);
$('.itemsUnfilterLink').click(function () {
unfilterTable($table);
});
alert('Filtered to only show rows containing ' + classAbbrev + ' gear.');
};
// Restore a table to its previous, un-filtered state
var unfilterTable = function ($table) {
$table.find('tr').show();
addFilterLink($table, true);
scrollToTable($table);
};
// When a user clicks on a table class filter link, handle it by asking them
// which class (and then filtering the table for that class)
var handleItemFilterLinkClick = function (e) {
var promptMessage =
'Please enter the three-letter abbreviation for the ' +
'class you want to filter by (eg. "brd" for "Bard").';
var $table = $(e.target).closest('table');
var classAbbrev = prompt(promptMessage).toUpperCase();
if (!classAbbrev || classAbbrev.length !== 3 || classAbbrev === 'ALL') {
alert(
'A 3-digit abbreviation wasn\'t entered (or "All" was entered); ' +
'filtering disabled'
);
unfilterTable($table);
return false;
}
filterTable($table, classAbbrev);
};
// Adds either a filter or unfilter link (as determined by showFilter) to the
// provided table
var addFilterLink = function ($table, showFilter) {
var $statsHeaderCells = $table.find('th:contains("Stats")');
var filterType = showFilter ? 'Filter' : 'Unfilter';
$statsHeaderCells.html(
'Stats <span style="float:right">' +
'<a style="text-decoration: underline" class="items' +
filterType +
'Link" href="#">' +
filterType +
(showFilter ? ' by Class' : '') +
'</a></span>'
);
var $link = $statsHeaderCells.find('.items' + filterType + 'Link');
if (showFilter) $link.click(handleItemFilterLinkClick);
else
$link.click(function () {
unfilterTable($table);
});
};
// Add class filtering links to all item tables
var addItemFilteringLinks = function () {
var $tables = $('table th:contains("Item Name")').closest('table');
$tables.each(function (i, table) {
var $table = $(table);
// Make sure it has both "Item Name" and "Stats" columns
if (!$table.has('th:contains("Stats")')) return;
addFilterLink($table, true);
});
};
addItemFilteringLinks();
//*****************************************
// End class-based filtering to item tables
//*****************************************
// Add No-Drop-Based filtering to the class equipment pages
if (window.location.pathname.includes('Special:ClassSlotEquip')) {
// Add checkboxes UI to the page
$('table').before(
'<label><input id="showNoDrop" type="checkbox" checked/> Show No Drop</label> ' +
'<label><input id="showDroppable" type="checkbox" checked/> Show Droppable</label>' /*+
'| <label><input id="showEffect" type="checkbox" checked/> Show With Effects</label>' +
'<label><input id="showNoEffect" type="checkbox" checked/> Show Without Effects</label>'*/
);
// Handle when drop/no drop box is checked
$('#showNoDrop, #showDroppable').change(function () {
var showNoDrop = $('#showNoDrop').is(':checked');
var showDroppable = $('#showDroppable').is(':checked');
// NOTE: Some tables are weird and don't keep their TRs in THEAD
// .... but those rows do have an old bgcolor="#cccccc" attribute
// that we can use to identify (and not hide) them
$('tbody tr[bgcolor!=#cccccc]').each(function (i, el) {
var text = $(el).find('td:eq(0) .itemdata').text();
var isNoDrop = text.includes('NO DROP');
$(el).toggle((showNoDrop && isNoDrop) || (showDroppable && !isNoDrop));
});
});
/*
Problem: the event handler needs to be merged so unchecking one box (eg. effect) doesn't undo the other (eg. no drop)
// Handle when effect/no effect box is checked
$('#showNoEfefct, #showEffect').change(function() {
var showNoEffect = $('#showNoEffect').is(':checked');
var showEffect = $('#showEffect').is(':checked');
// NOTE: Some tables are weird and don't keep their TRs in THEAD
// .... but those rows do have an old bgcolor="#cccccc" attribute
// that we can use to identify (and not hide) them
$('tbody tr[bgcolor!=#cccccc]').each(function(i, el) {
var text = $(el).find('td:eq(0) .itemdata').text();
var hasEffect = text.includes('NO DROP');
$(el).toggle((showEffect && hasEffect) || (showNoEffect && !hasEffect));
});
});
*/
}
// Generic Table Filtering (for Template:TableFilterCheckbox)
$('.table-filter-checkbox-container').each(function (i, el) {
var $container = $(el);
var matchSelector = $container.data('match');
var text = $container.text();
$container.html(
'<label><input class="table-filter-checkbox" type="checkbox" ' +
'value="' +
matchSelector +
'" checked />' +
text +
'</label>'
);
});
var shouldRowBeShown = function (tr) {
var $tr = $(tr);
// Check all the checkboxes to see if any given row should appear
// TODO: Instead of checking *every* checkbox, check ones in the same .filter-group
return $('.table-filter-checkbox')
.toArray()
.reduce(function (isShown, checkbox) {
var matchSelector = $(checkbox).val();
var matches = $tr.is(matchSelector) || !!$tr.has(matchSelector).length;
var isChecked = $(checkbox).attr('checked');
return isShown && !!(isChecked || (!isChecked && !matches));
}, true);
};
$('body').on('change', '.table-filter-checkbox', function (e) {
$('table').show();
$('table:not(.toc) tbody tr:not([bgcolor="#cccccc"])').each(function (
i,
tr
) {
$(tr).toggle(shouldRowBeShown(tr));
});
// If all of a table's non-header rows are hidden, hide it
$('table')
.filter(function (i, table) {
return !$(table).has('tr:visible:not([bgcolor="#cccccc"])').length;
})
.hide();
});
// Convert youtube template divs into actual iframes
$('.youtube-placeholder').each(function (i, placeholder) {
var $placeholder = $(placeholder);
var data = $placeholder.data();
var url = data.url;
// Youtube gets mad if you try to embed watch URLs
// @see https://stackoverflow.com/questions/25661182/embed-youtube-video-refused-to-display-in-a-frame-because-it-set-x-frame-opti
//if (url.includes('/watch?') url = url.replace('/watch?', '/embed?');
// TODO: get height/width from template?
$placeholder.replaceWith(
'<iframe ' +
'width="' +
(data.width || '') +
'" ' +
'height="' +
(data.height || '') +
'" ' +
'src="' +
url +
'" ' +
'frameborder="0" ' +
'allow="accelerometer; autoplay; encrypted-media; gyroscope; picture-in-picture" ' +
'allowfullscreen' +
'></iframe>'
);
});
importScript('MediaWiki:CheckboxLists.js');
importScript('MediaWiki:LocMaps.js');
var fullTitle = $('title').text();
var title = fullTitle.substr(
0,
fullTitle.length - ' - Project 1999 Wiki'.length
);
switch (title) {
case 'Magelo Blue':
case 'Magelo Green':
case 'Magelo Red':
$('.createboxInput').on('focus', function () {
this.value = '';
});
break;
// Give the Per-Level Hunting Guide Page its own JS
case 'Per-Level Hunting Guide':
importScript('MediaWiki:HuntingGuide.js');
break;
// The item category search also needs special JS
case 'Item Category Search':
importScript('MediaWiki:ItemCategorySearch.js');
break;
// So does the Solo Artist Challenge
case 'Solo Artist Challenge':
importScript('MediaWiki:SoloArtistChallenge.js');
break;
case 'Treasure Hunting Guide':
importScript('MediaWiki:TreasureHuntingGuide.js');
break;
case 'Buff Lines':
importScript('MediaWiki:BuffLines.js');
break;
case 'FashionQuest Finder':
importScript('MediaWiki:FashionQuest.js');
break;
case 'Magelo Import':
importScript('MediaWiki:MageloImport.js');
break;
case 'Mobs By Level':
// Basic DOM manipulation (since the wiki won't let us add <input> tags in the wiki text
$('#placeholder').replaceWith(
'<form id="form">' +
'Class: <input id="class" style="width: 8em" value="Warrior" /> ' +
'Level: <input id="level" style="width: 4em" /> ' +
'<input type="submit"/>' +
'</form>'
);
$('#form').submit(function () {
var clazz = $('#class').val();
var level = $('#level').val();
window.location =
'https://wiki.project1999.com/index.php?title=Special:Search&limit=500&offset=0&redirs=0&profile=default&search=%22Level%5C%3A%5C+' +
level +
'%22+-%22Shopkeeper%22+-%22Merchant%22+%22Class%5C%3A%5C+' +
clazz +
'%22+-"startMageloProfile"';
return false;
});
break;
case 'Patch Notes':
// Let users control patch note width and how
// the table of contents is shown
var setNotesColumns = function (cols) {
$('#notesWrapper').css('width', cols ? cols + 'em' : '');
};
var toggleNotRelevant = function (isChecked) {
$('#notesWrapper').find(':not(:visible)').show();
if (isChecked) return;
$('#notesWrapper')
.children()
.filter(function (i, el) {
var isRelevant = $(el).is('.relevant');
$(el).toggle(isRelevant);
// Show the patch header also
if (isRelevant) $(el).prevUntil('h3').last().prev().show();
});
};
var toggleTableOfContents = function (isChecked) {
$('#toc').toggle(isChecked);
};
var togglePatchHeaders = function (isChecked) {
$('.toclevel-4').toggle(isChecked);
};
var notesWidth = getStateByPage('notes-width') || '';
var showTableOfContents =
getStateByPage('show-table-of-contents') !== false;
var showPatchHeaders = getStateByPage('show-patch-headers') !== false;
var showNotRelevant = getStateByPage('show-not-relevant') !== false;
setNotesColumns(notesWidth);
toggleTableOfContents(showTableOfContents);
togglePatchHeaders(showPatchHeaders);
toggleNotRelevant(showNotRelevant);
$('#patchNoteOptions').html(
'<div><label><input ' +
(showTableOfContents ? 'checked ' : '') +
'id="show-table-of-contents" type="checkbox" /> Show Table of Contents?<label><br/>' +
'<label><input ' +
(showPatchHeaders ? 'checked ' : '') +
'id="show-patch-headers" type="checkbox"/> Show patch headers in Table of Contents?<label><br/>' +
'<label><input ' +
(showNotRelevant ? 'checked ' : '') +
'id="show-not-relevant" type="checkbox"/> Show content not marked as relevant to P99?<label></div>' +
'<div><label>Limit notes to a width of <input id="notes-width" placeholder="40" style="width: 4em;" value="' +
notesWidth +
'" /> columns (for readability)</label></div>'
);
$('#notes-width').change(function (e) {
var cols = parseFloat($(e.target).val());
setNotesColumns(cols);
setStateByPage('notes-width', cols);
});
$('#show-table-of-contents').change(function (e) {
var isChecked = $(e.target).is(':checked');
toggleTableOfContents(isChecked);
setStateByPage('show-table-of-contents', isChecked);
});
$('#show-patch-headers').change(function (e) {
var isChecked = $(e.target).is(':checked');
togglePatchHeaders(isChecked);
setStateByPage('show-patch-headers', isChecked);
});
$('#show-not-relevant').change(function (e) {
var isChecked = $(e.target).is(':checked');
toggleNotRelevant(isChecked);
setStateByPage('show-not-relevant', isChecked);
});
break;
}
// Warn users who accidentally try to edit a templated section
if (
(window.location + '').includes('title=Template:Namedmobpage&action=edit')
) {
alert(
"Warning: You are attempting you edit the template for all named mobs. You probably didn't mean to do that: you probably clicked on an edit link somewhere in the page and wound up here. To avoid this simply go back and use the edit *tab* at the top of the page instead."
);
}
// Warn uses who try to edit a mostly-transcluded section (and offer to take them to the transcluded page)
var text = $('#wpTextbox1').val();
var match = text && text.match(/\{\{\#lsth\:(.*?)\|\[\[(.*?)\]\](.*)\}\}/);
if (match) {
var pageName = match[1];
var section = match[2];
var extra = match[3] || '';
var isEdit = (window.location + '').includes('action=edit');
var isUnderTenLines = $('#wpTextbox1').val().split('\n').length < 10;
var url = '/' + pageName + '#' + (section + extra).replace(/ /g, '_');
var message =
'This page uses "transclusion" to show part of another page, specifically the code:\n\n {{#lsth:' +
pageName +
'|[[' +
section +
']]' +
extra +
'}}\n\nIf you want to edit the transcluded section, click "Ok": you will be taken to that page.' +
' If you want to stay on this page, click "Cancel".';
if (isEdit && isUnderTenLines && confirm(message)) location = url;
}
// *** AUCTION TRACKER RELATED ***
var selectedServer = getGlobalState('selectedServer') || 'Blue';
var buildTabHtml = function (serverNames) {
var tabDivs = serverNames.map(function (name, i) {
return (
'<div id="' +
name +
'Tab" class="tab' +
(name === selectedServer ? ' selected' : '') +
'">' +
name +
'</div>'
);
});
return (
'<div class="tabs">' +
tabDivs.join('') +
'<div class="clear"></div></div>'
);
};
var selectTab = function (name) {
// show the server's box (and hide the others)
$trackers.hide();
var $tracker = $('#auc_' + name).show();
// If the selected tab doesn't exist on this item, show the first tab instead
if (!$tracker.length) $tracker = $('.auctrackerbox:first').show();
// Select the tab for that server (and unselect the others)
$('.auctrackerbox .tab').removeClass('selected');
var $tab = $('.auctrackerbox .tab:contains("' + name + '")');
if (!$tab.length) $tab = $('.auctrackerbox .tab:first');
$tab.addClass('selected');
setGlobalState('selectedServer', name);
};
var $trackers = $('.auctrackerbox');
// if we're on an item page with an auction tracker
if ($trackers.length) {
// Convert IDs of "auc_Blue" into an array of ["Blue", "Green", ...]
var servers = $trackers.toArray().map(function (tracker) {
return tracker.id.substr(4);
});
$trackers.prepend(buildTabHtml(servers));
selectTab(selectedServer);
$trackers.on('click', '.tab', function (e) {
selectTab($(e.target).text());
});
// Add links to search the forum for items to their auction tracker
// Forum IDs come from forum URLs, eg. red's auction forum is:
// https://www.project1999.com/forums/forumdisplay.php?f=59
// so we have "red: 59 " below
var forumIds = { blue: 27, green: 77, red: 59, teal: 78 };
$('.auctrackerbox span span:contains("Project 1999 Auction Tracker")').each(
function (i, el) {
var $el = $(el);
var serverName = $el
.closest('.auctrackerbox')
.attr('id')
.substr(4)
.toLowerCase();
const forumSearchUrl =
'https://www.project1999.com/forums/search.php?do=process&forumchoice[]=' +
forumIds[serverName] +
'&query=%22' +
$('#firstHeading').text() +
'%22';
$el.append(
'<a ' +
'style="font-size: 0.5em; float: right" ' +
'target="_new" ' +
'href="' +
forumSearchUrl +
'"' +
'>Search Forum</a>'
);
}
);
}
});