From Brotato Wiki
(well im a div, I was using an ES6 template literal string (ie. backticks ``) đ¤Śââď¸) |
(add support for a button that toggles a class on the parent grid -- this will be used to add a button that makes the filters completely hide items, instead of just making them transparent) Â |
||
(21 intermediate revisions by the same user not shown) | |||
Line 1: | Line 1: | ||
/* Any JavaScript here will be loaded for all users on every page load. */ | /* Any JavaScript here will be loaded for all users on every page load. */ | ||
/* | |||
https://brotato.wiki.spellsandguns.com/MediaWiki:Common.js | |||
*/ | |||
/* | /* | ||
Line 12: | Line 15: | ||
// ============================================================================ | // ============================================================================ | ||
initCardTabs(); | initCardTabs(); // Template:StatsCardWeaponTabs | ||
initStatsCardsToggles(); // Allows hiding StatsCard (.ibox) elements, via toggle buttons (WIP) | |||
initStatsCardsMiscToggles(); // Toggles for misc (costs/tags) | |||
initStatsCardContainerToggles(); // Toggle for the StarsCard bar option buttons | |||
Line 72: | Line 78: | ||
}); | }); | ||
}); | }); | ||
}); | |||
// Tier toggles | |||
// --------------------------------------------------------------------- | |||
// Example: | |||
// <span class="btn btn--active" data-weapon-toggle="1">Tier 1</span> | |||
// <span class="btn btn--inactive" data-weapon-toggle="2">Tier 2</span> | |||
// <span class="btn btn--inactive" data-weapon-toggle="3">Tier 3</span> | |||
// <span class="btn btn--inactive" data-weapon-toggle="4">Tier 4</span> | |||
var $tierToggles = $( '[data-weapon-toggle]' ); | |||
$tierToggles.each( function( i1, el ) | |||
{ | |||
var $toggle = $( el ); | |||
var tierNum = $toggle.attr( 'data-weapon-toggle' ); | |||
$toggle.on( 'click', function( ev, el ) | |||
{ | |||
$tierToggles.not( $toggle ).addClass( 'btn--inactive' ); | |||
$tierToggles.not( $toggle ).removeClass( 'btn--active' ); | |||
$toggle.addClass( 'btn--active' ); | |||
$toggle.removeClass( 'btn--inactive' ); | |||
$containers.each( function( i2, el ) | |||
{ | |||
var $tabs = $( el ); | |||
var btnNum = tierNum; | |||
// @todo: Maybe refactor this to remove the stuff duped from above? | |||
var $panelsContainer = $tabs.children(Â '[data-cardtabs-panels]' ); | |||
var $btnsContainer = $tabs.children( '[data-cardtabs-btns]' ); | |||
var $panels = $panelsContainer.children( '[data-cardtabs-panel]' ); | |||
var $btns = $btnsContainer.children( '[data-cardtabs-btn]' ); | |||
var $btn = $btns.filter( '[data-cardtabs-btn="' + btnNum + '"]' ); | |||
if ( !$btn.length ) | |||
{ | |||
// If not button was found, it must have been a -1 button | |||
// (ie. a disabled tab), so let's find the next lowest tier | |||
for (var checkedNum = btnNum; checkedNum < 4; checkedNum++) | |||
{ | |||
$btn = $btns.filter( '[data-cardtabs-btn="' + checkedNum + '"]' ); | |||
console.log($btn.length); | |||
if ( $btn.length ) | |||
{ | |||
btnNum = checkedNum; | |||
break; | |||
} | |||
} | |||
if ( !$btn.length ) | |||
{ | |||
// If we still haven't found a button, just exit. | |||
// Should never get to this point though, unless | |||
// the ibox has hidden tiers that aren't in order | |||
return; | |||
} | |||
} | |||
var $panel = $panels.filter( '[data-cardtabs-panel="' + btnNum + '"]' ); | |||
var btnActiveCls = 'cardtabs__button--active'; | |||
var panelHideCls = 'cardtabs__panel--js-hidden'; | |||
// Hide all other panels, then show the button's own panel | |||
$panels.addClass( panelHideCls ); | |||
$panel.removeClass( panelHideCls ); | |||
$btns.removeClass( btnActiveCls ); | |||
$btn.addClass( btnActiveCls ); | |||
}); | |||
}); | |||
}); | }); | ||
}//end:initCardTabs | }//end:initCardTabs | ||
/** | |||
* Toggle a StatsCard box (.ibox) | |||
* | |||
* Targets elements with [data-ibox-type="item"], selecting them by the | |||
* given class (eg. rarity1), which should be applied to the element with | |||
* the data-ibox-type data attr | |||
* | |||
* @todo: Use the CSS class (ibox--hidden) instead of JS-injected opacity | |||
* | |||
* @return {void} | |||
*/ | |||
function initStatsCardsToggles() | |||
{ | |||
var $allBtns = $( '[data-hide-type="item"]' ); | |||
var $bulkBtns = $( '[data-hide-target="show-all"], [data-hide-target="show-none"]' ); | |||
var $nonBulkBtns = $allBtns.not( $bulkBtns ); | |||
var $allTargets = $( '[data-ibox-type="item"]' ); | |||
// Stores all target strings | |||
// Used to prevent iboxs from being hidden when they shouldn't be | |||
var allTargetStrs = []; | |||
var activeTargetStrs = [] | |||
var specialFilters = [ | |||
'show-all', | |||
'show-none' | |||
]; | |||
$allBtns.each( function( i, el ) | |||
{ | |||
var $btn = $( el ); | |||
var filterStr = $btn.attr( 'data-hide-target' ); // eg "rarity3" | |||
// ES5 version of Array.prototype.includes() | |||
if ( ( allTargetStrs.indexOf( filterStr ) === -1 ) && ( specialFilters.indexOf( filterStr ) === -1 ) ) | |||
{ | |||
allTargetStrs.push( filterStr ); | |||
} | |||
}); | |||
activeTargetStrs = allTargetStrs; | |||
$allBtns.on( 'click', function( ev ) | |||
{ | |||
var $btn   = $( ev.currentTarget ); | |||
var filterStr = $btn.attr( 'data-hide-target' ); // eg "rarity3" | |||
var $targets = $( '[data-ibox-type="item"]' + filterStr ); | |||
var $all   = $( '[data-ibox-type="item"]' ); | |||
if ( filterStr === 'show-all' || filterStr === 'show-none' ) | |||
{ | |||
// Bulk toggle ALL targets | |||
$targets = $all; | |||
switch( filterStr ) | |||
{ | |||
case 'show-all': | |||
$targets.removeClass( 'ibox--hidden' ); | |||
// $targets.css( { opacity: 1 } ); | |||
$nonBulkBtns.addClass( 'btn--active' ); | |||
$nonBulkBtns.removeClass( 'btn--inactive' ); | |||
activeTargetStrs = allTargetStrs; | |||
break; | |||
case 'show-none': | |||
$targets.addClass( 'ibox--hidden' ); | |||
// $targets.css( { opacity: 0.2 } ); | |||
$nonBulkBtns.removeClass( 'btn--active' ); | |||
$nonBulkBtns.addClass( 'btn--inactive' ); | |||
activeTargetStrs = []; | |||
break; | |||
} | |||
} | |||
else | |||
{ | |||
var strIndex = activeTargetStrs.indexOf( filterStr ); | |||
if ( $btn.hasClass( 'btn--active' ) ) | |||
{ | |||
// Button was active, so it's now INACTIVE | |||
// If all other buttons are active (ie. no buttons have been | |||
// selected yet), make this one active and all others disabled | |||
if ( activeTargetStrs.length === allTargetStrs.length ) | |||
{ | |||
// Disable all others, keep only this one | |||
$nonBulkBtns.not( $btn ).removeClass( 'btn--active' ); | |||
$nonBulkBtns.not( $btn ).addClass( 'btn--inactive' ); | |||
activeTargetStrs = []; | |||
activeTargetStrs.push( filterStr ); | |||
} | |||
// Or, if this was the last (ie. only) active button and it | |||
// was just disabled, enable every button | |||
else if ( activeTargetStrs.length === 1 ) | |||
{ | |||
$nonBulkBtns.removeClass( 'btn--inactive' ); | |||
$nonBulkBtns.addClass( 'btn--active' ); | |||
activeTargetStrs = allTargetStrs; | |||
} | |||
// Otherwise function normally: Just disable this button | |||
else | |||
{ | |||
$btn.removeClass( 'btn--active' ); | |||
$btn.addClass( 'btn--inactive' ); | |||
activeTargetStrs.splice( strIndex, 1 ); | |||
} | |||
} | |||
else | |||
{ | |||
// Button was inactive, so it's now ACTIVE | |||
$btn.removeClass( 'btn--inactive' ); | |||
$btn.addClass( 'btn--active' ); | |||
activeTargetStrs.push( filterStr ); | |||
} | |||
// Apply filters | |||
// Show all, if every filter is active (ie. if every ibox should be shown) | |||
if ( activeTargetStrs.length === allTargetStrs.length ) | |||
{ | |||
$allTargets.removeClass( 'ibox--hidden' ); | |||
// $allTargets.css( { opacity: 1 } ); | |||
} | |||
// Otherwise, apply the actual filters | |||
else | |||
{ | |||
// Hide all to start with | |||
$allTargets.addClass( 'ibox--hidden' ); | |||
// $allTargets.css( { opacity: 0.2 } ); | |||
// Show any that match the currently active filters | |||
for (var i = 0; i < activeTargetStrs.length; i++) | |||
{ | |||
var targetStr = activeTargetStrs[i]; | |||
var $currentTargets = $allTargets.filter( '[data-ibox-type="item"].' + targetStr ); | |||
$currentTargets.removeClass( 'ibox--hidden' ); | |||
// $currentTargets.css( { opacity: 1 } ); | |||
} | |||
} | |||
} | |||
}); | |||
}//end:initStatsCardsToggles | |||
/** | |||
* Toggle "misc" (costs/tags) | |||
* | |||
* Buttons: <span class="btn btn--active" data-hide-type="misc" data-hide-target=".myelement"> | |||
* Targets: <span class="myelement" data-target-type"misc"> | |||
* | |||
* @return {void} | |||
*/ | |||
function initStatsCardsMiscToggles() | |||
{ | |||
var $btns = $( '[data-hide-type="misc"]' ); | |||
$btns.each( function( i, el ) | |||
{ | |||
var $btn = $( el ); | |||
var targetStr = $btn.attr( 'data-hide-target' ); | |||
var $targets = $( '[data-target-type="misc"]' + targetStr ); | |||
if ( !$targets.length ) | |||
{ | |||
return; | |||
} | |||
$btn.on( 'click', function( ev ) | |||
{ | |||
$btn.toggleClass( 'btn--active' ); | |||
$btn.toggleClass( 'btn--inactive' ); | |||
$targets.toggle(); | |||
}); | |||
}); | |||
} | |||
/** | |||
* Toggles that affect classes on the container | |||
* | |||
* @todo: Use data attributes for the main parent + grid containers | |||
* (instead of targetting their classes, which are more subject to change) | |||
* | |||
* @return {void} | |||
*/ | |||
function initStatsCardContainerToggles() | |||
{ | |||
var $btns = $( '[data-hide-type="container_toggle"]' ); | |||
$btns.each( function( i, el ) | |||
{ | |||
var $btn = $( el ); | |||
var classStr = $btn.attr( 'data-container-class' ); | |||
var $container = $btn.closest('.statscard-grid'); | |||
var $grid = ( $container.length ) ? $container.find( '.statscard-grid__main' ) : null; | |||
if ( !classStr || classStr === "" ) | |||
{ | |||
console.warn('[initStatsCardContainerToggles] No class string was provided via the button\'s "data-container-class" attribute', { $btn:$btn } ); | |||
return; | |||
} | |||
if ( !$grid || !$grid.length ) | |||
{ | |||
console.warn('[initStatsCardContainerToggles] Could not find the items grid'); | |||
return; | |||
} | |||
$btn.on( 'click', function( ev ) | |||
{ | |||
$btn.toggleClass( 'btn--active' ); | |||
$btn.toggleClass( 'btn--inactive' ); | |||
$grid.toggleClass(classStr); | |||
}); | |||
}); | |||
} | |||
}); // end:$(document).ready | }); // end:$(document).ready |
Latest revision as of 06:41, 13 February 2023
/* Any JavaScript here will be loaded for all users on every page load. */ /* https://brotato.wiki.spellsandguns.com/MediaWiki:Common.js */ /* WARNING: ES5 ONLY! */ $(document).ready( function() { // Inits // ============================================================================ initCardTabs(); // Template:StatsCardWeaponTabs initStatsCardsToggles(); // Allows hiding StatsCard (.ibox) elements, via toggle buttons (WIP) initStatsCardsMiscToggles(); // Toggles for misc (costs/tags) initStatsCardContainerToggles(); // Toggle for the StarsCard bar option buttons // Funcs // ============================================================================ /** * Sets up tabs. Used by the StatsCardWeaponTabs template * * @link https://brotato.wiki.spellsandguns.com/Template:StatsCardWeaponTabs * @link https://brotato.wiki.spellsandguns.com/MediaWiki:Common.css * * @return {void} */ function initCardTabs() { var $containers = $( '[data-cardtabs]' ); if ( !$containers.length ) { return; } // Loop over every container $containers.each( function( i1, containerEl ) { var $tabs = $( containerEl ); // We use the extra step of targetting containers here, instead of // just using `.find`, because this lets us support nesteds tabs! var $panelsContainer = $tabs.children( '[data-cardtabs-panels]' ); var $btnsContainer = $tabs.children( '[data-cardtabs-btns]' ); var $panels = $panelsContainer.children( '[data-cardtabs-panel]' ); var $btns = $btnsContainer.children( '[data-cardtabs-btn]' ); // Loop over buttons and set up their onclicks $btns.each( function( i2, btnEl ) { var $btn = $( btnEl ); var btnNum = $btn.attr( 'data-cardtabs-btn' ); var $panel = $panels.filter( '[data-cardtabs-panel="' + btnNum + '"]' ); var btnActiveCls = 'cardtabs__button--active'; var panelHideCls = 'cardtabs__panel--js-hidden'; // Disabled buttons use "-1" for their numbers if ( btnNum === '-1' ) { return; } $btn.on( 'click', function() { // Hide all other panels, then show the button's own panel $panels.addClass( panelHideCls ); $panel.removeClass( panelHideCls ); $btns.removeClass( btnActiveCls ); $btn.addClass( btnActiveCls ); }); }); }); // Tier toggles // --------------------------------------------------------------------- // Example: // <span class="btn btn--active" data-weapon-toggle="1">Tier 1</span> // <span class="btn btn--inactive" data-weapon-toggle="2">Tier 2</span> // <span class="btn btn--inactive" data-weapon-toggle="3">Tier 3</span> // <span class="btn btn--inactive" data-weapon-toggle="4">Tier 4</span> var $tierToggles = $( '[data-weapon-toggle]' ); $tierToggles.each( function( i1, el ) { var $toggle = $( el ); var tierNum = $toggle.attr( 'data-weapon-toggle' ); $toggle.on( 'click', function( ev, el ) { $tierToggles.not( $toggle ).addClass( 'btn--inactive' ); $tierToggles.not( $toggle ).removeClass( 'btn--active' ); $toggle.addClass( 'btn--active' ); $toggle.removeClass( 'btn--inactive' ); $containers.each( function( i2, el ) { var $tabs = $( el ); var btnNum = tierNum; // @todo: Maybe refactor this to remove the stuff duped from above? var $panelsContainer = $tabs.children( '[data-cardtabs-panels]' ); var $btnsContainer = $tabs.children( '[data-cardtabs-btns]' ); var $panels = $panelsContainer.children( '[data-cardtabs-panel]' ); var $btns = $btnsContainer.children( '[data-cardtabs-btn]' ); var $btn = $btns.filter( '[data-cardtabs-btn="' + btnNum + '"]' ); if ( !$btn.length ) { // If not button was found, it must have been a -1 button // (ie. a disabled tab), so let's find the next lowest tier for (var checkedNum = btnNum; checkedNum < 4; checkedNum++) { $btn = $btns.filter( '[data-cardtabs-btn="' + checkedNum + '"]' ); console.log($btn.length); if ( $btn.length ) { btnNum = checkedNum; break; } } if ( !$btn.length ) { // If we still haven't found a button, just exit. // Should never get to this point though, unless // the ibox has hidden tiers that aren't in order return; } } var $panel = $panels.filter( '[data-cardtabs-panel="' + btnNum + '"]' ); var btnActiveCls = 'cardtabs__button--active'; var panelHideCls = 'cardtabs__panel--js-hidden'; // Hide all other panels, then show the button's own panel $panels.addClass( panelHideCls ); $panel.removeClass( panelHideCls ); $btns.removeClass( btnActiveCls ); $btn.addClass( btnActiveCls ); }); }); }); }//end:initCardTabs /** * Toggle a StatsCard box (.ibox) * * Targets elements with [data-ibox-type="item"], selecting them by the * given class (eg. rarity1), which should be applied to the element with * the data-ibox-type data attr * * @todo: Use the CSS class (ibox--hidden) instead of JS-injected opacity * * @return {void} */ function initStatsCardsToggles() { var $allBtns = $( '[data-hide-type="item"]' ); var $bulkBtns = $( '[data-hide-target="show-all"], [data-hide-target="show-none"]' ); var $nonBulkBtns = $allBtns.not( $bulkBtns ); var $allTargets = $( '[data-ibox-type="item"]' ); // Stores all target strings // Used to prevent iboxs from being hidden when they shouldn't be var allTargetStrs = []; var activeTargetStrs = [] var specialFilters = [ 'show-all', 'show-none' ]; $allBtns.each( function( i, el ) { var $btn = $( el ); var filterStr = $btn.attr( 'data-hide-target' ); // eg "rarity3" // ES5 version of Array.prototype.includes() if ( ( allTargetStrs.indexOf( filterStr ) === -1 ) && ( specialFilters.indexOf( filterStr ) === -1 ) ) { allTargetStrs.push( filterStr ); } }); activeTargetStrs = allTargetStrs; $allBtns.on( 'click', function( ev ) { var $btn = $( ev.currentTarget ); var filterStr = $btn.attr( 'data-hide-target' ); // eg "rarity3" var $targets = $( '[data-ibox-type="item"]' + filterStr ); var $all = $( '[data-ibox-type="item"]' ); if ( filterStr === 'show-all' || filterStr === 'show-none' ) { // Bulk toggle ALL targets $targets = $all; switch( filterStr ) { case 'show-all': $targets.removeClass( 'ibox--hidden' ); // $targets.css( { opacity: 1 } ); $nonBulkBtns.addClass( 'btn--active' ); $nonBulkBtns.removeClass( 'btn--inactive' ); activeTargetStrs = allTargetStrs; break; case 'show-none': $targets.addClass( 'ibox--hidden' ); // $targets.css( { opacity: 0.2 } ); $nonBulkBtns.removeClass( 'btn--active' ); $nonBulkBtns.addClass( 'btn--inactive' ); activeTargetStrs = []; break; } } else { var strIndex = activeTargetStrs.indexOf( filterStr ); if ( $btn.hasClass( 'btn--active' ) ) { // Button was active, so it's now INACTIVE // If all other buttons are active (ie. no buttons have been // selected yet), make this one active and all others disabled if ( activeTargetStrs.length === allTargetStrs.length ) { // Disable all others, keep only this one $nonBulkBtns.not( $btn ).removeClass( 'btn--active' ); $nonBulkBtns.not( $btn ).addClass( 'btn--inactive' ); activeTargetStrs = []; activeTargetStrs.push( filterStr ); } // Or, if this was the last (ie. only) active button and it // was just disabled, enable every button else if ( activeTargetStrs.length === 1 ) { $nonBulkBtns.removeClass( 'btn--inactive' ); $nonBulkBtns.addClass( 'btn--active' ); activeTargetStrs = allTargetStrs; } // Otherwise function normally: Just disable this button else { $btn.removeClass( 'btn--active' ); $btn.addClass( 'btn--inactive' ); activeTargetStrs.splice( strIndex, 1 ); } } else { // Button was inactive, so it's now ACTIVE $btn.removeClass( 'btn--inactive' ); $btn.addClass( 'btn--active' ); activeTargetStrs.push( filterStr ); } // Apply filters // Show all, if every filter is active (ie. if every ibox should be shown) if ( activeTargetStrs.length === allTargetStrs.length ) { $allTargets.removeClass( 'ibox--hidden' ); // $allTargets.css( { opacity: 1 } ); } // Otherwise, apply the actual filters else { // Hide all to start with $allTargets.addClass( 'ibox--hidden' ); // $allTargets.css( { opacity: 0.2 } ); // Show any that match the currently active filters for (var i = 0; i < activeTargetStrs.length; i++) { var targetStr = activeTargetStrs[i]; var $currentTargets = $allTargets.filter( '[data-ibox-type="item"].' + targetStr ); $currentTargets.removeClass( 'ibox--hidden' ); // $currentTargets.css( { opacity: 1 } ); } } } }); }//end:initStatsCardsToggles /** * Toggle "misc" (costs/tags) * * Buttons: <span class="btn btn--active" data-hide-type="misc" data-hide-target=".myelement"> * Targets: <span class="myelement" data-target-type"misc"> * * @return {void} */ function initStatsCardsMiscToggles() { var $btns = $( '[data-hide-type="misc"]' ); $btns.each( function( i, el ) { var $btn = $( el ); var targetStr = $btn.attr( 'data-hide-target' ); var $targets = $( '[data-target-type="misc"]' + targetStr ); if ( !$targets.length ) { return; } $btn.on( 'click', function( ev ) { $btn.toggleClass( 'btn--active' ); $btn.toggleClass( 'btn--inactive' ); $targets.toggle(); }); }); } /** * Toggles that affect classes on the container * * @todo: Use data attributes for the main parent + grid containers * (instead of targetting their classes, which are more subject to change) * * @return {void} */ function initStatsCardContainerToggles() { var $btns = $( '[data-hide-type="container_toggle"]' ); $btns.each( function( i, el ) { var $btn = $( el ); var classStr = $btn.attr( 'data-container-class' ); var $container = $btn.closest('.statscard-grid'); var $grid = ( $container.length ) ? $container.find( '.statscard-grid__main' ) : null; if ( !classStr || classStr === "" ) { console.warn('[initStatsCardContainerToggles] No class string was provided via the button\'s "data-container-class" attribute', { $btn:$btn } ); return; } if ( !$grid || !$grid.length ) { console.warn('[initStatsCardContainerToggles] Could not find the items grid'); return; } $btn.on( 'click', function( ev ) { $btn.toggleClass( 'btn--active' ); $btn.toggleClass( 'btn--inactive' ); $grid.toggleClass(classStr); }); }); } }); // end:$(document).ready