HKU-New-Moodle-Helper

course helper for HKU Moodle with new design

您需要先安装一款用户脚本管理器扩展,例如 Tampermonkey 篡改猴Greasemonkey 油猴子Violentmonkey 暴力猴,才能安装此脚本。

您需要先安装一款用户脚本管理器扩展,例如 Tampermonkey 篡改猴,才能安装此脚本。

您需要先安装一款用户脚本管理器扩展,例如 Tampermonkey 篡改猴Violentmonkey 暴力猴,才能安装此脚本。

您需要先安装一款用户脚本管理器扩展,例如 Tampermonkey 篡改猴Userscripts ,才能安装此脚本。

您需要先安装一款用户脚本管理器扩展,例如 Tampermonkey 篡改猴,才能安装此脚本。

您需要先安装一款用户脚本管理器扩展后才能安装此脚本。

(我已经安装了用户脚本管理器,让我安装!)

您需要先安装一款用户样式管理器扩展,比如 Stylus,才能安装此样式。

您需要先安装一款用户样式管理器扩展,比如 Stylus,才能安装此样式。

您需要先安装一款用户样式管理器扩展,比如 Stylus,才能安装此样式。

您需要先安装一款用户样式管理器扩展后才能安装此样式。

您需要先安装一款用户样式管理器扩展后才能安装此样式。

您需要先安装一款用户样式管理器扩展后才能安装此样式。

(我已经安装了用户样式管理器,让我安装!)

// ==UserScript==
// @name         HKU-New-Moodle-Helper
// @include      http://moodle.hku.hk/*
// @include      https://moodle.hku.hk/*
// @include      https://moodle.hku.hk/
// @match        https://moodle.hku.hk/my/courses.php
// @run-at 	 document-end
// @version      2024-08-26.05
// @description  course helper for HKU Moodle with new design
// @author       ArcaLunar
// @resource     mystyle https://cdn.jsdelivr.net/gh/ArcaLunar/hku-new-moodle-helper@578d6aa/website.css
// @resource     fontawesome https://cdnjs.cloudflare.com/ajax/libs/font-awesome/4.7.0/css/font-awesome.min.css
// @icon         https://www.google.com/s2/favicons?sz=64&domain=hku.hk
// @grant        GM_getResourceText
// @grant        GM_addStyle
// @grant        GM_getValue
// @grant        GM_setValue
// @namespace    https://github.com/ArcaLunar/hku-new-moodle-helper
// @license      CC BY-NC 4.0
// ==/UserScript==

