Implemented article outline traversing

This commit is contained in:
sairaj mote 2021-12-18 19:00:52 +05:30
parent 61b43b1213
commit 61c956ef33
4 changed files with 198 additions and 35 deletions

View File

@ -529,13 +529,50 @@ menu-option {
z-index: 2;
}
#filter_panel {
#options_panel {
position: sticky;
top: 6.5rem;
z-index: 1;
padding: 0.5rem 1.5rem;
grid-column: 1/-1;
background-color: var(--foreground-color);
overflow-x: auto;
}
.outline-button {
position: relative;
white-space: nowrap;
-webkit-box-pack: center;
-ms-flex-pack: center;
justify-content: center;
padding: 0.5rem 0;
}
.outline-button::after {
position: absolute;
content: "";
width: 1rem;
border-radius: 0.5rem;
height: 0.2rem;
-webkit-transition: opacity 0.1s, -webkit-transform 0.3s;
transition: opacity 0.1s, -webkit-transform 0.3s;
transition: transform 0.3s, opacity 0.1s;
transition: transform 0.3s, opacity 0.1s, -webkit-transform 0.3s;
bottom: 0;
background-color: rgba(var(--text-color), 0.5);
opacity: 0;
}
.outline-button:hover:not(.outline-button--active)::after {
opacity: 1;
background-color: rgba(var(--text-color), 0.5);
}
.outline-button:active::after {
opacity: 1;
-webkit-transform: scaleX(2);
transform: scaleX(2);
}
.outline-button--active::after {
opacity: 1;
background-color: var(--accent-color);
}
.label {
@ -666,6 +703,7 @@ menu-option {
gap: 1rem 0;
height: 100%;
overflow-y: auto;
scroll-padding-top: 1.5rem;
}
.heading {
@ -969,8 +1007,8 @@ menu-option {
grid-row: 2/3;
grid-column: 1/-1;
}
#article_name_wrapper #filter_button,
#selected_content_options #filter_button {
#article_name_wrapper #article_outline_button,
#selected_content_options #article_outline_button {
margin-left: auto;
}
@ -1045,7 +1083,7 @@ menu-option {
grid-template-columns: auto 1fr auto auto;
}
#filter_panel {
#options_panel {
top: 4.2rem;
}
@ -1053,8 +1091,18 @@ menu-option {
grid-template-rows: auto 1fr;
grid-template-columns: minmax(0, 1fr) 24rem;
}
#main_page.active-sidebar #version_history_panel,
#main_page.active-sidebar #article_wrapper {
#main_page.active-outline {
grid-template-rows: auto 1fr;
grid-template-columns: 20rem minmax(0, 1fr);
}
#main_page.active-sidebar.active-outline {
grid-template-rows: auto 1fr;
grid-template-columns: 20rem minmax(0, 1fr) 24rem;
}
#version_history_panel,
#article_outline_panel,
#article_wrapper {
-ms-scroll-chaining: none;
overscroll-behavior: contain;
}

2
css/main.min.css vendored

File diff suppressed because one or more lines are too long

View File

@ -460,13 +460,45 @@ menu-option {
z-index: 2;
}
#filter_panel {
#options_panel {
position: sticky;
top: 6.5rem;
z-index: 1;
padding: 0.5rem 1.5rem;
grid-column: 1/-1;
background-color: var(--foreground-color);
overflow-x: auto;
}
.outline-button{
position: relative;
white-space: nowrap;
justify-content: center;
padding: 0.5rem 0;
&::after{
position: absolute;
content: '';
width: 1rem;
border-radius: 0.5rem;
height: 0.2rem;
transition: transform 0.3s, opacity 0.1s;
bottom: 0;
background-color: rgba(var(--text-color), 0.5);
opacity: 0;
}
&:hover:not(.outline-button--active)::after{
opacity: 1;
background-color: rgba(var(--text-color), 0.5);
}
&:active::after{
opacity: 1;
transform: scaleX(2);
}
&--active{
&::after{
opacity: 1;
background-color: var(--accent-color);
}
}
}
.label {
@ -580,6 +612,7 @@ menu-option {
gap: 1rem 0;
height: 100%;
overflow-y: auto;
scroll-padding-top: 1.5rem;
}
.heading {
@ -719,7 +752,7 @@ menu-option {
}
#version_history_panel {
#version_history_panel{
border-radius: 0.5rem;
width: min(24rem, 100%);
background-color: var(--foreground-color);
@ -728,7 +761,7 @@ menu-option {
padding: 1rem;
}
}
#version_timeline {
#version_timeline{
padding: 1rem;
height: 100%;
overflow-y: auto;
@ -851,7 +884,7 @@ menu-option {
#selected_content_options {
grid-row: 2/3;
grid-column: 1/-1;
#filter_button {
#article_outline_button {
margin-left: auto;
}
}
@ -909,18 +942,27 @@ menu-option {
padding: 1rem 1.5rem;
grid-template-columns: auto 1fr auto auto;
}
#filter_panel {
#options_panel {
top: 4.2rem;
}
#main_page {
&.active-sidebar {
grid-template-rows: auto 1fr;
grid-template-columns: minmax(0, 1fr) 24rem;
#version_history_panel,
#article_wrapper {
overscroll-behavior: contain;
}
}
&.active-outline {
grid-template-rows: auto 1fr;
grid-template-columns: 20rem minmax(0, 1fr);
}
&.active-sidebar.active-outline {
grid-template-rows: auto 1fr;
grid-template-columns: 20rem minmax(0, 1fr) 24rem;
}
}
#version_history_panel,
#article_outline_panel,
#article_wrapper {
overscroll-behavior: contain;
}
#article_wrapper {
padding: 1.5rem;

