您需要先安装一个扩展,例如 篡改猴、Greasemonkey 或 暴力猴,之后才能安装此脚本。
您需要先安装一个扩展,例如 篡改猴 或 暴力猴,之后才能安装此脚本。
您需要先安装一个扩展,例如 篡改猴 或 暴力猴,之后才能安装此脚本。
您需要先安装一个扩展,例如 篡改猴 或 Userscripts ,之后才能安装此脚本。
您需要先安装一款用户脚本管理器扩展,例如 Tampermonkey,才能安装此脚本。
您需要先安装用户脚本管理器扩展后才能安装此脚本。
Simplification de l'affichage des voeux en attente sur ParcourSup!
// ==UserScript== // @name ParcourSimple // @namespace https://ypetit.net/ // @version 0.8.2 // @description Simplification de l'affichage des voeux en attente sur ParcourSup! // @author ypetit // @license GNU GPLv3 // @match https://dossierappel.parcoursup.fr/Candidat/admissions?ACTION=0 // @match https://dossier.parcoursup.fr/Candidat/admissions?ACTION=0 // @icon https://www.google.com/s2/favicons?sz=64&domain=parcoursup.fr // @grant GM_addStyle // ==/UserScript== (function () { 'use strict'; GM_addStyle(` #psimple{ position: absolute; top: 0; left: 0; display: block; z-index: 99999; height: 40px; padding: 4px 10px; background-color: var(--background-active-blue-france); color: #FFF; } #psimple img{ margin: 0 10px; } #psimple .key{ font-family: Courrier; background-color: lightgrey; color: #000; font-weight: bold; border: 1px solid black; border-radius: 3px; display: inline-block; padding: 0 8px 2px; } #psimple .help{ display: inline-block; padding: 0 10px; } #parcoursimple { position:fixed; z-index: 9999; top:40px; max-height: 98%; overflow-y: auto; overflow-x: hidden; background-color: whitesmoke; margin: 10px; border: dotted dimgray 1px; box-shadow: 10px 8px 5px gray; } #parcoursimple table{ background-color: #FFF; overflow-x: hidden; } #parcoursimple thead{ position: sticky; top: 0; z-index:99; } #parcoursimple tr{ line-height: 20px; } #parcoursimple tr:nth-child(even) {background: #DDF} #parcoursimple tr:nth-child(odd) {background: #EEE} #parcoursimple th{ color: #FFF; background-color: var(--background-active-blue-france); font-weight: bold; } #parcoursimple th, #parcoursimple td{ padding: 2px 4px; } #parcoursimple .right{ text-align: right; } #parcoursimple .bold{ font-weight: bold; } #parcoursimple .light{ color: lightgrey; } #parcoursimple .ok{ background-color: lightgreen; font-weight: bold; } #parcoursimple .nan{ background-color: #CCC; } #parcoursimple .ko{ background-color: lightpink; font-style: italic; } #parcoursimple .diff{ display: inline; font-size: x-small; min-width: 30px; } #parcoursimple .indicB{ font-size: xx-small; } #parcoursimple .indicB{ position: relative; top: 0; height: 20px; z-index: 0; } #parcoursimple .indicB .bar{ display:inline-block; } #parcoursimple .indicB .base{ background-color: lightblue; border: 1px solid black; text-align: left; padding-left: 1px; } #parcoursimple .indicB .propal{ background-color: lightgreen; border: 1px dashed black; text-align: center; } #parcoursimple .indicB .place{ background-color: gold; border: 1px dashed gray; border-right: solid black; border-width: 1px 1px 1px 0; text-align: center; } #parcoursimple .indicB .total{ background-color: coral; border: 1px dotted gray; text-align: right; padding-right: 1px; } #parcoursimple .blur{ color: transparent; text-shadow: 0 0 20px #002; } #parcoursimple .arrow { border: solid black; border-width: 0 2px 2px 0; display: inline-block; padding: 3px; } #parcoursimple .arrow.up { position: relative; top: 3px; left: 0px; transform: rotate(-135deg); } #parcoursimple .arrow.down { top: -24px; position: relative; left: -8px; transform: rotate(45deg); } #parcoursimple .marker{ position: relative; top: -10px; margin-left: -4px; } /* add other CSS here */ `); document.addEventListener('keyup', function (e) { // if click on a if (65 === e.which) { const x = document.getElementById('parcoursimple'); x.style.display = (x.style.display === "none") ? "block" : "none"; } else if (66 === e.which) { document.querySelectorAll("#parcoursimple tbody td:first-child").forEach(x => x.classList.add('blur')); document.querySelectorAll("#parcoursimple tbody td:nth-child(2)").forEach(x => x.classList.add('blur')); } }); $("body").prepend('<div id="psimple"><img src="/favicon.ico"> ' + 'Clavier : ' + '<div class="help"><div class="key">a</div> affiche/cache le tableau</div>' + '|<div class="help"><div class="key">b</div> floute les noms des écoles et formations</div>' + '</div>'); $("body").append( '<div id="parcoursimple" name="parcoursimple">' + '<table id="parcoursimple_table">' + '<thead><tr>' + ' <th>Ecole</th>' + ' <th>Cursus</th>' + ' <th>Places<br/>Dispo.</th>' + ' <th>Dernier<br/>2022</th>' + ' <th>Position au<br/>Classement</th>' + ' <th>Dernière<br/>Proposition</th>' + ' <th>Place en<br/>Liste</th>' + ' <th width="300px">Visualisation</th>' + ' <th>Total<br/>Attente</th>' + '</tr></thead>' + '<tbody id="parcoursimple_table_body"></tbody></table></div>' ); // get all wishes const cards = Array.from(document.querySelectorAll(".psup-wish-card--info")); const wishes = []; class Wish { constructor(school, course, id, waiting_position, waiting_total, places, ranking, last, lastLastYear) { this.school = school; this.course = course; this.id = id; this.waiting_position = Number(waiting_position); this.waiting_total = Number(waiting_total); this.places = Number(places); this.ranking = Number(ranking); this.last = Number(last); this.lastLastYear = Number(lastLastYear); this.error = false; } setError() { this.error = true; return this; }; show() { let ligne = "<tr>"; ligne += "<td>" + this.school + "</td>"; ligne += "<td>" + this.course + "</td>"; if (this.error) { ligne += "<td colspan='7'>Une erreur est survenue, classement indisponible dans ParcourSimple :(</td>"; } else { ligne += "<td class='right'>" + this.places + "</td>"; ligne += "<td class='right'>" + (Number.isNaN(this.lastLastYear) ? "???" : this.lastLastYear) + "</td>"; ligne += "<td class='right " + this.rankColor() + "'>" + this.ranking + this.rankDiff() + "</td>"; ligne += "<td class='right'>" + this.last + "</td>"; ligne += "<td class='right bold'>" + this.waiting_position + "</td>"; ligne += "<td>" + "<div class='indicB'>" + "<div class='bar base' style='width:" + (this.places / (this.last + this.waiting_total) * 100) + "%'>" + this.places + "</div>" + "<div class='bar propal' style='width:" + ((this.last - this.places) / (this.last + this.waiting_total) * 100) + "%'>" + (this.last - this.places) + "</div>" + "<div class='bar place' style='width:" + (this.waiting_position / (this.last + this.waiting_total) * 100) + "%'>" + this.waiting_position + "</div>" + "<div class='bar total' style='width:" + ((this.waiting_total - this.waiting_position) / (this.last + this.waiting_total) * 100) + "%'>" + (this.waiting_total - this.waiting_position) + "</div>" + "<div class='marker' style='left:" + ((this.last + this.waiting_position) / (this.last + this.waiting_total) * 100) + "%'>" + "<span class='arrow up'></span>" + "<span class='arrow down'></span>" + "</div>" + "</div>" + "</td>"; ligne += "<td class='right light'>" + this.waiting_total + "</td>"; } ligne += "</tr>"; return ligne; } rankColor() { return isNaN(this.lastLastYear) ? "nan" : this.lastLastYear > this.ranking ? "ok" : "ko"; } rankDiff() { return (Number.isNaN(this.lastLastYear) ? "" : " <div class='diff'>(" + (this.ranking - this.lastLastYear) + ")</div>"); } } const promises = []; cards.forEach(card => { const school = card.querySelectorAll('.psup-wish-card__school')[0].innerHTML; const course = card.querySelectorAll('.psup-wish-card__course')[0].innerHTML; try { const onclick = card.querySelectorAll('button')[0].getAttribute('onclick'); const id = onclick.substring(onclick.indexOf("&") + 1, onclick.lastIndexOf("'")); const URL = "admissions?ACTION=2&" + id + "&frOpened=false&frJsModalButton=true"; promises.push($.ajax({ url: URL, type: "GET", dataType: "html", success: function (h) { const template = document.createElement('div'); template.innerHTML = h.trim(); const waiting_position = template.querySelector("div ul li:nth-child(1) b").innerHTML; const waiting_total = template.querySelector("div ul li:nth-child(2) b").innerHTML; // -------------- const places = template.querySelector(".fr-alert ul li:nth-child(1) b").innerHTML; const ranking = template.querySelector(".fr-alert ul li:nth-child(2) p b").innerHTML; const last = template.querySelector(".fr-alert ul li:nth-child(3) b").innerHTML; const lastYear = template.querySelector(".fr-alert ul li:nth-child(4) b"); const lastLastYear = (lastYear) ? lastYear.innerHTML : "?"; wishes.push(new Wish(school, course, id, waiting_position, waiting_total, places, ranking, last, lastLastYear )); }, error: function (h) { console.err(h); }, complete: function () { } })); } catch (error) { // log the error in the console console.log(error); // send feedback console.info(card); // add placeholder wishes.push(new Wish(school, course).setError()); } }); $.when.apply($, promises).then(function () { wishes.sort((a, b) => a.waiting_position - b.waiting_position); let r = document.getElementById("parcoursimple_table_body"); for (let w in wishes) { r.innerHTML += wishes[w].show().trim(); } }); })();