on 45bb75d help sign in
webring/scripts/portal.js
116 lines 4.9 kB history raw
1'use strict'
3function Portal (sites) {
4 this.el = document.createElement('div')
5 this.el.id = 'portal'
6 this.sites = sites
8 // Templates
10 const _readme = '<p class="readme">This webring is an attempt to inspire artists & developers to build their own website and share traffic among each other. The ring welcomes personalized websites such as <b>diaries, wikis & portfolios</b>.</p><p>To add yourself to the ring, submit a <a href="https://github.com/XXIIVV/webring/edit/master/scripts/sites.js" target="_blank">Pull Request</a>.<br />If you found a broken link, please <a href="https://github.com/XXIIVV/webring/issues/new" target="_blank">report it</a>.</p>'
11 const _buttons = '<p class="buttons"><a href="#random" onClick="portal.reload()">Random</a> | <a href="https://github.com/XXIIVV/webring">Information</a> <a id="icon" href="#random" onClick="portal.reload()"></a> | <a href="hallway.html">The Hallway</a> | <a href="wiki.html">The Wiki</a> | <a id="opml">OPML</a></p>'
13 function _directory (sites) {
14 const siteTypesArray = [...new Set(sites.map(site => site.type).filter(Boolean))]
15 const siteLangsArray = [...new Set(sites
16 .reduce((flattened, site) => flattened.concat(site.langs), [])
17 .sort())]
19 const siteTypes = siteTypesArray.reduce((output, siteType) =>
20 `${output}<a data-type="${siteType}" href="#" onclick="filterSites(event)">&lt;${siteType}&gt;</a>`,
21 '<a class="currentType" data-type="all" href="#" onclick="filterSites(event)">&lt;all&gt;</a>')
23 const siteLangs = siteLangsArray.reduce((output, siteLang) =>
24 `${output}<a data-lang="${siteLang}" href="#" onclick="filterSites(event)">&lt;${siteLang}&gt;</a>`,
25 '<a class="currentLang" data-lang="all" href="#" onclick="filterSites(event)">&lt;all&gt;</a>')
27 const listItems = sites.reduce((acc, site, id) =>
28 `${acc}<li ${_type(site)} ${_lang(site)} id='${id}'><a href='${site.url}'>${_name(site)}</a></li>`, '')
29 return `<nav>${siteTypes}</nav><nav>${siteLangs}</nav><main><ul>${listItems}</ul></main><footer>${_readme}${_buttons}</footer>`
30 }
32 function _name (site) {
33 return site.title || `${site.url.split('//')[1].replace(/\/+$/,'')}`
34 }
36 function _type (site) {
37 return site.type ? `data-type="${site.type} "` : ''
38 }
40 function _lang (site) {
41 return `data-lang="${site.langs.join(' ').trim()}"`
42 }
44 function _redirectView (site) {
45 return `<main><p>Redirecting to <a href="${site.url}">${site.url}</a></p></main>
46 <footer><p class='buttons'><a href='#' onClick="portal.reload('')">Directory</a> | <a href='#${site.url}' onClick="portal.reload()">Skip</a> | <a href='#random' onClick="portal.reload()">Random</a> | <a href='https://github.com/XXIIVV/webring'>Information</a> <a id='icon' href='#random' onClick="portal.reload()"></a></p>`
47 }
49 //
51 this.install = function (host) {
52 host.appendChild(this.el)
53 }
55 this.start = function () {
56 if (window.location.hash && window.location.hash.length > 4) {
57 const site = this.next()
58 this.el.innerHTML = _redirectView(site)
59 setTimeout(() => { window.location = site.url }, 3000)
60 } else {
61 this.el.innerHTML = _directory(this.sites)
62 }
63 }
65 this.reload = function () {
66 setTimeout(() => { window.location.reload() }, 500)
67 }
69 this.navigate = function (target) {
70 setTimeout(() => { window.location.href = target }, 3000)
71 }
73 this.sitesMatchingLangs = this.sites
74 .filter(site => site.langs && site.langs.some(lang => navigator.languages.includes(lang)))
76 this.next = function () {
77 const hash = window.location.hash.replace('#', '').trim()
79 if (hash === 'random') {
80 return this.sitesMatchingLangs[Math.floor(Math.random() * this.sitesMatchingLangs.length)]
81 } else {
82 return sites.find(site => site.url.includes(hash))
83 ? sites.find(site => site.url.includes(hash))
84 : this.sitesMatchingLangs[Math.floor(Math.random() * this.sitesMatchingLangs.length)]
85 }
86 }
89function filterSites (e) {
90 e.preventDefault()
91 const navLink = e.target
92 const currentFilter = navLink.dataset.lang ? 'Lang' : 'Type'
94 document.querySelector(`nav a.current${currentFilter}`).classList.remove(`current${currentFilter}`)
95 navLink.classList.add(`current${currentFilter}`)
97 const typeFilter = document.querySelector('nav a.currentType').dataset.type
98 const langFilter = document.querySelector('nav a.currentLang').dataset.lang
100 const sites = document.querySelectorAll('main li')
101 sites.forEach(el => { el.style.display = 'block' })
103 sites.forEach(el => {
104 if (typeFilter !== 'all') {
105 if (el.dataset.type) {
106 if (el.dataset.type.trim() !== typeFilter) el.style.display = 'none'
107 } else {
108 el.style.display = 'none'
109 }
110 }
112 if (langFilter !== 'all') {
113 if (!el.dataset.lang.includes(langFilter)) el.style.display = 'none'
114 }
115 })