您需要先安装一个扩展,例如 篡改猴、Greasemonkey 或 暴力猴,之后才能安装此脚本。
您需要先安装一个扩展,例如 篡改猴 或 暴力猴,之后才能安装此脚本。
您需要先安装一个扩展,例如 篡改猴 或 暴力猴,之后才能安装此脚本。
您需要先安装一个扩展,例如 篡改猴 或 Userscripts ,之后才能安装此脚本。
您需要先安装一款用户脚本管理器扩展,例如 Tampermonkey,才能安装此脚本。
您需要先安装用户脚本管理器扩展后才能安装此脚本。
This userscript allows HKU students to show your current courses (in a semester) in a separate entry in HKU Moodle. By: Andrew Z, converted to userscript by q234rty
当前为
// ==UserScript== // @name HKU moodle helper // @include http://moodle.hku.hk/* // @include https://moodle.hku.hk/* // @version 1.4.5 // @description This userscript allows HKU students to show your current courses (in a semester) in a separate entry in HKU Moodle. By: Andrew Z, converted to userscript by q234rty // @author AENeuro, q234rty // @resource mystyle https://cdn.jsdelivr.net/gh/AENeuro/HKU-Moodle-Helper@2d0a17a/myStyle.css // @license CC BY-NC 4.0 // @grant GM_getResourceText // @grant GM_addStyle // @grant GM_getValue // @grant GM_setValue // @namespace https://greasyfork.org/users/78076 // ==/UserScript== globalThis.addFeedbackBox = function() { function showTextArea() { document.getElementById("helperFeedbackForm").classList.add("helper-shown") document.getElementById("helperFeedbackButton").insertAdjacentHTML("beforebegin", ` <p id="helperFeedbackButton2" style="color: #AAAAAA;">You can also submit an issue or PR on <a href="https://github.com/AENeuro/HKU-Moodle-Helper" target="_blank"> <span style="color: #AAAAAA;"><u>Github</u></span> </a> </p> `) document.getElementById("helperFeedbackButton").remove() } async function sendFeedback() { document.getElementById("helperFeedbackSend").disabled = true try { await request({ url: " https://j8n6ydl8hd.execute-api.ap-southeast-1.amazonaws.com/create", method: "POST", body: document.getElementById("helperFeedbackInput").value }) } catch (e) { alert("Network error") } document.getElementById("helperFeedbackForm").classList.remove("helper-shown") document.getElementById("helperFeedbackForm").insertAdjacentHTML("beforebegin", ` <p style="color: #AAAAAA">Thank you for your feedback!</p> `) document.getElementById("helperFeedbackButton2").remove() } // initialization var version = GM_info.script.version; document.getElementsByClassName("course-of-sem-wrapper")[0].insertAdjacentHTML("beforeend", ` <div class="helper-feedback"> <p>Powered by HKU Moodle Helper ver. ${version}</p> <p id="helperFeedbackButton">Feedback</p> <div id="helperFeedbackForm" class="helper-hidden"> <input id="helperFeedbackInput" type="text"/><br/> <button id="helperFeedbackSend">Send</button> </div> </div> `) document.getElementById("helperFeedbackButton").addEventListener("click", showTextArea) document.getElementById("helperFeedbackSend").addEventListener("click", sendFeedback) } globalThis.addMessageBox = function() { const messageBox = ` <section class="helper-extension-persistent helper-message-box block_html block card mb-3" role="complementary" data-block="html" aria-labelledby="instance-330654-header"> <div class="card-body p-3"> <h5 class="card-title d-inline">Message from HKU Moodle Helper</h5> <div class="card-text content mt-3"> <div class="no-overflow"> <p><span style="font-size:11.0pt;font-family:"Calibri",sans-serif;color:black"> This is a message generated by the chrome extension <i>HKU Moodle Helper</i> that you intsalled. </span></p> <p><span style="font-size:11.0pt;font-family:"Calibri",sans-serif;color:black"> As many of you have noticed, moodle underwent renovation, and it's unclear just how it would affect the extension yet. </span></p> <p><span style="font-size:11.0pt;font-family:"Calibri",sans-serif;color:black"> The extension will still be maintained, provided it's still relevant in new semesters to come. In the meantime, please condider becoming a dev in <a href="https://github.com/AENeuro/HKU-Moodle-Helper" target="_blank">HKU Moodle Helper</a>. Any PR or suggestions are welcomed of course. </span></p> </div> <div class="footer"></div> </div> </div> </section> ` document.getElementById("block-region-side-post").firstChild.insertAdjacentHTML("beforebegin", messageBox) } const request = obj => { return new Promise((resolve, reject) => { let xhr = new XMLHttpRequest(); xhr.open(obj.method || "GET", obj.url); if (obj.headers) { Object.keys(obj.headers).forEach(key => { xhr.setRequestHeader(key, obj.headers[key]); }); } xhr.onload = () => { if (xhr.status >= 200 && xhr.status < 300) { resolve(xhr.response); } else { reject(xhr.statusText); } }; xhr.onerror = () => reject(xhr.statusText); xhr.send(JSON.stringify(obj.body)); }); }; (function() { const my_css = GM_getResourceText("mystyle"); GM_addStyle(my_css); // Note: every element that is to be removed during a clearing session // should be marked with a "helper-extension" classname // Otherwise it should be marked with "helper-extension-persistent" // Code splitting was done through globalThis (which was confined within ContentScript. Thus no pollutions were made) mainFunction() async function mainFunction() { await addCourseOfSem() globalThis.addFeedbackBox() globalThis.addMessageBox() } async function addCourseOfSem() { courseHTML = new Array() courseIDs = JSON.parse(GM_getValue("courseid", "[]")) //console.log(GM_getValue("courseid","[]")) clearAll() var courses = document.getElementsByClassName("coursebox") for (var i = 0; i < courses.length; i++) { currentCourseID = courses[i].dataset.courseid var included = false if (courseIDs) { included = courseIDs.includes(currentCourseID) } if (included) { //如果在列表中 //复制element,存入数组 courseHTML.push(courses[i].cloneNode(true)) // Applies to all courses on the page that is in the list (in "my courses" section) courses[i].lastChild.lastChild.insertAdjacentHTML('beforebegin', ` <button class="helper-extension helper-remove-button" id="removeCourse${currentCourseID}"> Remove from this semester </button> `) document.getElementById("removeCourse" + currentCourseID).addEventListener("click", function(e) { removeCourse(e.target.id.slice(12), courseIDs) }) } else { // Applies to all courses on the page that is not in the list (in "my courses" section) courses[i].lastChild.lastChild.insertAdjacentHTML('beforebegin', ` <button class="helper-extension helper-add-button" id="addCourse${currentCourseID}"> Add to this semester </button> `) document.getElementById("addCourse" + currentCourseID).addEventListener("click", function(e) { addCourse(e.target.id.slice(9), courseIDs) }) } } var outerContainer = document.getElementById("frontpage-course-list") if (courseIDs && courseIDs.length) { //如果有课程 outerContainer.insertAdjacentHTML('afterbegin', ` <div class="helper-extension course-of-sem-wrapper"> <h2> Course of this semester <div id="removeAll">×</button> </h2> <div id="courseOfSem" class="courses frontpage-course-list-enrolled has-pre has-post course-of-sem"></div> </div> `) document.getElementById("removeAll").addEventListener("click", function() { if (confirm("Sure you wanna remove all courses from this semester?")) { removeAll() } }) } else { //没有课程 outerContainer.insertAdjacentHTML('afterbegin', ` <div class="helper-extension course-of-sem-wrapper"> <h2>Course of this semester</h2> <p><i>Please click 'Add to this semester' on a course to bring it here.</i></p> </div> `) } var innerContainer = document.getElementById("courseOfSem") for (var j = 0; j < courseHTML.length; j++) { if (j % 2) { //注意这里是偶数 => 这里是不能整除2(i是奇数),但是在显示顺序上是“偶数” courseHTML[j].className = "coursebox clearfix even" } else { courseHTML[j].className = "coursebox clearfix odd" } // applies to all courses in this semester (in "course of this semester" section) currentCourseID = courseHTML[j].dataset.courseid courseHTML[j].insertAdjacentHTML('afterbegin', ` <a id="removeCourseA${currentCourseID}" style="position: absolute; top: 5px; right: 5px; font-size: 25px; color: darkgrey; cursor: pointer"> × </a> `) innerContainer.appendChild(courseHTML[j]) document.getElementById("removeCourseA" + currentCourseID).addEventListener("click", function(e) { removeCourse(e.target.id.slice(13), courseIDs) }) } } // ====================================== // Helper functions function clearAll() { var clearElements = document.getElementsByClassName("helper-extension") //必须倒序删除,因为HTMLCollection会因为remove方法动态变化 for (var i = clearElements.length - 1; i >= 0; --i) { clearElements[i].remove() } } async function addCourse(courseCode, courseIDs) { if (courseIDs && courseIDs.length) { courseIDs.push(courseCode) } else { courseIDs = [courseCode] } //console.log(JSON.stringify(courseIDs)) GM_setValue("courseid", JSON.stringify(courseIDs)) mainFunction() } async function removeCourse(courseCode, courseIDs) { courseIDs = courseIDs.filter(function(value, index, arr) { return value !== courseCode; }); GM_setValue("courseid", JSON.stringify(courseIDs)) mainFunction() } async function removeAll() { GM_setValue("courseid", "[]") mainFunction() } })();