[ Disclaimer, Create new user --- Wiki markup help, Install P99 ]
Difference between revisions of "MediaWiki:HuntingGuide.js"
From Project 1999 Wiki
| Line 194: | Line 194: | ||
setResults(filteredSpots); | setResults(filteredSpots); | ||
}; | }; | ||
| − | + | $('.class-filter, .monster-filter').click(handleAnyFilteringElementChange); | |
| − | + | ||
| − | + | ||
| − | + | ||
| − | + | ||
| − | + | ||
| − | + | ||
| − | + | ||
| − | + | ||
| − | + | ||
| − | + | ||
| − | + | ||
| − | + | ||
| − | + | ||
| − | + | ||
| − | + | ||
| − | + | ||
| − | + | ||
| − | + | ||
| − | + | ||
| − | + | ||
| − | + | ||
| − | + | ||
| − | + | ||
| − | + | ||
| − | + | ||
| − | + | ||
| − | + | ||
| − | + | ||
| − | + | ||
| − | + | ||
| − | + | ||
| − | + | ||
| − | + | ||
| − | + | ||
| − | + | ||
| − | + | ||
| − | + | ||
| − | + | ||
| − | + | ||
| − | + | ||
| − | + | ||
| − | + | ||
| − | + | ||
| − | + | ||
| − | + | ||
| − | + | ||
| − | + | ||
| − | + | ||
| − | + | ||
| − | + | ||
| − | + | ||
| − | + | ||
| − | + | ||
| − | + | ||
| − | + | ||
| − | + | ||
| − | + | ||
| − | + | ||
| − | + | ||
| − | + | ||
| − | + | ||
| − | + | ||
| − | + | ||
| − | + | ||
| − | + | ||
| − | + | ||
| − | + | ||
| − | + | ||
| − | + | ||
| − | + | ||
| − | + | ||
| − | + | ||
| − | + | ||
| − | + | ||
| − | + | ||
| − | + | ||
| − | + | ||
| − | + | ||
| − | + | ||
| − | + | ||
| − | + | ||
| − | + | ||
| − | + | ||
| − | + | ||
| − | + | ||
| − | + | ||
| − | + | ||
| − | + | ||
| − | + | ||
| − | + | ||
| − | + | ||
| − | + | ||
| − | + | ||
| − | + | ||
| − | + | ||
| − | + | ||
| − | + | ||
| − | + | ||
| − | + | ||
| − | + | ||
| − | + | ||
| − | + | ||
| − | + | ||
| − | + | ||
| − | + | ||
| − | + | ||
| − | + | ||
| − | + | ||
| − | + | ||
| − | + | ||
| − | + | ||
| − | + | ||
| − | + | ||
| − | + | ||
| − | + | ||
| − | + | ||
| − | + | ||
| − | + | ||
| − | + | ||
| − | + | ||
| − | + | ||
| − | + | ||
| − | + | ||
| − | + | ||
| − | + | ||
| − | + | ||
| − | + | ||
| − | + | ||
| − | + | ||
| − | + | ||
| − | + | ||
| − | + | ||
| − | + | ||
| − | + | ||
| − | + | ||
| − | + | ||
| − | + | ||
| − | + | ||
| − | + | ||
| − | + | ||
| − | + | ||
| − | + | ||
| − | + | ||
| − | + | ||
| − | + | ||
| − | + | ||
| − | + | ||
| − | + | ||
| − | + | ||
| − | + | ||
| − | + | ||
| − | + | ||
| − | + | ||
$('#level-filter, #zone-filter').keydown(handleAnyFilteringElementChange); | $('#level-filter, #zone-filter').keydown(handleAnyFilteringElementChange); | ||
$('.era-filter').change(handleAnyFilteringElementChange); | $('.era-filter').change(handleAnyFilteringElementChange); | ||
Revision as of 19:35, 4 June 2020
// Basic DOM manipulation onReady (since the wiki won't let us add <input> tags in the wiki text
var buildEraCheckbox = function (era) {
return (
'<label><input checked class="eraFilter" type="checkbox" value="' +
era.substr(0, 3).toLowerCase() +
'"/>' +
era +
'</label>'
);
};
var eras = ['Classic', 'Kunark', 'Velious'];
$('#eraFilterPlaceholder').replaceWith(eras.map(buildEraCheckbox).join(''));
$('#levelFilterPlaceholder').replaceWith('<input id="level-filter" style="width:30px"/>');
$('#zoneFilterPlaceholder').replaceWith('<input id="zone-filter" style="width:50em"/>');
// Create filter results table
var $filterResults = $('table.eoTable3.wikitable.sortable').eq(0).clone().hide();
var $headerRow = $('.hunting-guide-row:first').clone();
var clearFilterResults = function () {
return $filterResults.empty().append($headerRow);
};
clearFilterResults();
$('h4:contains("Hunting Spots 1-4")').before($filterResults);
// Add radio buttons (since MediaWiki won't allow them as content)
$('.filter-link').each(function (i, el) {
var $el = $(el);
var eqClass = $el.text();
var htmlClass = $el.attr('class');
var name = htmlClass.split('-', 1)[0];
var inputHtml = '<input type="radio" name="' + name + '" ' + (i ? '' : ' checked') + '/>';
$el.replaceWith('<label class="' + htmlClass + '">' + inputHtml + eqClass + '</label>');
});
// Get jQuery object of every row in the hunting guide (because all of the filter functions need it)
var $rows = $('.wikitable tbody tr');
/**
* Build a in-memory data object with the data parsed from each row (which will tell us which
* levels/classes should be shown for any filter).
* @example a "spot" created by this function for critters in Butcherblock Mountains: {
* soloLevel: '04-06',
* groupLevel: '03-05',
* zone: 'Butcherblock Mountains',
* area: 'Greater Faydark zoneline',
* monsters: 'Assorted Critters ',
* xpMod: '100%',
* notes: '',
* $tr: *a jQuery object pointing to the <tr> that all this data originally came from*
* }
*/
var spots = [];
$rows.each(function (i, el) {
var groupLevel = $(el).children('td:eq(1)').text();
groupLevel = groupLevel.trim() === '-' ? null : groupLevel;
var $tr = $(el);
if ($tr.children('th').length) return; // Header row
spots.push({
soloLevel: $tr.children('td:eq(0)').text(),
groupLevel: groupLevel,
zone: $tr.children('td:eq(2)').text(),
area: $tr.children('td:eq(3)').text(),
monsters: $tr.children('td:eq(4)').text(),
xpMod: $tr.children('td:eq(5)').text(),
era: $tr.children('td:eq(6)').text(),
image: $tr.children('td:eq(7)').text(),
notes: $tr.children('td:eq(8)').text(),
for: $tr.find('.for').text(),
$tr: $tr,
});
});
// Clear garbage entries (wish I had ES6 filter ..)
var cleanedSpots = [];
$.each(spots, function (i, spot) {
if (spot.soloLevel && spot.zone) cleanedSpots.push(spot);
});
$('#numSpots').text(cleanedSpots.length);
var toClassAbbreviation = function (eqClass) {
return {
bard: 'BRD',
cleric: 'CLR',
druid: 'DRU',
enchanter: 'ENC',
magician: 'MAG',
monk: 'MNK',
necromancer: 'NEC',
paladin: 'PAL',
ranger: 'RNG',
'shadow knight': 'SHD',
shaman: 'SHM',
wizard: 'WIZ',
}[eqClasss.toLowerCase()];
};
var getFilteredSpots = function (
selectedClass,
selectedMonster,
selectedLevel,
selectedZone,
selectedEras
) {
return cleanedSpots.filter(function (spot) {
var classMatches = !selectedClass || spot.for.includes(toClassAbbreviation(selectedClass));
var monsterMatches =
!selectedMonster ||
spot.monsters.includes(selectedMonster) ||
spot.notes.includes(selectedMonster);
var minAndMax = spot.soloLevel.split('-');
var minLevel = parseFloat(minAndMax[0]);
var maxLevel = parseFloat(minAndMax[1] || minAndMax[0]);
var levelMatches = minLevel <= selectedLevel && maxLevel >= selectedLevel;
var lowerCaseZone = spot.zone.toLowerCase();
var zonePattern = new RegExp(selectedZone.toLowerCase());
var zoneMatches = lowerCaseZone.match(zonePattern);
var lowerCaseEra = spot.era.toLowerCase().trim();
var eraMatches = selectedEras.includes(lowerCaseEra);
return classMatches && monsterMatches && levelMatches && zoneMatches && eraMatches;
});
};
/**
* Replaces the contents of the search results UI with the rows of the provided hunting spots
*/
var setResults = function (spots) {
// Clear the results (but add back the header row), then append (clones of) the result rows
var $resultsTbody = clearFilterResults();
var resultRows = spots.map(function (spot) {
return spot.$tr.clone();
});
$resultsTbody.append(resultRows);
if (spots.length) return; // Show "no matches" UI only if there are no matches
$resultsTbody.append(
'<tr><th colspan="50" style="color:red; font-weight: bold; font-size: 2em; padding: 1em;">' +
'No results for those filters</th></tr>'
);
};
/**
* Re-filter the page when one of the filtering UI elements changes
*/
var handleAnyFilteringElementChange = function (e) {
var noFilterWasClicked = $(e.target).is('.no-filter');
if (noFilterWasClicked) {
// Clear the other radio buttons (the browser won't do it since they have different names)
$('.filter-link :radio').attr('checked', false);
// Clear the text inputs
$('#level-filter').val('');
$('#zone-filter').val('');
// Re-check all three era checkboxes
$('.era-filter').attr('checked', true);
} else {
$('.no-filter').attr('checked', false);
}
var selectedClass = $('.class-filter :checked').parent().text();
var selectedMonster = $('.monster-filter :checked').parent().text();
var selectedLevel = $('#level-filter').val();
var selectedZone = $('#zone-filter').val();
var selectedEras = $('.eraFilter:checked')
.map(function (i, el) {
return $(el).val();
})
.toArray();
// Are we actually filtering out anything?
var willFilter =
selectedClass || selectedMonster || selectedLevel || selectedZone || selectedEras.length < 3;
// If so, hide the normal UI and show results (otherwise show normal UI)
$('h4, .wikitable').toggle(!willFilter);
$filterResults.toggle(willFilter);
var filteredSpots = getFilteredSpots(
selectedClass,
selectedMonster,
selectedLevel,
selectedZone,
selectedEras
);
setResults(filteredSpots);
};
$('.class-filter, .monster-filter').click(handleAnyFilteringElementChange);
$('#level-filter, #zone-filter').keydown(handleAnyFilteringElementChange);
$('.era-filter').change(handleAnyFilteringElementChange);