View File

@ -62,12 +62,10 @@
<article id="main_page" class="grid page">
<header id="main_header">
<div class="logo">
<svg class="main-logo" width="23" height="22" viewBox="0 0 23 22" fill="none"
xmlns="http://www.w3.org/2000/svg">
<path fill-rule="evenodd" clip-rule="evenodd"
d="M15 0.749881C10.9026 2.35002 8 6.33604 8 11C8 15.664 10.9026 19.65 15 21.2501C13.7603 21.7343 12.4112 22 11 22C4.92487 22 0 17.0751 0 11C0 4.92487 4.92487 0 11 0C12.4112 0 13.7603 0.26573 15 0.749881Z" />
<path fill-rule="evenodd" clip-rule="evenodd"
d="M14 16.591C16.2349 15.7182 17.8182 13.544 17.8182 11C17.8182 8.45602 16.2349 6.28183 14 5.40903C14.6762 5.14494 15.4121 5 16.1818 5C19.4955 5 22.1818 7.68629 22.1818 11C22.1818 14.3137 19.4955 17 16.1818 17C15.4121 17 14.6762 16.8551 14 16.591Z" />
<svg class="main-logo" viewBox="0 0 27.25 32">
<title>RanchiMall</title>
<path
d="M27.14,30.86c-.74-2.48-3-4.36-8.25-6.94a20,20,0,0,1-4.2-2.49,6,6,0,0,1-1.25-1.67,4,4,0,0,1,0-2.26c.37-1.08.79-1.57,3.89-4.55a11.66,11.66,0,0,0,3.34-4.67,6.54,6.54,0,0,0,.05-2.82C20,3.6,18.58,2,16.16.49c-.89-.56-1.29-.64-1.3-.24a3,3,0,0,1-.3.72l-.3.55L13.42.94C13,.62,12.4.26,12.19.15c-.4-.2-.73-.18-.72.05a9.39,9.39,0,0,1-.61,1.33s-.14,0-.27-.13C8.76.09,8-.27,8,.23A11.73,11.73,0,0,1,6.76,2.6C4.81,5.87,2.83,7.49.77,7.49c-.89,0-.88,0-.61,1,.22.85.33.92,1.09.69A5.29,5.29,0,0,0,3,8.33c.23-.17.45-.29.49-.26a2,2,0,0,1,.22.63A1.31,1.31,0,0,0,4,9.34a5.62,5.62,0,0,0,2.27-.87L7,8l.13.55c.19.74.32.82,1,.65a7.06,7.06,0,0,0,3.46-2.47l.6-.71-.06.64c-.17,1.63-1.3,3.42-3.39,5.42L6.73,14c-3.21,3.06-3,5.59.6,8a46.77,46.77,0,0,0,4.6,2.41c.28.13,1,.52,1.59.87,3.31,2,4.95,3.92,4.95,5.93a2.49,2.49,0,0,0,.07.77h0c.09.09,0,.1.9-.14a2.61,2.61,0,0,0,.83-.32,3.69,3.69,0,0,0-.55-1.83A11.14,11.14,0,0,0,17,26.81a35.7,35.7,0,0,0-5.1-2.91C9.37,22.64,8.38,22,7.52,21.17a3.53,3.53,0,0,1-1.18-2.48c0-1.38.71-2.58,2.5-4.23,2.84-2.6,3.92-3.91,4.67-5.65a3.64,3.64,0,0,0,.42-2A3.37,3.37,0,0,0,13.61,5l-.32-.74.29-.48c.17-.27.37-.63.46-.8l.15-.3.44.64a5.92,5.92,0,0,1,1,2.81,5.86,5.86,0,0,1-.42,1.94c0,.12-.12.3-.15.4a9.49,9.49,0,0,1-.67,1.1,28,28,0,0,1-4,4.29C8.62,15.49,8.05,16.44,8,17.78a3.28,3.28,0,0,0,1.11,2.76c.95,1,2.07,1.74,5.25,3.32,3.64,1.82,5.22,2.9,6.41,4.38A4.78,4.78,0,0,1,21.94,31a3.21,3.21,0,0,0,.14.92,1.06,1.06,0,0,0,.43-.05l.83-.22.46-.12-.06-.46c-.21-1.53-1.62-3.25-3.94-4.8a37.57,37.57,0,0,0-5.22-2.82A13.36,13.36,0,0,1,11,21.19a3.36,3.36,0,0,1-.8-4.19c.41-.85.83-1.31,3.77-4.15,2.39-2.31,3.43-4.13,3.43-6a5.85,5.85,0,0,0-2.08-4.29c-.23-.21-.44-.43-.65-.65A2.5,2.5,0,0,1,15.27.69a10.6,10.6,0,0,1,2.91,2.78A4.16,4.16,0,0,1,19,6.16a4.91,4.91,0,0,1-.87,3c-.71,1.22-1.26,1.82-4.27,4.67a9.47,9.47,0,0,0-2.07,2.6,2.76,2.76,0,0,0-.33,1.54,2.76,2.76,0,0,0,.29,1.47c.57,1.21,2.23,2.55,4.65,3.73a32.41,32.41,0,0,1,5.82,3.24c2.16,1.6,3.2,3.16,3.2,4.8a1.94,1.94,0,0,0,.09.76,4.54,4.54,0,0,0,1.66-.4C27.29,31.42,27.29,31.37,27.14,30.86ZM6.1,7h0a3.77,3.77,0,0,1-1.46.45L4,7.51l.68-.83a25.09,25.09,0,0,0,3-4.82A12,12,0,0,1,8.28.76c.11-.12.77.32,1.53,1l.63.58-.57.84A10.34,10.34,0,0,1,6.1,7Zm5.71-1.78A9.77,9.77,0,0,1,9.24,7.18h0a5.25,5.25,0,0,1-1.17.28l-.58,0,.65-.78a21.29,21.29,0,0,0,2.1-3.12c.22-.41.42-.76.44-.79s.5.43.9,1.24L12,5ZM13.41,3a2.84,2.84,0,0,1-.45.64,11,11,0,0,1-.9-.91l-.84-.9.19-.45c.34-.79.39-.8,1-.31A9.4,9.4,0,0,1,13.8,2.33q-.18.34-.39.69Z" />
</svg>
<div class="grid">
<h4>RanchiMall CC</h4>
@ -83,6 +81,18 @@
</svg>
</button>
<text-field id="current_article_title"></text-field>
<button id="article_outline_button" class="icon-only" title="View article outline"
onclick="toggleOutlinePanel()">
<svg class="icon" xmlns="http://www.w3.org/2000/svg" enable-background="new 0 0 24 24" height="24px"
viewBox="0 0 24 24" width="24px" fill="#000000">
<g>
<rect fill="none" height="24" width="24" />
</g>
<g>
<path d="M9,18h12v-2H9V18z M3,6v2h18V6H3z M9,13h12v-2H9V13z" />
</g>
</svg>
</button>
<button id="filter_button" class="icon-only" title="Show filters" onclick="toggleFilterPanel()">
<svg class="icon" xmlns="http://www.w3.org/2000/svg" height="24px" viewBox="0 0 24 24" width="24px"
fill="#000000">
@ -90,7 +100,7 @@
<path d="M10 18h4v-2h-4v2zM3 6v2h18V6H3zm3 7h12v-2H6v2z" />
</svg>
</button>
<sm-menu align-options="right" title="Admin options">
<sm-menu align-options="right" title="Admin options" class="admin-option">
<menu-option onclick="showPopup('create_article_popup')">
<svg class="icon button__icon--left" xmlns="http://www.w3.org/2000/svg" height="24px"
viewBox="0 0 24 24" width="24px" fill="#000000">
@ -157,11 +167,17 @@
</svg>
</button>
</header>
<section id="filter_panel" class="flex hide-completely">
<sm-select id="sort_content_list" label="Sort by:">
<sm-option value="time">Most recent</sm-option>
<sm-option value="score">Score</sm-option>
</sm-select>
<section id="options_panel" class="flex hide-completely">
<div id="filter_panel" class="flex w-100">
<sm-select id="sort_content_list" label="Sort by:">
<sm-option value="time">Most recent</sm-option>
<sm-option value="score">Score</sm-option>
</sm-select>
</div>
<div id="article_outline_panel" class="flex align-center gap-1 hide-completely">
<h4>Outline</h4>
<ul id="article_outline" class="flex gap-1"></ul>
</div>
</section>
<div id="text_toolbar" class="hide-completely">
<button id="strong_button" title="Bold (ctrl+b)" class="formatting-button" onclick="formatDoc('bold')">
@ -1617,6 +1633,18 @@
getRef('current_article_title').value = title
getRef('article_wrapper').innerHTML = ''
getRef('article_wrapper').append(frag)
getRef('article_outline').innerHTML = ''
floGlobals.appObjects[floGlobals.currentArticle.id].sections.forEach(section => {
frag.append(createElement('button', {
attributes: { 'data-section-id': section.id },
className: 'outline-button',
textContent: section.title,
}))
})
getRef('article_outline').append(frag)
},
articleLink(details, isDefaultArticle) {
const { uid, timestamp, title } = details
@ -1714,6 +1742,7 @@
if (window.innerWidth < 640)
sectionMutationObserver.observe(section.querySelector('.article-section'), { childList: true })
section.querySelector('.article-section').append(frag)
headingIntersectionObserver.observe(section.children[1])
return section
},
sectionCard(details) {
@ -1735,7 +1764,6 @@
sections.forEach(({ id, title }) => {
floGlobals.currentArticle['sections'][id] = {
expanded: false,
lazyLoad: { startIndex: 0, endIndex: 5 },
title,
uniqueEntries: new Set()
}
@ -1765,7 +1793,7 @@
}
}
function toggleFilterPanel() {
function toggleOptionsPanel() {
const animInOptions = {
duration: 200,
fill: 'forwards',
@ -1777,9 +1805,9 @@
easing: 'ease'
}
if (getRef('filter_panel').classList.contains('hide-completely')) {
getRef('filter_panel').classList.remove('hide-completely')
getRef('filter_panel').animate(slideInDown, animInOptions)
if (getRef('options_panel').classList.contains('hide-completely')) {
getRef('options_panel').classList.remove('hide-completely')
getRef('options_panel').animate(slideInDown, animInOptions)
getRef('article_wrapper').animate([
{
transform: 'translateY(-3rem)'
@ -1788,9 +1816,9 @@
}
], animInOptions)
} else {
getRef('filter_panel').animate(slideOutUp, animOutOptions)
getRef('options_panel').animate(slideOutUp, animOutOptions)
.onfinish = () => {
getRef('filter_panel').classList.add('hide-completely')
getRef('options_panel').classList.add('hide-completely')
}
getRef('article_wrapper').animate([
{
@ -1802,6 +1830,46 @@
}
}
function toggleFilterPanel() {
getRef('filter_panel').classList.remove('hide-completely')
getRef('article_outline_panel').classList.add('hide-completely')
toggleOptionsPanel()
}
function toggleOutlinePanel() {
getRef('filter_panel').classList.add('hide-completely')
getRef('article_outline_panel').classList.remove('hide-completely')
toggleOptionsPanel()
}
getRef('article_outline').addEventListener('click', e => {
if (e.target.closest('.outline-button')) {
const sectionID = e.target.closest('.outline-button').dataset.sectionId
const target = document.querySelector(`.heading[data-section-id="${sectionID}"]`)
getRef('article_wrapper').scrollTo({
behavior: 'smooth',
top: target.getBoundingClientRect().top - getRef('article_wrapper').getBoundingClientRect().top + getRef('article_wrapper').scrollTop
})
}
})
function activeHeading(target) {
[...getRef('article_outline').children].forEach(elem => elem.classList.remove('outline-button--active'))
target.classList.add('outline-button--active')
target.scrollIntoView({ behavior: "smooth", block: "end", inline: "center" });
getRef('options_panel').scrollTo({
behavior: 'smooth',
left: target.getBoundingClientRect().left - getRef('options_panel').getBoundingClientRect().left + getRef('options_panel').scrollLeft
})
}
const headingIntersectionObserver = new IntersectionObserver(entries => {
entries.forEach(entry => {
if (entry.isIntersecting) {
activeHeading(getRef('article_outline').querySelector(`[data-section-id="${entry.target.dataset.sectionId}"]`))
}
})
}, {
threshold: 0.6
})
function sortSectionEntries() {
const sortByScore = getRef('sort_content_list').value === 'score'
const originalObj = {}
@ -2193,6 +2261,11 @@
floDapps.launchStartUp().then(async result => {
isSubAdmin = floGlobals.subAdmins.includes(myFloID)
if (isSubAdmin) {
document.querySelectorAll('.admin-option').forEach(elem => elem.classList.remove('hide-completely'))
} else {
document.querySelectorAll('.admin-option').forEach(elem => elem.classList.add('hide-completely'))
}
await Promise.all([
floCloudAPI.requestObjectData('cc'),
])