Make NTHU CCXP beauty
// ==UserScript==
// @name Beauty CCXP
// @namespace https://samuel21110.github.io/
// @version 0.1
// @description Make NTHU CCXP beauty
// @author Samuel
// @match https://www.ccxp.nthu.edu.tw/ccxp/INQUIRE/select_entry.php*
// @icon data:image/gif;base64,R0lGODlhAQABAAAAACH5BAEKAAEALAAAAAABAAEAAAICTAEAOw==
// @grant none
// @license MIT
// ==/UserScript==
(function() {
'use strict';
const main = () => {
class folder {
constructor(name) {
this.name = name;
this.items = [];
}
push(item) {
this.items.push(item);
}
print() {
console.log(this.items);
}
getArr() {
return this.items;
}
getName() {
return this.name;
}
}
class option {
constructor(name, url, target=0) {
this.name = name;
this.url = url;
this.target = target;
}
getName() {
return this.name;
}
getUrl() {
return this.url;
}
getTarget() {
return this.target;
}
}
const parse_folders = () => {
let frame = document.querySelectorAll("frame")[1];
let folders = frame.contentWindow.document.querySelectorAll('div[id^=folder]');
let items = Array.from(frame.contentWindow.document.querySelectorAll('div[id^=item]'));
let len = folders.length;
let main_folder = new folder("/");
for (let i = 1; i < len; i += 1) {
let name = folders[i].innerText.replace("\t", "");
let folder_num_st = folders[i].getAttribute("id").match(/\d+/);
// 10: hardcoded
const LAST_FOLDER_SIZE = 10;
let folder_num_ed = (i == len - 1) ? folder_num_st + LAST_FOLDER_SIZE : folders[i+1].getAttribute("id").match(/\d+/);
let items_cnt = folder_num_ed - folder_num_st - 1;
let f = new folder(name);
// console.log(i, " cnt:", items_cnt);
for (let j = 0; j < items_cnt; j += 1) {
if (items.length == 0) {
break;
}
let front = items.shift();
let optionName = front.innerText.replace("\t", "");
if (front.getAttribute("id").match("folder") != null) {
continue;
}
let id = front.getAttribute("id").match(/\d+/);
let url = front.querySelector("a").href;
let type = front.querySelector("a").target;
if (id <= folder_num_st || id >= folder_num_ed) {
// return -1;
}
type = type == "main" ? 0 : 1;
let add = new option(optionName, url, type);
console.log(optionName);
f.push(add);
}
if (items_cnt > 0) {
main_folder.push(f);
}
}
main_folder.print();
return main_folder;
}
const removeAllChildNodes = (parent) => {
while (parent.firstChild) {
parent.removeChild(parent.firstChild);
}
parent.remove();
}
const addBody = () => {
let body = document.createElement("body");
document.querySelector("html").append(body);
let link = document.createElement("link");
link.href = "https://use.fontawesome.com/releases/v5.7.2/css/all.css";
link.setAttribute("crossorigin", "anonymous")
link.rel = "stylesheet";
document.getElementsByTagName("head")[0].appendChild( link );
let style = `
@import url('https://fonts.googleapis.com/css?family=Poppins:400,500,600,700&display=swap');
*{
margin: 0;
padding: 0;
user-select: none;
box-sizing: border-box;
font-family: 'Poppins', sans-serif;
}
body{
background-color: #eee;
}
.btn{
position: absolute;
top: 10px;
left: 10px;
height: 37px;
width: 37px;
text-align: center;
background: #1b1b1b;
border-radius: 3px;
cursor: pointer;
transition: left 0.4s ease;
z-index: 2;
opacity: 20%;
}
.btn:hover {
opacity: 85%;
}
.btn.click{
left: 260px;
}
.btn span{
color: white;
font-size: 15px;
line-height: 36px;
}
.btn.click span:before{
content: '\f00d';
}
.sidebar{
position: fixed;
width: 250px;
height: 100%;
left: -250px;
background: #1b1b1b;
transition: left 0.4s ease;
z-index: 1;
overflow-y: scroll;
max-height: 100vh;
}
.sidebar.show{
left: 0px;
}
.sidebar .text{
color: white;
font-size: 19px;
font-weight: 600;
line-height: 65px;
text-align: center;
background: #1e1e1e;
letter-spacing: 1px;
}
nav ul{
background: #1b1b1b;
width: 100%;
list-style: none;
padding-left: 10px;
}
nav ul li{
line-height: 50px;
border-top: 1px solid rgba(255,255,255,0.1);
}
nav ul li:last-child{
border-bottom: 1px solid rgba(255,255,255,0.05);
}
nav ul li a{
position: relative;
color: white;
text-decoration: none;
font-size: 13px;
padding-left: 14px;
font-weight: 500;
display: block;
width: 100%;
border-left: 3px solid transparent;
}
nav ul li.active a{
color: #FC5404;
background: #1e1e1e;
border-left-color: #FC5404;
}
nav ul li a:hover{
background: #1e1e1e;
}
.feat-show{
transition: all 0.5s;
}
nav ul li.active ul{
transition: all 0.5s;
}
nav ul ul{
position: static;
display: none;
}
nav ul.show{
display: block;
transition: all 0.5s;
}
nav ul ul li{
line-height: 42px;
border-top: none;
}
nav ul ul li a{
font-size: 12px;
color: #e6e6e6;
}
nav ul li.active ul li a{
color: #e6e6e6;
background: #1b1b1b;
border-left-color: transparent;
}
a:hover{
color: #FC5404 !important;
}
nav ul ul li a:hover{
color: #FC5404 !important;
background: #1e1e1e!important;
}
nav ul li a span{
position: absolute;
top: 50%;
right: 20px;
transform: translateY(-50%);
font-size: 15px;
transition: transform 0.4s;
}
nav ul li a span.rotate{
transform: translateY(-50%) rotate(-180deg);
}
.content{
color: #202020;
z-index: 0;
text-align: center;
width: 100%;
height: 100%;
position: fixed;
}
.subwindow {
width: 100%;
height: 100%;
}
.main_side {
}
.hide {
display: none;
}
`
let styleDom = document.createElement("style");
styleDom.innerHTML = style;
document.querySelector("head").append(styleDom);
document.querySelector("head").innerHTML += `<meta name="viewport" content="width=device-width, initial-scale=1.0">`
}
// parse folders
let main_folder = parse_folders();
// remove all elements & add custom elements
removeAllChildNodes(document.querySelector("frameset"));
addBody();
// create buttons
document.querySelector("body").innerHTML = `
<div class="btn">
<span class="fas fa-bars"></span>
</div>
<div id="left">
<nav class="sidebar">
<div class="text">
NTHU CCXP
</div>
<ul class="main_side" id="main_side">
<div class="text"><input id="search" type="text" placeholder="\u641c\u5c0b" style="width: 100%;"></div>
</ul>
</nav>
</div>
<div class="content" id="right">
<div class="header" id="main">
<iframe class="subwindow" id="subwindow" src="https://www.ccxp.nthu.edu.tw/ccxp/INQUIRE/xp03_m.htm"/>
</div>
</div>
`
// add some event listeners
document.querySelector("#subwindow").addEventListener("load", () => {
document.querySelector("#subwindow").contentWindow.document.body.style.height = "100vh";
document.querySelector("#subwindow").contentWindow.document.body.style.textAlign = "center";
document.querySelector("#subwindow").contentWindow.document.body.onclick = () => {
if ($('.btn').hasClass("click")) {
$('.btn').toggleClass("click");
$('.sidebar').toggleClass("show");
}
}
});
document.querySelector("#search").oninput = (t) => {
let ele = t.target;
const val = ele.value.toLowerCase();
console.log(val);
let allFolders = document.querySelectorAll(".folder");
for (let folder of allFolders) {
let id = folder.querySelector("a").getAttribute('id');
if (val === "") {
folder.classList.remove("hide");
$('nav ul li ul.item-show-'+id).removeClass("show");
$('nav ul li #'+id+' span').removeClass("rotate");
}else {
if (folder.innerText.toLowerCase().match(val)) {
$('nav ul li ul.item-show-'+id).addClass("show");
$('nav ul li #'+id+' span').addClass("rotate");
folder.classList.remove("hide");
}else {
$('nav ul li ul.item-show-'+id).removeClass("show");
$('nav ul li #'+id+' span').removeClass("rotate");
folder.classList.add("hide");
}
}
}
}
const addItems = (folder, id) => {
let ul = document.createElement("ul");
ul.setAttribute("class", `item-show-${id}`);
const arr = folder.getArr();
for (let i of arr) {
let li = document.createElement("li");
let a = document.createElement("a");
let type = i.getTarget();
if (type === 0) {
a.onclick = () => {
document.querySelector("#subwindow").src = i.getUrl();
// $('#main').html(`<iframe class="subwindow" src="${i.getUrl()}"/>`);
}
}else {
a.href = i.getUrl();
a.target = "_blank";
}
a.innerText = `> ${i.getName().replaceAll("\n", " ")}`;
li.appendChild(a);
ul.appendChild(li);
console.log(`${a.innerText} ${i.getUrl()}`)
}
return ul;
}
const addFolder = (main_folder) => {
const arr = main_folder.getArr();
for (let i = 0; i < arr.length; i++) {
let folder = arr[i];
let li = document.createElement("li");
li.setAttribute("class", "folder");
li.innerHTML = `
<a href="#" id="${i}">${folder.getName()}
<span class="fas fa-caret-down"></span>
</a>
`
li.appendChild(addItems(folder, i));
document.querySelector("#main_side").appendChild(li);
}
};
addFolder(main_folder);
// load jQuery
const loadJquery = (callback) => {
let script = document.createElement('script');
document.head.appendChild(script);
script.type = 'text/javascript';
script.src = "https://ajax.googleapis.com/ajax/libs/jquery/3.6.3/jquery.min.js";
script.onload = callback;
}
loadJquery(() => {
console.log("finish load")
$('.btn').click(function() {
$(this).toggleClass("click");
$('.sidebar').toggleClass("show");
});
$('.sidebar ul li a').click(function(){
let id = $(this).attr('id');
$('nav ul li ul.item-show-'+id).toggleClass("show");
$('nav ul li #'+id+' span').toggleClass("rotate");
});
$('nav ul li').click(function(){
$(this).addClass("active").siblings().removeClass("active");
});
$('.content').click(() => {
if ($('.btn').hasClass("click")) {
$('.btn').toggleClass("click");
$('.sidebar').toggleClass("show");
}
})
});
}
const wait_loaded = () => {
let frame = document.querySelectorAll("frame")[1];
let folders = frame.contentWindow.document.querySelectorAll('div[id^=folder]');
if (folders.length < 20) {
setTimeout(wait_loaded, "50");
}else {
main();
}
}
wait_loaded();
})();
QingJ © 2025
镜像随时可能失效,请加Q群300939539或关注我们的公众号极客氢云获取最新地址