* Lehrgangsfuchs

Platziert die eigenen und offenen Lehrgänge auf Tabs, bietet Filtermöglichkeiten an und zeigt die Anzahl der Lehrgänge (gefiltert/gesamt) an

  1. // ==UserScript==
  2. // @name * Lehrgangsfuchs
  3. // @namespace bos-ernie.leitstellenspiel.de
  4. // @version 1.3.2
  5. // @license BSD-3-Clause
  6. // @author BOS-Ernie
  7. // @description Platziert die eigenen und offenen Lehrgänge auf Tabs, bietet Filtermöglichkeiten an und zeigt die Anzahl der Lehrgänge (gefiltert/gesamt) an
  8. // @match https://www.leitstellenspiel.de/schoolings*
  9. // @match https://polizei.leitstellenspiel.de/schoolings*
  10. // @icon https://www.google.com/s2/favicons?sz=64&domain=leitstellenspiel.de
  11. // @run-at document-idle
  12. // @grant none
  13. // @resource https://forum.leitstellenspiel.de/index.php?thread/24748-script-lehrgangsfuchs-by-bos-ernie/
  14. // ==/UserScript==
  15.  
  16. (function () {
  17. "use strict";
  18.  
  19. function getQueryParameter(name) {
  20. const url = new URL(window.location.href);
  21. return url.searchParams.get(name);
  22. }
  23.  
  24. function setQueryParameter(name, value) {
  25. const url = new URL(window.location.href);
  26. url.searchParams.set(name, value);
  27. window.history.replaceState({}, "", url);
  28. }
  29.  
  30. function removeQueryParameter(name) {
  31. const url = new URL(window.location.href);
  32. url.searchParams.delete(name);
  33. window.history.replaceState({}, "", url);
  34. }
  35.  
  36. function filterRows(startsWith) {
  37. if (startsWith === null) {
  38. startsWith = getQueryParameter("filter");
  39. } else {
  40. setQueryParameter("filter", startsWith);
  41. }
  42.  
  43. if (startsWith === null) {
  44. startsWith = "";
  45.  
  46. removeQueryParameter("filter");
  47. }
  48.  
  49. filterTableRows("schooling_own_table", startsWith);
  50. filterTableRows("schooling_opened_table", startsWith);
  51. }
  52.  
  53. function filterTableRows(tableId, startsWith) {
  54. const rows = document.getElementById(tableId).getElementsByTagName("tr");
  55.  
  56. for (let i = 0; i < rows.length; i++) {
  57. const row = rows[i];
  58. row.style.display = "";
  59.  
  60. if (row.innerText.startsWith("Lehrgang")) {
  61. continue;
  62. }
  63.  
  64. if (
  65. row.getElementsByTagName("td").length > 0 &&
  66. row.getElementsByTagName("td")[0].getElementsByTagName("a").length > 0 &&
  67. !row.getElementsByTagName("td")[0].getElementsByTagName("a")[0].innerText.toLowerCase().startsWith(startsWith)
  68. ) {
  69. row.style.display = "none";
  70. }
  71. }
  72.  
  73. updateCounters();
  74. }
  75.  
  76. function updateCounters() {
  77. updateCount("schooling_own_table", "count-own");
  78. updateCount("schooling_opened_table", "count-open");
  79. }
  80.  
  81. function updateCount(tableId, counterId) {
  82. const tableSchoolingsOpened = document.getElementById(tableId);
  83. const countOpen = tableSchoolingsOpened.getElementsByTagName("tr").length - 1;
  84. const countOpenFiltered = tableSchoolingsOpened.querySelectorAll("tr:not([style*='display: none'])").length - 1;
  85.  
  86. const spanCountOpen = document.getElementById(counterId);
  87. if (countOpen === countOpenFiltered) {
  88. spanCountOpen.innerText = countOpen;
  89. } else {
  90. spanCountOpen.innerText = countOpenFiltered + "/" + countOpen;
  91. }
  92. }
  93.  
  94. function createFilterButton(text) {
  95. const button = document.createElement("button");
  96. button.id = "filter-button-" + text.toLowerCase();
  97. button.type = "button";
  98. button.innerText = text;
  99. button.setAttribute("data-filter-value", text.toLowerCase());
  100.  
  101. if (getQueryParameter("filter") === text.toLowerCase()) {
  102. button.className = "btn btn-success";
  103. } else {
  104. button.className = "btn btn-default";
  105. }
  106.  
  107. button.addEventListener("click", function (event) {
  108. event.preventDefault();
  109.  
  110. if (button.className === "btn btn-success") {
  111. button.className = "btn btn-default";
  112. filterRows("");
  113. return;
  114. }
  115.  
  116. const buttons = document.getElementById("filter-button-group").getElementsByTagName("button");
  117. for (let i = 0; i < buttons.length; i++) {
  118. const button = buttons[i];
  119. if (button.id === event.target.id) {
  120. button.className = "btn btn-success";
  121. } else {
  122. button.className = "btn btn-default";
  123. }
  124. }
  125.  
  126. filterRows(event.target.getAttribute("data-filter-value"));
  127. });
  128.  
  129. return button;
  130. }
  131.  
  132. function addFilterButtonGroup() {
  133. const buttonGroup = document.createElement("div");
  134. buttonGroup.id = "filter-button-group";
  135. buttonGroup.className = "btn-group btn-group-sm";
  136. buttonGroup.style.margin = "0 0 10px 10px";
  137. buttonGroup.setAttribute("role", "group");
  138. buttonGroup.setAttribute("aria-label", "Filter");
  139.  
  140. buttonGroup.appendChild(createFilterButton("Feuerwehr"));
  141. buttonGroup.appendChild(createFilterButton("Rettungsdienst"));
  142. buttonGroup.appendChild(createFilterButton("Polizei"));
  143. buttonGroup.appendChild(createFilterButton("THW"));
  144.  
  145. const container = document.getElementById("iframe-inside-container");
  146. container.appendChild(buttonGroup);
  147. }
  148.  
  149. function placeTablesOnTabs() {
  150. let currentTab = getQueryParameter("tab");
  151. if (currentTab === null) {
  152. currentTab = "eigene";
  153. }
  154.  
  155. const headings = document.querySelectorAll("h3");
  156. for (let i = 0; i < headings.length; i++) {
  157. headings[i].remove();
  158. }
  159.  
  160. const tableSchoolings = document.getElementById("schooling_own_table");
  161.  
  162. const spanCountOwn = document.createElement("span");
  163. spanCountOwn.id = "count-own";
  164. spanCountOwn.innerText = "?/?";
  165.  
  166. const aOwn = document.createElement("a");
  167. aOwn.href = "#schooling_own_table";
  168. aOwn.setAttribute("data-toggle", "tab");
  169. aOwn.innerText = "Lehrgänge mit eigenen Teilnehmern ";
  170. aOwn.appendChild(spanCountOwn);
  171.  
  172. const liOwn = document.createElement("li");
  173. liOwn.appendChild(aOwn);
  174. aOwn.addEventListener("click", function (event) {
  175. event.preventDefault();
  176. setQueryParameter("tab", "eigene");
  177. });
  178.  
  179. if (currentTab === "eigene") {
  180. liOwn.className = "active";
  181. }
  182.  
  183. const divOwn = document.createElement("div");
  184. divOwn.id = "schooling_own_table";
  185. divOwn.className = "tab-pane";
  186. divOwn.appendChild(tableSchoolings);
  187.  
  188. if (currentTab === "eigene") {
  189. divOwn.classList.add("active");
  190. }
  191.  
  192. const tableSchoolingsOpened = document.getElementById("schooling_opened_table");
  193.  
  194. const spanCountOpen = document.createElement("span");
  195. spanCountOpen.id = "count-open";
  196. spanCountOpen.innerText = "?/?";
  197.  
  198. const aOpen = document.createElement("a");
  199. aOpen.href = "#schooling_opened_table";
  200. aOpen.setAttribute("data-toggle", "tab");
  201. aOpen.innerText = "Offene Lehrgänge ";
  202. aOpen.appendChild(spanCountOpen);
  203.  
  204. const liOpen = document.createElement("li");
  205. liOpen.appendChild(aOpen);
  206. aOpen.addEventListener("click", function (event) {
  207. event.preventDefault();
  208. setQueryParameter("tab", "offene");
  209. });
  210.  
  211. if (currentTab === "offene") {
  212. liOpen.className = "active";
  213. }
  214.  
  215. const divOpen = document.createElement("div");
  216. divOpen.className = "tab-pane";
  217. divOpen.id = "schooling_opened_table";
  218. divOpen.appendChild(document.querySelector("[search_class='schooling_opened_table_searchable']"));
  219. divOpen.appendChild(tableSchoolingsOpened);
  220.  
  221. if (currentTab === "offene") {
  222. divOpen.classList.add("active");
  223. }
  224.  
  225. const div = document.createElement("div");
  226. div.className = "tab-content";
  227. div.appendChild(divOwn);
  228. div.appendChild(divOpen);
  229.  
  230. const ul = document.createElement("ul");
  231. ul.className = "nav nav-tabs";
  232. ul.appendChild(liOwn);
  233. ul.appendChild(liOpen);
  234.  
  235. const tabs = document.createElement("div");
  236. tabs.className = "tabs";
  237. tabs.appendChild(ul);
  238. tabs.appendChild(div);
  239.  
  240. const container = document.getElementById("iframe-inside-container");
  241. container.appendChild(tabs);
  242. }
  243.  
  244. function main() {
  245. if (window.location.pathname.match(/\/schoolings\/\d+/)) {
  246. return;
  247. }
  248.  
  249. addFilterButtonGroup();
  250. placeTablesOnTabs();
  251. filterRows(null);
  252. }
  253.  
  254. main();
  255. })();