您需要先安装一个扩展,例如 篡改猴、Greasemonkey 或 暴力猴,之后才能安装此脚本。
您需要先安装一个扩展,例如 篡改猴 或 暴力猴,之后才能安装此脚本。
您需要先安装一个扩展,例如 篡改猴 或 暴力猴,之后才能安装此脚本。
您需要先安装一个扩展,例如 篡改猴 或 Userscripts ,之后才能安装此脚本。
您需要先安装一款用户脚本管理器扩展,例如 Tampermonkey,才能安装此脚本。
您需要先安装用户脚本管理器扩展后才能安装此脚本。
修改侧边栏显示的课程
当前为
// ==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 // ==/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 += `<li> <a class="list-group-item list-group-item-action ${classList[0]}" href="https://lexue.bit.edu.cn/course/view.php?id=${shown_courses[i][0]}" data-key="${shown_courses[i][0]}" data-isexpandable="1" data-indent="1" data-showdivider="0" data-type="20" data-nodetype="1" data-collapse="0" data-forceopen="0" data-isactive="0" data-hidden="0" data-preceedwithhr="0" data-parent-key=""> <div class="ml-1"> <div class="media"> <span class="media-left"> <i class="icon fa fa-${shown_courses[i][2]} fa-fw " aria-hidden="true"></i> </span> <span class="media-body ${classList[1]}">${shown_courses[i][1]}</span> </div> </div> </a> </li>` } } 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 = `<style> #popup_title{ width:100%; height:40px; line-height:40px; box-sizing:border-box; background-color:rgb(255,77,64); color:rgb(255,255,255); font-weight:700; font-size:20px; -webkit-touch-callout:none; -webkit-user-select:none; -khtml-user-select:none; -moz-user-select:none; -ms-user-select:none; user-select:none; } #close_popup{ text-decoration:none; color:rgb(255,255,255); position:absolute; right:10px; top:0px; font-size:25px; display:inline-block; cursor:pointer; } ul#shown_courses,ul#hidden_courses{ width:45%; height:60vh; display:inline; position:relative; background-color: #dddddd; border: 1px solid #000; -webkit-touch-callout:none; -webkit-user-select:none; -khtml-user-select:none; -moz-user-select:none; -ms-user-select:none; user-select:none; overflow-y:scroll; overflow-x:hidden; scrollbar-width: none;/* 兼容火狐 */ -ms-overflow-style: none;/* 兼容IE10+ */ text-align:center; word-break:break-all; list-style: none; padding-left: 0; } ul#shown_courses::-webkit-scrollbar,ul#hidden_courses::-webkit-scrollbar{ width: 0px;/* 兼容火狐 */ } ul#shown_courses>li,ul#hidden_courses>li{ cursor: grab; font-size: 16px; font-weight: bold; border: 1px solid #000; width: 100%; text-align: center; } ul#shown_courses span,ul#hidden_courses span{ min-height:24px; } span[contenteditable='true']{ border:thin solid #C0C0C0; } </style><div id="popup_title">编辑侧边栏课程 <div id="close_popup">×</div> </div> 通过拖动来归类和排序 <div style="display:flex;justify-content:center;"> <div style="width:45%;font-size:16px;">显示的课程</div> <div style="width:45%;font-size:16px;">隐藏的课程</div> </div> <div style="display:flex;justify-content:center;"> <ul id="shown_courses" ondragover="event.preventDefault();"></ul> <ul id="hidden_courses" ondragover="event.preventDefault();"></ul> </div> <button id="rewrite_sidebar" style="margin:1% 1% 1% 1%;">完成</button></div>` 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 = `<a class="list-group-item list-group-item-action"><div class="ml-1"><div class="media"><span class="media-left"><i class="icon fa fa-${shown_courses[i][2]} fa-fw" aria-hidden="true" ondblclick="this.style.display='none';this.nextSibling.style.display='block';this.nextSibling.focus();this.parentNode.parentNode.parentNode.parentNode.parentNode.draggable=false"></i><span class="media-body" style="cursor:auto;display:none" contenteditable="true" onfocus="this.innerText=this.dataset.icon" data-icon="${shown_courses[i][2]}" onblur="this.style.display='none';this.previousSibling.style.display='block';this.parentNode.parentNode.parentNode.parentNode.parentNode.draggable=true;this.dataset.icon=this.innerText;this.innerText='';this.previousSibling.className='icon fa fa-'+this.dataset.icon+' fa-fw';" onkeydown="if(event.keyCode===13){this.blur();}" onpaste="event.preventDefault();document.execCommand('insertText',false,event.clipboardData.getData('text/plain').replace(/[\\n|\\r]/gm,''))"></span></span><span class="media-body" ondblclick="this.setAttribute('contenteditable','true');this.focus();this.style.cursor='auto';this.parentNode.parentNode.parentNode.parentNode.draggable=false" onblur="this.removeAttribute('contenteditable');this.style.cursor='grab';this.parentNode.parentNode.parentNode.parentNode.draggable=true" onkeydown="if(event.keyCode===13){this.blur();}" onpaste="event.preventDefault();document.execCommand('insertText',false,event.clipboardData.getData('text/plain').replace(/[\\n|\\r]/gm,'')).replaceAll(' ',' ')">${shown_courses[i][1]}</span></div></div></a>` 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 = `<a class="list-group-item list-group-item-action"><div class="ml-1"><div class="media"><span class="media-left"><i class="icon fa fa-${hidden_courses[j][2]} fa-fw" aria-hidden="true" ondblclick="this.style.display='none';this.nextSibling.style.display='block';this.nextSibling.focus();this.parentNode.parentNode.parentNode.parentNode.parentNode.draggable=false"></i><span class="media-body" style="cursor:auto;display:none" contenteditable="true" onfocus="this.innerText=this.dataset.icon" data-icon="${hidden_courses[j][2]}" onblur="this.style.display='none';this.previousSibling.style.display='block';this.parentNode.parentNode.parentNode.parentNode.parentNode.draggable=true;this.dataset.icon=this.innerText;this.innerText='';this.previousSibling.className='icon fa fa-'+this.dataset.icon+' fa-fw'" onkeydown="if(event.keyCode===13){this.blur();}" onpaste="event.preventDefault();document.execCommand('insertText',false,event.clipboardData.getData('text/plain').replace(/[\\n|\\r]/gm,''))"></span></span><span class="media-body" ondblclick="this.setAttribute('contenteditable','true');this.focus();this.style.cursor='auto';this.parentNode.parentNode.parentNode.parentNode.draggable=false" onblur="this.removeAttribute('contenteditable');this.style.cursor='grab';this.parentNode.parentNode.parentNode.parentNode.draggable=true" onkeydown="if(event.keyCode===13){this.blur();}" onpaste="event.preventDefault();document.execCommand('insertText',false,event.clipboardData.getData('text/plain').replace(/[\\n|\\r]/gm,'')).replaceAll(' ',' ')">${hidden_courses[j][1]}</span></div></div></a>` 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, `<b style="color:red">${courses[i].fullname}</b>`, '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() } }) })()