// ==UserScript==
// @name BIT-乐学-修改侧边栏课程-GUI
// @namespace http://tampermonkey.net/
// @version 1.0.0
// @description 修改侧边栏显示的课程
// @license GPL-3.0-or-later
// @supportURL https://github.com/YDX-2147483647/BIT-enhanced/issues
// @author CJJ
// @match *://lexue.bit.edu.cn/*
// @icon https://lexue.bit.edu.cn/theme/image.php/eguru/theme/1724573654/favicon
// @grant GM_getValue
// @grant GM_setValue
// @grant GM_registerMenuCommand
// @downloadURL none
// ==/UserScript==
(async function () {
'use strict'
// GreasyFork提供:
/* global GM_getValue, GM_setValue, GM_registerMenuCommand */
// 乐学提供:
/* global M */
let dragsrc = null
let shown_courses = await GM_getValue('lexue_shown_courses') || []
let hidden_courses = await GM_getValue('lexue_hidden_courses') || []
const popup_cover = document.createElement('div')
const popup = document.createElement('div')
popup_cover.style = 'width:100%;height:100%;background-color:rgba(0,0,0,0.6);position:fixed;inset:0px;z-index:2000'
function rewrite_sidebar (shown_courses) {
const current_id = document.querySelector('[data-key="coursehome"].active_tree_node')?.href?.match(/(?<=id=)\w+/)?.join() // 如果找不到返回undefined
const mycourses = document.querySelector('li:has([data-key="mycourses"])')
const sidebar_course_list = mycourses.parentNode
let node = mycourses.nextSibling
while (node) {
node.parentNode.removeChild(node)
node = mycourses.nextSibling
}
for (let i = 0; i < shown_courses.length; i++) {
const classList = (current_id === shown_courses[i][0] ? ['list-group-item-action active active_tree_node ', 'font-weight-bold '] : ['', ''])
sidebar_course_list.innerHTML += `
`
}
}
function openPopup () {
popup.style = 'background-color:white;color:black;box-shadow:rgb(153,153,153) 0px 0px 2px;transform:translate(-50%,-50%);position:fixed;border:3px solid rgba(0,0,0,0.6);font-size:16px;overflow:hidden;z-index:3000;left:50%;top:50%;width:70%;text-align:center;'
popup.innerHTML = `
通过拖动来归类和排序
`
popup.querySelector('#close_popup').onclick = () => closePopup()
popup.querySelector('#rewrite_sidebar').onclick = () => {
closePopup()
shown_courses = []
hidden_courses = []
const shown_lis = popup.querySelectorAll('#shown_courses>li')
const hidden_lis = popup.querySelectorAll('#hidden_courses>li')
for (let i = 0; i < shown_lis.length; i++) {
shown_courses.push([shown_lis[i].dataset.id, shown_lis[i].innerText.replaceAll('&', '&').replaceAll('<', '<').replaceAll('>', '>').replaceAll(' ', ' '), shown_lis[i].querySelector('[data-icon]').dataset.icon])
}
for (let j = 0; j < hidden_lis.length; j++) {
hidden_courses.push([hidden_lis[j].dataset.id, hidden_lis[j].innerText.replaceAll('&', '&').replaceAll('<', '<').replaceAll('>', '>').replaceAll(' ', ' '), hidden_lis[j].querySelector('[data-icon]').dataset.icon])
}
GM_setValue('lexue_shown_courses', shown_courses)
GM_setValue('lexue_hidden_courses', hidden_courses)
rewrite_sidebar(shown_courses)
}
popup.querySelector('#shown_courses').addEventListener('drop', function (e) {
e.preventDefault()
this.append(dragsrc)
})
popup.querySelector('#hidden_courses').addEventListener('drop', function (e) {
e.preventDefault()
this.append(dragsrc)
})
for (let i = 0; i < shown_courses.length; i++) {
const shown_li = document.createElement('li')
shown_li.setAttribute('data-id', shown_courses[i][0])
shown_li.draggable = 'true'
shown_li.addEventListener('dragstart', function (e) {
dragsrc = this
})
shown_li.addEventListener('dragover', function (e) {
e.preventDefault()
})
shown_li.addEventListener('drop', function (e) {
e.stopPropagation()
if (this !== dragsrc) {
if (this.parentNode === dragsrc.parentNode && this.offsetTop > dragsrc.offsetTop) {
this.parentNode.insertBefore(dragsrc, this.nextSibling)// if this.nextSibling===null insert as the last child.
} else {
this.parentNode.insertBefore(dragsrc, this)
}
}
})
shown_li.innerHTML = ``
popup.querySelector('#shown_courses').append(shown_li)
}
for (let j = 0; j < hidden_courses.length; j++) {
const hidden_li = document.createElement('li')
hidden_li.setAttribute('data-id', hidden_courses[j][0])
hidden_li.draggable = 'true'
hidden_li.addEventListener('dragstart', function (e) {
dragsrc = this
})
hidden_li.addEventListener('dragover', function (e) {
e.preventDefault()
})
hidden_li.addEventListener('drop', function (e) {
e.stopPropagation()
if (this !== dragsrc) {
if (this.parentNode === dragsrc.parentNode && this.offsetTop > dragsrc.offsetTop) {
this.parentNode.insertBefore(dragsrc, this.nextSibling)// if this.nextSibling===null insert as the last child.
} else {
this.parentNode.insertBefore(dragsrc, this)
}
}
})
hidden_li.innerHTML = ``
popup.querySelector('#hidden_courses').append(hidden_li)
}
document.body.append(popup_cover)
document.body.append(popup)
}
function closePopup () {
document.body.removeChild(popup_cover)
document.body.removeChild(popup)
}
function reload_courses () {
const xhr = new XMLHttpRequest()
xhr.onreadystatechange = function () {
if (xhr.readyState === 4 && xhr.status === 200) {
const courses = JSON.parse(xhr.responseText)[0].data.courses
courses.sort((a, b) => a.enddate - b.enddate)
for (let i = 0; i < courses.length; i++) {
if (!hidden_courses.filter(hidden_course => parseInt(hidden_course[0]) === courses[i].id).length && !shown_courses.filter(shown_course => parseInt(shown_course[0]) === courses[i].id).length) {
hidden_courses.unshift([courses[i].id, `${courses[i].fullname}`, 'graduation-cap'])
}
}
openPopup()
}
}
xhr.open('POST', `https://lexue.bit.edu.cn/lib/ajax/service.php?sesskey=${M.cfg.sesskey}&info=core_course_get_enrolled_courses_by_timeline_classification`, true)
xhr.send('[{"index":0,"methodname":"core_course_get_enrolled_courses_by_timeline_classification","args":{"offset":0,"limit":0,"classification":"all","sort":"fullname","customfieldname":"","customfieldvalue":""}}]')
}
if (shown_courses.length || hidden_courses.length) {
rewrite_sidebar(shown_courses)
} else {
reload_courses()
}
GM_registerMenuCommand('更新课程并修改侧边栏', function () {
if (!popup.parentNode) {
reload_courses()
}
})
GM_registerMenuCommand('仅修改侧边栏', function () {
if (!popup.parentNode) {
openPopup()
}
})
})()