Advertisement
Not a member of Pastebin yet?
Sign Up,
it unlocks many cool features!
- // ==UserScript==
- // @name Chapter counter for Map and Next Chapter choice
- // @version 3.0.0
- // @description Counts and displays how many chapters each branch has inside on the map screen and when choosing your next chapter
- // @author sllypper
- // @namespace https://greasyfork.org/en/users/55535-sllypper
- // @match *://chyoa.com/story/*
- // @match *://chyoa.com/chapter/*
- // @icon https://chyoa.com/favicon.png
- // @grant GM.getValue
- // @grant GM.setValue
- // @grant GM.deleteValue
- // @grant GM.listValues
- // @grant GM.registerMenuCommand
- // ==/UserScript==
- /* Load the entire map by moving to the bottom, then click the Regenerate button. */
- // runs automatically when opening a new map
- let runAutomatically = true
- // shows the floating buttons on the bottom-right of the page
- let showFloatingButton = true
- let showTogglerButton = true
- // Style for the counter on the chapter pages. Use one of the below between ""
- // alternative | simple | crazy | default
- const cssStyle = "alternative"
- /************************/
- let chapterDataArray;
- let chapterData;
- let storyStorageId;
- let pageType = getPageType()
- console.log('The current page is a ' + pageType);
- /************************/
- (async() => {
- if (pageType == "map") {
- GM.registerMenuCommand("Regenerate map data", generateDraw, "r");
- GM.registerMenuCommand("Redraw map counters", drawChildrenCounter, "d");
- GM.registerMenuCommand("Fold read chapters", foldTopmostReadChapters, "f");
- GM.registerMenuCommand("Fold unread chapters", foldTopmostUnreadChapters, "u");
- await loadMapData()
- if (showFloatingButton) { document.body.appendChild(btnLoad()) }
- addStyleHead(".title-wrapper > .children { padding-right: 8px; }")
- if (showTogglerButton) { collapsibator() }
- }
- // /chapter/* and /story/* pages
- if (pageType == "chapter") {
- await showChapterCountOnChapterChoices()
- showChapterDate()
- // previous chapters map tree on clicking the link
- await prevMapInit()
- }
- GM.registerMenuCommand("Delete this from cache", deleteThisFromCache, "c");
- GM.registerMenuCommand("Delete entire cache", deleteEntireCache, "a");
- })();
- return
- /************************/
- async function loadMapData() {
- if (!await attemptLoadChapterArrayFromCache() && runAutomatically) {
- // no map data on cache
- generateMap()
- drawChildrenCounter()
- } else {
- // got map data from cache
- drawChildrenCounter()
- }
- }
- function generateDraw() {
- generateMap()
- drawChildrenCounter()
- }
- function createChildrenElement(chapterCount) {
- var child = document.createElement('span')
- child.setAttribute('class', 'control-item children')
- let icon = document.createElement('i')
- icon.setAttribute('class', 'btb bt-folder')
- child.appendChild(icon);
- let count = document.createTextNode(" "+chapterCount)
- child.appendChild(count)
- return child
- }
- function addStyleHead(css) {
- var style = document.createElement('style');
- document.head.appendChild(style);
- style.textContent = css;
- };
- async function attemptLoadChapterArrayFromCache() {
- if (!storyStorageId) loadStoryPathName()
- if (!await storyIsInTheCache(storyStorageId)) {
- console.log('story not found in cache', GM.listValues(), storyStorageId);
- return false
- }
- var value = await GM.getValue(storyStorageId);
- chapterDataArray = JSON.parse(value);
- console.log("!! got map from cache");
- unsafeWindow.chapterDataArray = chapterDataArray
- console.log("Map available as a javascript array on `chapterDataArray`")
- return true
- }
- function deleteThisFromCache() {
- if (pageType == "map") {
- GM.deleteValue(getStoryStorageId())
- }
- let storyStorageId = getStoryStorageId()
- GM.deleteValue(storyStorageId)
- }
- function deleteEntireCache() {
- (GM.listValues()).forEach((value) => {
- GM.deleteValue(value)
- })
- }
- async function readOrGenerateMap() {
- if (! await attemptLoadChapterArrayFromCache()) generateMap()
- }
- function generateMap() {
- console.log("!! generating map");
- chapterDataArray = createStoryMap()
- console.log("Chapter Count = ", chapterDataArray.length);
- unsafeWindow.chapterDataArray = chapterDataArray
- console.log("Map available as a javascript array on `chapterDataArray`");
- console.log("!! assembling hierarchy tree");
- countMapChapters();
- console.log("!! done counting the children");
- // cache it
- GM.setValue(getStoryStorageId(), JSON.stringify(chapterDataArray))
- }
- /**
- * counts and assigns the children count of all elements
- */
- function countMapChapters() {
- for (const chapter of chapterDataArray) {
- // find the leaves of the tree
- if (chapter.children.length !== 0) continue;
- chapter.chapterCount = 0;
- let next = chapter.parent != null ? chapter.parent : -1;
- // rise through the branch until it can't
- while (next != -1) {
- //console.log("from", chapter.id, "to", next);
- next = countChildChaptersOf(next);
- }
- // then continue to the next chapter childless chapter
- }
- // done
- }
- /**
- * Counts and assigns the chapterCount of the node at that index
- * Aborts returning -1 if it already has been counted
- * or can't because one of its children hasn't been counted yet
- *
- * @param {number} currIndex - The index of the node
- * @returns {number} The index of the next node. -1 to abort
- */
- function countChildChaptersOf(currIndex) {
- let nextIndex = -1;
- // if (currIndex > chapterDataArray.length) console.log('currIndex > chapterDataArray.length', currIndex, chapterDataArray.length)
- const currentNode = chapterDataArray[currIndex];
- if (currentNode.chapterCount != undefined) {
- // this node was already been processed
- // abort
- return nextIndex;
- }
- // sum the counts of its children
- const chapterCountSum = sumChildrenChaptersCount(currentNode);
- if (chapterCountSum === -1) {
- // one or more children haven't been processed yet
- // abort
- return nextIndex;
- }
- // on successful sum
- currentNode.chapterCount = chapterCountSum + currentNode.children.length;
- nextIndex = currentNode.parent !== null ? currentNode.parent : -1;
- return nextIndex;
- }
- /**
- * Sums the chapterCount of all children of the attribute node
- */
- function sumChildrenChaptersCount(chapterObj) {
- return chapterObj.children.reduce((acc, curr) => {
- const currentNode = chapterDataArray[curr];
- if (currentNode.chapterCount == undefined) {
- return -1;
- }
- return acc !== -1 ? acc + currentNode.chapterCount : acc;
- }, 0);
- }
- function drawChildrenCounter() {
- let list = document.querySelectorAll(".title-wrapper");
- if (list.length !== chapterDataArray.length) {
- console.log('Outdated data. Please regenerate the map');
- if (list.length >= chapterDataArray.length) { return }
- }
- list.forEach((elem, i) => {
- let existingChildren = elem.querySelector('.children')
- if (existingChildren) {
- // redraw
- existingChildren.remove()
- }
- let child = createChildrenElement(chapterDataArray[i].chapterCount)
- let page = elem.querySelector('.page')
- elem.insertBefore(child, page)
- })
- }
- // receives html dom element
- // returns parsed element as an object
- function createChapterObj(el) {
- const pel = {};
- let tempEl = el.querySelector(".title");
- pel.title = tempEl.textContent;
- pel.url = tempEl.href;
- // sometimes the author is empty and there's no <a> inside it
- tempEl = el.querySelector(".username > a");
- pel.author = tempEl ? tempEl.textContent : "";
- // page is completely unreliable for chapters loaded afterwards. It resets on loading
- // pel.page = el.querySelector(".page").textContent;
- // Sometimes the date is empty, but there's no issue here
- // console.log(el)
- pel.date = el.querySelector(".date").textContent;
- pel.parent = null;
- pel.children = [];
- // pel.linksTo = null;
- pel.margin = parseInt(el.style["margin-left"]);
- // link chapters don't have views, likes, or comments
- // so find out if the chapter is a link chapter or not
- const viewsEl = el.querySelector(".views");
- if (viewsEl == null) {
- pel.views = null;
- pel.likes = null;
- pel.comments = null;
- pel.isLinkChapter = 1;
- return pel;
- }
- pel.views = parseInt(viewsEl.textContent.split(",").join("")) || 0;
- pel.likes = parseInt(el.querySelector(".likes").textContent) || 0;
- pel.comments = parseInt(el.querySelector(".comments").textContent) || 0;
- pel.isLinkChapter = 0;
- return pel;
- }
- // final list like [ chapterObj, (...) ]
- // where every element has its parent and children noted
- function createStoryMap() {
- // temporary list, to get the DOM element from the page
- // let list = document.getElementsByClassName("story-map-content");
- // if (list == null || !list) return;
- // list = Array.from(list[0].children);
- let chapterElementArray = Array.from(document.querySelectorAll(".story-map-chapter"))
- let prevParentI = -1;
- const finalList = [];
- chapterElementArray.forEach((el, i) => {
- // for (const i in chapterElementArray) {
- // console.log("- Processing Chapter", i);
- // const el = chapterElementArray[i];
- // parse el and add it to the final list
- const chapterObj = createChapterObj(el);
- finalList[i] = chapterObj;
- // console.log(chapterObj)
- // now we find the parent of el
- // before checking margin
- // check if it's the first element of the list
- if (i == 0) {
- prevParentI = 0;
- // continue; // when using a for loop
- return;
- }
- // check margins
- const currElMargin = chapterObj.margin
- const prevElMargin = finalList[i-1].margin
- // check if el is child of prev el
- if (prevElMargin < currElMargin) {
- // prev el is parent
- chapterObj.parent = parseInt(i - 1);
- // add this el as child of prev element
- finalList[i - 1].children.push(parseInt(i));
- // set prev parent to prev element
- prevParentI = i - 1;
- // continue; // when using a for loop
- return;
- }
- // check if el is sibling of prev el
- if (prevElMargin == currElMargin) {
- // they share the same parent
- // prevParent is parent
- chapterObj.parent = prevParentI;
- // add this el as child of prevParent
- finalList[prevParentI].children.push(i);
- // continue; // when using a for loop
- return;
- }
- // then el must be the "uncle" of prev el
- // prevElMargin > currElMargin
- // use a loop go back through the parents from the previous node
- // to find the first element with margin smaller than self
- const selfMargin = chapterObj.margin;
- for (let j = i - 1; j >= 0; j = finalList[j].parent) {
- if (finalList[j].margin < selfMargin) {
- // found the parent: j
- const actualParentI = j;
- chapterObj.parent = actualParentI;
- // add this el as child of actual parent
- // finalList[actualParentI].children.push(chapterObj.id);
- finalList[actualParentI].children.push(i);
- // set prev parent to actual parent
- prevParentI = actualParentI;
- break;
- }
- }
- // } // when using a for loop
- })
- return finalList;
- }
- // button stuff
- function createButton(text, action, styleStr) {
- let button = document.createElement('button');
- button.textContent = text;
- button.onclick = action;
- button.setAttribute('style', styleStr || '');
- return button;
- };
- function toStyleStr(obj, selector) {
- let stack = [],
- key;
- for (key in obj) {
- if (obj.hasOwnProperty(key)) {
- stack.push(key + ':' + obj[key]);
- }
- }
- if (selector) {
- return selector + '{' + stack.join(';') + '}';
- }
- return stack.join(';');
- };
- function btnLoadCss() {
- return toStyleStr({
- 'position': 'fixed',
- 'bottom': 0,
- 'right': 0,
- 'padding': '2px',
- 'margin': '0 10px 10px 0',
- 'color': '#333',
- 'background-color': 'rgb(246, 245, 244)',
- 'z-index': '9999999999'
- })
- }
- function btnLoad() {
- return createButton('Regenerate', function() {
- generateDraw()
- // this.remove();
- }, btnLoadCss());
- }
- /* Depth Toggler */
- function collapsibator() {
- const input = document.createElement('input')
- input.defaultValue = 1
- input.setAttribute('id', 'toggler-input')
- input.setAttribute('style', toStyleStr({
- // 'padding': '2px',
- 'color': '#333',
- 'width': '30px'
- // 'display': 'inline-block'
- }))
- const button = document.createElement('button')
- button.setAttribute('id', 'toggler-btn')
- button.textContent = 'Toggle'
- button.setAttribute('style', toStyleStr({
- 'padding': '2px',
- 'color': '#333',
- 'background-color': 'rgb(246, 245, 244)',
- 'display': 'inline-block',
- 'font-size': '12px',
- 'margin-left': '4px',
- }))
- button.onclick = () => {
- const level = document.getElementById('toggler-input').value
- toggleCollapsibleLevel(level)
- }
- const cont = document.createElement('div')
- cont.setAttribute('id', 'toggler-container')
- cont.setAttribute('style', toStyleStr({
- 'position': 'fixed',
- 'bottom': '50px',
- 'right': '10px',
- 'padding': '2px',
- 'z-index': '9999999999'
- }))
- cont.appendChild(input)
- cont.appendChild(button)
- document.body.appendChild(cont)
- }
- // toggle all collapsibles from depht level "level"
- function toggleCollapsibleLevel(level) {
- const chapters = Array.from(document.getElementsByClassName("story-map-chapter"));
- if (chapters == null) return;
- // if (!chapterDataArray.length) { console.error('chapterDataArray is undefined'); return; }
- if (!chapterDataArray) { console.error('chapterDataArray is undefined'); return; }
- const firstMargin = parseInt(chapters[0].style['margin-left'])
- const marginGap = parseInt(chapters[1].style['margin-left']) - firstMargin;
- for (let i = 0; i < chapterDataArray.length; i++) {
- // if (st.margin == (level*marginGap + firstMargin)) {
- if (chapterDataArray[i].margin == (level*marginGap + firstMargin)) {
- // toggle it
- const btn = chapters[i].querySelector('.btn.btn-link.collapsable.js-collapsable')
- if (btn) btn.click()
- // maybe will use this in the future for better performance???
- // wasn't able to figure it out
- // expand
- // let clazz = Array.from(chapters[i].getAttribute('class')).split(' ').filter(c=>c!="hidden")
- // chapters[i].setAttribute('class', clazz)
- // clazz = Array.from(chapters[i].querySelector(".js-collapsable > i").getAttribute('class')).split(' ').filter(c=>c!="bt-minus"&&c!="bt-plus")
- // clazz.push('bt-minus')
- // chapters[i].querySelector(".js-collapsable > i").setAttribute('class', clazz)
- // collapse
- // if (chapterDataArray[i].margin == (level*marginGap + firstMargin)) {
- // let el = chapters[i].querySelector(".js-collapsable > i")
- // let clazz = el.getAttribute('class').split(' ').filter(c=>c!="bt-minus").join(' ') + " bt-plus"
- // el.setAttribute('class', clazz)
- // if (chapterDataArray[i].margin > (level*marginGap + firstMargin)) {
- // let el = chapters[i]
- // let clazz = el.getAttribute('class') + " hidden"
- // el.setAttribute('class', clazz)
- }
- }
- // })
- }
- function getPageType() {
- let url = window.location.pathname
- // // console.log(url)
- if (url.search(/\/story\/.*\/map/) >= 0) {
- return "map"
- }
- if (url.search(/\/chapter\//) >= 0) {
- return "chapter"
- }
- if (url.search(/\/story\/.*\.[0-9]+$\/?/) >= 0) {
- // first chapter of story
- return "chapter"
- }
- }
- async function storyIsInTheCache(storyStorageId) {
- var values = await GM.listValues();
- return (values.indexOf(storyStorageId) >= 0)
- }
- // get story url
- // find it on cache
- // get chapter url
- // compare with chapters listed
- async function showChapterCountOnChapterChoices() {
- let storyStorageId = getStoryStorageId()
- // check if chapterData is undefined
- // if it is, try fetching it
- if (!chapterData) {
- //fetch story data array first
- if (!chapterDataArray) if (!await attemptLoadChapterArrayFromCache()) return false;
- // fetch story data
- chapterData = await getChapterData(storyStorageId)
- if (!chapterData) return console.error('Story found but Chapter not found. Please regenerate the map.');
- }
- let nextChapterIndexList = chapterData.children
- // get chapter choices
- let chapterChoices = Array.from(document.querySelectorAll(".question-content a"))
- // Remove "Add a new chapter" link from the list (if the story is not private)
- // its link ends with "/new"
- if (chapterChoices[chapterChoices.length-1].href.search(/\/new$/) > -1) {
- chapterChoices.pop()
- }
- // prepare Count Number css style
- if (cssStyle == "crazy") { applyCrazyCSS() } else
- if (cssStyle == "alternative") { applyAlternativeCSS() }
- chapterChoices.forEach((el, i) => {
- let mapIndex = nextChapterIndexList[i]
- if (mapIndex == undefined) { return console.log('Chapter "'+el.textContent+'" not found. Please regenerate the story map.'); }
- drawLinkChapterCount(el, chapterDataArray[mapIndex], cssStyle)
- })
- }
- async function getChapterData() {
- if (chapterData) return chapterData;
- if (!chapterDataArray) chapterDataArray = await attemptLoadChapterArrayFromCache()
- if (!chapterDataArray) return false;
- // story is on cache as chapterDataArray
- // let chapterDataArray = JSON.parse(await GM.getValue(storyStorageId))
- // getting the chapter url if we're in /story/
- let chapterUrl = window.location.href
- if (chapterUrl.search(/\/story\//) > -1) {
- let els = document.querySelectorAll('.controls-left a')
- let chapterNum = els[els.length-1].href.match(/\d+\/?$/)[0]
- chapterUrl = "https://chyoa.com/chapter/Introduction."+chapterNum;
- }
- // console.log(chapterDataArray, chapterDataArray[1].url, chapterUrl)
- return chapterDataArray.find(c=>c.url==chapterUrl)
- }
- // Show chapter date under its Title
- // assuming pageType == "chapter"
- function showChapterDate() {
- if (!chapterData) return false;
- let date = document.createElement('div')
- date.textContent = chapterData.date
- document.querySelector('.meta').append(date)
- }
- // crazy css
- function applyCrazyCSS() {
- let style = toStyleStr({
- 'display': 'flex',
- 'width': '55px',
- 'justify-content': 'space-between',
- 'align-items': 'center',
- 'margin': '0 8px 0 -55px !important',
- 'position': 'inherit !important',
- 'float': 'left',
- 'border-right': '1px solid',
- 'padding': '0 8px 0 0',
- 'font-family': 'monospace',
- 'font-size': '14px',
- 'line-height': '27px',
- }, '.question-content .chapterCount')
- addStyleHead(style)
- }
- function applyAlternativeCSS() {
- let style = toStyleStr({
- 'position': 'absolute',
- 'left': '-45px',
- 'text-align': 'right',
- 'width': '40px',
- 'padding': '11px 0',
- 'top': '0',
- }, '.question-content .chapterCount')
- + toStyleStr({
- 'position': 'relative',
- }, '.question-content a')
- addStyleHead(style)
- }
- function drawLinkChapterCount(el, chapterObj, cssStyle = 'default') {
- const chapterCount = chapterObj.chapterCount
- const isLinkChapter = chapterObj.isLinkChapter
- let span = document.createElement('SPAN')
- if (isLinkChapter) {
- let icon = document.createElement('i')
- icon.setAttribute('class', 'btb bt-external-link')
- el.insertAdjacentElement('afterbegin',icon)
- return
- }
- span.setAttribute('class', 'chapterCount')
- if (cssStyle == 'simple') {
- span.textContent = " ("+chapterCount+")"
- el.append(span)
- return
- }
- if (cssStyle == 'alternative') {
- let icon = document.createElement('i')
- icon.setAttribute('class', 'btb bt-folder')
- span.textContent = Number(chapterCount).toString()
- el.append(span)
- el.insertAdjacentElement('afterbegin', icon)
- return
- }
- // default & carzy markup
- let icon = document.createElement('i')
- icon.setAttribute('class', 'btb bt-folder')
- span.appendChild(icon);
- let count = document.createTextNode(" "+chapterCount)
- span.append(count)
- el.insertAdjacentElement('afterbegin',span)
- // skip styling if cssStyle is set to 'crazy'
- if (cssStyle != 'crazy') {
- let color = window.getComputedStyle(el).color
- span.setAttribute('style', 'position: absolute; margin: 0 0 0 -60px; color: '+color+' !important;')
- icon.setAttribute('style', 'margin: 0 2px 0 0;')
- }
- }
- function loadStoryPathName() {
- storyStorageId = getStoryStorageId()
- }
- function getStoryStorageId() {
- if (storyStorageId) return storyStorageId;
- if (pageType == "map") return window.location.pathname;
- if (pageType != "chapter") return console.error("Unrecognizable page type");
- // pageType is chapter
- let href = document.querySelectorAll('.controls-left a')
- href = href[href.length-2].href
- return href.slice(href.search(/\/story/)) + '/map';
- }
- function foldTopmostReadChapters() {
- let ignoreList = []
- const els = Array.from(document.querySelectorAll(".story-map-chapter"))
- if (chapterDataArray.length != els.length) return false;
- // iterate all chapters
- // fold all read chapters not in the ignore list
- // put its children in the ignore list
- // put every ignored chapter children in the ignored list
- // console.log(chapterDataArray)
- for (const i in chapterDataArray) {
- if (i == 0) continue
- // console.log('in for')
- // check if chapter read && i different from 0
- if (els[i].classList.length == 1) {
- // console.log('unread chapter found')
- // if (binarySearch(i, ignoreList) == -1 && i != 0) {
- if (binarySearch(i, ignoreList) == -1) {
- console.log('success at i = ', i);
- // console.log('first unread not in ignore list, fold')
- els[i].querySelector('.btn').click()
- }
- // console.log('add children to ignored list')
- ignoreList = ignoreList.concat(chapterDataArray[i].children)
- }
- }
- }
- function foldTopmostUnreadChapters() {
- let ignoreList = []
- const els = Array.from(document.querySelectorAll(".story-map-chapter"))
- if (chapterDataArray.length != els.length) return false;
- for (const i in chapterDataArray) {
- if (i == 0) continue
- if (els[i].classList.length != 1) {
- if (binarySearch(i, ignoreList) == -1) {
- console.log('success at i = ', i);
- els[i].querySelector('.btn').click()
- }
- ignoreList = ignoreList.concat(chapterDataArray[i].children)
- }
- }
- console.log('ignoreList leng',ignoreList.length);
- }
- function binarySearch(value, list) {
- return list.find(a=>a==value) ? 1 : -1;
- let first = 0; //left endpoint
- let last = list.length - 1; //right endpoint
- let position = -1;
- let found = false;
- let middle;
- if (value < 100) console.log('search', value, list)
- while (found === false && first <= last) {
- middle = Math.floor((first + last)/2);
- if (list[middle] == value) {
- found = true;
- position = middle;
- } else if (list[middle] > value) { //if in lower half
- last = middle - 1;
- } else { //in in upper half
- first = middle + 1;
- }
- }
- return position;
- }
- // TODO
- // index to remain in cache forever containing a story index with the number of chapters and other story stats
- // update index if the generated data has more chapters than what's on the index
- // detect branches (chapters where child chapters have many chapters) and note them down
- // on chapter pages, check if it belongs to any recognizable branch and print its name on the page
- // fold all topmost read chapters
- // prev chapters map
- // let prevMapContainer;
- function prevMapShow() {
- let container = document.querySelector('.prevMapContainer')
- // if (container === null) {
- // container = prevMapRender()
- // container = document.querySelector('.prevMapContainer')
- // }
- container.classList.toggle('show');
- // prevMapContainer.classList.toggle('show');
- }
- async function prevMapRender() {
- let storyStorageId = getStoryStorageId()
- // check if chapterData is undefined
- // if it is, try fetching it
- if (!chapterData) {
- //fetch story data array first
- // if (!chapterDataArray) if (!attemptLoadChapterArrayFromCache()) {
- if (!chapterDataArray) {
- if (!await attemptLoadChapterArrayFromCache()) {
- document.querySelector('.question').insertAdjacentText('Map data not found. Please regenerate the map.')
- return false;
- }
- }
- // fetch story data
- chapterData = getChapterData(storyStorageId)
- if (!chapterData) {
- document.querySelector('.question').insertAdjacentText('Unable to find Chapter in the story data. Please regenerate the mapp.')
- // return console.error('Unable to find Chapter in the story data. Please regenerate the map.');
- return false;
- }
- }
- if (document.querySelector('.prevMapContainer') === null) {
- // if (prevMapContainer === null) {
- document.querySelector('.question').insertAdjacentHTML('beforeend', '<div class="prevMapContainer"></div>')
- // prevMapContainer = document.querySelector('.prevMapContainer')
- }
- // drawThisChapter()
- drawParentTree()
- }
- function drawThisChapter() {
- let container = document.querySelector('.prevMapContainer')
- container.insertAdjacentHTML('beforend', '<div class="prevMap_chapter prevMap_currentChapter"><a href="'+chapterData.url+'">'+chapterData.title+'</a></div>')
- }
- function drawParentTree() {
- let container = document.querySelector('.prevMapContainer')
- let chapter = chapterData
- // let chapter = chapterDataArray[chapterData.parent]
- while (chapter.parent != null) {
- container.insertAdjacentHTML('afterbegin', '<div class="prevMap_chapter"><a href="'+chapter.url+'">'+chapter.title+'</a></div>')
- chapter = chapterDataArray[chapter.parent]
- }
- }
- async function prevMapInit() {
- document.querySelector('.controls-left').insertAdjacentHTML('beforeend','<br class="visible-xs-inline"> <a href="#" class="prevMap_button"><i class="btb bt-sitemap"></i>Prev Chapters</a>')
- let prevMapButton = document.querySelector('.prevMap_button')
- prevMapButton.addEventListener('click', function(e) {
- e.preventDefault();
- prevMapShow()
- });
- await prevMapRender()
- let style = toStyleStr({
- 'display': 'none',
- }, '.prevMapContainer')
- + toStyleStr({
- 'display': 'block',
- }, '.prevMapContainer.show')
- addStyleHead(style)
- }
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement