MediaWiki:Gadget-collectionTracker.js

From Another Eden Wiki

Note: After saving, you may have to bypass your browser's cache to see the changes.

  • Firefox / Safari: Hold Shift while clicking Reload, or press either Ctrl-F5 or Ctrl-R (⌘-R on a Mac)
  • Google Chrome: Press Ctrl-Shift-R (⌘-Shift-R on a Mac)
  • Internet Explorer / Edge: Hold Ctrl while clicking Refresh, or press Ctrl-F5
  • Opera: Go to Menu → Settings (Opera → Preferences on a Mac) and then to Privacy & security → Clear browsing data → Cached images and files.
"use strict";

$(document).ready(function () {
	var tracker = document.getElementById("tracker-wrap");
	tracker.innerHTML = '<div class="tracker-filter-options" data-option="o">\
   <label>\
     Search: <input type="text" id="tracker-search" placeholder="Name" />\
   </label>\
   <br />\
 </div>\
 <div style="display: block; float: left; clear: both;">\
   <div data-option="y" class="mw-ui-button-group tracker-filter-group" id="tracker-filter-rarity">\
     <label class="mw-ui-button mw-ui-disabled label">Class</label>\
     <div class="mw-ui-button-group items">\
       <label data-value="*" class="mw-ui-button mw-ui-progressive">All</label>\
       <label data-bit="0" data-value="5★" class="mw-ui-button">5★</label>\
       <label data-bit="1" data-value="AS" class="mw-ui-button">AS</label>\
       <label data-bit="2" data-value="ES" class="mw-ui-button">ES</label>\
       <label data-bit="3" data-value="AC" class="mw-ui-button">AC</label>\
     </div>\
   </div>\
   <div data-option="l" class="mw-ui-button-group tracker-filter-group" id="tracker-filter-element">\
     <label class="mw-ui-button mw-ui-disabled label">Element</label>\
     <div class="mw-ui-button-group items">\
       <label data-value="*" class="mw-ui-button mw-ui-progressive">All</label>\
       <label data-bit="0" data-value="fire" class="mw-ui-button">Fire</label>\
       <label data-bit="1" data-value="water" class="mw-ui-button">Water</label>\
       <label data-bit="2" data-value="earth" class="mw-ui-button">Earth</label>\
       <label data-bit="3" data-value="wind" class="mw-ui-button">Wind</label>\
       <label data-bit="4" data-value="shade" class="mw-ui-button">Shade</label>\
       <label data-bit="5" data-value="thunder" class="mw-ui-button">Thunder</label>\
       <label data-bit="6" data-value="crystal" class="mw-ui-button">Crystal</label>\
       <label data-bit="7" data-value="none" class="mw-ui-button">None</label>\
     </div>\
   </div>\
   <div data-option="i" class="mw-ui-button-group tracker-filter-group" id="tracker-filter-obtain">\
     <label class="mw-ui-button mw-ui-disabled label">Obtain</label>\
     <div class="mw-ui-button-group items">\
       <label data-value="*" class="mw-ui-button mw-ui-progressive">All</label>\
       <label data-bit="0"  data-value="gacha" class="mw-ui-button">Gacha</label>\
       <label data-bit="1"  data-value="free" class="mw-ui-button">Free</label>\
     </div>\
   </div>\
   <div data-option="p" class="mw-ui-button-group tracker-filter-group" id="tracker-filter-weapon">\
     <label class="mw-ui-button mw-ui-disabled label">Weapon</label>\
     <div class="mw-ui-button-group items">\
       <label data-value="*" class="mw-ui-button mw-ui-progressive">All</label>\
       <label data-bit="0" data-value="staff" class="mw-ui-button">Staff</label>\
       <label data-bit="1" data-value="sword" class="mw-ui-button">Sword</label>\
       <label data-bit="2" data-value="katana" class="mw-ui-button">Katana</label>\
       <label data-bit="3" data-value="ax" class="mw-ui-button">Ax</label>\
       <label data-bit="4" data-value="lance" class="mw-ui-button">Lance</label>\
       <label data-bit="5" data-value="bow" class="mw-ui-button">Bow</label>\
       <label data-bit="6" data-value="fists" class="mw-ui-button">Fists</label>\
       <label data-bit="7" data-value="hammer" class="mw-ui-button">Hammer</label>\
     </div>\
   </div>\
   <div data-option="q" class="mw-ui-button-group tracker-filter-group" id="tracker-filter-4star">\
     <label class="mw-ui-button mw-ui-disabled label">4.5</label>\
     <div class="mw-ui-button-group items">\
       <label data-value="*" class="mw-ui-button mw-ui-progressive">All</label>\
       <label data-bit="0" data-value="true" class="mw-ui-button">Yes</label>\
       <label data-bit="1" data-value="false" class="mw-ui-button">No</label>\
     </div>\
   </div>\
   <div data-option="u" class="mw-ui-button-group tracker-filter-group" id="tracker-filter-released">\
     <label class="mw-ui-button mw-ui-disabled label">Released</label>\
     <div class="mw-ui-button-group items">\
       <label data-value="*" class="mw-ui-button mw-ui-progressive">All</label>\
       <label data-bit="0" data-value="true" class="mw-ui-button">Yes</label>\
       <label data-bit="1" data-value="false" class="mw-ui-button">No</label>\
     </div>\
   </div>\
   <div data-option="w" class="mw-ui-button-group tracker-filter-group" id="tracker-filter-owned">\
     <label class="mw-ui-button mw-ui-disabled label">Owned</label>\
     <div class="mw-ui-button-group items">\
       <label data-value="*" class="mw-ui-button mw-ui-progressive">All</label>\
       <label data-bit="0" data-value="true" class="mw-ui-button">Yes</label>\
       <label data-bit="1" data-value="maybe" class="mw-ui-button">Half</label>\
       <label data-bit="2" data-value="false" class="mw-ui-button">No</label>\
     </div>\
   </div>\
 </div>\
 <div style="display: block; float: left; clear: both;" id="tracker-savedstate-container">\
   <div class="mw-ui-button-group tracker-filter-group" id="tracker-local-container">\
     <label class="mw-ui-button mw-ui-disabled label" title="Stores collection data in your browser\'s local storage.">Save locally</label>\
     <div class="mw-ui-button-group items">\
       <label class="mw-ui-button" id="tracker-local-save">Save</label>\
       <label class="mw-ui-button" id="tracker-local-load">Load</label>\
     </div>\
   </div>\
 </div>\
 <div style="clear: both"></div>' + tracker.innerHTML;
 
const addEventForChild = function(parent, eventName, childSelector, callback){
    parent.addEventListener(eventName, function(event){
      const clickedElement = event.target;
      const matchingChild = clickedElement.closest(childSelector);
      if (matchingChild)
        callback(event, matchingChild);
    });
  }; 

const toggleVisible = function(node, visible) {
    node.style.display = (visible ? '' : 'none');
  };

const makeSave = function() {
  var ownString = '';

  var settings = document.querySelectorAll('label.mw-ui-button.mw-ui-progressive');

  settings.forEach(function(filter){
    ownString += filter.parentElement.parentElement.dataset.option + filter.dataset.value + ",";
  });

  ownString = ownString.slice(0, ownString.length - 1) + "&";

  var owned = document.querySelectorAll('[data-owned=true]');

  owned.forEach(function(char){
    ownString+=char.dataset.id+",";
  });

  ownString = ownString.slice(0, ownString.length - 1);
  localStorage.collectionTrackerState = ownString;
  window.location.hash = localStorage.collectionTrackerState;
};

const loadSave = function(manual){
  if (manual) {
  	var save = document.querySelector('#tracker-manual-load').innerText;
  	
  	if (save.slice(0,8) == "https://") {
  		save = save.split("#")[1];
  	}
  }
  else{
	var save = localStorage.collectionTrackerState;
  }
  
  if(save){
    var settings =  save.split('&')[0];
    var owned =  (save.split('&')[1] ? save.split('&')[1] : "");

    //Reset Tracker
    document.querySelectorAll('.tracker-filter-group label.mw-ui-progressive').forEach(function(label) { label.classList.remove('mw-ui-progressive'); });
    document.querySelectorAll('.tracker-filter-group label[data-value="*"]').forEach(function(label) { label.classList.add('mw-ui-progressive'); });

    document.querySelectorAll('.tracker-item').forEach(function(item) {
      item.dataset.owned = 'false';
      item.classList.toggle('half-selected', false);
      item.classList.toggle('selected', false);
    });

    //Load Settings
    var eachSetting = settings.split(',');

    for (var i = 0; i < eachSetting.length; i++){
      Array.from(document.querySelector('[data-option='+eachSetting[i][0]+']').children[1].children).forEach(function(opt){
        if ((opt.dataset.value !== "*") && (opt.dataset.value == eachSetting[i].slice(1, eachSetting[i].length))) {
          opt.classList.add('mw-ui-progressive');
          document.querySelector('[data-option='+eachSetting[i][0]+'] > div > label[data-value="*"]').classList.remove('mw-ui-progressive');
        }
      });
    }

    //Load Characters
    var currentChar;

	if (owned) {
	    var eachOwned = owned.split(',');
	    eachOwned.forEach(function(item){
	       evolve(document.querySelector('[data-id="'+item+'"]'));
	    });
	}
  }
};


const evolve = function(node) {
    var selected = node.classList.contains('selected');
  
    var otherForms = [];
    
    document.querySelectorAll('[data-name^='+node.dataset.name.split(' ')[0]+']').forEach(function(char) {
    	if ((node.dataset.name !== 'Cyrus Albright')  && (char.dataset.name !== 'Cyrus Albright')  && (char.dataset.name !== node.dataset.name)  && (char.dataset.name.split(' ')[0] === node.dataset.name.split(' ')[0])){
    		otherForms.push(char);
    	}
      });
    
    
    if (selected){
      node.dataset.owned = 'false';
      node.classList.toggle('selected', false);
      
      var otherFormsOwned = false;
      otherForms.forEach(function(char) {
	  	  if (char.classList.contains('selected')){
			otherFormsOwned = true;
			}	
	  });
      
      if (!otherFormsOwned){
      	otherForms.forEach(function(char) {
	      	char.dataset.owned = 'false';
	    	char.classList.toggle('half-selected', false);
    	});
    	if (node.dataset.id.split('_')[1] === 'rank4'){
      		var five = document.querySelector('[data-name='+node.dataset.name+'][data-id="'+node.dataset.id.split('_')[0]+'"]');
			five.dataset.owned = 'false';
	    	five.classList.toggle('half-selected', false);
    	}
      }
      else {
      	if (node.dataset.id.split('_')[1] !== 'rank4'){
	      	node.dataset.owned = 'maybe';
	    	node.classList.toggle('half-selected', true);
      	}
      }
      
    } else {
      node.dataset.owned = 'true';
      node.classList.toggle('half-selected', false);
      node.classList.toggle('selected', true);
      
      otherForms.forEach(function(char) {
      	if ((!char.classList.contains('selected')) && (char.dataset.id.split('_')[1] !== 'rank4')){
			char.dataset.owned = 'maybe';
	    	char.classList.toggle('half-selected', true);
		}
    	});
    	
      if ((node.dataset.rarity === "5★") && (node.dataset.name.indexOf('(Alter)') === -1)){
      	if (node.dataset.id.split('_')[1] === 'rank4'){
      		var five = document.querySelector('[data-name='+node.dataset.name+'][data-id="'+node.dataset.id.split('_')[0]+'"]');
      		if (five){
      		    five.dataset.owned = 'maybe';
	        	five.classList.toggle('selected', false);
	        	five.classList.toggle('half-selected', true);
      		}
      	}
      	else{
      		var four = document.querySelector('[data-name="'+node.dataset.name+'"][data-id="'+node.dataset.id+'_rank4"]');
      		if (four){
      			four.dataset.owned = 'false';
	    		four.classList.toggle('selected', false);
      		}
      	}
      }
    }
  };
 
 const moveItems = function(weapon) {
   var divSelector = '#tracker-'+weapon+'-characters';
   var tracker = document.querySelector(divSelector);
   var selector = '.tracker-item[data-weapon="'+weapon+'"]';
   document.querySelectorAll(selector).forEach(function(node) {
     node.dataset.owned = 'false';
     node.parentElement.removeChild(node);
     tracker.insertBefore(node, null);
   });
 };
 
 const getFilter = function(name) {
    var result = [];
    var selector = '#tracker-filter-'+name+' label.mw-ui-progressive';
    var filters = document.querySelectorAll(selector);
    for (var i = 0; i < filters.length; i++) {
      var filter = filters[i];
      if (filter.dataset.value === '*')
        return true;
      var values = filter.dataset.value.split(';');
      values.forEach(function(value) {
        result.push(value);
      });
    }
    return result;
  };
 
 const updateItems = function() {
    console.time('updating');
    var rarity = getFilter('rarity');
    var element = getFilter('element');
    var obtain = getFilter('obtain');
    var weapon = getFilter('weapon');
    var released = getFilter('released');
    var owned = getFilter('owned');
    var four = getFilter('4star');
    var search = document.querySelector('#tracker-search').value;
    var reSearch;
    try {
      reSearch = new RegExp('.*'+search+'.*','i');
    } catch (e) {
      reSearch = new RegExp('.*'+search.replace(/[\-\[\]\/\{\}\(\)\*\+\?\.\\\^\$\|]/g, "\\$&")+'.*','i');
    }
    
    document.querySelectorAll('.tracker-item').forEach(function(item) {
      var visible = true;
      if ((rarity !== true) && (rarity.indexOf(item.dataset.rarity) === -1)) {
        visible = false;
      } else if ((obtain !== true) && (obtain.indexOf(item.dataset.obtain) === -1)) {
        visible = false;
      } else if ((weapon !== true) && (weapon.indexOf(item.dataset.weapon) === -1)) {
        visible = false;
      } else if ((released !== true) && (released.indexOf(item.dataset.released) === -1)) {
        visible = false;
      } else if ((owned !== true) && (owned.indexOf(item.dataset.owned) === -1)) {
        visible = false;
      }
      if (visible && (element !== true)) {
      	visible = false;
      	for (var i = 0; i < element.length; i++){
	        if (item.dataset.element.indexOf(element[i]) !== -1) {
	          visible = true;
	          break;
        	}
      	}
      }
      if (visible && (four !== true)) {
      	if ((four[0] === 'false') && (item.dataset.id.split('_')[1] === 'rank4')){
      		visible = false;
      	}
      	else if ((four[0] === 'true') && (item.dataset.id.split('_')[1] !== 'rank4')){
      		visible = false;
      	}
      }
      if (visible && (search.length > 0)) {
        visible = reSearch.test(item.dataset.id) || reSearch.test(item.dataset.name);
      }
      toggleVisible(item, visible);
    });
    document.querySelectorAll('.tracker-box').forEach(function(box) {
      var visible = false;
      for (var i = 0; i < box.childNodes.length; i++){
        if (box.childNodes[i].style.display !== 'none') {
          visible = true;
          break;
        }
      }
      toggleVisible(box, visible);
    });

    console.timeEnd('updating');
 };

 console.time('moving');
 ['staff','sword','katana','ax','lance','bow','fists','hammer'].forEach(function(weapon) {
     moveItems(weapon);
 });
 console.timeEnd('moving');		
 
// Clicking a tracker item
 addEventForChild(document, 'click', '.tracker-item', function(event, item) {
   if (event.button !== 0) return; // Do nothing unless it's a left-mouse-button click
   event.preventDefault();
   console.time('Click Item');
   evolve(item);
   //makeHash();
   console.timeEnd('Click Item');
 });
 
 addEventForChild(document, 'click', '.mw-ui-button-group > label:not(.mw-ui-disabled)', function(event, label) {
    console.time('Click Label');
    var group = label.parentElement;
    var all = group.querySelector('label[data-value="*"]');

    if (label === all) {
      if (!all.classList.contains('mw-ui-progressive')) {
        group.querySelectorAll('label').forEach(function(sibling) {
          sibling.classList.remove('mw-ui-progressive');
        });
        all.classList.add('mw-ui-progressive');
      }
    } else if (group.childElementCount === 3) {
        group.querySelectorAll('label').forEach(function(sibling) {
          sibling.classList.remove('mw-ui-progressive');
        });
        label.classList.add('mw-ui-progressive');
    } else {
      all.classList.remove('mw-ui-progressive');
      label.classList.toggle('mw-ui-progressive');
      if (group.querySelectorAll('.mw-ui-progressive').length < 1)
        all.classList.add('mw-ui-progressive');
    }
    setTimeout(function() {
      console.time('Click Label Update');
      updateItems();
      //makeHash();
      console.timeEnd('Click Label Update');
    }, 0);
    console.timeEnd('Click Label');
  });
  
  addEventForChild(document, 'change', '#tracker-search', function() { updateItems(); });
  addEventForChild(document, 'keyup', '#tracker-search', function() { updateItems(); });
  
  document.querySelector('#tracker-filter-released label[data-value="*"]').classList.remove('mw-ui-progressive');
  document.querySelector('#tracker-filter-released label[data-value="true"]').classList.add('mw-ui-progressive');
  
  //document.querySelector('#tracker-filter-4star label[data-value="*"]').classList.remove('mw-ui-progressive');
  //document.querySelector('#tracker-filter-4star label[data-value="false"]').classList.add('mw-ui-progressive');
  
  addEventForChild(document, 'click', '#tracker-local-save', function() {
    makeSave();
  });
  
  addEventForChild(document, 'click', '#tracker-local-load', function() {
    //window.location.hash = localStorage.collectionTrackerState;
	loadSave(false);
	updateItems();
  });
  
  loadSave(true);
  updateItems();
});