Greasy Fork

Greasy Fork is available in English.

Custom Anime Scheduler

Lets users track past seasons as they go by, with some QOL improvements for adding older anime.

当前为 2023-05-06 提交的版本,查看 最新版本

您需要先安装一款用户脚本管理器扩展,例如 Tampermonkey 篡改猴Greasemonkey 油猴子Violentmonkey 暴力猴,才能安装此脚本。

您需要先安装一款用户脚本管理器扩展,例如 Tampermonkey 篡改猴,才能安装此脚本。

您需要先安装一款用户脚本管理器扩展,例如 Tampermonkey 篡改猴Violentmonkey 暴力猴,才能安装此脚本。

您需要先安装一款用户脚本管理器扩展,例如 Tampermonkey 篡改猴Userscripts ,才能安装此脚本。

您需要先安装一款用户脚本管理器扩展,例如 Tampermonkey 篡改猴,才能安装此脚本。

您需要先安装一款用户脚本管理器扩展后才能安装此脚本。

(我已经安装了用户脚本管理器,让我安装!)

您需要先安装一款用户样式管理器扩展,比如 Stylus,才能安装此样式。

您需要先安装一款用户样式管理器扩展,比如 Stylus,才能安装此样式。

您需要先安装一款用户样式管理器扩展,比如 Stylus,才能安装此样式。

您需要先安装一款用户样式管理器扩展后才能安装此样式。

您需要先安装一款用户样式管理器扩展后才能安装此样式。

您需要先安装一款用户样式管理器扩展后才能安装此样式。

(我已经安装了用户样式管理器,让我安装!)

// ==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
    });
});

});