TSWRP Calendar Events Filtering

Adds filters for TSW-RP Calendar

Voor het installeren van scripts heb je een extensie nodig, zoals Tampermonkey, Greasemonkey of Violentmonkey.

Voor het installeren van scripts heb je een extensie nodig, zoals Tampermonkey of Violentmonkey.

Voor het installeren van scripts heb je een extensie nodig, zoals Tampermonkey of Violentmonkey.

Voor het installeren van scripts heb je een extensie nodig, zoals Tampermonkey of Userscripts.

Voor het installeren van scripts heb je een extensie nodig, zoals {tampermonkey_link:Tampermonkey}.

Voor het installeren van scripts heb je een gebruikersscriptbeheerder nodig.

(Ik heb al een user script manager, laat me het downloaden!)

Voor het installeren van gebruikersstijlen heb je een extensie nodig, zoals {stylus_link:Stylus}.

Voor het installeren van gebruikersstijlen heb je een extensie nodig, zoals {stylus_link:Stylus}.

Voor het installeren van gebruikersstijlen heb je een extensie nodig, zoals {stylus_link:Stylus}.

Voor het installeren van gebruikersstijlen heb je een gebruikersstijlbeheerder nodig.

Voor het installeren van gebruikersstijlen heb je een gebruikersstijlbeheerder nodig.

Voor het installeren van gebruikersstijlen heb je een gebruikersstijlbeheerder nodig.

(Ik heb al een beheerder - laat me doorgaan met de installatie!)

// ==UserScript==
// @name            TSWRP Calendar Events Filtering
// @description:en  Adds filters for TSW-RP Calendar
// @namespace       http://www.tsw-rp.com
// @include         http://tsw-rp.com/events
// @include         http://www.tsw-rp.com/events
// @version         5
// @grant           none
// @description Adds filters for TSW-RP Calendar
// ==/UserScript==

/*****
   Default filters. First text is what will be shown next to the checkbox,
   second text is a part of the event name that will be filtered
   ("RFG -" will filter out all events containing "RFG -" in title)
*****/
function getDefaultFilters() {
  return {
    "Radio Free Gaia": "RFG -,Anarchist Dictatorship,DJ Ashval",
    "GridStream Productions": "GSP -,DJ Daydreaming",
    "Happy Tentacle Radio": "Happy Tentacle Radio,DJ Dynamiks,The Fratelli",
    "PizzaNights": "PizzaNight",
    "MEZ raid": "MEZ training",
    "Seoul RP": "Seoul RP",
    "Tuesday Night RP": "TNRP - Tuesday Night RP",
    "Sunday Morning Gaming": "SMG - Sunday Morning Gaming",
  }
}



$(function() {
  initCalendarFilters();
});

$(document).ajaxComplete(function() {
  filterEvents();
});

function initCalendarFilters() {
  var allFilters = loadFilters();
  uncheckFiltersByPreferences(allFilters);
  renderFilteringContainer(allFilters);
}

// Loads and prepares both default and custom filters (custom are stored in browser's cookie)
function loadFilters() {
  var customFilters = readCookie("CalendarCustomFilters");
  for (var filterName in customFilters) {
    customFilters[filterName] = {"filter": customFilters[filterName], "checked": true, "custom": true};
  }
  var defaultFilters = getDefaultFilters();
  for (var filterName in defaultFilters) {
    defaultFilters[filterName] = {"filter": defaultFilters[filterName], "checked": true, "custom": false};
  }
  var allFilters = $.extend(defaultFilters, customFilters);
  return allFilters;
}

// Loads a list of filters that should be unchecked (stored in browser's cookie)
function uncheckFiltersByPreferences(filters) {
  var uncheckedFilters = readCookie("CalendarUncheckedFilters");
  if (uncheckedFilters != null) {
    for (var i = 0; i < uncheckedFilters.length; ++i) {
      var filterName = uncheckedFilters[i];
      if (filters[filterName]) {
        filters[filterName]["checked"] = false;
      }
    }
  }
}

