MediaWiki:ComparisonPage-TranslatedJapaneseGames.js

//// MediaWiki:ComparisonPage-TranslatedJapaneseGames.js //// A script file that contains all the HTML and Javascript to add to the page Comparison_of_translated_Japanese_femdom_games in order to implement useful table organization functions. //// Called by MediaWiki:Common.js only if the current page is Comparison_of_translated_Japanese_femdom_games.

// Modified hash function from https://stackoverflow.com/questions/6122571/simple-non-secure-hash-function-for-javascript String.prototype.hashCode = function { var hash = 0; if (this.length == 0) { return hash; }   for (var i = 0; i < this.length; i++) { var char = this.charCodeAt(i); hash = ((hash<<5)-hash)+char; hash = hash & hash; // Convert to 32bit integer }   return hash.toString(17).substr(4, 8); } // Example use: translatedTitle.hashCode

var e, s; // Variables to store e (div element of each Template) and s (scripts stored within div elements). Also, confirm that e is not null (that the Template is placed on the page) before modifying it.

// Fill out the div of Template:List1ColumnCheckboxes to contain the HTML for the column checkboxes & select/unselect all button e = document.getElementById('fdw-list1-column-checkboxes'); if (e != null) { e.innerHTML = '' + 'Column Display: ' + 'Select All / Unselect All / Default Columns  ' + 'Cover   |   ' + 'Translated Title   |   ' + 'Romanized Title   |   ' + 'Kanji Title   |   ' + 'Developer   |   ' + 'Original Release Date   |   ' + 'Translator   |   ' + 'Translation Date   |   ' + 'Genres   |   ' + 'Engine   |   ' + 'Estimated Play Length   |   ' + 'Developer Type   |   ' + 'Art Style   |   ' + 'Resolution   |   ' + 'Structure   |   ' + 'Non-Femdom <input type="checkbox" id="fdw-list1-columnNonFD-checkbox" checked="true">  |   ' + 'Themes <input type="checkbox" id="fdw-list1-columnSetting-checkbox" checked="true">  |   ' + 'Fetishes <input type="checkbox" id="fdw-list1-columnFetishes-checkbox" checked="true">  |   ' + 'Notes <input type="checkbox" id="fdw-list1-columnNotes-checkbox">  |   ' + 'Screenshots <input type="checkbox" id="fdw-list1-columnScreenshots-checkbox" checked="true">  |   ' + 'External Links <input type="checkbox" id="fdw-list1-columnLinks-checkbox" checked="true">'; } // Fill out the div of Template:List1ColumnCheckboxesLogic to contain the JavaScript logic related to the column checkboxes e = document.getElementById('fdw-list1-column-checkboxes-logic'); if (e != null) { s = document.createElement("script"); s.text = '' + 'var columnCheckboxArray = [];' + '\n' + 'columnCheckboxArray.push([document.getElementById("fdw-list1-columnCover-checkbox"), 1]);' + '\n' + 'columnCheckboxArray.push([document.getElementById("fdw-list1-columnTranslated-checkbox"), 2]);' + '\n' + 'columnCheckboxArray.push([document.getElementById("fdw-list1-columnRomanized-checkbox"), 3]);' + '\n' + 'columnCheckboxArray.push([document.getElementById("fdw-list1-columnKanji-checkbox"), 4]);' + '\n' + 'columnCheckboxArray.push([document.getElementById("fdw-list1-columnDeveloper-checkbox"), 5]);' + '\n' + 'columnCheckboxArray.push([document.getElementById("fdw-list1-columnDate-checkbox"), 6]);' + '\n' + 'columnCheckboxArray.push([document.getElementById("fdw-list1-columnTL-checkbox"), 7]);' + '\n' + 'columnCheckboxArray.push([document.getElementById("fdw-list1-columnTLDate-checkbox"), 8]);' + '\n' + 'columnCheckboxArray.push([document.getElementById("fdw-list1-columnGenres-checkbox"), 9]);' + '\n' + 'columnCheckboxArray.push([document.getElementById("fdw-list1-columnEngine-checkbox"), 10]);' + '\n' + 'columnCheckboxArray.push([document.getElementById("fdw-list1-columnPlayLength-checkbox"), 11]);' + '\n' + 'columnCheckboxArray.push([document.getElementById("fdw-list1-columnDevType-checkbox"), 12]);' + '\n' + 'columnCheckboxArray.push([document.getElementById("fdw-list1-columnArtStyle-checkbox"), 13]);' + '\n' + 'columnCheckboxArray.push([document.getElementById("fdw-list1-columnResolution-checkbox"), 14]);' + '\n' + 'columnCheckboxArray.push([document.getElementById("fdw-list1-columnStructure-checkbox"), 15]);' + '\n' + 'columnCheckboxArray.push([document.getElementById("fdw-list1-columnNonFD-checkbox"), 16]);' + '\n' + 'columnCheckboxArray.push([document.getElementById("fdw-list1-columnSetting-checkbox"), 17]);' + '\n' + 'columnCheckboxArray.push([document.getElementById("fdw-list1-columnFetishes-checkbox"), 18]);' + '\n' + 'columnCheckboxArray.push([document.getElementById("fdw-list1-columnNotes-checkbox"), 19]);' + '\n' + 'columnCheckboxArray.push([document.getElementById("fdw-list1-columnScreenshots-checkbox"), 20]);' + '\n' + 'columnCheckboxArray.push([document.getElementById("fdw-list1-columnLinks-checkbox"), 21]);' + '\n' + '// Check all columns to start (to match the fact that all columns are displayed by default on the wiki page)' + '\n' + '// Then load states into columns checkboxes based on URL parameter hcols, or based on a coded default undisplayed column list if hcols does not exist' + '\n' + 'columnCheckboxArray.forEach(function(item) {' + '\n' + '  item[0].checked = "checked";' + '\n' +  '});' + '\n' + 'var params = new URLSearchParams(window.location.search);' + '\n' + 'var checkedArray2 = JSON.parse(params.get("hcols"));' + '\n' + 'if (!checkedArray2) {' + '\n' + ' checkedArray2 = JSON.parse("[3,4,6,7,10,11,12,13,14,15,16,19]");' + '\n' + '}' + '\n' + 'if (checkedArray2) { ' + '\n' + ' for (var i=0; i < checkedArray2.length; i++) {' + '\n' + '   columnCheckboxArray.forEach(function(item) {' + '\n' +  '      var checkbox = item[0];' + '\n' +  '      var offset = item[1];' + '\n' +  '      if (checkedArray2[i] == offset) {' + '\n' +  '        checkbox.checked = "";' + '\n' +  '      }' + '\n' +  '    });' + '\n' + ' }' + '\n' + '}' + '\n' + '// Define the function that is run upon clicking Select All/Unselected All' + '\n' + 'function fdw_list1_checkall {' + '\n' + ' var checkboxes = document.querySelectorAll("input[type=checkbox][id^=fdw-list1-column]");' + '\n' + ' var checkedCheckboxes = document.querySelectorAll("input:checked[id^=fdw-list1-column]");' + '\n' + ' if (checkedCheckboxes.length == checkboxes.length) {' + '\n' + '   // All checked already, so uncheck all' + '\n' + '   checkboxes.forEach(function(checkbox) {' + '\n' +  '      checkbox.checked = false;' + '\n' +  '    });' + '\n' + ' } else if (checkedCheckboxes.length == 0) {' + '\n' + '   // None checked, so check the default columns' + '\n' + '   checkboxes[0].checked = true;' + '\n' + '   checkboxes[1].checked = true;' + '\n' + '   checkboxes[4].checked = true;' + '\n' + '   checkboxes[7].checked = true;' + '\n' + '   checkboxes[8].checked = true;' + '\n' + '   checkboxes[16].checked = true;' + '\n' + '   checkboxes[17].checked = true;' + '\n' + '   checkboxes[19].checked = true;' + '\n' + '   checkboxes[20].checked = true;' + '\n' + ' } else {' + '\n' + '   // Otherwise, just check all columns' + '\n' + '   checkboxes.forEach(function(checkbox) {' + '\n' +  '      checkbox.checked = true;' + '\n' +  '    });' + '\n' + ' }' + '\n' + '}' + '\n' + ''; e.appendChild(s); }

