Greasy Fork is available in English.
Lets users track past seasons as they go by, with some QOL improvements for adding older anime.
当前为
// ==UserScript==
// @name Custom Anime Scheduler
// @namespace http://tampermonkey.net/
// @version 0.1
// @description Lets users track past seasons as they go by, with some QOL improvements for adding older anime.
// @author You
// @icon https://www.google.com/s2/favicons?sz=64&domain=tampermonkey.net
// @grant GM_setValue
// @grant GM_getValue
// @match *.livechart.me/*
// @require https://code.jquery.com/jquery-3.6.4.min.js
// @run-at document-end
// @license MIT
// ==/UserScript==
const $ = window.jQuery;
//Converts a Date object to the format YYYY-MM-DD
function convertToDateLinkText(date) {
let realMonth = date.getMonth() + 1; // getMonth() returns months starting at 0 for January, so fixing it.
let dateString = date.getDate();
if (dateString < 10) { //Adding a 0 so that it matches up with the url text for checking whether the week is the current one.
dateString = '0' + dateString;
}
if (realMonth < 10) {
realMonth = '0' + realMonth;
}
const dateLinkFormat_ = date.getFullYear() + '-' + realMonth + '-' + dateString;
return dateLinkFormat_;
}
//Converts texts in format YYYY-MM-DD to a Date object
function convertToDateObject(dateString) {
const modifiedDateString = dateString + " 00:00:00"; //Without this, it will be set to the day before
const dateObject = new Date(modifiedDateString);
return dateObject;
}
//Returns the number of days since the last starting day, either Monday or Sunday
function daysSinceStartingDay(date) {
let daysSince;
const startingDay_ = GM_getValue("starting_day");
if (startingDay_ == "monday") { //getDay() returns 0-6 depending days away from Sunday.
daysSince = (date.getDay() + 6) % 7;
}
else {
daysSince = date.getDay();
}
return daysSince;
}
//Adjusts how much the schedule changed based on the time-flow options chosen. (potential update: adding the schedule's current date to make choices outside of 1 & 7 easier to track)
function speedChange(diff) {
const daysString = GM_getValue("days_speed");
const speed = Number(daysString);
const newDiff = diff * Math.ceil(7 / speed); // speed=7 means that time passes normally, while speed=1 means that it passes 7 times faster
return newDiff;
}
//Shifts the Date forward by the number of days specified in diff
function shiftDate(date, diff) {
const daysShifted = date.getDate() + diff; //Needs getDate() because it starting at the beginning of the month.
date.setDate(daysShifted);
}
function getDayTextFromNum(num) {
let weekDay;
switch(num) {
case 0:
weekDay = "Sun";
break;
case 1:
weekDay = "Mon";
break;
case 2:
weekDay = "Tue";
break;
case 3:
weekDay = "Wed";
break;
case 4:
weekDay = "Thu";
break;
case 5:
weekDay = "Fri";
break;
case 6:
weekDay = "Sat";
break;
}
return weekDay;
}
//Returns the 3-letter text form of week days
function getDayText(date) {
let weekDay;
const dayNum = date.getDay();
weekDay = getDayTextFromNum(dayNum);
return weekDay;
}
//Converts a Date object to the text displayed by the last-week button
function convertToDateButtonText(date) {
let retString;
let dateString = date.getDate();
const weekDay = getDayText(date);
const realMonth = date.getMonth() + 1;
if (dateString < 10) { //Adding a 0 so that it is two digits like in the original program.
dateString = '0' + dateString;
}
retString = weekDay + ' ' + realMonth + '/' + dateString;
return retString;
}
function GetURLParameter(sParam) { //From: https://stackoverflow.com/questions/12456639/how-to-get-data-from-url-with-jquery
const sPageURL = window.location.search.substring(1);
const sURLVariables = sPageURL.split('&');
for (let i = 0; i < sURLVariables.length; i++) {
let sParameterName = sURLVariables[i].split('=');
if (sParameterName[0] == sParam) {
return decodeURIComponent(sParameterName[1]);
}
}
}
//The code is highlight which day is the currrent custom day, or to highlight future days black
function highlightTTDay(dayText, dayStatus) {
let timeTableBox = $('.timetable');
const tTDayQuery = 'h2:contains("' + dayText + '")';
let TTDayH2 = timeTableBox.find(tTDayQuery);
let TTDay = TTDayH2.parent().parent();
TTDay.removeClass("past");
TTDay.addClass(dayStatus);
}
$(window).bind("load", function () {
const $today = new Date();
const todayHoursToMidnight = convertToDateObject(convertToDateLinkText($today)); //Making sure there no weird behavior by setting the time to 00:00 or midnight like it is with the time of setting
let scheduleDate = convertToDateObject(GM_getValue("start_date"));
const settingDate = convertToDateObject(GM_getValue("setting_date"));
const daysDiff = (todayHoursToMidnight - settingDate) / (1000 * 60 * 60 * 24); //Since the difference given is in ms, converting it to days
const daysDiffWithSpeed = speedChange(daysDiff);
shiftDate(scheduleDate, daysDiffWithSpeed);
const currentCustomDateText = convertToDateLinkText(scheduleDate);
//Setting the timetable to start on the chosen starting day
const weekStartDiff = -daysSinceStartingDay(scheduleDate);
shiftDate(scheduleDate, weekStartDiff);
const dateLinkFormat = convertToDateLinkText(scheduleDate);
const scheduleDateLink = 'https://www.livechart.me/timetable?date=' + dateLinkFormat;
const SettingsTab = '<li class="hide-for-small-only"><a class="nav-link schedule-settings-button" href="https://www.livechart.me/preferences/general">Settings</a></li>';
const CustomScheduleTab = '<li class="hide-for-small-only"><a class="nav-link" href="' + scheduleDateLink + '">Custom Schedule</a></li>';
$(SettingsTab).insertBefore('.site-header--navigation>.flex-spacer'); //Flex Spacer is the space between the top bar and the magnifying glass.
let headlinesButton = $('a[href="/headlines"]').parent();
$(headlinesButton).attr('id', 'headlines-button');
$(CustomScheduleTab).insertBefore('.site-header--navigation>#headlines-button');
//Adding a "last week" button
const urlDateText = GetURLParameter('date');
let urlDateObject = convertToDateObject(urlDateText);
shiftDate(urlDateObject, -7);
const urlDateLastWeekText = convertToDateLinkText(urlDateObject);
const urlDateButtonText = convertToDateButtonText(urlDateObject);
const lastWeekButton = '<div class="column small-6"><a class="button clear" href="/timetable?date=' + urlDateLastWeekText + '" rel="nofollow"><i class="icon-navigate_first"></i>' + urlDateButtonText + '</a></div>';
let weekChangeRow = $('div.column.small-6.float-right.text-right').parent()
if (weekChangeRow.find("a").length == 1) { //If is only the "next week" button.
weekChangeRow.prepend(lastWeekButton);
}
//Highlighting the current day
// Attribute data-timetable-day-start starts at -32400 on Jan 1, 1970, so dtds + 32400 = Jan 1 1970 date
let currentCustomDate = convertToDateObject(currentCustomDateText);
const scheduleDayText = getDayText(currentCustomDate);
console.log("urlDateText is "+urlDateText+" and dateLinkFormat is "+dateLinkFormat);
if (urlDateText == dateLinkFormat) { //If the url matches the current custom week
highlightTTDay(scheduleDayText, "today");
const scheduleDayNum = currentCustomDate.getDay();
for (let i = scheduleDayNum; i < 7; i++) {
let futureDayText = getDayTextFromNum(i);
highlightTTDay(futureDayText, "future");
}
const startingDay = GM_getValue("starting_day");
if (startingDay == "monday") {
highlightTTDay("Sun", "future");
}
}
// Make it more readable, try making it list them vertically instead. 21 rows per column
//Making it easier to search for years before 3 years ago
let BrowseList = $('.small-up-4');
$('.small-up-4 > div:last-child').remove();
//Tried a number of other ways, but transposing matrices is the only thing that worked
const rowsNum = 20;
const colsNum = 4;
let yearGrid = new Array (colsNum);
for (let i = 0; i < colsNum; i++) {
yearGrid[i] = new Array(rowsNum);
}
let i = 0;
let k = 0;
$('.small-up-4 div').each(function() {
if (i < rowsNum) {
yearGrid[k][i] = $(this);
i++;
}
else {
k++;
if (k < colsNum) {
i = 0;
yearGrid[k][i] = $(this);
} //Break wasn't working with .each()
}
});
const thisYear = $today.getFullYear();
//Using the i and k values from the previous loop
for (let year = (thisYear - 3); year >= 1960; year--) {
if (i < rowsNum) {
yearGrid[k][i] = ('<div class="cell"><a class="px0" href="/winter-' + year + '/tv">' + year + '</a></div>');
i++;
}
else {
k++;
if (k < colsNum) {
i = 0;
year++;
}
}
}
$(BrowseList).empty();
let r = 0;
let c = 0;
for (let r = 0; r < rowsNum; r++) {
for (let c = 0; c < colsNum; c++) {
$(BrowseList).append(yearGrid[c][r]);
}
}
$(BrowseList).removeClass('grid-padding-x');
//Changing the name so users will know that it does something new (too slow)//const BrowseTab = 'label[for="browse_dropdown_trigger"]';//$(BrowseTab).text('Browse by Year ');//$(BrowseTab).append('<i class="caret"></i>');
//Adding the Customize Schedule settings bar
let PreferencesList = '.large-push-2 > div[class="ul-tabs-overflow"] > ul[class="ul-tabs"]'; //note: selecting multiple classes doesn't work with > operator
const ScheduleSettingsPrefTab = '<li class="ul-tab schedule-pref-tab"><a>Edit Schedule</a></li>';
$(PreferencesList).append(ScheduleSettingsPrefTab);
let prefBody = $('form[action*="/preferences/"]');
//Button Events
$(".schedule-pref-tab").click(function() {
const SchedulePrefFormStart = '<div class="callout">';
const StartDate = '<label class="string required" for="start_date"><abbr title="required">Type out the date that your custom schedule starts (YYYY-MM-DD)</label><input class="string required" required="required" aria-required="true" placeholder="2013-05-23" maxlength="20" pattern="*" size="20" type="text" value="" name="user[username]" id="start-date">';
const StartingDay = '<label for="starting_day">The starting day of the week is</label><select name="preferences[titles]" id="starting-day">';
const StartingDayOptions = '<option value="monday">Monday (Mo. Tu. We. Th. Fr. Sa. Su.)</option><option value="sunday">Sunday (Su. Mo. Tu. We. Th. Fr. Sa.)</option></select>';
const DaysSpeed = '<label for="days_speed">Speed that schedule time passes</label><select name="preferences[titles]" id="days-speed">';
const DaysSpeedOptions = '<option value="7">Each week lasts 7 days</option><option value="1">Each week lasts 1 day</option><option value="2">Each week lasts 2 days</option><option value="3">Each week lasts 3 days</option><option value="4">Each week lasts 4 days</option></select>';
const SchedulePrefFormEnd = '<hr><button class="button" name="schedule-button">Save</button></div>';
//Setting the "Edit Schedule" button to the only active one.
$('.ul-tabs li').each(function() {
$(this).removeClass('active');
});
$(".schedule-pref-tab").addClass('active');
prefBody.empty();
prefBody.append(SchedulePrefFormStart + StartDate + StartingDay + StartingDayOptions + DaysSpeed + DaysSpeedOptions + SchedulePrefFormEnd);
let startDateValue = $('label[for="starting_day"]').val();
//Setting the default to the last chosen values
const prevStartingDayOption = 'option[value="' + GM_getValue("starting_day") + '"]';
$(prevStartingDayOption).attr("selected", "selected");
const prevSpeedOption = 'option[value="' + GM_getValue("days_speed") + '"]';
$(prevSpeedOption).attr("selected", "selected");
$('button[name="schedule-button"]').on('click', function(event) {
event.preventDefault();
console.log("within $('input[name='schedule-button']').click(function() {");
let startDateValue = $('#start-date').val();
console.log("startDateValue is "+startDateValue);
let startingDayValue = $('#starting-day').val();
let daysSpeedValue = $('#days-speed').val();
GM_setValue("start_date", startDateValue);
GM_setValue("starting_day", startingDayValue);
GM_setValue("days_speed", daysSpeedValue);
let $thisDate = new Date();
let thisDateText = convertToDateLinkText($thisDate);
GM_setValue("setting_date", thisDateText);
location.reload(); //So that Custom Schedule updates right away so that clicking on it doesn't lead to the old settings
});
});
});