function renderFilteringContainer(filters) {
  var $filterContainer = $("<div id='calendar-filters-cont'/>");
  $filterContainer.append("<h3>Event Filters:</h3>")
  var $filterList = $("<ul id='calendar-filters'/>");
  $filterContainer.append($filterList);
  $(".calendar-container").before($filterContainer);
  
  // Sort filters by label
  var filterNames = [];
  for (var filterName in filters) {
    filterNames.push(filterName);
  }
  filterNames = filterNames.sort();
  
  $.each(filterNames, function() {
    var filterName = this;
    var filter = filters[filterName];
    renderFilter($filterList, filterName, filter["filter"], filter["checked"], filter["custom"]);
  });
  
  // Render "Add Custom Filter"
  var $customFilterContainer = $("<div id='custom-filter-add-cont'/>");
  var $customFilterButtons = $("<div id='custom-filters-buttons'/>");
  var $showAddCustomFilterButton = $("<button style='margin: 0 10px; padding: 3px;'>Add Custom Filter</button>");
  $showAddCustomFilterButton.click(function() {
    $(this).parent().hide();
    $("#custom-filter-add-form").show();
  });
  $customFilterButtons.append($showAddCustomFilterButton);
  var $deleteCustomFiltersButton = $("<button style='padding: 3px;'>Delete Custom Filters</button>");
  $deleteCustomFiltersButton.click(function() {
    deleteCustomFilters();
  });
  $customFilterButtons.append($deleteCustomFiltersButton);
  $customFilterContainer.append($customFilterButtons);
  var $customFilterForm = $("<div id='custom-filter-add-form' style='display: none;'/>");
  $customFilterForm.append("<label for='custom-filter-name'>Name: </label><input type='text' id='custom-filter-name' style='margin-right: 10px;'/>");
  $customFilterForm.append("<label for='custom-filter-val'>Text to filter: </label><input type='text' id='custom-filter-val' style='margin-right: 10px;'/>");
  var $addCustomFilterButton = $("<button style='padding: 3px;'>Add</button>");
  $addCustomFilterButton.click(function() {
    addCustomFilter($("#custom-filter-name").val(), $("#custom-filter-val").val());
    $("#custom-filter-add-form").hide();
    $("#custom-filters-buttons").show();
  });
  $customFilterForm.append($addCustomFilterButton);
  $customFilterForm.append("<div style='font-size: 8pt; padding: 5px;'>All events that contain the 'Text to filter' in their title will be filtered. " +
                           "You can also specify multiple values separated by comma for filtering similar events that have different names. " +
                           "<br/>E.g. GridStream filter text is <strong>GSP,DJ Daydreaming</strong></div>");
  $customFilterContainer.append($customFilterForm);
  $filterContainer.append($customFilterContainer);
}

function renderFilter($filterList, filterName, filterValue, filterChecked, isCustom) {
  var $filterLi = $("<li style='display: inline-block; white-space: nowrap; padding: 5px 10px;'/>");
  var $filterCheckbox = $("<input type='checkbox' name='"+filterName+"' value='"+filterValue+"' data-custom-filter='"+isCustom+"'/>");
  $filterLi.append($filterCheckbox);
  $filterLi.append(" "+filterName);
  $filterList.append($filterLi);
  $filterCheckbox.prop("checked", filterChecked);
  $filterCheckbox.change(function() {
    filterChanged();
  });
}

function filterChanged() {
  filterEvents();
  saveUncheckFiltersPreferencies();
}

function filterEvents() {
  var $eventDivs = $(".calendar-container .fc-view-month > div > div");
  showAllEvents($eventDivs);
  $("#calendar-filters input:not(:checked)").each(function() {
    hideByNames($eventDivs, $(this).val());
  });
}

function showAllEvents($eventDivs) {
  $eventDivs.find(".fc-event-title").parent().parent().show();
  $eventDivs.find(".desc-wrapper").parent().parent().show();
}

function hideByNames($eventDivs, names) {
  $.each(names.split(","), function() {
    var textToFilter = this.trim();
    $eventDivs.find(".fc-event-title:contains(" + textToFilter + ")").parent().parent().hide();
    $eventDivs.find(".desc-wrapper:contains(" + textToFilter + ")").parent().parent().hide();
  });
}

function saveUncheckFiltersPreferencies() {
  var uncheckedFilters = [];
  $("#calendar-filters input:not(:checked)").each(function() {
    uncheckedFilters.push($(this).prop("name"));
  });
  storeCookie("CalendarUncheckedFilters", uncheckedFilters);
}

function addCustomFilter(name, value) {
  renderFilter($("#calendar-filters"), name, value, false, true);
  saveCustomFilters();
  filterEvents();
}

function saveCustomFilters() {
  var customFilters = {};
  $("#calendar-filters input[data-custom-filter='true']").each(function() {
    customFilters[$(this).prop("name")] = $(this).val();
  });
  storeCookie("CalendarCustomFilters", customFilters);
  saveUncheckFiltersPreferencies();
}

function deleteCustomFilters() {
  $("#calendar-filters input[data-custom-filter='true']").each(function() {
    $(this).closest("li").remove();
  });
  storeCookie("CalendarCustomFilters", {});
  saveUncheckFiltersPreferencies();
  filterEvents();
}

/*** Cookie related functions ***/

function storeCookie(name, value) {
  value = JSON.stringify(value);
  var date = new Date();
  date.setYear(date.getFullYear()+30);
  var expires = "; expires=" + date.toGMTString();
  document.cookie = encodeURIComponent(name) + "=" + encodeURIComponent(value) + expires + "; path=/";
}

function readCookie(name) {
    var nameEQ = encodeURIComponent(name) + "=";
    var ca = document.cookie.split(';');
    for (var i = 0; i < ca.length; i++) {
        var c = ca[i];
        while (c.charAt(0) === ' ') c = c.substring(1, c.length);
        if (c.indexOf(nameEQ) === 0) return JSON.parse(decodeURIComponent(c.substring(nameEQ.length, c.length)));
    }
    return null;
}