// Fill out the div of Template:List1CoverDisplay to contain the JavaScript that turns the column 1 covers into pairs of thumbnails and hover-able full size versions // Also, here is where I will add the style for screenshots e = document.getElementById('fdw-list1-cover-display'); if (e != null) { s = document.createElement("script"); s.text = '' + 'var coverColumnImages = document.querySelectorAll("#table1 tr td:nth-child(1) img");' + '\n' + 'coverColumnImages.forEach(function(coverImage) {' + '\n' + '  var coverImageFullSize = coverImage.cloneNode(true);' + '\n' +  '  var coverImageFullSizeDiv;' + '\n' +  '  var newURL;' + '\n' +  '  newURL = coverImageFullSize.src.replace("/thumb/", "/");' + '\n' +  '  newURL= newURL.substr(0, newURL.lastIndexOf("/"));' + '\n' +  '  coverImageFullSize.src = newURL;' + '\n' +  '  coverImageFullSize.removeAttribute("width");' + '\n' +  '  coverImageFullSize.removeAttribute("height");' + '\n' +  '  coverImageFullSize.removeAttribute("srcset");' + '\n' +  '  coverImageFullSize.style.display = "block";' + '\n' +  '  coverImageFullSize.style.padding = "10px";' + '\n' +  '  coverImageFullSize.style.maxWidth = "100%";' + '\n' +  '  coverImageFullSize.style.maxHeight = "100%";' + '\n' +  '  coverImageFullSize.style.auto = "100%";' + '\n' +  '  coverImageFullSize.style.width = "auto";' + '\n' +  '  coverImageFullSize.style.height = "auto";' + '\n' + ' coverImageFullSizeDiv = document.createElement("div");' + '\n' + ' coverImageFullSizeDiv.style.display = "block";' + '\n' + ' coverImageFullSizeDiv.style.position = "absolute";' + '\n' + ' coverImageFullSizeDiv.style.auto = "100%";' + '\n' + ' coverImageFullSizeDiv.style.width = "800px";' + '\n' + ' coverImageFullSizeDiv.style.height = "800px";' + '\n' + ' coverImageFullSizeDiv.appendChild(coverImageFullSize);' + '\n' + ' coverImageFullSizeDiv.style.marginLeft = "200px";' + '\n' + ' coverImageFullSizeDiv.style.marginTop = "-500px";' + '\n' + ' coverImage.addEventListener("mouseenter", (event) => { ' + '\n' +  '    coverImage.after(coverImageFullSizeDiv);' + '\n' +  // Remove comment if I want the cover image to be offset vertically so that its cells are not covered up //  '    coverImageFullSizeDiv.style.marginTop = "-" + (coverImageFullSize.naturalHeight+210) + "px";' + '\n' +  '  });' + '\n' + ' coverImage.addEventListener("mouseleave", (event) => { ' + '\n' +  '    coverImageFullSizeDiv.remove;' + '\n' +  '  });' + '\n' + '});' + '\n' + 'var ssColumnImages = document.querySelectorAll("#table1 tr td:nth-child(20) img");' + '\n' +  'for (var i = 0; i < ssColumnImages.length; i++) {' + '\n' +  '  ssColumnImages[i].style.padding = "2px";' + '\n' +  '}' + '\n' +  ''; e.appendChild(s); }

