// ==UserScript==
// @icon http://www.tsinghua.edu.cn/publish/newthu/images/favicon.ico
// @name 网络学堂2018助手
// @namespace exhen32@live.com
// @version 2019年3月1日03版
// @description 微调排版,提醒更醒目; 支持导出日历,课程一目了然;更多功能开发中!
// @require http://cdn.bootcss.com/jquery/3.2.1/jquery.min.js
// @require https://cdn.bootcss.com/jqueryui/1.12.1/jquery-ui.min.js
// @author Exhen
// @match http*://learn.tsinghua.edu.cn/f/wlxt/index/course/student/
// @grant GM_xmlhttpRequest
// @grant GM_setClipboard
// @grant GM_addStyle
// @grant GM_setValue
// @grant GM_getValue
// @connect learn.tsinghua.edu.cn
// @run-at document-idle
// @downloadURL none
// ==/UserScript==
var saveAs = saveAs || (function (view) {
"use strict";
// IE <10 is explicitly unsupported
if (typeof view === "undefined" || typeof navigator !== "undefined" && /MSIE [1-9]\./.test(navigator.userAgent)) {
return;
}
var
doc = view.document
// only get URL when necessary in case Blob.js hasn't overridden it yet
,
get_URL = function () {
return view.URL || view.webkitURL || view;
},
save_link = doc.createElementNS("http://www.w3.org/1999/xhtml", "a"),
can_use_save_link = "download" in save_link,
click = function (node) {
var event = new MouseEvent("click");
node.dispatchEvent(event);
},
is_safari = /constructor/i.test(view.HTMLElement) || view.safari,
is_chrome_ios = /CriOS\/[\d]+/.test(navigator.userAgent),
throw_outside = function (ex) {
(view.setImmediate || view.setTimeout)(function () {
throw ex;
}, 0);
},
force_saveable_type = "application/octet-stream"
// the Blob API is fundamentally broken as there is no "downloadfinished" event to subscribe to
,
arbitrary_revoke_timeout = 1000 * 40 // in ms
,
revoke = function (file) {
var revoker = function () {
if (typeof file === "string") { // file is an object URL
get_URL().revokeObjectURL(file);
} else { // file is a File
file.remove();
}
};
setTimeout(revoker, arbitrary_revoke_timeout);
},
dispatch = function (filesaver, event_types, event) {
event_types = [].concat(event_types);
var i = event_types.length;
while (i--) {
var listener = filesaver["on" + event_types[i]];
if (typeof listener === "function") {
try {
listener.call(filesaver, event || filesaver);
} catch (ex) {
throw_outside(ex);
}
}
}
},
auto_bom = function (blob) {
// prepend BOM for UTF-8 XML and text/* types (including HTML)
// note: your browser will automatically convert UTF-16 U+FEFF to EF BB BF
if (/^\s*(?:text\/\S*|application\/xml|\S*\/\S*\+xml)\s*;.*charset\s*=\s*utf-8/i.test(blob.type)) {
return new Blob([String.fromCharCode(0xFEFF), blob], {
type: blob.type
});
}
return blob;
},
FileSaver = function (blob, name, no_auto_bom) {
if (!no_auto_bom) {
blob = auto_bom(blob);
}
// First try a.download, then web filesystem, then object URLs
var
filesaver = this,
type = blob.type,
force = type === force_saveable_type,
object_url, dispatch_all = function () {
dispatch(filesaver, "writestart progress write writeend".split(" "));
}
// on any filesys errors revert to saving with object URLs
,
fs_error = function () {
if ((is_chrome_ios || (force && is_safari)) && view.FileReader) {
// Safari doesn't allow downloading of blob urls
var reader = new FileReader();
reader.onloadend = function () {
var url = is_chrome_ios ? reader.result : reader.result.replace(/^data:[^;]*;/, 'data:attachment/file;');
var popup = view.open(url, '_blank');
if (!popup) view.location.href = url;
url = undefined; // release reference before dispatching
filesaver.readyState = filesaver.DONE;
dispatch_all();
};
reader.readAsDataURL(blob);
filesaver.readyState = filesaver.INIT;
return;
}
// don't create more object URLs than needed
if (!object_url) {
object_url = get_URL().createObjectURL(blob);
}
if (force) {
view.location.href = object_url;
} else {
var opened = view.open(object_url, "_blank");
if (!opened) {
// Apple does not allow window.open, see https://developer.apple.com/library/safari/documentation/Tools/Conceptual/SafariExtensionGuide/WorkingwithWindowsandTabs/WorkingwithWindowsandTabs.html
view.location.href = object_url;
}
}
filesaver.readyState = filesaver.DONE;
dispatch_all();
revoke(object_url);
};
filesaver.readyState = filesaver.INIT;
if (can_use_save_link) {
object_url = get_URL().createObjectURL(blob);
setTimeout(function () {
save_link.href = object_url;
save_link.download = name;
click(save_link);
dispatch_all();
revoke(object_url);
filesaver.readyState = filesaver.DONE;
});
return;
}
fs_error();
},
FS_proto = FileSaver.prototype,
saveAs = function (blob, name, no_auto_bom) {
return new FileSaver(blob, name || blob.name || "download", no_auto_bom);
};
// IE 10+ (native saveAs)
if (typeof navigator !== "undefined" && navigator.msSaveOrOpenBlob) {
return function (blob, name, no_auto_bom) {
name = name || blob.name || "download";
if (!no_auto_bom) {
blob = auto_bom(blob);
}
return navigator.msSaveOrOpenBlob(blob, name);
};
}
FS_proto.abort = function () {};
FS_proto.readyState = FS_proto.INIT = 0;
FS_proto.WRITING = 1;
FS_proto.DONE = 2;
FS_proto.error =
FS_proto.onwritestart =
FS_proto.onprogress =
FS_proto.onwrite =
FS_proto.onabort =
FS_proto.onerror =
FS_proto.onwriteend =
null;
return saveAs;
}(
typeof self !== "undefined" && self ||
typeof window !== "undefined" && window ||
this.content
));
// `self` is undefined in Firefox for Android content script context
// while `this` is nsIContentFrameMessageManager
// with an attribute `content` that corresponds to the window
if (typeof module !== "undefined" && module.exports) {
module.exports.saveAs = saveAs;
} else if ((typeof define !== "undefined" && define !== null) && (define.amd !== null)) {
define("FileSaver.js", function () {
return saveAs;
});
}
var getJSON = function (url, callback) {
GM_xmlhttpRequest({
method: 'GET',
url: url,
headers: {
'Accept': 'application/json'
},
onload: function (response) {
if (response.status >= 200 && response.status < 400) {
callback(JSON.parse(response.responseText), url);
} else {
callback(false, url);
}
}
});
};
function waitForKeyElements(
selectorTxt,
/* Required: The jQuery selector string that
specifies the desired element(s).
*/
actionFunction,
/* Required: The code to run when elements are
found. It is passed a jNode to the matched
element.
*/
bWaitOnce,
/* Optional: If false, will continue to scan for
new elements even after the first match is
found.
*/
iframeSelector
/* Optional: If set, identifies the iframe to
search.
*/
) {
var targetNodes, btargetsFound;
if (typeof iframeSelector == "undefined")
targetNodes = jQuery(selectorTxt);
else
targetNodes = jQuery(iframeSelector).contents()
.find(selectorTxt);
if (targetNodes && targetNodes.length > 0) {
btargetsFound = true;
/*--- Found target node(s). Go through each and act if they
are new.
*/
targetNodes.each(function () {
var jThis = jQuery(this);
var alreadyFound = jThis.data('alreadyFound') || false;
if (!alreadyFound) {
//--- Call the payload function.
var cancelFound = actionFunction(jThis);
if (cancelFound)
btargetsFound = false;
else
jThis.data('alreadyFound', true);
}
});
} else {
btargetsFound = false;
}
//--- Get the timer-control variable for this selector.
var controlObj = waitForKeyElements.controlObj || {};
var controlKey = selectorTxt.replace(/[^\w]/g, "_");
var timeControl = controlObj[controlKey];
//--- Now set or clear the timer as appropriate.
if (btargetsFound && bWaitOnce && timeControl) {
//--- The only condition where we need to clear the timer.
clearInterval(timeControl);
delete controlObj[controlKey]
} else {
//--- Set a timer, if needed.
if (!timeControl) {
timeControl = setInterval(function () {
waitForKeyElements(selectorTxt,
actionFunction,
bWaitOnce,
iframeSelector
);
},
300
);
controlObj[controlKey] = timeControl;
}
}
waitForKeyElements.controlObj = controlObj;
}
function PrefixInteger(num, length) {
return (Array(length).join(0) + num).slice(-length);
}
function init() {
if (!document.getElementById("dUietC") && $('ul.stu').length) {
var dUietC = document.createElement("a");
dUietC.id = "dUietC";
document.getElementsByTagName("html")[0].appendChild(dUietC);
console.log('网络学堂2018助手 is running!')
// 新通知数量重新排版
$('.unsee').remove();
$('li.clearfix').each(function () {
$(this).css('height', '90px')
$(this).css('padding', '8px 8px')
if (parseInt($(this).find('span.stud').text()) > 0) {
$(this).find('span.stud').css('font-size', '50px');
$(this).find('span.stud').css('display', 'block');
$(this).find('span.stud').css('padding-left', 'none');
$(this).find('span.stud').css('text-align', 'center');
//$(this).find('span.name').text($(this).find('span.liulan').text());
$(this).find('span.liulan').remove();
} else {
$(this).find('span.stud').remove();
}
})
$('ul.stu').each(function () {
$(this).find('li').first().css('padding', '0px');
})
// 图片提醒
$('dd.stu').each(function () {
if (parseInt($(this).find('span.green').text()) > 0) {
//var wlkcid = $(this).find('.hdtitle a').attr('href').match(/(?<=wlkcid=).*/);
var wlkcid = $(this).find('.hdtitle a').attr('href').slice(43);
$(this).attr('id', wlkcid)
getJSON(`http://learn.tsinghua.edu.cn/b/wlxt/kczy/zy/student/index/zyListWj?wlkcid=${wlkcid}&size=99`, function (doc, url) {
if (doc) {
var ddl = 0;
var now=new Date();
for (var i = 0; i < doc.object.iTotalRecords; i++) {
if (ddl <= 0 || (ddl > doc.object.aaData[i].jzsj&&doc.object.aaData[i].jzsj>now.getTime())) {
ddl = doc.object.aaData[i].jzsj
}
}
console.log(ddl)
var now = new Date();
var time = ddl - now.getTime();
console.log(time)
var days = Math.ceil(time / 86400000);
if (time <= 0) {
$(`#${wlkcid}`).find('li.clearfix').first().css('background', 'url(https://raw.githubusercontent.com/Exhen/learn2018helper/master/liangle.jpg)');
$(`#${wlkcid}`).find('li.clearfix').first().append(`已经截至`)
} else if (time <= 86400000) { //多于7天
$(`#${wlkcid}`).find('li.clearfix').first().css('background', 'url(https://raw.githubusercontent.com/Exhen/learn2018helper/master/ddl.jpg)');
$(`#${wlkcid}`).find('li.clearfix').first().append(`最后一天`)
} else {
$(`#${wlkcid}`).find('li.clearfix').first().css('background', 'url(https://raw.githubusercontent.com/Exhen/learn2018helper/master/ddl.jpg)');
$(`#${wlkcid}`).find('li.clearfix').first().append(`还剩${days}天`)
}
$(`#${wlkcid}`).find('p.p_img').remove();
}
})
} else {
$(this).find('li.clearfix').first().css('background', 'url(https://raw.githubusercontent.com/Exhen/learn2018helper/master/good.jpg)');
$(this).find('li.clearfix').first().append(`没有作业`)
$(this).find('p.p_img').remove();
}
})
$('head').append('