Greasy Fork is available in English.

Smartschool+

Change your name and customize Smartschool! Search for other students! Calculate the total score of your grades! Add quick shortcuts. Adds a customizable menu bar for Smartschool. Calculate the total score of your grades. Removes useless buttons and adds quick shortcuts. You can change your name and profile picture by typing the word "change" on your keyboard. You can find all existing users by typing the word "find" on your keyboard.

Instalar este script¿?
Script recomendado por el autor

Puede que también te guste Auto-login Smartschool.

Instalar este script
  1. // ==UserScript==
  2. // @name Smartschool+
  3. // @name:nl Smartschool+
  4. // @name:en Smartschool+
  5. // @namespace http://tampermonkey.net/
  6. // @icon https://static1.smart-school.net/smsc/svg/favicon/favicon.svg
  7. // @version 5.2
  8. // @description:en Change your name and customize Smartschool! Search for other students! Calculate the total score of your grades! Add quick shortcuts. Adds a customizable menu bar for Smartschool. Removes useless buttons and adds quick shortcuts like the "Planner" button in your navigation bar. You can change your name and profile picture by typing the word "change" on your keyboard. You can find all existing users by typing the word "find" on your keyboard.
  9. // @description:nl Voegt een aanpasbare menubalk toe voor Smartschool. Verwijdert nutteloze knoppen en voegt snelle snelkoppelingen toe, zoals de "Planner" knop in je navigatiebalk. Je kunt je naam en profielfoto wijzigen door het woord "change" op je toetsenbord in te typen. Alle bestaande gebruikers kun je vinden door het woord "find" op je toetsenbord in te typen.
  10. // @author Chromeextensions
  11. // @match https://*.smartschool.be/*
  12. // @homepage https://greasyfork.org/en/scripts/476176-smartschool
  13. // @grant GM_getValue
  14. // @grant GM_setValue
  15. // @grant GM_deleteValue
  16. // @run-at document-body
  17. // @copyright Copyright (c) 2021 Chromeextensions. The content presented herein may not, under any circumstances, be reproduced in whole or in any part or form without written permission from Chromeextensions.
  18. // @require https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js
  19. // @require https://update.greasyfork.org/scripts/481384/1290420/Grid%20Smartschool.js
  20. // @description Change your name and customize Smartschool! Search for other students! Calculate the total score of your grades! Add quick shortcuts. Adds a customizable menu bar for Smartschool. Calculate the total score of your grades. Removes useless buttons and adds quick shortcuts. You can change your name and profile picture by typing the word "change" on your keyboard. You can find all existing users by typing the word "find" on your keyboard.
  21. // ==/UserScript==
  22.  
  23. if (typeof GM_getValue("ShouldGoTo") !== "undefined" && GM_getValue("ShouldGoTo") !== null) {
  24. window.location.href = GM_getValue("ShouldGoTo");
  25. console.log(GM_getValue("ShouldGoTo"))
  26. GM_deleteValue("ShouldGoTo");
  27. }
  28. // top bar
  29. let topnav_go_button = document.getElementsByClassName("js-btn-go topnav__btn")[0];
  30. topnav_go_button.parentNode.removeChild(topnav_go_button);
  31. let topnavElement = document.getElementsByClassName("topnav")[0];
  32.  
  33. function setCookie(cookieName, value) {
  34. var TIME = new Date;
  35. TIME.setTime(TIME.getTime() + 31536e6); //31536e6 is one year
  36. var EXPR = "expires=" + TIME.toUTCString();
  37. document.cookie = cookieName + "=" + value + ";" + EXPR + ";path=/";
  38. }
  39.  
  40. function getCookie(cookieName) {
  41. var cookievalue = cookieName + "=";
  42. var decodedCookie = decodeURIComponent(document.cookie);
  43. var cookieAray = decodedCookie.split(";");
  44. for (var i = 0; i < cookieAray.length; i++) {
  45. var currentCookie = cookieAray[i];
  46. while (currentCookie.charAt(0) == " ") {
  47. currentCookie = currentCookie.substring(1);
  48. }
  49. if (currentCookie.indexOf(cookievalue) == 0) {
  50. return currentCookie.substring(cookievalue.length, currentCookie.length);
  51. }
  52. }
  53. return "";
  54. }
  55.  
  56.  
  57.  
  58. (function() {
  59. ("AND ITS NAME IS PLANNER!!!");
  60. let topnavElement = document.getElementsByClassName("topnav")[0];
  61. let plannerElement = document.createElement("a");
  62. plannerElement.setAttribute("href", "/planner/main/");
  63. plannerElement.setAttribute("class", "js-btn-messages topnav__btn");
  64. plannerElement.innerHTML = "Planner";
  65. topnavElement.appendChild(plannerElement)
  66. for (let i = 0; i < 5; i++) {
  67. topnavElement.insertBefore(plannerElement, plannerElement.previousElementSibling);
  68. }
  69. }());
  70.  
  71.  
  72.  
  73.  
  74. let lastTime = performance.now();
  75. let deltaTime = 0;
  76.  
  77. function update() {
  78. let currentTime = performance.now();
  79. deltaTime = (currentTime - lastTime) / 1000; // Convert to seconds
  80. lastTime = currentTime;
  81.  
  82. requestAnimationFrame(update);
  83. }
  84.  
  85. // Start the loop
  86. update();
  87.  
  88. let usernameElement;
  89. let username = getCookie("username");
  90. const interval = setInterval(function () {
  91. let userIconImageElement = document.getElementsByTagName("img")[0];
  92. if (userIconImageElement) {
  93. userIconImageElement.style.display = "none"
  94. }
  95.  
  96. usernameElement = document.querySelector(".hlp-vert-box span");
  97. if (usernameElement) {
  98. clearInterval(interval);
  99. doProfileThings();
  100. customizePage()
  101.  
  102. }
  103. }, 1);
  104.  
  105. async function doProfileThings() {
  106. let userIconImageElement = document.getElementsByTagName("img")[0];
  107.  
  108. if (!username) {
  109. username = "@MACHINE.DON4TCHANGE7829";
  110. setCookie("username", username);
  111. }
  112. if (username !== "@MACHINE.DON4TCHANGE7829") {
  113.  
  114. usernameElement.innerHTML = username;
  115. userIconImageElement.style.display = "none"
  116. let userIconUrl = getCookie("usericon")
  117. userIconImageElement.src = userIconUrl;
  118. userIconImageElement.style.display = "block"
  119.  
  120. let mainPfpElement = document.getElementsByClassName("header__avatar js-header-avatar")[0];
  121. if (mainPfpElement) {
  122. mainPfpElement.remove();
  123. }
  124. let pfpElement = document.getElementsByClassName("splitdetail__header__avatar js-splitdetail-header-avatar")[0];
  125. if (pfpElement) {
  126. pfpElement.remove();
  127. }
  128.  
  129. let tempImageElement = new Image();
  130. tempImageElement.src = userIconUrl;
  131. tempImageElement.onload = function () {
  132. userIconImageElement.src = userIconUrl;
  133. };
  134. tempImageElement.onerror = function () {
  135. userIconImageElement.src = "https://previews.123rf.com/images/asmati/asmati1701/asmati170100239/68986859-no-user-sign-illustration-.jpg";
  136. setCookie("usericon", "https://previews.123rf.com/images/asmati/asmati1701/asmati170100239/68986859-no-user-sign-illustration-.jpg");
  137. };
  138.  
  139.  
  140. } else {
  141.  
  142. let userIconImageElement = document.getElementsByTagName("img")[0];
  143. userIconImageElement.style.display = "block"
  144. }
  145. }
  146.  
  147.  
  148. async function customizePage () {
  149.  
  150. // top bar
  151. let topnav_go_button = document.getElementsByClassName("js-btn-go topnav__btn")[0];
  152.  
  153. if (topnav_go_button) {
  154. topnav_go_button.parentNode.removeChild(topnav_go_button);
  155. }
  156. let topnavElement = document.getElementsByClassName("topnav")[0];
  157. let hueValue = parseFloat(getCookie("hue")) || 0;
  158. if (isNaN(hueValue)) {
  159. hueValue = 0;
  160. }
  161. topnavElement.style.backgroundColor = `hsl(${hueValue}, 100%, 50%)`;
  162.  
  163.  
  164.  
  165. function incrementAndSetHueValue(newHueValue) {
  166. if (typeof newHueValue === 'string' && newHueValue.toLowerCase() === 'rainbow') {
  167. hueValue = hueValue + (0.5*(deltaTime*40)) % 360;
  168. } else if (typeof newHueValue === 'string' && newHueValue.toLowerCase() === 'slider') {
  169. hueValue = sliderID.value
  170. } else if (typeof newHueValue === 'number') {
  171. hueValue = newHueValue;
  172. }
  173. if (typeof newHueValue === 'string' && newHueValue.toLowerCase() === 'rainbow') {
  174. let secondHue = hueValue+50
  175. topnavElement.style.background = `linear-gradient(to left, hsl(${hueValue}, 100%, 40%), hsl(${secondHue}, 100%, 40%))`;
  176. }
  177. else {
  178. topnavElement.style.background = `hsl(${hueValue}, 100%, 40%)`;
  179. }
  180. setCookie("hue", hueValue);
  181. }
  182. var colorMethod = GM_getValue("colorMethod") || "rainbow";
  183. setInterval(function () {
  184. if (!document.hidden) {
  185. if (typeof getColorMethod === "function") {
  186. colorMethod = getColorMethod()
  187. }
  188. incrementAndSetHueValue(colorMethod);
  189. GM_setValue("colorMethod", colorMethod);
  190. }
  191. else {
  192. if (typeof getColorMethod === "function") {
  193. colorMethod = getColorMethod()
  194. }
  195. deltaTime = 0
  196. }
  197. }, 15);
  198. }
  199. function getColorMethod () {
  200. return colorMethod
  201. }
  202.  
  203.  
  204.  
  205.  
  206. function changeProfile() {
  207. let userIconImageElement = document.getElementsByTagName("img")[0];
  208. let usernameValue = prompt("Enter your new username:");
  209. if (!usernameValue) {
  210. username = "@MACHINE.DON4TCHANGE7829";
  211. setCookie("username", username);
  212. alert("Your username and profile picture have been reset.\nReload the page to see changes.")
  213. }
  214. if (username !== "@MACHINE.DON4TCHANGE7829") {
  215. usernameElement.innerHTML = usernameValue;
  216. setCookie("username", usernameValue);
  217. let tempImageElement = new Image();
  218. let iconUrlValue = prompt("Enter your new user icon URL:");
  219. tempImageElement.src = iconUrlValue;
  220. tempImageElement.onload = function () {
  221. userIconImageElement.src = iconUrlValue;
  222. setCookie("usericon", iconUrlValue);
  223. };
  224. tempImageElement.onerror = function () {
  225. userIconImageElement.src = "https://previews.123rf.com/images/asmati/asmati1701/asmati170100239/68986859-no-user-sign-illustration-.jpg";
  226. setCookie("usericon", "https://previews.123rf.com/images/asmati/asmati1701/asmati170100239/68986859-no-user-sign-illustration-.jpg");
  227. };
  228. }
  229. }
  230.  
  231. // the change keybuffer is defined in the profile_customizationAndTopBar.js
  232. let keyBuffer = "";
  233. document.addEventListener("keydown", EventListener => {
  234. keyBuffer += EventListener.key;
  235. if (keyBuffer.endsWith("change")) {
  236. changeProfile()
  237. keyBuffer = "";
  238. }
  239. else if (keyBuffer.endsWith("find")) {
  240. search()
  241. keyBuffer = "";
  242. }
  243. });
  244.  
  245. window.onload = function() {
  246. let mainPfpElement = document.getElementsByClassName("header__avatar js-header-avatar")[0];
  247. if (mainPfpElement) {
  248. mainPfpElement.remove();
  249. }
  250. let pfpElement = document.getElementsByClassName("splitdetail__header__avatar js-splitdetail-header-avatar")[0];
  251. if (pfpElement) {
  252. pfpElement.remove();
  253. }
  254. };
  255.  
  256.  
  257. // Create the modal element
  258. const modal = document.createElement("div");
  259. modal.id = "settingsModal";
  260. modal.style.display = "none";
  261. modal.style.position = "fixed";
  262. modal.style.zIndex = "1";
  263. modal.style.left = "0";
  264. modal.style.top = "0";
  265. modal.style.width = "100%";
  266. modal.style.height = "100%";
  267. modal.style.overflow = "auto";
  268. modal.style.backgroundColor = "rgba(0,0,0,0.4)";
  269.  
  270. // Create the modal content
  271. const modalContent = document.createElement("div");
  272. modalContent.id = "settingsContent";
  273. modalContent.style.backgroundColor = "#fefefe";
  274. modalContent.style.margin = "15% auto";
  275. modalContent.style.padding = "20px";
  276. modalContent.style.border = "1px solid #888";
  277. modalContent.style.width = "80%";
  278.  
  279. // Add the modal content to the modal element
  280. modal.appendChild(modalContent);
  281.  
  282. // Create the "Settings" button
  283. const settingsBtn = document.createElement("a");
  284. settingsBtn.classList.add("topnav__menuitem", "topnav__menuitem--img");
  285. settingsBtn.setAttribute("role", "menuitem");
  286. settingsBtn.setAttribute("id", "settingsBtn");
  287.  
  288. const settingsImg = document.createElement("img");
  289. settingsImg.src = "https://upload.wikimedia.org/wikipedia/commons/6/6d/Windows_Settings_app_icon.png";
  290. settingsImg.alt = "Profiel afbeelding";
  291.  
  292. const settingsSpan = document.createElement("span");
  293. settingsSpan.textContent = "Settings";
  294.  
  295. // Add the image and span to the "Settings" button
  296. settingsBtn.appendChild(settingsImg);
  297. settingsBtn.appendChild(settingsSpan);
  298.  
  299. // Add the "Settings" button to the topnav menu
  300. const topnavMenu = document.getElementsByClassName("topnav__menu")[0];
  301. topnavMenu.appendChild(settingsBtn);
  302.  
  303. // Add an event listener to the "Settings" button to show the modal
  304. settingsBtn.addEventListener("click", function(e) {
  305. e.preventDefault();
  306. modal.style.display = "block";
  307. });
  308.  
  309. // Create the "Close" button
  310. const closeBtn = document.createElement("button");
  311. closeBtn.textContent = "Close";
  312. closeBtn.id = "closeSettings";
  313.  
  314. // Add an event listener to the "Close" button to hide the modal
  315. closeBtn.addEventListener("click", function() {
  316. modal.style.display = "none";
  317. });
  318. var slider = document.createElement("input");
  319. slider.setAttribute("id", "slider-id");
  320. slider.type = "range";
  321. slider.min = 0;
  322. slider.max = 360;
  323. slider.value = getCookie('hue');
  324. slider.step = 1;
  325. slider.style.width = "200px";
  326.  
  327. var checkbox = document.createElement("input");
  328. checkbox.setAttribute("id", "checkbox");
  329. checkbox.type = "checkbox";
  330. checkbox.style.width = "200px";
  331. var colorMethod = GM_getValue("colorMethod") || "rainbow";
  332. if (colorMethod === "rainbow") {
  333. checkbox.checked = true
  334. }
  335. else {
  336. checkbox.checked = false
  337. }
  338. function updateColor(checkbox) {
  339. checkbox = document.getElementById("checkbox")
  340. if (checkbox.checked === true) {
  341. colorMethod = 'rainbow'
  342. }
  343. else {
  344. colorMethod = 'slider'
  345. }
  346. }
  347. setInterval(updateColor,500)
  348.  
  349.  
  350. // Add the "Close" button to the modal content
  351. modalContent.appendChild(closeBtn);
  352.  
  353. // Add the "Close" button to the modal content
  354. modalContent.appendChild(checkbox);
  355. modalContent.appendChild(slider);
  356. // Add your custom code here to modify the modal content and add event listeners
  357.  
  358. // Add the modal to the page
  359. document.body.appendChild(modal);
  360.  
  361. var sliderID = document.getElementById("slider-id");
  362.  
  363. // Grid
  364.  
  365. // License: https://raw.githubusercontent.com/EbbDrop/SmarterSmartchool/main/LICENSE
  366.  
  367. // Target element
  368. const smartersmartschool = document.getElementById("show-grid");
  369.  
  370. // Callback function to be executed when the element exists
  371. const handleElementExistence = () => {
  372. alert('Delete SmarterSmartschool or this script will not work!!!');
  373. };
  374.  
  375. // Check if the element already exists
  376. if (smartersmartschool) {
  377. handleElementExistence();
  378. } else {
  379. // Create a MutationObserver instance
  380. const observer = new MutationObserver((mutationsList) => {
  381. for (const mutation of mutationsList) {
  382. // Check if the target element is added to the DOM
  383. if (mutation.type === "childList" && mutation.addedNodes.length > 0) {
  384. const addedElement = mutation.addedNodes[0];
  385. if (addedElement.id === "show-grid") {
  386. // Call the callback function when the element is added
  387. handleElementExistence();
  388. // Disconnect the observer since the task is complete
  389. observer.disconnect();
  390. break;
  391. }
  392. }
  393. }
  394. });
  395.  
  396. // Start observing changes in the DOM
  397. observer.observe(document.body, { childList: true, subtree: true });
  398. }
  399.  
  400.  
  401.  
  402. (function() {
  403. ("Message/tutorial"); // future feature
  404. if (false) {
  405. // Get the reference to the container div
  406. var containerDiv = document.getElementById("smscTopContainer");
  407. var newDiv = document.createElement("div");
  408. newDiv.innerHTML = '<div id="smsctopnavmessage" class="smscTopNavMessage blue" role="alert">Smartschool wil graag jouw feedback weten over Planner. <a href="/infobarlink?i=2303&amp;c=1&amp;l=MUIEAM7BADyBFPG6g-zRyNxZIGXE0iECnTOpwbYXYNyWXy8iEYoJdFcUsSXPJJThDOOmSWXl50pgTVWceshutc02nwvq9B_NJzFBVfjUnUNetvhrf2rDxCM2UQ9MuHHYnKSHeJs3hzgWkWhJt3EcHuttGVp0BiMtRuZefW0uoLgCdfNNRvM2VrMTH8HXZ0hYzejSUhX_2-5eEeOnQHUTrvk=" target="_blank"> Vul deze korte bevraging in (max. 5 min.).</a></div>';
  409. containerDiv.appendChild(newDiv.firstChild);
  410. }
  411. }());
  412.  
  413. const pupilCache = {}; // Cache object to store fetched pupils
  414.  
  415. async function dataBaseImport (){
  416. // Function to make a request for a specific letter, with caching
  417. async function importData () {
  418. let time = performance.now()
  419. const cachedPupilsDB = await databaseGetItem("allPupilsJSON").catch((error) => {
  420. console.error("Error fetching cached pupils:", error);
  421. return null;
  422. });
  423. pupilCache["_"] = cachedPupilsDB
  424. console.log("Time to load DataBase ms:",performance.now()-time)
  425. time = performance.now()
  426. console.log(pupilCache["_"])
  427. console.log(performance.now()-time)
  428.  
  429. }
  430. // IndexedDB Database
  431. let db;
  432.  
  433. // Function to Initialize the IndexedDB
  434. function databaseInit() {
  435. const request = indexedDB.open("database", 1);
  436.  
  437. request.onerror = function (event) {
  438. console.log("error: ");
  439. };
  440.  
  441. request.onsuccess = function (event) {
  442. console.log("success: ");
  443. db = request.result;
  444. importData()
  445.  
  446. };
  447.  
  448. request.onupgradeneeded = function (event) {
  449. const db = event.target.result;
  450. db.createObjectStore("items", { keyPath: "name" });
  451. };
  452. }
  453.  
  454. // Function to Add a New Item to the IndexedDB Database
  455. function databaseSetItem(name, value) {
  456. const transaction = db.transaction(["items"], "readwrite");
  457. const objectStore = transaction.objectStore("items");
  458.  
  459. // Instead of storing each item individually, store the entire pupilCache object
  460. objectStore.add({ name, value: JSON.stringify(value) });
  461. }
  462.  
  463. // Function to Retrieve an Item from the IndexedDB Database
  464. function databaseGetItem(name) {
  465. return new Promise((resolve, reject) => {
  466. const transaction = db.transaction(["items"], "readonly");
  467. const objectStore = transaction.objectStore("items");
  468.  
  469. const request = objectStore.get(name);
  470.  
  471. request.onsuccess = function (event) {
  472. const result = event.target.result;
  473. if (result) {
  474. resolve(JSON.parse(result.value));
  475. } else {
  476. reject(new Error("Item not found"));
  477. }
  478. };
  479.  
  480. request.onerror = function (event) {
  481. reject(event.target.error);
  482. };
  483. });
  484. }
  485.  
  486. // Initialize the Database
  487. databaseInit();
  488.  
  489. }
  490.  
  491. function search () {
  492. var search = prompt("What user\(s\) do you want to search?")
  493.  
  494. fetch("/planner/api/v1/quick-search/planned-meetings/extra-participants/search", {
  495. method: "POST",
  496. headers: {
  497. "accept": "*/*",
  498. "accept-language": "en,nl;q=0.9,en-US;q=0.8",
  499. "cache-control": "no-cache",
  500. "content-type": "application/json",
  501. "pragma": "no-cache",
  502. "sec-ch-ua": "\"Chromium\";v=\"118\", \"Google Chrome\";v=\"118\", \"Not=A?Brand\";v=\"99\"",
  503. "sec-ch-ua-mobile": "?0",
  504. "sec-ch-ua-platform": "\"Chrome OS\"",
  505. "sec-fetch-dest": "empty",
  506. "sec-fetch-mode": "cors",
  507. "sec-fetch-site": "same-origin"
  508. },
  509. referrer: location.host,
  510. referrerPolicy: "strict-origin",
  511. body: JSON.stringify({
  512. "searchString": search,
  513. "searchOptions": []
  514. }),
  515. mode: "cors",
  516. credentials: "include"
  517. })
  518. .then(response => {
  519. // Log the response status and optionally the JSON body
  520. console.log("Response status:", response.status);
  521. return response.json(); // This returns a Promise as well
  522. })
  523. .then(data => {
  524. if (data !== null) {
  525. al(data,search)
  526. // Log the parsed JSON data
  527. console.log("Response data:", data);
  528. let stringResult = JSON.stringify(data);
  529. let singleUser = JSON.parse(stringResult); // Parse the JSON string to an object and access the first element in the 'a' property
  530. var g = JSON.stringify(singleUser).replace(/[\[\]\,\"]/g, ''); // stringify and remove all "stringification" extra data
  531. console.log("Bytes:",g.length); // this will be your length.
  532.  
  533. }
  534. })
  535. .catch(error => {
  536. // Log any errors that occurred during the fetch
  537. console.error("Fetch error:", error);
  538. });
  539. }
  540. function al(parm_data, searchQuery) {
  541. for (var i = 0; i < parm_data.length; i++) {
  542. var name = parm_data[i].origin.name;
  543. var id = parm_data[i].identifier.id;
  544. var titleArray = parm_data[i].title;
  545. var lastPart = titleArray[titleArray.length - 1].part;
  546.  
  547. if (searchQuery == "3Dd") {
  548. console.log("3Dd was searched");
  549. }
  550.  
  551. let isStudent = titleArray.some(item => item.part === "•");
  552. if (isStudent) {
  553. console.log(lastPart);
  554. alert("Name: " + name + "\nId: " + id + "\nClass: " + lastPart);
  555. } else {
  556. console.log("No class");
  557. alert("Name: " + name + "\nId: " + id + "\nClass: No class");
  558. }
  559. }
  560.  
  561.  
  562. }