// Fill out the div of Template:List1FilterSection to contain the buttons used to create theme and fetish filters e = document.getElementById('fdw-list1-filter-section'); if (e != null) { e.innerHTML = '' + 'Filters: ' + '\n' + '<button id="fdw-list1-filter-theme-button" onClick="fdw_list1_add_theme_filter">Add a Theme Filter ' + '\n' + '<button id="fdw-list1-filter-fetish-button" onClick="fdw_list1_add_fetish_filter">Add a Fetish Filter  ' + '\n' + 'Only titles that match all filters will be displayed. Use capitalized OR or commas to separate terms when you want to let the filter match any one of them. Use leading minus (-) to exclude a term instead.' + '\n' + ''; } // Fill out the div of Template:List1FilterSectionLogic to contain the JavaScript that allows dynamic creation and deletion of theme and fetish filters e = document.getElementById('fdw-list1-filter-section-logic'); if (e != null) { s = document.createElement("script"); s.text = '' + 'function fdw_list1_add_theme_filter {' + '\n' + ' var newFilter = document.createElement("div");' + '\n' + ' newFilter.innerHTML = "Theme: ";' + '\n' + ' var newFilterText = document.createElement("input");' + '\n' + ' var newFilterButton = document.createElement("button");' + '\n' + ' newFilter.appendChild(newFilterText);' + '\n' + ' newFilter.appendChild(newFilterButton);' + '\n' + ' newFilterText.classList.add("theme-filter-text");' + '\n' + ' newFilterButton.innerHTML = "⊗";' + '\n' + ' newFilterButton.onclick = function { newFilter.remove; }' + '\n' + ' var filterArea = document.getElementById("fdw-list1-filter-section");' + '\n' + ' filterArea.appendChild(newFilter); // Hopefully this will not persistently affect fdw-list1-filter-section upon reload' + '\n' + '}' + '\n' + 'function fdw_list1_add_fetish_filter {' + '\n' + // Same as previous function but change theme-filter-text to fetish-filter-text and Theme: to Fetish: ' var newFilter = document.createElement("div");' + '\n' + ' newFilter.innerHTML = "Fetish: ";' + '\n' + ' var newFilterText = document.createElement("input");' + '\n' + ' var newFilterButton = document.createElement("button");' + '\n' + ' newFilter.appendChild(newFilterText);' + '\n' + ' newFilter.appendChild(newFilterButton);' + '\n' + ' newFilterText.classList.add("fetish-filter-text");' + '\n' + ' newFilterButton.innerHTML = "⊗";' + '\n' + ' newFilterButton.onclick = function { newFilter.remove; }' + '\n' + ' var filterArea = document.getElementById("fdw-list1-filter-section");' + '\n' + ' filterArea.appendChild(newFilter);' + '\n' + '}' + '\n' + ''; e.appendChild(s); }

// Fill out the div of Template:List1RedisplayButton to contain the button used to redisplay the table e = document.getElementById('fdw-list1-redisplay-button'); if (e != null) { e.innerHTML = '<button id="fdw-list1-column-button" onClick="fdw_list1_column_toggle">Redisplay Table   Show Only Favorites <input type="checkbox" id="fdw-list1-showOnlyFavs">      '; } // Fill out the div of Template:List1RedisplayButtonLogic to contain the logic used to redisplay the table and code to automatically check the show only favorites checkbox e = document.getElementById('fdw-list1-redisplay-button-logic'); if (e != null) { s = document.createElement("script"); s.text = '' + '\n' + 'var params = new URLSearchParams(window.location.search);' + '\n' + 'var checkedArray = JSON.parse(params.get("favs"));' + '\n' + 'if (checkedArray && checkedArray.length > 0) {' + '\n' + ' var elem = document.getElementById("fdw-list1-showOnlyFavs");' + '\n' + ' elem.checked = "checked";' + '\n' + '}' + '\n' + 'function fdw_list1_column_toggle {' + '\n' + '// Handle checkboxes' + '\n' + 'var elem;' + '\n' + 'var elems;' + '\n' + 'var offset;' + '\n' + 'columnCheckboxArray.forEach(function(item) {' + '\n' + '  checkbox = item[0];' + '\n' +  '  offset = item[1];' + '\n' +  '  // Evaluate every cell from top to bottom that is the nth-child column based on offset, which is within the tr of the body (not the header/first row)' + '\n' +  '  elems = document.querySelectorAll("#table1 tbody>tr>:nth-child(" + offset + ")");' + '\n' +  '  for (var i = 0; i < elems.length; i++) {' + '\n' +  '    if (checkbox.checked == true) {' + '\n' +  '      elems[i].style.display = "";' + '\n' +  '    } else {' + '\n' +  '      elems[i].style.display = "none";' + '\n' +  '  }}' + '\n' +  '  // Evaluate every cell from top to bottom that is the nth-child column based on offset, which is within the tr of the header' + '\n' +  '  elem = document.querySelector("#table1 thead>tr>:nth-child(" + offset + ")");' + '\n' +  '  if (checkbox.checked == true) {' + '\n' + '   elem.style.display = "";' + '\n' + ' } else {' + '\n' + '   elem.style.display = "none";' + '\n' + ' }' + '\n' + '});' + '\n' + '// Handle filters' + '\n' +  'var table = document.querySelector("#table1");' + '\n' +  '// Get all text box HTML elements, then use map to obtain an array of their .value properties, then remove elements which are pure whitespace' + '\n' +  'var theme_includes = Array.from(document.getElementsByClassName("theme-filter-text")).map(e => e.value).filter(function(v) { return v.trim.length > 0; });' + '\n' +  'var fetish_includes = Array.from(document.getElementsByClassName("fetish-filter-text")).map(e => e.value).filter(function(v) { return v.trim.length > 0; });' + '\n' +  'var filtersExist = (theme_includes.join != "" || fetish_includes.join != "");' + '\n' +  '// Set variable to check whether only favorited rows should be shown later' + '\n' +  'var showOnlyFavs;' + '\n' +  'var showOnlyFavsCheckbox = document.getElementById("fdw-list1-showOnlyFavs");' + '\n' + 'if (showOnlyFavsCheckbox.checked == true) {' + '\n' + ' showOnlyFavs = true;' + '\n' + '} else {' + '\n' + ' showOnlyFavs = false;' + '\n' + '}' + '\n' + '// Iterate through all table rows. Start at 1 to skip the table header' + '\n' + 'for (var i=1; i < table.rows.length; i++) {' + '\n' + ' // If show only favorites is checked but the row is not favorited, set the row to not display' + '\n' + ' if (showOnlyFavs == true && table.rows[i].cells[21].lastChild.checked != true) {' + '\n' + '   table.rows[i].style.display = "none";' + '\n' + ' // If there are no filters, set each row to display properly. Otherwise, set each row to not display and only redisplay if it matches all filters.' + '\n' + ' } else if (!filtersExist) {' + '\n' + '   table.rows[i].style.display = "";' + '\n' + ' } else {' + '\n' + '   table.rows[i].style.display = "none";' + '\n' + '   var displayRow = true; // Change to false if it fails any filter tests. We know at least 1 exists' + '\n' + '   // Process theme filters' + '\n' + '   for (var j = 0; j < theme_includes.length; j++) {' + '\n' + '     // Change all " OR " to commas' + '\n' + '     theme_includes[j] = theme_includes[j].replaceAll(" OR ", ", ");' + '\n' + '     // If the include string contains a comma, check if at least comma-split term matches; if not, set displayRow to false' + '\n' + '     // If the include string does NOT contain a comma, check for leading minus (negation), and based on that, set displayRow to false if it does/does not match' + '\n' + '     // In other words, negation and commas are treated as mutually exclusive (negation is ignored if a comma is detected)' + '\n' + '     if (theme_includes[j].includes(",")) {' + '\n' + '       var atLeastOneMatches = false;' + '\n' + '       var validTerms = theme_includes[j].split(",").filter(function(v) { return v.trim.length > 0; });' + '\n' + '       validTerms.forEach(function (term) {' + '\n' +  '          if (table.rows[i].cells[16].innerHTML.toLowerCase.includes(term.trim.toLowerCase)) {' + '\n' +  '            atLeastOneMatches = true;' + '\n' +  '          }' + '\n' +  '        });' + '\n' + '       if (atLeastOneMatches == false) {' + '\n' + '         displayRow = false;' + '\n' + '       }' + '\n' + '     } else {' + '\n' + '       if (theme_includes[j].trim.charAt(0) == "-") {' + '\n' + '         if (table.rows[i].cells[16].innerHTML.toLowerCase.includes(theme_includes[j].trim.substring(1).toLowerCase)) {' + '\n' + '           displayRow = false;' + '\n' + '         }' + '\n' + '       } else if (!(table.rows[i].cells[16].innerHTML.toLowerCase.includes(theme_includes[j].trim.toLowerCase))) {' + '\n' + '         displayRow = false;' + '\n' + '       }' +'\n' + '     }' + '\n' + '   }' + '\n' + '   // Now for fetish filters (largely redundant)' + '\n' + '   for (var j = 0; j < fetish_includes.length; j++) {' + '\n' + '     // Change all " OR " to commas' + '\n' + '     fetish_includes[j] = fetish_includes[j].replaceAll(" OR ", ", ");' + '\n' + '     // If the include string contains a comma, check if at least comma-split term matches; if not, set displayRow to false' + '\n' + '     // If the include string does NOT contain a comma, check for leading minus (negation), and based on that, set displayRow to false if it does/does not match' + '\n' + '     // In other words, negation and commas are treated as mutually exclusive (negation is ignored if a comma is detected)' + '\n' + '     if (fetish_includes[j].includes(",")) {' + '\n' + '       var atLeastOneMatches = false;' + '\n' + '       var validTerms = fetish_includes[j].split(",").filter(function(v) { return v.trim.length > 0; });' + '\n' + '       validTerms.forEach(function (term) {' + '\n' +  '          if (table.rows[i].cells[17].innerHTML.toLowerCase.includes(term.trim.toLowerCase)) {' + '\n' +  '            atLeastOneMatches = true;' + '\n' +  '          }' + '\n' +  '        });' + '\n' + '       if (atLeastOneMatches == false) {' + '\n' + '         displayRow = false;' + '\n' + '       }' + '\n' + '     } else {' + '\n' + '       if (fetish_includes[j].trim.charAt(0) == "-") {' + '\n' + '         if (table.rows[i].cells[17].innerHTML.toLowerCase.includes(fetish_includes[j].trim.substring(1).toLowerCase)) {' + '\n' + '           displayRow = false;' + '\n' + '         }' + '\n' + '       } else if (!(table.rows[i].cells[17].innerHTML.toLowerCase.includes(fetish_includes[j].trim.toLowerCase))) {' + '\n' + '         displayRow = false;' + '\n' + '       }' +'\n' + '     }' + '\n' + '   }' + '\n' + '   // If displayRow was never switched to false, it is safe to display the row' + '\n' + '   if (displayRow == true) {' + '\n' + '     table.rows[i].style.display = "";' + '\n' + '   }' + '\n' + ' }' + '\n' + '}' + '\n' + 'var visibleRows = $("#table1 tr:visible").length;' + '\n' + 'var results = document.querySelector("#resultsInfo");' + '\n' + 'results.innerHTML = (visibleRows-1) + " results found.";' + '\n' + '}' + '\n'; // Close the onclick function e.appendChild(s); }

