NOTICE: By continued use of this site you understand and agree to the binding Terms of Service and Privacy Policy.
// ==UserScript== // @name Sluggy Freelance - give back navigation buttons! // @namespace http://vcsajen.com/sluggynavbtns // @description Returns navigation buttons for Sluggy Freelance web comic. And calendar widget. And subchapter navigation list. // @copyright 2018, VcSaJen // @license MIT // @include http://sluggy.com/* // @include http://www.sluggy.com/* // @include http://archives.sluggy.com/* // @include https://sluggy.com/* // @include https://www.sluggy.com/* // @include https://archives.sluggy.com/* // @version 1.0 // @grant none // ==/UserScript== /*eslint-disable no-unused-vars*/ (function () { 'use strict'; var isComicPage = document.querySelector(".comic_list") !== null; if (!isComicPage) return; var domain = window.location.hostname; var chapterElem = null; var currentPage = ""; var currentChapterNumber = 0; var isFirstChapterInBook = false; var dateRegEx = /^#((\d{4})-(\d\d)-(\d\d)(?:-(\d{1,4}))?)(?:,(\w+))?$/; var urlPrev = "", urlNext = "", urlCur = ""; var fullComicDatesLoaded = false; var comicDates = new Set(); var comicSubchapterCache = {}; if (domain === "sluggy.com" || domain === "www.sluggy.com") { let comicWrapper = document.querySelector(".comic_wrapper"); comicWrapper.id = "main_comic_wrapper"; comicWrapper.insertBefore(getNavPanel(), comicWrapper.querySelector(".comic_links")); if (comicWrapper.querySelector(".comic_popup") === null) { let comicPopup = document.createElement("div"); comicPopup.className = "comic_popup"; comicPopup.style.display = "none"; comicWrapper.insertBefore(comicPopup, document.getElementById("comic_navigation")); } currentPage = comicWrapper.parentElement.dataset.comic_date; let chapterNum, chapterName, subchapterName; [].some.call(comicWrapper.parentElement.querySelector(".story_info").childNodes, function(infoNode) { if (infoNode.nodeType == Node.TEXT_NODE) { let chapterMatch = /^\s*Chapter (\d+): (.+?) - (.+?)\s*$/.exec(infoNode.nodeValue); if (chapterMatch !== null) { [, chapterNum, chapterName, subchapterName] = chapterMatch; return true;//break } } return false;//continue }); let selEl = document.getElementById('nav_sel_subchapter'); selEl.add(new Option("Comics Not Yet in Books")); selEl.add(new Option("\u00a0\u00a0Chapter "+chapterNum+": "+chapterName)); selEl.add(new Option("\u00a0\u00a0\u00a0\u00a0"+subchapterName)); selEl.selectedIndex = 2; generateCalendar(); //var chapterNum = /Chapter ([0-9]+): /.exec(comicWrapper.parentElement.querySelector(".story_info").textContent)[1]; currentChapterNumber = chapterNum; urlCur = "//archives.sluggy.com/book.php?chapter="+chapterNum; disableButtons(false); } if (domain === "archives.sluggy.com") { //alert("Archives Page!"); var dateMatch = dateRegEx.exec(window.location.hash); if (dateMatch !== null && document.getElementById(dateMatch[1]) !== null) { currentPage = dateMatch[1]; urlCur = window.location.href; chapterElem = document.getElementById('page').cloneNode(true); processPage(chapterElem); var date = new Date(dateMatch[2], dateMatch[3]-1, dateMatch[4]); //alert(date); var headerElem = document.getElementById('book-header'); if (headerElem !== null) headerElem.parentElement.removeChild(headerElem); var comicsContainerElem = document.getElementById('innerLeft'); var currentComicElem = document.getElementById(currentPage).parentElement; while (comicsContainerElem.firstChild) { comicsContainerElem.removeChild(comicsContainerElem.firstChild); } comicsContainerElem.appendChild(currentComicElem); let comicWrapper = document.querySelector(".comic_wrapper"); comicWrapper.id = "main_comic_wrapper"; comicWrapper.appendChild(getNavPanel()); var linksElem = comicWrapper.querySelector(".comic_links"); comicWrapper.removeChild(linksElem); comicWrapper.appendChild(linksElem); if (comicWrapper.querySelector(".comic_popup") === null) { let comicPopup = document.createElement("div"); comicPopup.className = "comic_popup"; comicPopup.style.display = "none"; comicWrapper.insertBefore(comicPopup, document.getElementById("comic_navigation")); } if (comicWrapper.querySelector(".comic_popup") === null) { let comicPopup = document.createElement("div"); comicPopup.className = "comic_popup"; comicPopup.style.display = "none"; comicWrapper.insertBefore(comicPopup, document.getElementById("comic_navigation")); } var chapNav = currentComicElem.querySelector(".chapter_nav.comic_spacer"); if (chapNav !== null) chapNav.parentElement.removeChild(chapNav); postprocessPage(); //Incomplete scroll while images load workaround let viewportH = Math.max(document.documentElement.clientHeight, window.innerHeight || 0); var spaceFillerElem = document.createElement("div"); spaceFillerElem.style.minHeight = (viewportH-230)+"px"; comicsContainerElem.appendChild(spaceFillerElem); //Fixing pagespeed shenanigans let realBGStyle = document.querySelector("#parallax-group + style"); realBGStyle.id = "parallax-styles"; let fakeBGStyle = document.querySelector("body > div:not([class]):not([id]) > style:only-child"); if (fakeBGStyle !== null) { fakeBGStyle.parentElement.removeChild(fakeBGStyle); document.body.appendChild(realBGStyle); } //Handling commands sent by main page redirect if (dateMatch[6]=='next' || dateMatch[6]=='prev') { jumpToStrip(dateMatch[6]); } else { comicWrapper.scrollIntoView(); let selEl = document.getElementById('nav_sel_subchapter'); selEl.selectedIndex = +selEl.dataset.subchapterIndexOffset + +comicSubchapterCache[currentPage].selIndex; generateCalendar(); if (dateMatch[6]=='loadcalendar') { loadDates(); } } updateURL(true); disableButtons(false); } } window.addEventListener('popstate', windowOnPopState); //Adding my style let myStyleElem = document.createElement("style"); myStyleElem.id = "btnnavstyle"; myStyleElem.textContent = getMyCSSText(); document.body.appendChild(myStyleElem); /** * @param {Element} elem */ function processPage(elem) { var garbages = elem.querySelectorAll("#innerLeft > :not(.comic_list)"); [].forEach.call(garbages, function(garbage) { if (garbage.parentNode) garbage.parentNode.removeChild(garbage); }); var uselessFirst = elem.querySelector("#begin"); if (uselessFirst !== null) uselessFirst.parentElement.parentElement.removeChild(uselessFirst.parentElement); urlPrev = ""; urlNext = ""; var aPrevChapterElem = elem.querySelector(".chapter_nav > .previous > a"); if (aPrevChapterElem!==null) urlPrev = aPrevChapterElem.href; var aNextChapterElem = elem.querySelector(".chapter_nav > .next > a"); if (aNextChapterElem!==null) urlNext = aNextChapterElem.href; } function postprocessPage() { var selEl = document.getElementById('nav_sel_subchapter'); while (selEl.length > 0) selEl.remove(0); //selEl.add(new Option("Subchapter name", "URL", false, false)); var bookTitle = chapterElem.querySelector("#book-header-title").textContent; var bookMatch = /^Book (\d+): (.+)$/.exec(bookTitle); var bookOpt = new Option( bookTitle, (bookMatch !== null) ? bookMatch[1] : 0, false, false); bookOpt.dataset.type = "book"; selEl.add(bookOpt); var comicElems = chapterElem.querySelectorAll("#innerLeft > .comic_list"); if (!fullComicDatesLoaded) comicDates = new Set(); comicSubchapterCache = {}; var lastSubchapterName = ""; var subchapters = []; var chapter; [].forEach.call(comicElems, function(comicElem) { //subchapters var comicSpacerElem = comicElem.querySelector(".comic_spacer"); var comicDate = comicSpacerElem.id; if (!fullComicDatesLoaded && /^((\d{4})-(\d\d)-(\d\d)?)$/.test(comicDate)) { comicDates.add(comicDate); } var storyInfoElem = comicElem.querySelector(".story_info"); var infoNodes = storyInfoElem.childNodes; [].some.call(infoNodes, function(infoNode) { if (infoNode.nodeType == Node.TEXT_NODE) { var chapterRegEx = /^\s*Chapter (\d+): (.+?) - (.+?)\s*$/; var chapterValue = infoNode.nodeValue; var chapterMatch = chapterRegEx.exec(chapterValue); if (chapterMatch !== null) { chapter = chapterMatch[1]; var chapterName = chapterMatch[2]; var subchapterName = chapterMatch[3]; if (lastSubchapterName !== subchapterName) { lastSubchapterName = subchapterName; subchapters.push({"subchName": subchapterName, "subchDate": comicDate}); } comicSubchapterCache[comicDate] = {}; comicSubchapterCache[comicDate].selIndex = subchapters.length-1; comicSubchapterCache[comicDate].name = subchapterName; /*if (comicDate === currentPage) { selEl[selEl.length-1].defaultSelected = true; selEl[selEl.length-1].selected = true; }*/ return true;//break } } return false;//continue }); }); currentChapterNumber = chapter; isFirstChapterInBook = false; var chapterLinkElems = chapterElem.querySelectorAll("#book-header-chapters > .book-header-chapter"); [].forEach.call(chapterLinkElems, function(chapterLinkElem, index) { //chapters var chapterNumString = chapterLinkElem.querySelector(".book-header-chapter-number").textContent; var chapterNumMatch = /^\s*Chapter (\d+)\s*$/.exec(chapterNumString); if (chapterNumMatch === null) return; var chapterNum = chapterNumMatch[1]; var chapterName = chapterLinkElem.querySelector(".book-header-chapter-name").textContent; var chapterOpt = new Option( "\u00a0\u00a0Chapter "+chapterNum+": "+chapterName, chapterNum, false, false); chapterOpt.dataset.type = "chapter"; selEl.add(chapterOpt); if (index === 0 && chapterNum === chapter) { isFirstChapterInBook = true; } if (chapterNum === chapter) { selEl.dataset.subchapterIndexOffset = selEl.length; subchapters.forEach(function(subchapter) { var opt = new Option("\u00a0\u00a0\u00a0\u00a0"+subchapter.subchName, subchapter.subchDate, false, false); opt.dataset.type = "subchapter"; selEl.add(opt); }); } }); } /** * @param {number} direction - 1 - next, -1 - prev * @returns {?Element} */ function getSiblingComicElem(direction) { if (chapterElem===null) return null; var elem = chapterElem.querySelector("div[id='"+currentPage+"']"); if (elem===null) return null; elem = elem.parentElement; if (elem===null) return null; if (direction == 1) return elem.nextElementSibling; if (direction == -1) return elem.previousElementSibling; if (direction == 0) return elem; return null; } /** * @param {MouseEvent} event */ function onNavBtnClick(event) { var btn = event.target; if (chapterElem===null) { window.location = urlCur+"#"+currentPage+","+((btn.id === "nav_prev") ? "prev" : "next"); //loadChapter("http://archives.sluggy.com/daily.php?date="+currentPage, (btn.id === "nav_prev") ? "prev" : "next"); return; } var elem = chapterElem.querySelector("div[id='"+currentPage+"']"); if (elem===null) return; elem = elem.parentElement; if (elem===null) return; if (btn.id === "nav_prev") { elem=elem.previousElementSibling; } else if (btn.id === "nav_next") { elem=elem.nextElementSibling; } else return; if (elem===null) { //Jump to prev/next chapter disableButtons(true); var curComicContent = document.querySelector("#main_comic_wrapper .comic_content"); if (curComicContent !== null) curComicContent.style.opacity="0.5"; if (btn.id === "nav_prev") { loadChapter(urlPrev, "last"); } else { loadChapter(urlNext, "first"); } } else { //Normal jumpToStrip((btn.id === "nav_prev") ? "prev" : "next"); updateURL(); } } /** * @param {boolean} disable - true if disable, false if undisable */ function disableButtons(disable) { var btnNext = document.getElementById('nav_next'); var btnPrev = document.getElementById('nav_prev'); var btnFirst = document.getElementById('nav_first'); var btnLast = document.getElementById('nav_last'); var btnGo = document.getElementById('nav_goto_subchapter'); var tblCalendar = document.getElementById('nav_calendar'); if (btnNext === null || btnPrev === null) return; if (disable) { btnFirst.disabled = true; btnNext.disabled = true; btnPrev.disabled = true; btnGo.disabled = true; tblCalendar.dataset.disabled = ""; } else { if (chapterElem === null) { btnNext.disabled = true; btnPrev.disabled = false; btnGo.disabled = true; } else { btnNext.disabled = (getSiblingComicElem(1) === null) && (urlNext === ""); btnPrev.disabled = (getSiblingComicElem(-1) === null) && (urlPrev === ""); btnGo.disabled = false; } btnFirst.disabled = btnPrev.disabled; btnLast.disabled = btnNext.disabled; if (tblCalendar.dataset.disabled !== undefined) delete tblCalendar.dataset.disabled; } } function fixImgSrcs(elem) { var imgs = elem.querySelectorAll("img[data-src]"); [].forEach.call(imgs, function(img) { img.src = img.dataset.src; delete img.dataset.src; }); } /** * @param {PopStateEvent} event */ function windowOnPopState(event) { var newUrl = new URL(location.href); var newComicPage = newUrl.searchParams.get('date'); if (newComicPage === null) return; jumpToArbitraryStrip(newUrl, newComicPage, false); } /** * @param {boolean} [replace=false] - true = replace state, false = push state */ function updateURL(replace) { if (replace === undefined) replace = false; //var data = {}; //data.url = urlCur; //data.comicPage = currentPage; var result = dateRegEx.exec("#"+currentPage); if (result !== null) document.title = result[3]+"/"+result[4]+"/"+result[2]+(result[5] ? " (recap #"+result[5]+")" : "")+" - Sluggy Freelance Archives"; if (replace) { history.replaceState(/*data*/ null, null, "daily.php?date="+currentPage); } else { history.pushState(/*data*/ null, null, "daily.php?date="+currentPage); } } function jumpToArbitraryStrip(url, strip, updateUrl) { if (updateUrl === undefined) updateUrl=true; if (strip === currentPage) return; if (url==null) url="//archives.sluggy.com/daily.php?date="+strip; if (!jumpToStrip(strip)) { disableButtons(true); var el = document.querySelector("#main_comic_wrapper > .comic_content"); if (el !== null) el.style.opacity = "0.5"; loadChapter(url, strip, updateUrl); } else { if (updateUrl) updateURL(); } } /** * @param {string} strip - 'first', 'prev', 'next', 'last' (in chapter), or ID (YYYY-MM-DD) of strip * @returns {boolean} success */ function jumpToStrip(strip) { if (chapterElem === null) return false; var container = chapterElem.querySelector("#innerLeft"); var stripElem = null; var currentStrip = container.querySelector("div[id='"+currentPage+"']");//only for next and prev!!! switch (strip) { case 'first': stripElem = container.querySelector(".comic_list"); break; case 'last': stripElem = container.querySelector(".comic_list:last-of-type"); break; case 'next': if (currentStrip !== null) stripElem = currentStrip.parentElement.nextElementSibling; break; case 'prev': if (currentStrip !== null) stripElem = currentStrip.parentElement.previousElementSibling; break; default: if (dateRegEx.test("#"+strip)) { stripElem = container.querySelector("div[id='"+strip+"']"); if (stripElem !== null) stripElem = stripElem.parentElement; } } if (stripElem === null) { console.log("FAIL stripElem is null"); return false; } var newComicWrapper = stripElem.querySelector(".comic_wrapper"); var realComicWrapper = document.getElementById('main_comic_wrapper'); if (newComicWrapper === null || realComicWrapper === null) return false; newComicWrapper = newComicWrapper.cloneNode(true); realComicWrapper.style.backgroundColor = newComicWrapper.style.backgroundColor; var newDate = stripElem.querySelector(".comic_spacer").id; var newComicContent = newComicWrapper.querySelector(".comic_content"); fixImgSrcs(newComicContent); realComicWrapper.replaceChild(newComicContent, realComicWrapper.querySelector(".comic_content")); var newComicPopup = newComicWrapper.querySelector(".comic_popup"); if (newComicPopup !== null) { realComicWrapper.replaceChild(newComicWrapper.querySelector(".comic_popup"), realComicWrapper.querySelector(".comic_popup")); } else { realComicWrapper.querySelector(".comic_popup").style.display = "none"; } realComicWrapper.replaceChild(newComicWrapper.querySelector(".comic_links"), realComicWrapper.querySelector(".comic_links")); var newStoryInfo = stripElem.querySelector(".story_info").cloneNode(true); var realStoryInfo = realComicWrapper.parentElement.querySelector(".story_info"); realComicWrapper.parentElement.replaceChild(newStoryInfo, realStoryInfo); currentPage = newDate; disableButtons(false); var selElem = document.getElementById('nav_sel_subchapter'); if (comicSubchapterCache[newDate]) selElem.selectedIndex = +selElem.dataset.subchapterIndexOffset + +comicSubchapterCache[newDate].selIndex; generateCalendar(); realComicWrapper.scrollIntoView(); return true; } /** * @param {string} url - chapter url in archive * @param {string} jumpToStrip - 'first', 'prev', 'next', 'last' (in chapter) * @param {boolean} [updateUrl=true] */ function loadChapter(url, strip, updateUrl) { if (updateUrl === undefined) updateUrl=true; var xhr = new XMLHttpRequest(); xhr.onload = function() { chapterElem = xhr.response.getElementById('page'); processPage(chapterElem); postprocessPage(); urlCur = url; updateChapterBackground(); jumpToStrip(strip); generateCalendar(true); if (updateUrl) updateURL(); //console.log(this.responseXML.title); }; xhr.onerror = function(e) { console.log("Error: "+e.target.status); }; xhr.open("GET", url); xhr.responseType = "document"; xhr.send(); } function updateChapterBackground() { var newParallaxGroup = chapterElem.querySelector("#parallax-group"); var newBGStyle = chapterElem.querySelector("#parallax-group + style"); var realParallaxGroup = document.querySelector("#parallax-group"); var realBGStyle = document.querySelector("#parallax-styles"); if (newParallaxGroup === null || newBGStyle === null || realParallaxGroup === null || realBGStyle === null) return; newParallaxGroup = newParallaxGroup.cloneNode(true); newBGStyle = newBGStyle.cloneNode(true); newBGStyle.id = "parallax-styles"; realParallaxGroup.parentElement.replaceChild(newParallaxGroup, realParallaxGroup); realBGStyle.parentElement.replaceChild(newBGStyle, realBGStyle); } function loadDates() { var url = "http://archives.sluggy.com/calendar.php"; var xhr = new XMLHttpRequest(); xhr.onload = function() { var scriptText = xhr.response.getElementById('innerLeft').querySelector("#calendar + script").textContent; var startMarker = "var dates_available=['"; var endMarker = "',];var monthsWide"; var startIndex = scriptText.indexOf(startMarker)+startMarker.length; var endIndex = scriptText.lastIndexOf(endMarker); scriptText = scriptText.substring(startIndex, endIndex); let dateArr = scriptText.split("','"); comicDates = new Set(); let len = dateArr.length; for(let i = 0; i<len; i++) { comicDates.add(dateArr[i]); } fullComicDatesLoaded = true; document.getElementById('nav_calendar_overlay').remove(); generateCalendar(true); }; xhr.onerror = function(e) { console.log("Error while loading calendar page: "+e.target.status); }; xhr.open("GET", url); xhr.responseType = "document"; xhr.send(); } /** * @param {MouseEvent} event */ function onTblCalendarMonthNavClick(event) { var tblCalendar = document.getElementById('nav_calendar'); if (event.target.classList.contains('nav_prev_month') === event.target.classList.contains('nav_next_month')) return; event.preventDefault(); event.stopPropagation(); var offset = event.target.classList.contains('nav_prev_month') ? -1 : 1; var year, month; [year, month] = tblCalendar.dataset.month.split('-').map(Number); month-=1; var date = new Date(Date.UTC(year, month+offset)); generateCalendar(false, date.getUTCFullYear(), date.getUTCMonth()); } /** * @param {MouseEvent} event */ function onTblCalendarCellClick(event) { var tblCalendar = document.getElementById('nav_calendar'); if (tblCalendar.dataset.disabled !== undefined) return; var cell = event.target; if (cell.classList.contains("nav_calendar_clickable")) { var strip = cell.dataset.date; jumpToArbitraryStrip("http://archives.sluggy.com/daily.php?date="+strip, strip); } } /** * Updates calendar to reflect month * When year and month parameters are not present, month for current comic is used. * @param [boolean] force - force full update * @param [number] year - year, for example, 2013 * @param [number] month - month, 0 for January, 11 for December */ function generateCalendar(force, year, month) { if (force === undefined) force = false; if (month === undefined && year === undefined) { [year, month] = currentPage.split("-").map(Number); month -= 1; } if (month === undefined) month = 0; var tblCalendar = document.getElementById('nav_calendar'); var monthStart = new Date(Date.UTC(year, month)); if (!force && tblCalendar.dataset.month === monthStart.toISOString().substring(0, 7)) { tblCalendar.querySelectorAll(".nav_calendar_current_date").forEach(function (curDateElem) { curDateElem.classList.remove("nav_calendar_current_date"); }); let elem = tblCalendar.querySelector('[data-date="'+currentPage+'"]'); if (elem!==null) elem.classList.add("nav_calendar_current_date"); return; } tblCalendar.dataset.month = monthStart.toISOString().substring(0, 7); var curMonthElem = tblCalendar.querySelector(".nav_cur_month"); var prevMonthElem = tblCalendar.querySelector(".nav_prev_month"); var nextMonthElem = tblCalendar.querySelector(".nav_next_month"); var locale = "en-us"; curMonthElem.textContent = monthStart.toLocaleString(locale, {timeZone: "UTC", year: "numeric", month: "short"}); prevMonthElem.textContent = "["+(new Date(Date.UTC(year, month-1))).toLocaleString(locale, {timeZone: "UTC", month: "short"})+"]"; nextMonthElem.textContent = "["+(new Date(Date.UTC(year, month+1))).toLocaleString(locale, {timeZone: "UTC", month: "short"})+"]"; var dateOffset = -monthStart.getUTCDay(); var rows = tblCalendar.tBodies[0].rows; for (let i=0; i<6; i++) { let cells = rows[i+1].cells; //i+1 because first row with th's is skipped let curMonthDaysNum = 0;//in current week for (let j=0; j<7; j++) { let cell = cells[j]; let date = new Date(Date.UTC(year, month, dateOffset+i*7+j+1)); let stringDate = date.toISOString().split("T")[0]; cell.textContent = date.getUTCDate(); cell.classList.toggle("nav_calendar_curmonth_date", date.getUTCMonth() === month); cell.classList.toggle("nav_calendar_current_date", stringDate === currentPage); cell.dataset.date = stringDate; cell.classList.toggle("nav_calendar_clickable", comicDates.has(stringDate)); if (date.getUTCMonth() === month) curMonthDaysNum++; } rows[i+1].style.display = (curMonthDaysNum===0) ? "none" : null; } //enable/disable overlay if (!fullComicDatesLoaded && chapterElem !== null) { let y,m,d; [y,m,d] = chapterElem.querySelector(".comic_list:first-child").querySelector(".comic_spacer").id.split("-").map(Number); var chapterStartDate = new Date(y,m-1,d); [y,m,d] = chapterElem.querySelector(".comic_list:last-child").querySelector(".comic_spacer").id.split("-").map(Number); var chapterEndDate = new Date(y,m-1,d); var calendarStartDate = new Date(Date.UTC(year, month, dateOffset)); var monthEnd = new Date(Date.UTC(year, month+1)); monthEnd = new Date(Date.UTC(monthEnd.getUTCFullYear(), monthEnd.getUTCMonth(), monthEnd.getUTCDate()-1)); var endOffset = 6-monthEnd.getUTCDay(); var calendarEndDate = new Date(Date.UTC(monthEnd.getUTCFullYear(), monthEnd.getUTCMonth(), monthEnd.getUTCDate()+endOffset)); var overlayElem = document.getElementById('nav_calendar_overlay'); if (chapterStartDate>calendarStartDate || chapterEndDate<monthEnd) { overlayElem.style.display = null; } else { overlayElem.style.display = "none"; } } } /** * @returns {Element} */ function getNavPanel() { var navPanel = document.createElement("nav"); navPanel.id = 'comic_navigation'; var btnFirst = document.createElement("button"); btnFirst.id = 'nav_first'; btnFirst.classList.add("comic_nav_btn"); btnFirst.textContent = "First"; btnFirst.addEventListener('click', function(event) { if (chapterElem == null) { window.location = "//archives.sluggy.com/daily.php?date=1997-08-25"; } else { jumpToArbitraryStrip("http://archives.sluggy.com/book.php?chapter=1", "1997-08-25"); } }); var btnPrev = document.createElement("button"); btnPrev.id = 'nav_prev'; btnPrev.classList.add("comic_nav_btn"); btnPrev.textContent = "Prev."; btnPrev.addEventListener('click', onNavBtnClick); var btnNext = document.createElement("button"); btnNext.id = 'nav_next'; btnNext.classList.add("comic_nav_btn"); btnNext.textContent = "Next"; btnNext.addEventListener('click', onNavBtnClick); var btnLast = document.createElement("button"); btnLast.id = 'nav_last'; btnLast.classList.add("comic_nav_btn"); btnLast.textContent = "Last"; btnLast.addEventListener('click', function(event) { window.location = "//sluggy.com/"; }); var btnChapter = document.createElement("button"); btnChapter.id = 'nav_chapter'; btnChapter.classList.add("comic_nav_btn"); btnChapter.textContent = "Chapter"; btnChapter.title = "View comic chapter by chapter"; btnChapter.addEventListener('click', function(event) { window.location = urlCur.replace(/#.+$/, ""); }); var cbSubchapterNav = document.createElement("select"); cbSubchapterNav.id = 'nav_sel_subchapter'; /*cbSubchapterNav.add(new Option("First option")); cbSubchapterNav.add(new Option("Second option")); cbSubchapterNav.add(new Option("Third option"));*/ var btnGoToSubchapter = document.createElement("button"); btnGoToSubchapter.id = 'nav_goto_subchapter'; btnGoToSubchapter.classList.add("comic_nav_btn"); btnGoToSubchapter.textContent = "Go"; if (chapterElem == null) { btnGoToSubchapter.disabled = true; } btnGoToSubchapter.addEventListener('click', function(event) { if (cbSubchapterNav.selectedIndex >= 0) { var el = document.querySelector("#main_comic_wrapper > .comic_content"); var opt = cbSubchapterNav[cbSubchapterNav.selectedIndex]; switch (opt.dataset.type) { case ("subchapter"): jumpToStrip(opt.value); updateURL(); break; case ("chapter"): if (currentChapterNumber !== opt.value) { disableButtons(true); if (el !== null) el.style.opacity = "0.5"; loadChapter("http://archives.sluggy.com/book.php?chapter="+opt.value, "first"); } else { jumpToStrip("first"); updateURL(); } break; case ("book"): if (isFirstChapterInBook) { jumpToStrip("first"); updateURL(); } else { disableButtons(true); if (el !== null) el.style.opacity = "0.5"; loadChapter("http://archives.sluggy.com/book.php?book="+opt.value, "first"); } break; } } }); var tblCalendarWrapper = document.createElement("div"); tblCalendarWrapper.classList.add("nav_calendar_wrapper"); var tblCalendar = document.createElement("table"); tblCalendar.id = 'nav_calendar'; var tHead = tblCalendar.createTHead(); let tHeadRow = tHead.insertRow(); let tHeadCell = document.createElement("th"); tHeadCell.colSpan = 7; tHeadRow.appendChild(tHeadCell); let prevMonth = document.createElement("span"); prevMonth.textContent = "[prev]"; //TODO: Убрать prevMonth.classList.add("nav_prev_month"); prevMonth.classList.add("nav_calendar_clickable"); prevMonth.addEventListener('click', onTblCalendarMonthNavClick, true); let curMonth = document.createElement("span"); curMonth.textContent = "[cur]"; //TODO: Убрать curMonth.classList.add("nav_cur_month"); let nextMonth = document.createElement("span"); nextMonth.textContent = "[next]"; //TODO: Убрать nextMonth.classList.add("nav_next_month"); nextMonth.classList.add("nav_calendar_clickable"); nextMonth.addEventListener('click', onTblCalendarMonthNavClick, true); tHeadCell.appendChild(prevMonth); tHeadCell.appendChild(curMonth); tHeadCell.appendChild(nextMonth); var tBody = tblCalendar.appendChild(document.createElement("tbody")); let wdays = ["Su", "M", "Tu", "W", "Th", "F", "Sa"]; for (let i=0;i<7;i++) { let row = tBody.insertRow(); for (let j=0;j<7;j++) { let span = document.createElement("span"); let cell; if (i===0) { cell = document.createElement("th"); span.textContent = wdays[j]; cell.appendChild(span); row.appendChild(cell); } else { cell = row.insertCell(); span.textContent = "0"; //TODO: Убрать cell.appendChild(span); cell.addEventListener('click', onTblCalendarCellClick); } } } var tblCalendarOverlay = document.createElement("div"); tblCalendarOverlay.id = "nav_calendar_overlay"; tblCalendarOverlay.classList.add("nav_calendar_overlay"); tblCalendarOverlay.textContent = "Click to load"; tblCalendarOverlay.addEventListener('click', function (event) { if (chapterElem === null) { window.location = urlCur+"#"+currentPage+",loadcalendar"; return; } if (event.target.dataset.disabled===undefined) { event.target.dataset.disabled=""; event.target.textContent="Loading..."; loadDates(); } }); tblCalendarWrapper.appendChild(tblCalendar); tblCalendarWrapper.appendChild(tblCalendarOverlay); navPanel.appendChild(btnFirst); navPanel.appendChild(btnPrev); navPanel.appendChild(btnNext); navPanel.appendChild(btnLast); navPanel.appendChild(btnChapter); navPanel.appendChild(cbSubchapterNav); navPanel.appendChild(btnGoToSubchapter); navPanel.appendChild(tblCalendarWrapper); document.addEventListener('keydown', function(event) { switch (event.key) { case "ArrowRight": btnNext.click(); break; case "ArrowLeft": btnPrev.click(); break; } }); return navPanel; } function getMyCSSText() { return String.raw`/*My CSS*/ #comic_navigation { padding: 0 25px 0 25px; margin-top: 10px; } #comic_navigation > * { float: left; } #nav_sel_subchapter { border: 1px solid #cccccc; font-size: 10px; margin: 0px 4px 0px 0px; padding: .4em .2em; border-radius: 4px; height: 16px; box-sizing: content-box; background: #f6f6f6 url(//ajax.googleapis.com/ajax/libs/jqueryui/1.10.2/themes/ui-lightness/images/ui-bg_glass_100_f6f6f6_1x400.png) 50% 50% repeat-x; } .comic_nav_btn { height: 16px; box-sizing: content-box; border: 1px solid #cccccc; background: #f6f6f6 url(//ajax.googleapis.com/ajax/libs/jqueryui/1.10.2/themes/ui-lightness/images/ui-bg_glass_100_f6f6f6_1x400.png) 50% 50% repeat-x; font-weight: bold; color: #1c94c4; font-size: 10px; margin: 0 4px 0 0; padding: .4em 1em; border-radius: 4px; } .comic_nav_btn:hover { border: 1px solid #fbcb09; background: #fdf5ce url(http://ajax.googleapis.com/ajax/libs/jqueryui/1.10.2/themes/ui-lightness/images/ui-bg_glass_100_fdf5ce_1x400.png) 50% 50% repeat-x; color: #c77405; } .comic_nav_btn:active { filter: brightness(0.9) saturate(150%); } .comic_nav_btn:disabled:active { filter: brightness(1) saturate(1); } .comic_nav_btn:disabled { opacity: 0.35; } .comic_nav_btn:disabled:hover { opacity: 0.4; } #nav_first:before, #nav_prev:before, #nav_next:after, #nav_last:after, #nav_chapter:before { content: " "; display: inline-block; height: 16px; width: 16px; line-height: 16px; margin: 0px 0px -5px 0px; position: relative; top: -1px; left: 0px; background: url("http://ajax.googleapis.com/ajax/libs/jqueryui/1.10.2/themes/ui-lightness/images/ui-icons_ef8c08_256x240.png") no-repeat left center transparent; } #nav_first:before { background-position: -80px -160px; left: -4px; } #nav_prev:before { background-position: -48px -160px; left: -4px; } #nav_chapter:before { background-position: -224px -96px; left: -4px; } #nav_next:after { background-position: -32px -160px; left: 4px; } #nav_last:after { background-position: -64px -160px; left: 4px; } #main_comic_wrapper > .comic_popup { margin-bottom: 0px; } .nav_calendar_wrapper { position: relative; width: 175px; } #nav_calendar { font-size: 10px; background-color: #cccccc; table-layout: fixed; width: 100%; font-family: Verdana, Geneva, Arial, Helvetica, sans-serif; border-spacing: 2px; border-collapse: separate; border-radius: 4px; border: 1px solid #dddddd; background: #eeeeee url(//ajax.googleapis.com/ajax/libs/jqueryui/1.10.2/themes/ui-lightness/images/ui-bg_highlight-soft_100_eeeeee_1x100.png) 50% top repeat-x; } #nav_calendar > thead > tr > th { position: relative; z-index: 1; border: 1px solid #e78f08; background: #f6a828 url(//ajax.googleapis.com/ajax/libs/jqueryui/1.10.2/themes/ui-lightness/images/ui-bg_gloss-wave_35_f6a828_500x100.png) 50% 50% repeat-x; color: #ffffff; font-weight: bold; border-radius: 4px; } #nav_calendar th { font-weight: 800; } #nav_calendar th, #nav_calendar td { text-align: center; } .nav_prev_month { float: left; } .nav_next_month { float: right; } .nav_calendar_overlay { border-radius: 4px; position: absolute; top: 0; bottom: 0; background-color: rgba(255, 255, 255, 0.75); width: 100%; height: 100%; display: flex; flex-direction: row; justify-content: center; align-items: center; cursor: pointer; } .nav_calendar_overlay.nav_loading { cursor: default; } .nav_calendar_curmonth_date { border: 1px solid #cccccc; background: #f6f6f6 url(//ajax.googleapis.com/ajax/libs/jqueryui/1.10.2/themes/ui-lightness/images/ui-bg_glass_100_f6f6f6_1x400.png) 50% 50% repeat-x; } #nav_calendar td:not(.nav_calendar_curmonth_date):not(.nav_calendar_clickable) { color: #9b9b9b; } #nav_calendar td.nav_calendar_curmonth_date { text-align: right; } #nav_calendar .nav_calendar_curmonth_date:not(.nav_calendar_clickable) { opacity: .35; } .nav_calendar_curmonth_date.nav_calendar_current_date { background: #ffffff url(//ajax.googleapis.com/ajax/libs/jqueryui/1.10.2/themes/ui-lightness/images/ui-bg_glass_65_ffffff_1x400.png) 50% 50% repeat-x; border: 1px solid #fbd850; font-weight: bold; } .nav_calendar_clickable { color: #1c94c4; cursor: pointer; } td.nav_calendar_clickable:hover { border: 1px solid #fbcb09; background: #fdf5ce url(//ajax.googleapis.com/ajax/libs/jqueryui/1.10.2/themes/ui-lightness/images/ui-bg_glass_100_fdf5ce_1x400.png) 50% 50% repeat-x; color: #c77405; } #nav_calendar[data-disabled] td.nav_calendar_clickable { color: #9b9b9b; cursor: default; opacity: .5; } `; } })();