site-libsoc/Server/app/svelte/src/manifesto-component.svelte

409 lines
12 KiB
Svelte
Raw Normal View History

2023-06-24 04:39:41 +07:00
<svelte:options tag="manifesto-component" />
<script>
// Import statements
import { onMount } from 'svelte'
2023-06-24 20:44:16 +07:00
import { getData } from "/js/libraries/serverTools.js"
2023-06-26 19:56:49 +07:00
import { px2rem } from "/js/libraries/miscTools.js"
2023-07-04 01:12:28 +07:00
import { locales } from "/js/libraries/serverTools.js"
2023-06-24 04:39:41 +07:00
// Import components
// Main code
2023-06-24 20:44:16 +07:00
let manifesto = []
let key
2023-06-25 21:34:27 +07:00
let contentButton
let contentArrow
let contentBlock
let buttons = []
let headingsObjects = {}
let contentHeadings = []
let contentTable
2023-06-26 20:25:38 +07:00
let lastTop = 0
let margin = 0
2023-06-26 23:26:50 +07:00
let root
let main
2023-06-24 04:39:41 +07:00
2023-07-04 01:12:28 +07:00
let locale
let localeUrl = location.href.split("/").filter(x => Object.keys(locales).includes(x))
if (localeUrl.length==0) {
locale = "en"
}
else {
locale = localeUrl[0]
}
2023-06-24 20:44:16 +07:00
const htmlDelims = ["ul","ol"]
2023-07-04 01:12:28 +07:00
getData("/locales/"+ locale + "/manifesto.txt",function(response) {
2023-06-24 20:44:16 +07:00
let splitText = response.split(/\r?\n/)
2023-06-25 21:34:27 +07:00
let currentChapter
let cnt = 0
2023-06-24 20:44:16 +07:00
for (let j=0;j<splitText.length;j++) {
let line = splitText[j]
let delimInd = htmlDelims.map((x) => line.includes("<"+x+">")).findIndex((x) => x)
if (delimInd!=-1) {
let delim = htmlDelims[delimInd]
let obj = {}
obj[delim] = []
let delimEndTag = "</"+delim+">"
while (true) {
j += 1
line = splitText[j]
if (line.includes(delimEndTag)) {
manifesto.push(obj)
break
}
else {
obj[delim].push(line)
}
}
}
else {
2023-06-25 21:34:27 +07:00
if (line.slice(0,3)=="###") {
let heading = line.slice(4,line.length)
let id = heading.toLowerCase().trim().replaceAll(" ","-")
currentChapter.push({
id: id,
name: heading,
index: cnt
})
cnt += 1
manifesto.push({type: "h3", id: id, line: heading, index: cnt})
}
else if (line.slice(0,2)=="##") {
let heading = line.slice(3,line.length)
let id = heading.toLowerCase().trim().replaceAll(" ","-")
contentHeadings.push({
id: heading.toLowerCase().trim().replaceAll(" ","-"),
name: heading,
index: cnt
})
cnt += 1
currentChapter = []
contentHeadings.push(currentChapter)
manifesto.push({type: "h2", id: id, line: heading, index: cnt})
}
else {
manifesto.push(line)
}
2023-06-24 20:44:16 +07:00
}
}
key += 1
})
2023-06-24 04:39:41 +07:00
2023-06-25 21:34:27 +07:00
function hideBlock(arrow,block) {
if (block.style.display=="none" || block.style.display=="") {
block.style.display = "initial"
arrow.style.transform = "scaleY(-1)"
localStorage.setItem("manifesto-hide-content", "false");
}
else {
block.style.display = "none"
arrow.style.transform = ""
localStorage.setItem("manifesto-hide-content", "true");
}
}
function goToChapter(id) {
headingsObjects[id].scrollIntoView({block: 'start'}, true);
}
2023-06-26 19:56:49 +07:00
addEventListener("scroll", (event) => {
2023-06-26 23:26:50 +07:00
if (window.innerWidth>1080) {
2023-06-26 20:25:38 +07:00
let top = px2rem(window.scrollY)
2023-06-26 23:26:50 +07:00
let textBottom = px2rem(root.getBoundingClientRect().bottom + window.scrollY)
let tableBottom = px2rem(contentTable.getBoundingClientRect().bottom + window.scrollY)
if ((top>lastTop && top<5) || (top<lastTop && top<5)) {
margin = -Math.min(px2rem(window.scrollY),5)
}
else if (tableBottom >= (textBottom - 1.5)) {
margin = margin - (tableBottom - (textBottom - 1.5))
}
else {
if (margin>-5) {
margin = -5
2023-06-26 20:25:38 +07:00
}
2023-06-26 23:26:50 +07:00
if (top<5 && top!=0) {
2023-06-26 20:25:38 +07:00
let dif = px2rem(contentTable.offsetHeight - window.innerHeight)
margin = -Math.min(px2rem(window.scrollY),5 + dif + 2.5)
}
2023-06-26 23:26:50 +07:00
else if (top<lastTop || margin==0) {
if (margin <-5) {
2023-06-26 20:25:38 +07:00
margin = margin + (lastTop-top)
}
else {
2023-06-26 23:26:50 +07:00
margin = -5
}
}
else {
if (contentTable.offsetHeight > window.innerHeight) {
let dif = px2rem(contentTable.offsetHeight) - px2rem(window.innerHeight)
if (margin > -(dif+8)) {
margin = margin + (lastTop-top)
}
else {
margin = -(dif+8)
}
2023-06-26 20:25:38 +07:00
}
}
}
2023-06-26 23:26:50 +07:00
contentTable.style.marginTop = margin + "rem"
2023-06-26 20:25:38 +07:00
lastTop = px2rem(window.scrollY)
2023-06-26 23:26:50 +07:00
}
else {
contentTable.style.marginTop = "0rem"
}
2023-06-26 19:56:49 +07:00
})
2023-06-25 21:34:27 +07:00
onMount(() => {
let hideBool = localStorage.getItem("manifesto-hide-content")
if (hideBool!=undefined && hideBool!=null) {
if (hideBool=="true") {
hideBlock(contentArrow,contentBlock)
}
}
2023-06-24 04:39:41 +07:00
})
</script>
2023-06-26 23:26:50 +07:00
<div id="container" bind:this={root}>
2023-06-24 20:44:16 +07:00
<div id="text-container">
{#key key}
2023-06-25 21:34:27 +07:00
<div bind:this={contentTable} id="table-content">
<button id="toggle-content" bind:this={contentButton} on:click={() => hideBlock(contentArrow,contentBlock)}>
TABLE OF CONTENTS
<img bind:this={contentArrow} src="../assets/arrow_down.svg" alt="arrow down" style="transform: scaleY(-1)">
</button>
2023-06-28 21:26:07 +07:00
<div bind:this={contentBlock} class="module" style="display: initial;">
2023-06-25 21:34:27 +07:00
{#each contentHeadings as obj}
{#if Array.isArray(obj)}
{#each obj as obj2}
<div class="heading-button-wrapper">
<button bind:this={buttons[obj2.index]} on:click={() => goToChapter(obj2.id)} class="level1 heading-button">
{obj2.name}
</button>
</div>
{/each}
{:else}
<div class="heading-button-wrapper">
<button bind:this={buttons[obj.index]} on:click={() => goToChapter(obj.id)} class="level0 heading-button">
{obj.name}
</button>
</div>
{/if}
{/each}
</div>
</div>
2023-06-26 23:26:50 +07:00
<div id="main" bind:this={main}>
2023-06-26 19:56:49 +07:00
{#each manifesto as line}
{#if line!==""}
{#if typeof (line === 'object') && (Object.keys(line)[0]=="ul")}
<ul>
{#each line.ul as line2}
<li>{line2}</li>
{/each}
</ul>
{:else if typeof (line === 'object') && (Object.keys(line)[0]=="ol")}
<ol>
{#each line.ol as line2}
<li>
{@html line2}
</li>
{/each}
</ol>
{:else if typeof (line === 'object') && (line.type=="h3")}
<button on:click ={contentTable.scrollIntoView({block: 'start'}, true)} style="display: block; width: 100%;">
<h3 bind:this={headingsObjects[line.id]} id={line.id}>{@html line.line}</h3>
</button>
{:else if typeof (line === 'object') && (line.type=="h2")}
<button on:click ={contentTable.scrollIntoView({block: 'start'}, true)} style="display: block; width: 100%;">
<h2 bind:this={headingsObjects[line.id]} id={line.id}>{@html line.line}</h2>
</button>
{:else if line[0]=="#"}
<h1>{@html line.slice(2,line.length)}</h1>
{:else}
<p class="margin-end">
{@html line}
</p>
{/if}
2023-06-26 23:26:50 +07:00
{:else if false}
<b></b>
2023-06-24 20:44:16 +07:00
{/if}
2023-06-26 19:56:49 +07:00
{/each}
</div>
2023-06-24 20:44:16 +07:00
{/key}
</div>
</div>
2023-06-24 04:39:41 +07:00
<style>
@import '/css/common.css';
2023-06-26 23:26:50 +07:00
#main b {
color: #d50400;
}
2023-06-25 21:34:27 +07:00
#table-content {
2023-06-26 19:56:49 +07:00
position: fixed;
display: flex;
flex-direction: column;
2023-06-28 21:17:51 +07:00
border: #cdcdcd 0.1rem solid;
2023-06-25 21:34:27 +07:00
border-radius: 1rem;
padding: 2rem;
2023-06-28 21:26:07 +07:00
padding-top: 1rem;
2023-06-26 19:56:49 +07:00
padding-right: 0.8rem;
2023-06-25 21:34:27 +07:00
padding-bottom: 1.5rem;
margin-bottom: 2rem;
2023-06-26 19:56:49 +07:00
width: 20rem;
height: max-content;
2023-06-25 21:34:27 +07:00
}
#toggle-content {
position: relative;
width: 100%;
2023-06-28 21:17:51 +07:00
font-size: 1.2rem;
2023-06-25 21:34:27 +07:00
font-family: var(--sans-serif,sans-serif);
text-align: left;
2023-06-28 21:26:07 +07:00
padding-bottom: 1rem;
2023-06-25 21:34:27 +07:00
font-weight: bold;
2023-06-29 03:10:24 +07:00
padding-top: 0.3rem;
2023-06-25 21:34:27 +07:00
}
#toggle-content img {
position: absolute;
2023-06-29 03:10:24 +07:00
top: 0.3rem;
2023-06-26 19:56:49 +07:00
right: 0.8rem;
2023-06-25 21:34:27 +07:00
width: 1.5rem;
}
.module {
2023-06-26 19:56:49 +07:00
position: relative;
display: inline-block;
2023-06-25 21:34:27 +07:00
width: 100%;
2023-06-26 19:56:49 +07:00
height: max-content;
padding-right: 1.2rem;
2023-06-25 21:34:27 +07:00
}
.heading-button-wrapper {
position: relative;
}
.heading-button {
color: black;
height: auto;
width: 100%;
2023-06-28 21:17:51 +07:00
padding-top: 0.25rem;
padding-bottom: 0.35rem;
2023-06-25 21:34:27 +07:00
text-align: left;
font-family: var(--sans-serif,sans-serif);
2023-06-28 21:17:51 +07:00
font-size: 1.2rem;
2023-06-25 21:34:27 +07:00
}
.level0 {
position: relative;
padding-left: 0.5rem;
z-index: 1;
}
.level1 {
position: relative;
padding-left: 1.5rem;
z-index: 1;
2023-06-26 19:56:49 +07:00
margin-left: 1rem;
2023-06-26 23:34:26 +07:00
width: calc(100% - 1rem);
2023-06-28 21:17:51 +07:00
border-left: #cdcdcd 0.1rem solid;
2023-06-25 21:34:27 +07:00
}
.heading-button:hover {
background-color: hsla(344, 73%, 57%, 0.12);
}
.heading-button:active {
background-color: hsla(344, 73%, 57%, 0.5);
}
2023-06-24 20:44:16 +07:00
h1 {
margin-bottom: 1rem;
2023-06-28 21:17:51 +07:00
font-size: 2rem;
2023-06-24 20:44:16 +07:00
text-align: center;
}
h2 {
margin-bottom: 1rem;
text-align: center;
}
h3 {
margin-bottom: 1rem;
}
#text-container {
2023-06-26 19:56:49 +07:00
position: relative;
display: grid;
2023-06-28 21:17:51 +07:00
grid-template-columns: 20rem 700px 20rem;
2023-06-26 19:56:49 +07:00
grid-gap: 2rem;
2023-06-24 20:44:16 +07:00
max-width: calc(100vw - 4rem);
margin: auto;
}
#container {
2023-06-26 19:56:49 +07:00
display: flex;
align-content: center;
2023-06-24 20:44:16 +07:00
margin: auto;
2023-06-26 19:56:49 +07:00
max-width: min(1800px,100vw);
2023-06-24 20:44:16 +07:00
margin-top: 1rem;
margin-bottom: 4rem;
}
2023-06-26 19:56:49 +07:00
#main {
grid-column: 2;
}
#main>p {
2023-06-24 20:44:16 +07:00
margin-bottom: 1rem;
}
#container p {
text-align: justify;
}
2023-06-24 04:39:41 +07:00
2023-06-26 23:34:26 +07:00
@media only screen and (max-width: 1210px) {
2023-06-26 19:56:49 +07:00
#text-container {
position: relative;
display: grid;
grid-template-columns: auto;
grid-gap: 2rem;
2023-06-30 16:08:03 +07:00
max-width: calc(1800px,100vw - 4rem);
2023-06-26 19:56:49 +07:00
margin: auto;
}
2023-06-26 23:34:26 +07:00
#toggle-content img {
right: 0;
}
2023-06-26 19:56:49 +07:00
#table-content {
position: relative;
border: #a9a9a9 0.1rem solid;
border-radius: 1rem;
padding: 2rem;
padding-bottom: 1.5rem;
margin-bottom: 2rem;
height: max-content;
width: 100%;
}
2023-06-26 23:34:26 +07:00
.module {
padding-right: 0;
}
2023-06-26 19:56:49 +07:00
#main {
grid-column: 1;
}
2023-06-30 16:08:03 +07:00
#container {
max-width: min(700px,100vw);
}
2023-06-26 19:56:49 +07:00
}
2023-06-24 04:39:41 +07:00
</style>