// Fill out the div of Template:List1FavoritesButtons to contain the buttons to save and reset favorites e = document.getElementById('fdw-list1-favorites-buttons'); if (e != null) { e.innerHTML = '' + 'Favorites: <button onClick="fdw_list1_favorites_save">Save Favorites & Columns to URL Bar to Share ' + '\n' + '<button onClick="fdw_list1_favorites_reset">Reset Favorites / Favorite All  ' + '\n' + ''; } // Fill out the div of Template:List1FavoritesButtonsLogic to load favorites checkboxes and contain favorites buttons logic. Also column logic e = document.getElementById('fdw-list1-favorites-buttons-logic'); if (e != null) { s = document.createElement("script"); s.text = '' + 'var favoritesCheckboxesArray = [];' + '\n' + 'var table = document.querySelector("#table1");' + '\n' + 'for (var i=1; i < table.rows.length; i++) { // Start on second row (past header)' + '\n' + ' var newCheckbox = document.createElement("input");' + '\n' + ' newCheckbox.type = "checkbox";' + '\n' + ' newCheckbox.style.msTransform = "scale(2)"; // IE' + '\n' + ' newCheckbox.style.MozTransform = "scale(2)"; // FF' + '\n' + ' newCheckbox.style.WebkitTransform = "scale(2)"; // Safari and Chrome' + '\n' + ' newCheckbox.style.OTransform = "scale(2)"; // Opera' + '\n' + ' newCheckbox.style.transform = "scale(2)";' + '\n' + ' newCheckbox.setAttribute("id", table.rows[i].cells[1].innerHTML.trim);' + '\n' + ' newCheckbox.setAttribute("class", "list1-favs-checkbox");' + '\n' + ' newCheckbox.onclick =  function  {' + '\n' + '   if (this.parentNode.parentNode.style.backgroundColor == "") {' + '\n' + '     this.parentNode.parentNode.style.backgroundColor = "#90ee90";' + '\n' + '     this.parentNode.setAttribute("data-sort-value", "Selected");' + '\n' + '   } else if (this.parentNode.parentNode.style.backgroundColor != "") {' + '\n' + '     this.parentNode.parentNode.style.backgroundColor = "";' + '\n' + '     // TODO Low priority, but change the string(s) so that when unchecked, selected rows are not awkwardly sandwiched like [NoDataSortValue]->Selected->Unselected. Set to empty string instead of Unselected?' + '\n' + '     this.parentNode.setAttribute("data-sort-value", "Unselected");' + '\n' + '   }' + '\n' + ' };' + '\n' + ' favoritesCheckboxesArray.push(newCheckbox);' + '\n' + ' table.rows[i].cells[21].appendChild(newCheckbox);' + '\n' + ' table.rows[i].cells[21].setAttribute("data-sort-value", "Unselected");' + '\n' + '}' + '\n' + '// Load initial favorites based on URL parameter' + '\n' + '// Also, assume that only favorites should be displayed (default behavior upon first visiting the page)' + '\n' + 'var params = new URLSearchParams(window.location.search);' + '\n' + 'var checkedArray = JSON.parse(params.get("favs"));' + '\n' + 'if (checkedArray && checkedArray.length > 0) { ' + '\n' + ' for (i=1; i< table.rows.length; i++) {' + '\n' + '   if (checkedArray.indexOf(table.rows[i].cells[1].innerHTML.trim.hashCode) > -1) {' + '\n' + '     table.rows[i].cells[21].childNodes[1].checked = "checked";' + '\n' + '     table.rows[i].style.backgroundColor = "#90ee90";' + '\n' + '     table.rows[i].cells[21].setAttribute("data-sort-value", "Selected");' + '\n' + '   } else {' + '\n' + '     table.rows[i].style.display = "none";' + '\n' + '   }' + '\n' + ' }' + '\n' + '}' + '\n' + '// Initially undisplay columns based on hcols rather than column checkbox states, because there is no guarantee that column checkboxes will have loaded in the DOM by the time this code is run' + '\n' + 'var checkedArray2 = JSON.parse(params.get("hcols"));' + '\n' + '// Set the default columns if hcols does not exist' + '\n' + 'if (!checkedArray2) {' + '\n' + ' checkedArray2 = JSON.parse("[3,4,6,7,10,11,12,13,14,15,16,19]");' + '\n' + '}' + '\n' + 'if (checkedArray2) {' + '\n' + ' for (var i=0; i < checkedArray2.length; i++) {' + '\n' + '   // checkedArray2[i] = an offset for which every table cell should be undisplayed by setting display to none (the checkbox checked property will also be set to empty string in another function at some point)' + '\n' + '   // Evaluate every cell from top to bottom that is the nth-child column based on offset, which is within the tr of the body (not the header/first row)' + '\n' + '   var elems = document.querySelectorAll("#table1 tbody>tr>:nth-child(" + checkedArray2[i] + ")");' + '\n' + '   for (var j = 0; j < elems.length; j++) {' + '\n' + '       elems[j].style.display = "none";' + '\n' + '   }' + '\n' + '   // Evaluate every cell from top to bottom that is the nth-child column based on offset, which is within the tr of the header' + '\n' + '   var elem = document.querySelector("#table1 thead>tr>:nth-child(" + checkedArray2[i] + ")");' + '\n' + '   if (elem != null) { // For some reason, this occasionally is set to null, but there are no display-related problems either way' + '\n' + '     elem.style.display = "none";' + '\n' + '   }' + '\n' + ' }' + '\n' + '}' + '\n' +

