- // ==UserScript==
- // @name Hinatazaka46 Layout change NEWS / SCHEDULE
- // @name:ja 日向坂46 レイアウト変更 NEWS / SCHEDULE
- // @namespace naoqv.hinatazaka
- // @description Change the layout of the "News" and "Schedule" pages on the Hinatazaka46 website
- // @description:ja 日向坂46サイト「ニュース」「スケジュール」ページのレイアウト変更
- // @version 1.15
- // @match https://www.hinatazaka46.com/s/official/news/*
- // @match https://www.hinatazaka46.com/s/official/media/*
- // @require https://update.gf.qytechs.cn/scripts/510022/1453515/HinatazakaStyleSetting.js
- // @require https://update.gf.qytechs.cn/scripts/509934/1453163/HinatazakaExceptionHandlingWrapper.js
- // @icon https://cdn.hinatazaka46.com/files/14/hinata/img/favicons/favicon-32x32.png
- // @compatible chrome
- // @compatible firefox
- // @grant none
- // @license MIT
- // ==/UserScript==
-
- const SCRIPT_NAME = "日向坂46 NEWS / SCHEDULE レイアウト変更";
-
- handleException(()=> {
-
- const PAGE_TYPE_ERROR_MSG = "Processing of out-of-scope pages. Check the settings @match.";
-
- const pageType = (location.href).match(new RegExp('\/(media|news)\/'))[1];
- const isDetail = ((location.href).match(new RegExp('\/detail\/')) != null);
-
- const SELECTORS = ((x) => {
- switch (x) {
- case "news":
- return {"pArrow": ".p-news__pager-arrow",
- "cArrowLeft": ".c-news_pager-arrow--left",
- "cArrowRight" : ".c-news_pager-arrow--right",
- "cPageMonth": ".c-news__page_month",
- "cPageYear": ".c-news__page_year",
- "lMainContentsUl": ".l-maincontents--news ul",
- "pDate": ".p-news__page_date",
- "lSubContents": ".l-sub-contents--news"};
- case "media":
- return {"pArrow": ".p-schedule__pager-arrow",
- "cArrowLeft": ".c-schedule_pager-arrow--left",
- "cArrowRight" : ".c-schedule_pager-arrow--right",
- "cPageMonth": ".c-schedule__page_month",
- "cPageYear": ".c-schedule__page_year",
- "lMainContentsUl": ".l-maincontents--schedule ul",
- "pDate": ".p-schedule__page_date",
- "lSubContents": ".l-sub-contents--schedule"};
- default:
- throw new Error(PAGE_TYPE_ERROR_MSG);
- }
- })(pageType);
-
- const pageYear = ((y) => {return (y === null || y === undefined) ? null : y.innerText;})(document.querySelector(SELECTORS['cPageYear']));
-
- (() => {
-
- if (isDetail) {
- return;
- }
-
- darkMode();
- menuBarSetting();
-
- if (pageYear !== "年") {
-
- //console.log("日向坂46 cal");
-
- const daysOfWeek = ['Su', 'M', 'Tu', 'W', 'Th', 'F', 'Sa'];
- const now = new Date();
- const year = now.getFullYear();
- const month = now.getMonth() + 1;
- // 月初
- const first = new Date(year, month - 1, 1);
- // 月末
- const end = new Date(year, month, 0);
- // 月末の日
- const endDate = end.getDate();
- // 前月末
- const endPrevMonth = new Date(year, month - 1, 0);
- // 前月末の日
- const endDatePrevMonth = endPrevMonth.getDate();
- // 月初の曜日
- const firstDayOfWeek = first.getDay();
-
- let numOfDay = 1;
- let calendarHtml = '';
-
- const pageMonth = ((m) => {return m !== null ? m.innerText : "";})(document.querySelector(SELECTORS['cPageMonth']));
-
- const leftArrowHref = document.querySelector(SELECTORS['cArrowLeft']).children[0].href;
- const rightArrowHref = document.querySelector(SELECTORS['cArrowRight']).children[0].href;
-
- calendarHtml += '<table class="cale_table" style="width: 210px; margin: -130px 0 20px -50px;">';
- calendarHtml += `<tr><td></td><td class="cale_prev"><a id="cale_prev" href="${leftArrowHref}"><</a></td>
- <td class="cale_month" colspan="3">${pageYear} ${pageMonth}</td><td class="cale_next"><a href="${rightArrowHref}">></a></td><td></td></tr>`;
-
- calendarHtml += '<tr>';
-
- for (let i = 0; i < daysOfWeek.length; i++) {
- calendarHtml += '<td class="cale_wek' + i + '">' + daysOfWeek[i] + '</td>';
- }
-
- calendarHtml += '</tr>';
-
- for (let w = 0; w < 6; w++) {
- calendarHtml += '<tr>'
-
- for (let d = 0; d < 7; d++) {
- if (w == 0 && d < firstDayOfWeek) {
- // 前月
- let num = endDatePrevMonth - firstDayOfWeek + d + 1;
- calendarHtml += '<td class="cale_day' + d + ' is-disabled">' + num + '</td>';
- } else if (numOfDay > endDate) {
- // 次月
- let num = numOfDay - endDate;
- calendarHtml += '<td class="cale_day' + d + ' is-disabled">' + num + '</td>';
- numOfDay++;
- w = 99; // カレンダーの最下端が次月の日付のみになるのを防止
- } else {
- calendarHtml += '<td class="cale_day' + d + '">' + numOfDay + '</td>';
- numOfDay++;
- }
- }
- calendarHtml += '</tr>'
- }
-
- calendarHtml += '</table>';
-
- document.querySelector(SELECTORS["lSubContents"]).insertAdjacentHTML('afterbegin', calendarHtml);
- }
- })();
-
- (() => {
- //console.log("日向坂46 NEWS / スケジュール");
-
- // 選択カテゴリ(ALL / 握手会・・・)
- const categorySelectorSuffix
- = ((c) => {
- let value = "";
- if (c.length == 0) {
- value = "all";
- } else {
- const tempValue = c[0].value;
-
- switch (tempValue) {
- case "birthday":
- value = "birth";
- break;
-
- case "fanclub":
- value = "fanclubonly";
- break;
-
- default:
- value = tempValue;
- }
- }
-
- return value;
- })(document.getElementsByName("cd"));
-
- const categoryElem = document.querySelector('.c-button-category.category_' + categorySelectorSuffix);
- const categoryStyles = window.getComputedStyle(categoryElem);
- const categoryParent = categoryElem.parentElement;
- categoryParent.style.marginLeft = "-5px";
- categoryParent.style.paddingLeft = "4.5px";
- categoryParent.style.marginRight = "40px";
- categoryElem.style.color = `rgb(from ${categoryStyles.color} calc(r - 64) calc(g - 64) calc(b - 64))`;
- categoryParent.style.backgroundColor = `rgb(from ${categoryStyles.color} calc(r + 64) calc(g + 64) calc(b + 64))`;
- categoryParent.style.border = `solid 0.5px ${categoryElem.style.color}`;
-
- const now = new Date();
- const nowYearMonth = String(now.getFullYear()) + String(now.getMonth() + 1).padStart( 2, '0');
-
- // 詳細ページの場合 処理を終了
- if (isDetail) {
- return;
- }
-
- /*
- * フルブラウザ上ではNEWS/スケジュールが多い月は見づらいため
- * 自動スクロール、表示色を追加設定
- */
-
- const HOVER_CL = "#ddffff";
- const HOVER_BG_CL_UPPER = "#20cccc";
- const HOVER_BG_CL_LOWER = "#202040";
- const PAST_BG_CL = "#303040";
- const TODAY_DATE_CL = "orange";
- const TODAY_BG_CL_UPPER = "#30aaaa";
- const TODAY_BG_CL_LOWER = "#303050";
- const TODAY_BORDER_CL_UPPER = "#5bbee5";
- const TODAY_BORDER_CL_LOWER = "#d7eeff";
- const PAGER_MARGIN_TOP = 20;
-
- const styleElem = document.createElement("style");
- styleElem.setAttribute("rel", "stylesheet");
-
- let styleText = `
- .is-disabled {
- color: silver;
- }
- .p-page-head {
- padding-top: 20px;
- }
- .l-container {
- color: ${DEFAULT_CL};
- background-color: #202050;
- }
- .c-pager__item a svg {
- fill: #7ab6db;
- }
- .module-modal.js-member-filter .mordal-box .member-box ul li p.check input[type=checkbox]:checked+label:before {
- background-color:#6bcaea;
- border:1px solid #6bcaea;
- }`;
-
- switch (pageType) {
- case "news":
- styleText += `
- .p-news__list {background-color: ${DEFAULT_BG_CL};}
- .p-news__item:hover {
- background: linear-gradient(${HOVER_BG_CL_UPPER}, 20%, ${HOVER_BG_CL_LOWER});
- outline: 1px solid ${TODAY_BORDER_CL_UPPER}; outline-offset: ipx;
- }
- .p-news__item:hover .c-news__date, .p-news__item:hover .c-news__text, .p-news__item:hover .c-news__time--list {
- color: ${HOVER_CL};
- }`;
- break;
- case "media":
- styleText += `
- .p-schedule__item:hover {
- background: linear-gradient(${HOVER_BG_CL_UPPER}, 20%, ${HOVER_BG_CL_LOWER});
- outline: 1px solid ${TODAY_BORDER_CL_UPPER}; outline-offset: ipx;
- }
- .p-schedule__item:hover .c-schedule__text, .p-schedule__item:hover .c-schedule__time--list {
- color: ${HOVER_CL};
- }
- .schedule__list-pastday {background-color: ${PAST_BG_CL};}
- .schedule__date-today {color: ${TODAY_DATE_CL};}
- .schedule__list-today {background: linear-gradient(${TODAY_BG_CL_UPPER}, 10%, ${TODAY_BG_CL_LOWER}); border: 2px solid;
- border-image: linear-gradient(to bottom, ${TODAY_BORDER_CL_UPPER}, ${TODAY_BORDER_CL_LOWER}) 1;}
- .schedule__list-future {background-color: ${DEFAULT_BG_CL};}
- `;
- break;
- default:
- throw new Error(PAGE_TYPE_ERROR_MSG);
- }
-
- styleElem.textContent = styleText;
-
- document.head.appendChild(styleElem);
-
- // リスト上方 "xxxx年 yy月" 行
- const pDate = document.querySelector(SELECTORS["pDate"]);
-
- // "xxxx年" ではなく "年"のみの場合
- if (pageYear === "年") {
- const cPageYear = document.querySelector(SELECTORS["cPageYear"]);
- cPageYear.innerText = String(now.getFullYear()) + "年";
- cPageYear.style.fontSize = "4.8rem";
- document.querySelector(SELECTORS["cPageMonth"]).remove();
- document.querySelector(SELECTORS["pArrow"]).remove();
- }
-
- pDate.style.marginBottom = "5px";
-
- // ニュース/スケジュール リスト
- const lMainContentsUl = document.querySelector(SELECTORS["lMainContentsUl"]);
-
- const lMainContentsUlTop = lMainContentsUl.getBoundingClientRect().top;
-
- const pDateHeight = pDate.offsetHeight;
-
- // リスト下方 前月/次月ページャ
- const pPager = document.querySelector(".p-pager");
-
- // "xxxx年" ではなく "年"のみの場合
- if (pageYear === "年") {
- pPager.innerText = "";
-
- pPager.style.marginTop = "0px";
- } else {
-
- pPager.style.marginTop = `${PAGER_MARGIN_TOP}px`;
- }
-
- const pPagerHeight = PAGER_MARGIN_TOP + pPager.offsetHeight;
- const lMainContentsUlHeight = document.documentElement.clientHeight - pDateHeight - pPagerHeight;
-
- // スクロール表示
- lMainContentsUl.setAttribute("style", `height:${lMainContentsUlHeight}px; overflow: scroll; border: solid 1px #32a1ce;`);
-
- const scrollTop = lMainContentsUlTop - pDateHeight;
-
- // スクロール位置リセット 〜「再読み込み」ボタン押下時の位置ズレ対応
- scrollTo(0, 0);
-
- // リスト位置までページ内で縦スクロール
- scrollTo({
- top: scrollTop,
- behavior: "smooth"
- });
-
- const dispYear = document.querySelector(SELECTORS['cPageYear']);
- const dispMonth = document.querySelector(SELECTORS['cPageMonth']);
-
- // 表示対象の年月(ex.202404)を取得。設定がなければ当月
- const dispYearMonth
- = ((y, m) => {return (y == null || m == null) ? nowYearMonth : y.innerText.replace('年', '') + m.innerText.replace('月', '')})(dispYear, dispMonth);
-
- // NEWS/スケジュールが当月以前の月の場合
- if (dispYearMonth < nowYearMonth) {
-
- lMainContentsUl.style.background = `${PAST_BG_CL}`;
- }
-
- const DELTA = 2;
- const createAnchor
- = (y, d) => `<a href="javascript:document.querySelector('${SELECTORS['lMainContentsUl']}').scroll({top:${y}, behavior: 'smooth'});">${d}</a>`;
-
- switch(pageType) {
-
- case "news":
-
- const newsList = Array.prototype.map.call(document.getElementsByClassName("c-news__date"),
- (x) => [parseInt(x.innerText.match(new RegExp(/\d{4}\.\d{2}\.(\d{2})/))[1]), x.getBoundingClientRect().top] );
-
- const dayMap = new Map();
-
- Array.prototype.forEach.call(newsList, (x) => {
-
- if (! dayMap.has(x[0]) || x[1] < dayMap.get(x[0])) {
- // Map(day, top)
- dayMap.set(x[0], x[1]);
- }
- });
-
- Map.prototype.forEach.call(dayMap, (top, day) => {
-
- Array.prototype.some.call(document.querySelectorAll("table.cale_table tbody tr td"), (td) => {
-
- if (!td.classList.contains("is-disabled") && day === parseInt(td.innerText)) {
-
- td.innerHTML = createAnchor((top - lMainContentsUlTop - DELTA), day);
-
- return true;
- }
- });
- });
-
- break;
-
- case "media":
-
- const today = now.getDate();
-
- lMainContentsUl.scroll(0, 0);
-
- let isScrolled = false;
-
- Array.prototype.forEach.call(document.getElementsByClassName("c-schedule__date--list"), (dayElem) => {
-
- // 日付(innerText)の文字列 '(日付)\n(曜日)' から日付を抽出
- let day = ((x) => {return parseInt(x.substr(0, x.indexOf(`\n`)));})(dayElem.innerText);
-
- Array.prototype.some.call(document.querySelectorAll("table.cale_table tbody tr td"), (td) => {
-
- if ( !td.classList.contains("is-disabled") && day === parseInt(td.innerText)) {
-
- td.innerHTML = createAnchor((dayElem.getBoundingClientRect().top - lMainContentsUlTop - DELTA), day);
-
- return true;
- }
- });
-
- // 表示スケジュールが当月の場合
- if (dispYearMonth === nowYearMonth) {
- // 過去日
- if (day < today) {
-
- dayElem.parentElement.classList.add("schedule__list-pastday");
-
- // 「今日」(ページを表示した日付)
- } else if (day === today) {
-
- dayElem.classList.add("schedule__date-today");
- dayElem.parentElement.classList.add("schedule__list-today");
- }
-
- if (day >= today) {
-
- dayElem.parentElement.classList.add("schedule__list-future");
-
- if (!isScrolled) {
- // 「今日」以降(「今日」を含めて)で最早のスケジュール日要素にスクロール
- lMainContentsUl.scroll({
-
- top: dayElem.getBoundingClientRect().top - lMainContentsUlTop - DELTA,
- behavior: "smooth"
- });
-
- isScrolled = true;
- }
- }
- }
- });
-
- break;
-
- default:
- throw new Error(PAGE_TYPE_ERROR_MSG);
- }
- })();
- }, SCRIPT_NAME);