//  #region 检查是否有本地数据,没有则初始化
(() => {
  if (
    !(
      GM_getValue("selectedCoursesList", { src: undefined }).src instanceof
      Array
    )
  ) {
    GM_setValue("selectedCoursesList", { src: [] });
  }
})();
// GM_setValue("selectedCoursesList", { src: [] });
// #endregion

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 () {
  // 加载样式
  GM_addStyle(GM_getResourceText("mystyle"));
  //   var url = window.location.href;
  // =====================
  // #region 监听 my/courses 页面变化
  const targetNode = document.getElementById("page-content");
  const config = { attributes: true, childList: true, subtree: true };

  const url = window.location.href;

  const callback = function (mutationsList, observer) {
    let url = window.location.href;
    if (url.includes("my/courses.php")) {
      var viewPage = document.getElementsByClassName(
        "paged-content-page-container"
      );
      if (viewPage.length > 0) {
        console.log("View Page Detected");
        console.log(viewPage[0]);

        var coursePageList = viewPage[0].children;
        console.log("Course Page List Detected");
        console.log(coursePageList);

        // 检查是否加载完成
        if (coursePageList.length > 0) {
          var containsDivOnly = true;
          for (var i = 0; i < coursePageList.length; i++) {
            if (coursePageList[i].tagName != "DIV") {
              containsDivOnly = false;
              break;
            }
          }
          if (containsDivOnly) {
            console.log("Contains Div");
            initButton(coursePageList); // 初始化按钮
            initButtonAction(coursePageList); // 初始化按钮事件
          }
        }
      }
    }
  };

  const observer = new MutationObserver(callback);
  observer.observe(targetNode, config);

  window.addEventListener("load", function () {
    const url = window.location.href;
    if (url == "https://moodle.hku.hk/") {
      // 主页
      console.log("rendering");
      renderMainPage();
    } else if (url.includes("course/search.php")) {
      // Search 界面
      let allCourses = document.getElementsByClassName("coursebox");
      if (allCourses && allCourses.length > 0) {
        console.log("Search Page Detected. Start initializing");
        console.log(allCourses);
        initButtonSearchPage(allCourses);
      }
    }
  });
  // #endregion

  // =====================
  // #region 添加按钮
  // coursePageList: 分页的课程列表
  function initButton(coursePageList) {
    observer.disconnect(); // 不观测,防止递归
    // 提取已选课程列表
    let selectedCoursesList = GM_getValue("selectedCoursesList", {
      src: [],
    }).src;
    console.log("Selected Courses List: ");
    console.log(selectedCoursesList);

    // 删掉所有 Button
    (() => {
      let allButtons = document.getElementsByClassName("moodle-helper");
      for (let i = allButtons.length - 1; i >= 0; i--) {
        allButtons[i].remove();
      }
    })();

    // 在哪一页
    var activeIndex = (() => {
      if (url.includes("my/courses.php")) {
        for (let i = 0; i < coursePageList.length; i++) {
          if (!coursePageList[i].classList.contains("hidden")) {
            return i;
          }
        }
      }
    })();

    // 什么视图?
    var view = (() => {
      if (window.location.href.includes("my/courses.php")) {
        let button = document.getElementById("displaydropdown");
        return button.children[0].textContent.trim();
      }
    })();

    console.log("Active Index: " + activeIndex);

    // 遍历当前页面的课程
    if (activeIndex != undefined && activeIndex != null) {
      var currentPage = coursePageList[activeIndex].children[0].children; // 课程 HTML 代码
      if (view == "Card") {
        if (!currentPage[0].classList.contains("card")) {
          observer.observe(targetNode, config); // 重新激活
          return;
        }
      } else {
        if (!currentPage[0].classList.contains("course-listitem")) {
          observer.observe(targetNode, config); // 重新激活
          return;
        }
      }
      console.log("Current Page: ");
      console.log(currentPage);

      for (var i = 0; i < currentPage.length; i++) {
        let hasBeenAdded = false;
        var currentCourseId = currentPage[i].dataset.courseId;
        console.log(currentCourseId);

        // 检查是否已添加
        for (var j = 0; j < selectedCoursesList.length; j++) {
          if (currentCourseId == selectedCoursesList[j].courseId) {
            hasBeenAdded = true;
            break;
          }
        }

        let displayedInfo;
        if (view != "Card") {
          displayedInfo = currentPage[i].children[0].children[1]; // div.row // flex-column
        } else {
          displayedInfo = currentPage[i].children[1].children[0].children[0]; // div.card-body
        }

        // 新增的按钮
        // 检查按钮是否已被添加
        var getButton = document.getElementById(`course${currentCourseId}`);
        // 判断是 remove 还是 add
        var initState = getButton == null || getButton == undefined;

        // 初始化按钮
        let newButton = document.createElement("button");
        newButton.id = `course${currentCourseId}`;
        newButton.classList.add("moodle-helper");
        newButton.classList.add("btn");
        newButton.classList.add("btn-primary");
        newButton.relatedCourseId = currentCourseId;

        if (initState) {
          if (hasBeenAdded) {
            newButton.textContent = "Remove from this semester";
            newButton.action = "to-remove";
            newButton.classList.add("helper-remove-button");
            displayedInfo.appendChild(newButton);
          } else {
            newButton.textContent = "Add to this semester";
            newButton.action = "to-add";
            newButton.classList.add("helper-add-button");
            displayedInfo.appendChild(newButton);
          }
          currentPage[i].initComplete = true;
        }
      }
    }

    console.log("Button Init Complete");

    observer.observe(targetNode, config); // 重新激活
  }
  function initButtonSearchPage(allCourses) {
    // 提取已选课程列表
    let selectedCoursesList = GM_getValue("selectedCoursesList", {
      src: [],
    }).src;
    console.log("Selected Courses List: ");
    console.log(selectedCoursesList);
    // 删掉所有 button

    for (let i = 0; i < allCourses.length; i++) {
      let hasBeenAdded = false;
      let currentCourseId = allCourses[i].dataset.courseid;

      (() => {
        let allButtons = allCourses[i].getElementsByClassName("moodle-helper");
        for (let i = allButtons.length - 1; i >= 0; i--) {
          allButtons[i].remove();
        }
      })();
      // 检查是否已添加
      for (let j = 0; j < selectedCoursesList.length; j++) {
        if (currentCourseId == selectedCoursesList[j].courseId) {
          hasBeenAdded = true;
          break;
        }
      }

      let getButton = document.getElementById(`course${currentCourseId}`);
      let initState = getButton == null || getButton == undefined;

      // 初始化按钮
      let newButton = document.createElement("button");
      newButton.classList.add("moodle-helper");
      newButton.classList.add("btn");
      newButton.classList.add("btn-primary");
      newButton.id = `course${currentCourseId}`;
      newButton.relatedCourseId = currentCourseId;

      if (hasBeenAdded) {
        newButton.textContent = "Remove from this semester";
        newButton.action = "to-remove";
        newButton.classList.add("helper-remove-button");
      } else {
        newButton.textContent = "Add to this semester";
        newButton.action = "to-add";
        newButton.classList.add("helper-add-button");
      }

      newButton.addEventListener("click", function () {
        if (this.action == "to-add") {
          this.classList.remove("helper-add-button");
          this.classList.add("helper-remove-button");
          this.textContent = "Remove from this semester";
          addToSemester(
            this.relatedCourseId,
            GM_getValue("selectedCoursesList", { src: [] }).src
          );
          this.action = "to-remove";
        } else if (this.action == "to-remove") {
          this.classList.remove("helper-remove-button");
          this.classList.add("helper-add-button");
          this.textContent = "Add to this semester";
          removeFromSem(
            this.relatedCourseId,
            GM_getValue("selectedCoursesList", { src: [] }).src
          );
          this.action = "to-add";
        }
      });

      let whereToInsert = allCourses[i].getElementsByClassName("course-btn")[0];
      whereToInsert.insertBefore(newButton, whereToInsert.firstChild);
    }
  }
  // #endregion

  /* #region 初始化按钮监听 */
  function initButtonAction(coursePageList) {
    observer.disconnect(); // 不观测,防止递归
    // 获取所有按钮
    let allButtons = document.getElementsByClassName("moodle-helper");
    let selectedCoursesList = GM_getValue("selectedCoursesList", {
      src: [],
    }).src;

    for (let i = 0; i < allButtons.length; i++) {
      allButtons[i].addEventListener("click", function () {
        if (this.action == "to-add") {
          addToSemester(this.relatedCourseId, selectedCoursesList);
          this.classList.remove("helper-add-button");
          this.classList.add("helper-remove-button");
          this.textContent = "Remove from this semester";
          this.action = "to-remove";
        } else if (this.action == "to-remove") {
          removeFromSem(this.relatedCourseId, selectedCoursesList);
          this.classList.remove("helper-remove-button");
          this.classList.add("helper-add-button");
          this.textContent = "Add to this semester";
          this.action = "to-add";
        }

        // 重新刷新
        let url = window.location.href;
        if (url == "https://moodle.hku.hk/") renderMainPage();
      });
    }

    observer.observe(targetNode, config); // 重新激活
  }
  /* #endregion */

  function removeFromSem(currentCourseId, selectedCoursesList) {
    console.log("removed");
    // 从课表删除
    var filteredList = [];
    for (var i = 0; i < selectedCoursesList.length; i++) {
      if (selectedCoursesList[i].courseId != currentCourseId) {
        filteredList.push(selectedCoursesList[i]);
      }
    }
    GM_setValue("selectedCoursesList", { src: filteredList });
    console.log(filteredList);
  }

  function addToSemester(currentCourseId, selectedCoursesList) {
    console.log("added");
    // 添加到课表
    var info;
    if (window.location.href == "https://moodle.hku.hk/my/courses.php") {
      info = parseCourseInfo(currentCourseId);
    } else if (window.location.href == "https://moodle.hku.hk/") {
      info = parseCourseInfoMainPage(currentCourseId);
    } else if (window.location.href.includes("course/search.php")) {
      info = parseCourseInfoSearchPage(currentCourseId);
    }

    var currentCourse = {
      courseId: currentCourseId,
      courseInfoPack: info,
    };
    selectedCoursesList.push(currentCourse);
    GM_setValue("selectedCoursesList", { src: selectedCoursesList });
    console.log(selectedCoursesList);
  }

  /* #region  主页渲染 */
  function renderMainPage() {
    const selectedCoursesList = GM_getValue("selectedCoursesList", {
      src: [],
    }).src;

    // 先全部清除
    (() => {
      let allCards = document.getElementsByClassName("moodle-helper-card");
      for (let i = allCards.length - 1; i >= 0; i--) {
        allCards[i].remove();
      }
    })();

    let mainPage = document.getElementById("frontpage-course-list");
    let checkCourseOfSemWrapper = document.getElementById(
      "course-of-sem-wrapper"
    );
    if (checkCourseOfSemWrapper != null) {
      checkCourseOfSemWrapper.remove();
    }
    // 插入 H2 标题
    let courseOfSemWrapper = document.createElement("div");
    courseOfSemWrapper.classList.add("course-of-sem-wrapper");
    courseOfSemWrapper.id = "course-of-sem-wrapper";
    let courseOfSemTitle = document.createElement("h2");
    courseOfSemTitle.textContent = "Courses of the Semester";
    courseOfSemTitle.id = "course-of-sem-title";
    courseOfSemWrapper.appendChild(courseOfSemTitle);

    // 插入选择的课程
    for (let i = 0; i < selectedCoursesList.length; i++) {
      let course = createCard(selectedCoursesList[i]);
      courseOfSemWrapper.appendChild(course);
    }

    // 插入到主页
    mainPage.insertBefore(courseOfSemWrapper, mainPage.firstChild);

    injectMainPageButton();
  }
  /* #endregion */

  /* #region  解析 my/courses.php 界面的课程信息 */
  function parseCourseInfo(courseId) {
    // 什么视图?
    var view = (() => {
      if (window.location.href.includes("my/courses.php")) {
        let button = document.getElementById("displaydropdown");
        return button.children[0].textContent.trim();
      }
    })();
    var viewPage = document.getElementsByClassName(
      "paged-content-page-container"
    );
    var coursePageList = viewPage[0].children;
    if (view != "Card") {
      for (let i = 0; i < coursePageList.length; i++) {
        // 第一级
        for (
          let c = 0;
          c < coursePageList[i].children[0].children.length;
          c++
        ) {
          // 第二级
          let currentCourse = coursePageList[i].children[0].children[c];
          if (currentCourse.dataset.courseId == courseId) {
            let ret = {};
            let row = currentCourse.children[0];
            // Image
            var courseImg =
              row.children[0].children[0].children[0].attributes["style"].value;
            ret.courseImg = courseImg;

            // Info
            let courseInfo = row.children[1];
            // Course Name
            var courseName = courseInfo.children[0];
            ret.courseName = courseName.outerHTML;

            // Category
            ret.courseCategory = courseInfo.children[1].outerHTML;
            // Year
            ret.courseYear = courseInfo.children[2].outerHTML;

            // Summary
            var courseSummary = courseInfo.children[3];
            ret.courseSummary = courseSummary.outerHTML;

            console.log(ret);

            return ret;
          }
        }
      }
    } else {
      for (let i = 0; i < coursePageList.length; i++) {
        // 第一级
        for (
          let j = 0;
          j < coursePageList[i].children[0].children.length;
          j++
        ) {
          let course = coursePageList[i].children[0].children[j];
          let currentCourseId = course.dataset.courseId;
          if (currentCourseId == courseId) {
            let ret = {};
            // Image
            let courseImg =
              course.children[0].children[0].attributes["style"].value;
            ret.courseImg = courseImg;

            let courseInfo = course.children[1].children[0].children[0];
            // Course Name
            ret.courseName = courseInfo.children[0].outerHTML;
            // Category
            ret.courseCategory = courseInfo.children[1].children[0].outerHTML;
            // Year
            ret.courseYear = courseInfo.children[1].children[1].outerHTML;
            // Summary
            ret.courseSummary = document.createElement("div").outerHTML;

            return ret;
          }
        }
      }
    }
  }
  function parseCourseInfoMainPage(courseId) {
    let page = document.getElementsByClassName(
      "frontpage-course-list-enrolled"
    )[0];
    let courses = page.getElementsByClassName("coursebox");

    console.log(courses);

    for (let i = 0; i < courses.length; i++) {
      if (courseId == courses[i].dataset.courseid) {
        let course = courses[i];
        let ret = {};

        // class name
        let courseName = course.getElementsByClassName("coursename")[0];
        ret.courseName = courseName.outerHTML;

        // Image
        let courseImg =
          'background-image: url("' +
          course.getElementsByClassName("courseimage")[0].dataset.src +
          '");';
        ret.courseImg = courseImg;

        // Category
        let coursecat = course.getElementsByClassName("coursecat")[0].children;
        let category = coursecat[0].outerHTML;
        let year = coursecat[1].outerHTML;
        ret.courseCategory = category;
        ret.courseYear = year;

        // summary
        let summary = course.getElementsByClassName("no-overflow")[0];
        if (summary) {
          summary.classList.remove("no-overflow");
          summary.classList.add("summary");
        } else {
          summary = document.createElement("div");
        }
        ret.courseSummary = summary.outerHTML;

        console.log(ret);

        return ret;
      }
    }
  }
  function parseCourseInfoSearchPage(courseId) {
    console.log("Parsing Course Info");
    let allCourses = document.getElementsByClassName("coursebox");
    // 定位到课程
    for (let i = 0; i < allCourses.length; i++) {
      if (courseId == allCourses[i].dataset.courseid) {
        let course = allCourses[i];
        let content = course.getElementsByClassName("content")[0];
        let ret = {};

        // courseImage
        let courseImg =
          content.getElementsByClassName("courseimage")[0].attributes["style"]
            .value;
        ret.courseImg = courseImg;

        // courseName
        let courseName = content.getElementsByClassName("coursename")[0];
        ret.courseName = courseName.outerHTML;

        // courseCategory
        let courseCategory =
          content.getElementsByClassName("coursecat")[0].children[0];
        ret.courseCategory = courseCategory.outerHTML;

        // courseYear
        let courseYear =
          content.getElementsByClassName("coursecat")[0].children[1];
        ret.courseYear = courseYear.outerHTML;

        // courseSummary
        let courseSummary = content.getElementsByClassName("no-overflow")[0];
        if (courseSummary) {
          courseSummary.classList.remove("no-overflow");
          courseSummary.classList.add("summary");
        } else {
          courseSummary = document.createElement("div");
        }
        ret.courseSummary = courseSummary.outerHTML;

        console.log(ret);

        return ret;
      }
    }
  }
  /* #endregion */

  /* #region  主页的课程卡片 */
  function createCard(courseInfo) {
    let card = document.createElement("div");
    card.classList.add("moodle-helper-card");
    card.classList.add("coursebox");
    card.classList.add("list");
    card.classList.add("clearfix");
    card.courseId = courseInfo.courseId;
    card.id = `courseCard${courseInfo.courseId}`;
    card.type = "1";

    let content = document.createElement("div");
    content.classList.add("content");
    // 缩略图
    let alink = document.createElement("a");
    alink.href = `https://moodle.hku.hk/course/view.php?id=${courseInfo.courseId}`;
    let img = document.createElement("div");
    img.classList.add("courseimage");
    img.setAttribute("style", courseInfo.courseInfoPack.courseImg);
    img.dataset.src = courseInfo.courseInfoPack.courseImg
      .replace('background-image: url("', "")
      .replace('");', "");
    alink.appendChild(img);

    // Summary 部分
    let summary = document.createElement("div");
    summary.classList.add("summary");
    // 课程名称
    let h3 = document.createElement("h3");
    h3.classList.add("coursename");
    let h3a = document.createElement("a");
    h3a.innerHTML = courseInfo.courseInfoPack.courseName;
    h3.appendChild(h3a);
    // Category
    let category = document.createElement("div");
    category.classList.add("coursecat");
    category.classList.add("text-muted");
    let csp1 = document.createElement("span");
    csp1.innerHTML = courseInfo.courseInfoPack.courseCategory;
    category.appendChild(csp1);
    let csp2 = document.createElement("span");
    csp2.innerHTML = courseInfo.courseInfoPack.courseYear;
    category.appendChild(csp2);
    // CourseSummary
    let courseSummary = document.createElement("div");
    courseSummary.innerHTML = courseInfo.courseInfoPack.courseSummary;
    summary.appendChild(h3);
    summary.appendChild(category);
    summary.appendChild(courseSummary);

    // 移除课程
    let removeCourse = document.createElement("button");
    removeCourse.classList.add("btn");
    removeCourse.classList.add("btn-primary");
    removeCourse.classList.add("moodle-helper");
    removeCourse.classList.add("helper-remove-button");
    removeCourse.textContent = "Remove from this semester";
    removeCourse.action = "to-remove";
    removeCourse.relatedCourseId = courseInfo.courseId;
    removeCourse.addEventListener("click", function () {
      removeFromSem(
        this.relatedCourseId,
        GM_getValue("selectedCoursesList", { src: [] }).src
      );
      let thiscard = document.getElementById(
        `courseCard${this.relatedCourseId}`
      );
      thiscard.remove();
      renderMainPage();
    });

    // enter course
    let enterCourse = document.createElement("div");
    enterCourse.classList.add("course-btn");
    let p1 = document.createElement("p");
    p1.appendChild(removeCourse);
    enterCourse.appendChild(p1);
    let p = document.createElement("p");
    let pa = document.createElement("a");
    pa.classList.add("btn");
    pa.classList.add("btn-primary");
    pa.href = `https://moodle.hku.hk/course/view.php?id=${courseInfo.courseId}`;
    pa.textContent = "Click to enter this course";
    p.appendChild(pa);
    enterCourse.appendChild(p);

    content.appendChild(alink);
    content.appendChild(summary);
    content.appendChild(enterCourse);

    card.appendChild(content);
    return card;
  }
  /* #endregion */

  /* #region 在主页插入按钮 */
  function injectMainPageButton() {
    let courseBoxes = document.getElementsByClassName("coursebox");
    let selectedCoursesList = GM_getValue("selectedCoursesList", {
      src: [],
    }).src;

    for (let i = 0; i < courseBoxes.length; i++) {
      if (courseBoxes[i].classList.contains("moodle-helper-card")) continue;
      let courseId = courseBoxes[i].dataset.courseid;
      let courseButton = courseBoxes[i].getElementsByClassName("course-btn")[0];

      // 移除已有按钮
      let buttonElement =
        courseBoxes[i].getElementsByClassName("moodle-helper");
      for (let j = buttonElement.length - 1; j >= 0; j--) {
        buttonElement[j].remove();
      }

      // 检查是否已添加
      var hasBeenAdded = false;
      for (let j = 0; j < selectedCoursesList.length; j++) {
        if (selectedCoursesList[j].courseId == courseId) {
          hasBeenAdded = true;
          break;
        }
      }

      // 如果已添加
      if (hasBeenAdded) {
        let removeButton = document.createElement("button");
        removeButton.classList.add("btn");
        removeButton.classList.add("btn-primary");
        removeButton.classList.add("moodle-helper");
        removeButton.classList.add("helper-remove-button");
        removeButton.textContent = "Remove from this semester";
        removeButton.action = "to-remove";
        removeButton.relatedCourseId = courseId;
        removeButton.addEventListener("click", function () {
          if (this.action == "to-add") {
            addToSemester(this.relatedCourseId, selectedCoursesList);
            this.classList.remove("helper-add-button");
            this.classList.add("helper-remove-button");
            this.textContent = "Remove from this semester";
            this.action = "to-remove";
          } else if (this.action == "to-remove") {
            removeFromSem(this.relatedCourseId, selectedCoursesList);
            this.classList.remove("helper-remove-button");
            this.classList.add("helper-add-button");
            this.textContent = "Add to this semester";
            this.action = "to-add";
          }

          // 重新刷新
          let url = window.location.href;
          if (url == "https://moodle.hku.hk/") renderMainPage();
        });
        courseButton.insertBefore(removeButton, courseButton.firstChild);
      } else {
        let addButton = document.createElement("button");
        addButton.classList.add("btn");
        addButton.classList.add("btn-primary");
        addButton.classList.add("moodle-helper");
        addButton.classList.add("helper-add-button");
        addButton.textContent = "Add to this semester";
        addButton.action = "to-add";
        addButton.relatedCourseId = courseId;
        addButton.addEventListener("click", function () {
          if (this.action == "to-add") {
            addToSemester(this.relatedCourseId, selectedCoursesList);
            this.classList.remove("helper-add-button");
            this.classList.add("helper-remove-button");
            this.textContent = "Remove from this semester";
            this.action = "to-remove";
          } else if (this.action == "to-remove") {
            removeFromSem(this.relatedCourseId, selectedCoursesList);
            this.classList.remove("helper-remove-button");
            this.classList.add("helper-add-button");
            this.textContent = "Add to this semester";
            this.action = "to-add";
          }

          // 重新刷新
          let url = window.location.href;
          if (url == "https://moodle.hku.hk/") renderMainPage();
        });
        courseButton.insertBefore(addButton, courseButton.firstChild);
      }
    }
  }
  /* #endregion */
})();