'// Button click functions' + '\n' + 'function fdw_list1_favorites_save {' + '\n' + ' // Favorites' + '\n' + ' var table = document.querySelector("#table1");' + '\n' + ' var checkedRows = [];' + '\n' + ' for (i=0; i < favoritesCheckboxesArray.length; i++) {' + '\n' + '   if (favoritesCheckboxesArray[i].checked)  {' + '\n' + '     checkedRows.push(favoritesCheckboxesArray[i].getAttribute("id").hashCode);' + '\n' + '   }' + '\n' + ' }' + '\n' + ' var params = new URLSearchParams;' + '\n' + ' params.append("favs", JSON.stringify(checkedRows));' + '\n' + ' // Columns' + '\n' + ' var uncheckedColumns = [];' + '\n' + ' for (i=0; i < columnCheckboxArray.length; i++) {' + '\n' + '   if (columnCheckboxArray[i][0].checked == "")  {' + '\n' + '     uncheckedColumns.push(columnCheckboxArray[i][1]);' + '\n' + '   }' + '\n' + ' }' + '\n' + ' var columns_stringified = JSON.stringify(uncheckedColumns);' + '\n' + ' if (columns_stringified != "[3,4,6,7,10,11,12,13,14,15,16,19]") { // Do not bother to save column param that is already default' + '\n' + '   params.append("hcols", columns_stringified);' + '\n' + ' }' + '\n' + ' window.history.pushState("object or string", "Title", "Comparison_of_translated_Japanese_femdom_games?" + params.toString);' + '\n' + '}' + '\n' + 'function fdw_list1_favorites_reset {' + '\n' + ' var checkedFavsCheckboxes = document.querySelectorAll("input:checked[class=list1-favs-checkbox]");' + '\n' + ' var elem = document.getElementById("fdw-list1-showOnlyFavs");' + '\n' + ' if (checkedFavsCheckboxes.length == 0) {' + '\n' + '   // No favorites checked, so check all favorites rather than reset' + '\n' + '   favoritesCheckboxesArray.forEach(function(checkbox) {' + '\n' +  '      if ($(checkbox).is(":visible")) {' + '\n' +  '        checkbox.checked = true;' + '\n' +  '        checkbox.parentNode.parentNode.style.backgroundColor = "#90ee90";' + '\n' +  '        checkbox.parentNode.setAttribute("data-sort-value", "Selected");' + '\n' +  '      }' + '\n' +  '    });' + '\n' + '   // Might as well check the show only favs checkbox too' + '\n' + '   elem.checked = true;' + '\n' + ' } else {' + '\n' + '   // Reset' + '\n' + '   favoritesCheckboxesArray.forEach(function(checkbox) {' + '\n' +  '      checkbox.checked = "";' + '\n' +  '      checkbox.parentNode.parentNode.style.backgroundColor = "";' + '\n' +  '      checkbox.parentNode.setAttribute("data-sort-value", "Unselected");' + '\n' +  '    });' + '\n' + '   // Might as well clear the show only favs checkbox too' + '\n' + '   elem.checked = "";' + '\n' + ' }' + '\n' + '}' + '\n'; // Close the onclick function e.appendChild(s); }