You cannot select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
198 lines
4.2 KiB
JavaScript
198 lines
4.2 KiB
JavaScript
export class NavMenu extends HTMLElement {
|
|
textByLang = {
|
|
en: {
|
|
pages: 'Pages',
|
|
localStorage: 'Local storage',
|
|
full: 'full',
|
|
},
|
|
es: {
|
|
pages: 'Páginas',
|
|
localStorage: 'Almacenamiento local',
|
|
full: 'lleno',
|
|
},
|
|
}
|
|
|
|
constructor() {
|
|
super()
|
|
this.attachShadow({mode: 'open'})
|
|
this.language = navigator.language
|
|
this.pages = []
|
|
this.handleLinks = false
|
|
}
|
|
|
|
connectedCallback() {
|
|
const style = document.createElement('style')
|
|
style.textContent = `
|
|
:host {
|
|
display: flex;
|
|
flex-direction: column;
|
|
color: #000;
|
|
height: 100dvh;
|
|
max-height: 100dvh;
|
|
}
|
|
.location-bar {
|
|
padding: 5px 25px;
|
|
display: flex;
|
|
flex-direction: row;
|
|
}
|
|
.location-box {
|
|
border: 2px solid #aaa;
|
|
border-radius: 3px;
|
|
flex-grow: 1;
|
|
padding: 5px;
|
|
font-size: 14px;
|
|
}
|
|
h1 {
|
|
width: 100%;
|
|
text-align: center;
|
|
font-size: 18px;
|
|
margin: 0;
|
|
padding: 5px;
|
|
}
|
|
.page-list {
|
|
flex-grow: 1;
|
|
overflow-y: auto;
|
|
padding-bottom: 50px;
|
|
}
|
|
a {
|
|
display: block;
|
|
margin: 8px 10px;
|
|
}
|
|
.footer {
|
|
padding: 3px 5px;
|
|
}
|
|
`
|
|
this.shadowRoot.append(style)
|
|
this.locationBar = document.createElement(
|
|
'div'
|
|
)
|
|
this.locationBar.classList.add(
|
|
'location-bar'
|
|
)
|
|
this.locationBox = document.createElement(
|
|
'div'
|
|
)
|
|
this.locationBox.classList.add(
|
|
'location-box'
|
|
)
|
|
this.locationBar.append(this.locationBox)
|
|
this.locationBox.addEventListener(
|
|
'click',
|
|
() => {
|
|
this.dispatchEvent(new CustomEvent(
|
|
'click-location', {bubbles: true}
|
|
))
|
|
}
|
|
)
|
|
this.shadowRoot.append(this.locationBar)
|
|
this.renderLocation()
|
|
this.header = document.createElement('h1')
|
|
this.header.innerText = this.text.pages
|
|
this.shadowRoot.append(this.header)
|
|
this.pageList = document.createElement('div')
|
|
this.pageList.classList.add('page-list')
|
|
this.shadowRoot.append(this.pageList)
|
|
this.renderPageList()
|
|
this.footer = document.createElement('div')
|
|
this.footer.classList.add('footer')
|
|
this.shadowRoot.append(this.footer)
|
|
this.renderFooter()
|
|
this.shadowRoot.addEventListener('click', e => {
|
|
if (e.target.classList.contains('page')) {
|
|
if (this.handleLinks) {
|
|
e.preventDefault()
|
|
}
|
|
this.dispatchEvent(new CustomEvent(
|
|
'close-menu', {bubbles: true}
|
|
))
|
|
if (this.handleLinks) {
|
|
const hash = '#' + e.target.innerText
|
|
location.hash = hash
|
|
}
|
|
}
|
|
})
|
|
}
|
|
|
|
get language() {
|
|
return this._language
|
|
}
|
|
|
|
set language(language) {
|
|
this._language = language
|
|
this.text = this.textByLang[
|
|
this.langEs ? 'es' : 'en'
|
|
]
|
|
}
|
|
|
|
get langEs() {
|
|
return /^es\b/.test(this.language)
|
|
}
|
|
|
|
set location(location) {
|
|
this._location = location
|
|
if (this.locationBox) {
|
|
this.renderLocation()
|
|
}
|
|
}
|
|
|
|
get location() {
|
|
return this._location
|
|
}
|
|
|
|
renderLocation() {
|
|
this.locationBox.innerText = this.location
|
|
}
|
|
|
|
set pages(pages) {
|
|
this._pages = pages
|
|
if (this.pageList) {
|
|
this.renderPageList()
|
|
}
|
|
}
|
|
|
|
get pages() {
|
|
return this._pages
|
|
}
|
|
|
|
renderPageList() {
|
|
const els = this.pages.map(page => {
|
|
const el = document.createElement('a')
|
|
el.href = `#${page.replace(/^#/, '%23')}`
|
|
el.innerText = page
|
|
el.classList.add('page')
|
|
return el
|
|
})
|
|
this.pageList.replaceChildren(...els)
|
|
}
|
|
|
|
set storageUse(n) {
|
|
this._storageUse = n
|
|
if (this.footer) {
|
|
this.renderFooter()
|
|
}
|
|
}
|
|
|
|
get storageUse() {
|
|
return this._storageUse
|
|
}
|
|
|
|
renderFooter() {
|
|
if (this.storageUse !== undefined) {
|
|
const fmt = new Intl.NumberFormat(
|
|
this.language,
|
|
{
|
|
style: 'percent',
|
|
minimumFractionDigits: 2,
|
|
maximumFractionDigits: 2,
|
|
},
|
|
)
|
|
this.footer.innerText = (
|
|
this.text.localStorage + ' ' +
|
|
fmt.format(
|
|
this.storageUse
|
|
).replaceAll(/\s+/g, '') + ' ' +
|
|
this.text.full
|
|
)
|
|
}
|
|
}
|
|
} |