/* eslint-env browser *//* eslint-disable no-multi-str */ function cancelDefault (e) { e.preventDefault() e.stopPropagation()} const warningMsg = () => 'Leaving will interrupt transfer?\n'const rmMsg = () => !confirm('Remove file?\n')const ensureMove = () => !confirm('move items?')const isRo = () => window.ro // DOM elementsconst upBarName = document.getElementById('upBarName')const upBarPc = document.getElementById('upBarPc')const upGrid = document.getElementById('drop-grid')const pics = document.getElementById('pics')const picsHolder = document.getElementById('picsHolder')const video = document.getElementById('video')const videoHolder = document.getElementById('videoHolder')const manualUpload = document.getElementById('clickupload')const pdf = document.getElementById('pdf')const help = document.getElementById('help')const okBadge = document.getElementById('ok')const sadBadge = document.getElementById('sad')const pageTitle = document.head.querySelector('title')const pageH1 = document.body.querySelector('h1')const editor = document.getElementById('text-editor')const crossIcon = document.getElementById('quitAll')const toast = document.getElementById('toast')const table = document.getElementById('linkTable')const helpMsg = document.getElementById('help_message') const transparentPixel = 'data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAEAAAABCAQAAAC1HAwCAAAAC0lEQVR42mNkYAAAAAYAAjCB0C8AAAAASUVORK5CYII=' // helperslet allAlet imgsIndexlet allImgsconst decode = a => decodeURIComponent(a).replace(location.origin, '')const getArrowSelected = () => document.querySelector('.arrow-selected')const getASelected = () => !getArrowSelected() ? false : getArrowSelected().parentElement.parentElement.querySelectorAll('a')[0]const prependPath = a => a.startsWith('/') ? a : decodeURI(location.pathname) + aconst prevent = e => e.preventDefault()const flicker = w => w.classList.remove('runFade') || void w.offsetWidth || w.classList.add('runFade') // eslint-disable-line const encodeURIHash = e => encodeURI(e).replaceAll('#', '%23') // Manual uploadmanualUpload.addEventListener('change', () => Array.from(manualUpload.files).forEach(f => isDupe(f.name) || postFile(f, '/' + f.name)), false) // Soft navasync function browseTo (href, flickerDone, skipHistory) { try { const r = await fetch(href, { credentials: 'include' }) const t = await r.text() const parsed = new DOMParser().parseFromString(t, 'text/html') table.innerHTML = parsed.getElementById('linkTable').innerHTML const title = parsed.head.querySelector('title').innerText // check if is current path - if so skip following if (pageTitle.innerText !== title) { if (!skipHistory) { const escaped = encodeURIHash(window.extraPath + title) history.pushState({}, '', escaped) } pageTitle.innerText = title pageH1.innerText = '.' + title setTitle() } init() if (flickerDone) flicker(okBadge) } catch (error) { flicker(sadBadge) }} window.onClickLink = e => { const a = e ? e.target : getASelected() if (e) { setCursorTo(e.target.innerText) } // always force download if ctrl pressed (also covers zipping folders) if (e && e.ctrlKey) { dl(a) return false } // follow dirs if (isFolder(a)) { browseTo(a.href) return false // enable notepad if relevant } else if (!window.ro && isTextFile(a.innerText) && !isEditorMode()) { padOn(a) return false // toggle picture carousel } else if (isPic(a.href) && !isPicMode()) { picsOn(a.href) return false // toggle videos mode } else if (isVideo(a.href) && !isVideoMode()) { videoOn(a.href) return false // let html be displayed naturally } else if (a.innerText.endsWith('.html')) { return true } else if (isPdf(a.href)) { openPDF(a.href) return false } // else just force download dl(a) return false} let softStatePushedfunction pushSoftState (d) { if (softStatePushed) { return } softStatePushed = true history.pushState({}, '', encodeURIHash(d))} const refresh = () => browseTo(location.href, true) const softPrev = () => history.replaceState({}, '', location.href.split('/').slice(0, -1).join('/') + '/') const isAtExtraPath = url => location.origin + window.extraPath + '/../' === urlconst prevPage = (url, skipHistory) => window.quitAll() || isAtExtraPath(url) || browseTo(url, false, skipHistory) window.onpopstate = () => prevPage(location.href, true) // RPCfunction upload (id, what, path, cbDone, cbErr, cbUpdate) { const xhr = new XMLHttpRequest() xhr.open('POST', location.origin + window.extraPath + '/post') xhr.setRequestHeader('gossa-path', path) xhr.upload.addEventListener('load', cbDone) xhr.upload.addEventListener('progress', cbUpdate) xhr.upload.addEventListener('error', cbErr) xhr.upload.id = id xhr.send(what)} function rpc (call, args, cb) { console.log('RPC', call, args) const xhr = new XMLHttpRequest() xhr.open('POST', location.origin + window.extraPath + '/rpc') xhr.setRequestHeader('Content-Type', 'application/json;charset=UTF-8') xhr.send(JSON.stringify({ call, args })) xhr.onload = cb xhr.onerror = () => flicker(sadBadge)} const mkdirCall = (path, cb) => rpc('mkdirp', [prependPath(path)], cb)const rmCall = (path1, cb) => rpc('rm', [prependPath(path1)], cb)const mvCall = (path1, path2, cb) => rpc('mv', [path1, path2], cb)const sumCall = (path, type, cb) => rpc('sum', [prependPath(path), type], cb) // File uploadlet totalDone = 0let totalUploads = 0let totalUploadsSize = 0let totalUploadedSize = [] const dupe = test => allA.find(a => a.innerHTML.replace('/', '') === test)const isDupe = t => dupe(t) ? alert(t + ' already already exists') || true : false function shouldRefresh () { totalDone += 1 if (totalUploads === totalDone) { window.onbeforeunload = null console.log('done uploading ' + totalDone + ' files') totalDone = 0 totalUploads = 0 totalUploadsSize = 0 totalUploadedSize = [] upBarPc.style.display = upBarName.style.display = 'none' table.classList.remove('uploading-table') setTimeout(refresh, 200) }} function updatePercent (ev) { totalUploadedSize[ev.target.id] = ev.loaded const ttlDone = totalUploadedSize.reduce((s, x) => s + x) const pc = Math.floor(100 * ttlDone / totalUploadsSize) + '%' upBarPc.innerText = pc upBarPc.style.width = pc} function postFile (file, path) { if (window.ro) return path = decodeURI(location.pathname).slice(0, -1) + path window.onbeforeunload = warningMsg table.classList.add('uploading-table') upBarPc.style.display = upBarName.style.display = 'block' totalUploads += 1 totalUploadsSize += file.size upBarName.innerText = totalUploads > 1 ? totalUploads + ' files' : file.name const formData = new FormData() formData.append(file.name, file) upload(totalUploads, formData, encodeURIComponent(path), shouldRefresh, null, updatePercent)} const parseDomFolder = f => f.createReader().readEntries(e => e.forEach(i => parseDomItem(i))) function parseDomItem (domFile, shoudCheckDupes) { if (shoudCheckDupes && isDupe(domFile.name)) { return } if (domFile.isFile) { domFile.file(f => postFile(f, domFile.fullPath)) } else { // remove absolute path const f = domFile.fullPath.startsWith('/') ? domFile.fullPath.slice(1) : domFile.fullPath mkdirCall(f, () => parseDomFolder(domFile)) }} function pushEntry (entry) { if (!entry.webkitGetAsEntry && !entry.getAsEntry) { return alert('Unsupported browser ! Please update to chrome/firefox.') } else { entry = entry.webkitGetAsEntry() || entry.getAsEntry() } parseDomItem(entry, true)} window.titleClick = function (e) { const p = Array.from(document.querySelector('h1').childNodes).map(k => k.innerText) const i = p.findIndex(s => s === e.target.innerText) const dst = p.slice(0, i + 1).join('').slice(1) const target = location.origin + window.extraPath + encodeURIHash(dst) browseTo(target, false)} // Move files and foldersconst isFolder = e => e && e.href && e.innerText.endsWith('/') const setBackgroundLinks = t => { t.classList.add('highlight') } const getLink = () => document.querySelector('.highlight') || {} const resetBackgroundLinks = () => { try { getLink().classList.remove('highlight') } catch(e) { /* */ } } // eslint-disable-line // Not the nicest - sometimes, upon hover, firefox reports nodeName === '#text', and chrome reports nodeName === 'A'...const getClosestRow = t => t.nodeName === '#text' ? t.parentElement.parentElement : t.nodeName === 'A' ? t.parentElement : t let draggingSrc upGrid.ondragend = upGrid.ondragexit = upGrid.ondragleave = e => { cancelDefault(e) upGrid.style.display = 'none'} // Handle hoverdocument.ondragenter = e => { if (isEditorMode() || isPicMode() || window.ro) { return } cancelDefault(e) resetBackgroundLinks() // Display upload grid when uploading new elements if (!draggingSrc) { upGrid.style.display = 'flex' e.dataTransfer.dropEffect = 'copy' // Or highlight entry if drag and drop } else if (draggingSrc) { const t = getClosestRow(e.target) isFolder(t.firstChild) && setBackgroundLinks(t) }} document.ondragstart = e => { draggingSrc = e.target.innerHTML } document.ondragend = e => resetBackgroundLinks() document.ondragover = e => { cancelDefault(e) return false} // Handle dropdocument.ondrop = e => { if (window.ro) return cancelDefault(e) upGrid.style.display = 'none' const t = getLink().firstChild // move to a folder if (draggingSrc && t) { const dest = t.innerHTML + draggingSrc ensureMove() || mvCall(prependPath(draggingSrc), prependPath(dest), refresh) // ... or upload } else if (e.dataTransfer.items.length) { Array.from(e.dataTransfer.items).forEach(pushEntry) } resetBackgroundLinks() draggingSrc = null return false} // Notepadconst isEditorMode = () => editor.style.display === 'block'const textTypes = ['.txt', '.rtf', '.md', '.markdown', '.log', '.yaml', '.yml']const isTextFile = src => src && textTypes.find(type => src.toLocaleLowerCase().includes(type))let fileEdited function saveText (quitting) { const formData = new FormData() formData.append(fileEdited, editor.value) const path = encodeURIComponent(decodeURI(location.pathname) + fileEdited) upload(0, formData, path, () => { toast.style.display = 'none' if (!quitting) return clearInterval(window.padTimer) window.onbeforeunload = null resetView() softPrev() refresh() }, () => { toast.style.display = 'block' if (!quitting) return alert('cant save!\r\nleave window open to resume saving\r\nwhen connection back up') })} function padOff () { if (!isEditorMode()) { return } saveText(true) return true} async function padOn (a) { if (a) { try { fileEdited = a.innerHTML const f = await fetch(a.href, { credentials: 'include', headers: new Headers({ pragma: 'no-cache', 'cache-control': 'no-cache' }) }) editor.value = await f.text() } catch (error) { return alert('cant read file') } } else { fileEdited = prompt('new filename', '') if (!fileEdited) { return } fileEdited = isTextFile(fileEdited) ? fileEdited : fileEdited + '.txt' if (isDupe(fileEdited)) { return } editor.value = '' } console.log('editing file', fileEdited) setCursorTo(fileEdited) editor.style.display = crossIcon.style.display = 'block' table.style.display = 'none' editor.focus() window.onbeforeunload = warningMsg window.padTimer = setInterval(saveText, 5000) pushSoftState('?editor=' + fileEdited)} window.displayPad = padOn // quit pictures or editorfunction resetView () { softStatePushed = false table.style.display = 'table' picsHolder.src = transparentPixel videoHolder.src = '' pdf.innerHTML = '' editor.style.display = pics.style.display = video.style.display = pdf.style.display = crossIcon.style.display = 'none' scrollToArrow()} window.quitAll = () => helpOff() || sumsOff() || picsOff() || videosOff() || padOff() || pdfOff() // Mkdir iconwindow.mkdirBtn = function () { const folder = prompt('new folder name', '') if (folder && !isDupe(folder)) { mkdirCall(folder, refresh) }} // Icon click handlerconst getBtnA = e => e.target.closest('tr').querySelector('a') window.rm = e => { if (window.ro) return true clearTimeout(window.clickToken) const target = e.key ? getASelected() : getBtnA(e) if (target.innerText === '../') return if (rmMsg()) return moveArrow() rmCall(decode(target.href), refresh)} window.rename = (e, commit) => { if (window.ro) return true clearTimeout(window.clickToken) if (!commit) { window.clickToken = setTimeout(window.rename, 300, e, true) return } const target = e.key ? getASelected() : getBtnA(e) if (target.innerText === '../') return const chg = prompt('rename to', target.innerText) if (chg && !isDupe(chg)) { mvCall(prependPath(target.innerText), prependPath(chg), refresh) }} function aboveBelowRightin (el) { const itemPos = el.getBoundingClientRect() return itemPos.top < 0 ? -1 : itemPos.bottom > window.innerHeight ? 1 : 0} function scrollToArrow () { const el = getASelected() while (1) { const pos = aboveBelowRightin(el) if (pos === -1) { scrollBy(0, -300) } else if (pos === 1) { scrollBy(0, 300) } else { break } }} function clearArrowSelected () { const arr = getArrowSelected() if (!arr) { return } arr.classList.remove('arrow-selected')} window.setCursorTo = setCursorTofunction setCursorTo (where) { if (!where) return false clearArrowSelected() let a = allA.find(el => el.innerText === where || el.innerText === where + '/') if (!a) { if (allA[0].innerText === '../') { a = allA[1] || allA[0] } else { a = allA[0] } } const icon = a.parentElement.parentElement.querySelectorAll('.arrow-icon')[0] icon.classList.add('arrow-selected') scrollToArrow() storeArrow(where) return true} function moveArrow (down) { const all = Array.from(document.querySelectorAll('.arrow-icon')) let i = all.findIndex(el => el.classList.contains('arrow-selected')) clearArrowSelected() if (down) { i = all[i + 1] ? i + 1 : 0 } else { i = all[i - 1] ? i - 1 : all.length - 1 } all[i].classList.add('arrow-selected') storeArrow(getASelected().innerText) scrollToArrow()} const storeArrow = src => localStorage.setItem('last-selected' + window.extraPath + location.pathname, src) const isTop = () => window.scrollY === 0const isBottom = () => (window.innerHeight + window.scrollY) >= document.body.offsetHeightconst hasScroll = () => table.clientHeight > window.innerHeight function movePage (up) { const current = getASelected().href if (!hasScroll()) returnLines 1–500 of 925. Load more
/* eslint-env browser */ /* eslint-disable no-multi-str */ function cancelDefault (e) { e.preventDefault() e.stopPropagation() } const warningMsg = () => 'Leaving will interrupt transfer?\n' const rmMsg = () => !confirm('Remove file?\n') const ensureMove = () => !confirm('move items?') const isRo = () => window.ro // DOM elements const upBarName = document.getElementById('upBarName') const upBarPc = document.getElementById('upBarPc') const upGrid = document.getElementById('drop-grid') const pics = document.getElementById('pics') const picsHolder = document.getElementById('picsHolder') const video = document.getElementById('video') const videoHolder = document.getElementById('videoHolder') const manualUpload = document.getElementById('clickupload') const pdf = document.getElementById('pdf') const help = document.getElementById('help') const okBadge = document.getElementById('ok') const sadBadge = document.getElementById('sad') const pageTitle = document.head.querySelector('title') const pageH1 = document.body.querySelector('h1') const editor = document.getElementById('text-editor') const crossIcon = document.getElementById('quitAll') const toast = document.getElementById('toast') const table = document.getElementById('linkTable') const helpMsg = document.getElementById('help_message') const transparentPixel = 'data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAEAAAABCAQAAAC1HAwCAAAAC0lEQVR42mNkYAAAAAYAAjCB0C8AAAAASUVORK5CYII=' // helpers let allA let imgsIndex let allImgs const decode = a => decodeURIComponent(a).replace(location.origin, '') const getArrowSelected = () => document.querySelector('.arrow-selected') const getASelected = () => !getArrowSelected() ? false : getArrowSelected().parentElement.parentElement.querySelectorAll('a')[0] const prependPath = a => a.startsWith('/') ? a : decodeURI(location.pathname) + a const prevent = e => e.preventDefault() const flicker = w => w.classList.remove('runFade') || void w.offsetWidth || w.classList.add('runFade') // eslint-disable-line const encodeURIHash = e => encodeURI(e).replaceAll('#', '%23') // Manual upload manualUpload.addEventListener('change', () => Array.from(manualUpload.files).forEach(f => isDupe(f.name) || postFile(f, '/' + f.name)), false) // Soft nav async function browseTo (href, flickerDone, skipHistory) { try { const r = await fetch(href, { credentials: 'include' }) const t = await r.text() const parsed = new DOMParser().parseFromString(t, 'text/html') table.innerHTML = parsed.getElementById('linkTable').innerHTML const title = parsed.head.querySelector('title').innerText // check if is current path - if so skip following if (pageTitle.innerText !== title) { if (!skipHistory) { const escaped = encodeURIHash(window.extraPath + title) history.pushState({}, '', escaped) } pageTitle.innerText = title pageH1.innerText = '.' + title setTitle() } init() if (flickerDone) flicker(okBadge) } catch (error) { flicker(sadBadge) } } window.onClickLink = e => { const a = e ? e.target : getASelected() if (e) { setCursorTo(e.target.innerText) } // always force download if ctrl pressed (also covers zipping folders) if (e && e.ctrlKey) { dl(a) return false } // follow dirs if (isFolder(a)) { browseTo(a.href) return false // enable notepad if relevant } else if (!window.ro && isTextFile(a.innerText) && !isEditorMode()) { padOn(a) return false // toggle picture carousel } else if (isPic(a.href) && !isPicMode()) { picsOn(a.href) return false // toggle videos mode } else if (isVideo(a.href) && !isVideoMode()) { videoOn(a.href) return false // let html be displayed naturally } else if (a.innerText.endsWith('.html')) { return true } else if (isPdf(a.href)) { openPDF(a.href) return false } // else just force download dl(a) return false } let softStatePushed function pushSoftState (d) { if (softStatePushed) { return } softStatePushed = true history.pushState({}, '', encodeURIHash(d)) } const refresh = () => browseTo(location.href, true) const softPrev = () => history.replaceState({}, '', location.href.split('/').slice(0, -1).join('/') + '/') const isAtExtraPath = url => location.origin + window.extraPath + '/../' === url const prevPage = (url, skipHistory) => window.quitAll() || isAtExtraPath(url) || browseTo(url, false, skipHistory) window.onpopstate = () => prevPage(location.href, true) // RPC function upload (id, what, path, cbDone, cbErr, cbUpdate) { const xhr = new XMLHttpRequest() xhr.open('POST', location.origin + window.extraPath + '/post') xhr.setRequestHeader('gossa-path', path) xhr.upload.addEventListener('load', cbDone) xhr.upload.addEventListener('progress', cbUpdate) xhr.upload.addEventListener('error', cbErr) xhr.upload.id = id xhr.send(what) } function rpc (call, args, cb) { console.log('RPC', call, args) const xhr = new XMLHttpRequest() xhr.open('POST', location.origin + window.extraPath + '/rpc') xhr.setRequestHeader('Content-Type', 'application/json;charset=UTF-8') xhr.send(JSON.stringify({ call, args })) xhr.onload = cb xhr.onerror = () => flicker(sadBadge) } const mkdirCall = (path, cb) => rpc('mkdirp', [prependPath(path)], cb) const rmCall = (path1, cb) => rpc('rm', [prependPath(path1)], cb) const mvCall = (path1, path2, cb) => rpc('mv', [path1, path2], cb) const sumCall = (path, type, cb) => rpc('sum', [prependPath(path), type], cb) // File upload let totalDone = 0 let totalUploads = 0 let totalUploadsSize = 0 let totalUploadedSize = [] const dupe = test => allA.find(a => a.innerHTML.replace('/', '') === test) const isDupe = t => dupe(t) ? alert(t + ' already already exists') || true : false function shouldRefresh () { totalDone += 1 if (totalUploads === totalDone) { window.onbeforeunload = null console.log('done uploading ' + totalDone + ' files') totalDone = 0 totalUploads = 0 totalUploadsSize = 0 totalUploadedSize = [] upBarPc.style.display = upBarName.style.display = 'none' table.classList.remove('uploading-table') setTimeout(refresh, 200) } } function updatePercent (ev) { totalUploadedSize[ev.target.id] = ev.loaded const ttlDone = totalUploadedSize.reduce((s, x) => s + x) const pc = Math.floor(100 * ttlDone / totalUploadsSize) + '%' upBarPc.innerText = pc upBarPc.style.width = pc } function postFile (file, path) { if (window.ro) return path = decodeURI(location.pathname).slice(0, -1) + path window.onbeforeunload = warningMsg table.classList.add('uploading-table') upBarPc.style.display = upBarName.style.display = 'block' totalUploads += 1 totalUploadsSize += file.size upBarName.innerText = totalUploads > 1 ? totalUploads + ' files' : file.name const formData = new FormData() formData.append(file.name, file) upload(totalUploads, formData, encodeURIComponent(path), shouldRefresh, null, updatePercent) } const parseDomFolder = f => f.createReader().readEntries(e => e.forEach(i => parseDomItem(i))) function parseDomItem (domFile, shoudCheckDupes) { if (shoudCheckDupes && isDupe(domFile.name)) { return } if (domFile.isFile) { domFile.file(f => postFile(f, domFile.fullPath)) } else { // remove absolute path const f = domFile.fullPath.startsWith('/') ? domFile.fullPath.slice(1) : domFile.fullPath mkdirCall(f, () => parseDomFolder(domFile)) } } function pushEntry (entry) { if (!entry.webkitGetAsEntry && !entry.getAsEntry) { return alert('Unsupported browser ! Please update to chrome/firefox.') } else { entry = entry.webkitGetAsEntry() || entry.getAsEntry() } parseDomItem(entry, true) } window.titleClick = function (e) { const p = Array.from(document.querySelector('h1').childNodes).map(k => k.innerText) const i = p.findIndex(s => s === e.target.innerText) const dst = p.slice(0, i + 1).join('').slice(1) const target = location.origin + window.extraPath + encodeURIHash(dst) browseTo(target, false) } // Move files and folders const isFolder = e => e && e.href && e.innerText.endsWith('/') const setBackgroundLinks = t => { t.classList.add('highlight') } const getLink = () => document.querySelector('.highlight') || {} const resetBackgroundLinks = () => { try { getLink().classList.remove('highlight') } catch(e) { /* */ } } // eslint-disable-line // Not the nicest - sometimes, upon hover, firefox reports nodeName === '#text', and chrome reports nodeName === 'A'... const getClosestRow = t => t.nodeName === '#text' ? t.parentElement.parentElement : t.nodeName === 'A' ? t.parentElement : t let draggingSrc upGrid.ondragend = upGrid.ondragexit = upGrid.ondragleave = e => { cancelDefault(e) upGrid.style.display = 'none' } // Handle hover document.ondragenter = e => { if (isEditorMode() || isPicMode() || window.ro) { return } cancelDefault(e) resetBackgroundLinks() // Display upload grid when uploading new elements if (!draggingSrc) { upGrid.style.display = 'flex' e.dataTransfer.dropEffect = 'copy' // Or highlight entry if drag and drop } else if (draggingSrc) { const t = getClosestRow(e.target) isFolder(t.firstChild) && setBackgroundLinks(t) } } document.ondragstart = e => { draggingSrc = e.target.innerHTML } document.ondragend = e => resetBackgroundLinks() document.ondragover = e => { cancelDefault(e) return false } // Handle drop document.ondrop = e => { if (window.ro) return cancelDefault(e) upGrid.style.display = 'none' const t = getLink().firstChild // move to a folder if (draggingSrc && t) { const dest = t.innerHTML + draggingSrc ensureMove() || mvCall(prependPath(draggingSrc), prependPath(dest), refresh) // ... or upload } else if (e.dataTransfer.items.length) { Array.from(e.dataTransfer.items).forEach(pushEntry) } resetBackgroundLinks() draggingSrc = null return false } // Notepad const isEditorMode = () => editor.style.display === 'block' const textTypes = ['.txt', '.rtf', '.md', '.markdown', '.log', '.yaml', '.yml'] const isTextFile = src => src && textTypes.find(type => src.toLocaleLowerCase().includes(type)) let fileEdited function saveText (quitting) { const formData = new FormData() formData.append(fileEdited, editor.value) const path = encodeURIComponent(decodeURI(location.pathname) + fileEdited) upload(0, formData, path, () => { toast.style.display = 'none' if (!quitting) return clearInterval(window.padTimer) window.onbeforeunload = null resetView() softPrev() refresh() }, () => { toast.style.display = 'block' if (!quitting) return alert('cant save!\r\nleave window open to resume saving\r\nwhen connection back up') }) } function padOff () { if (!isEditorMode()) { return } saveText(true) return true } async function padOn (a) { if (a) { try { fileEdited = a.innerHTML const f = await fetch(a.href, { credentials: 'include', headers: new Headers({ pragma: 'no-cache', 'cache-control': 'no-cache' }) }) editor.value = await f.text() } catch (error) { return alert('cant read file') } } else { fileEdited = prompt('new filename', '') if (!fileEdited) { return } fileEdited = isTextFile(fileEdited) ? fileEdited : fileEdited + '.txt' if (isDupe(fileEdited)) { return } editor.value = '' } console.log('editing file', fileEdited) setCursorTo(fileEdited) editor.style.display = crossIcon.style.display = 'block' table.style.display = 'none' editor.focus() window.onbeforeunload = warningMsg window.padTimer = setInterval(saveText, 5000) pushSoftState('?editor=' + fileEdited) } window.displayPad = padOn // quit pictures or editor function resetView () { softStatePushed = false table.style.display = 'table' picsHolder.src = transparentPixel videoHolder.src = '' pdf.innerHTML = '' editor.style.display = pics.style.display = video.style.display = pdf.style.display = crossIcon.style.display = 'none' scrollToArrow() } window.quitAll = () => helpOff() || sumsOff() || picsOff() || videosOff() || padOff() || pdfOff() // Mkdir icon window.mkdirBtn = function () { const folder = prompt('new folder name', '') if (folder && !isDupe(folder)) { mkdirCall(folder, refresh) } } // Icon click handler const getBtnA = e => e.target.closest('tr').querySelector('a') window.rm = e => { if (window.ro) return true clearTimeout(window.clickToken) const target = e.key ? getASelected() : getBtnA(e) if (target.innerText === '../') return if (rmMsg()) return moveArrow() rmCall(decode(target.href), refresh) } window.rename = (e, commit) => { if (window.ro) return true clearTimeout(window.clickToken) if (!commit) { window.clickToken = setTimeout(window.rename, 300, e, true) return } const target = e.key ? getASelected() : getBtnA(e) if (target.innerText === '../') return const chg = prompt('rename to', target.innerText) if (chg && !isDupe(chg)) { mvCall(prependPath(target.innerText), prependPath(chg), refresh) } } function aboveBelowRightin (el) { const itemPos = el.getBoundingClientRect() return itemPos.top < 0 ? -1 : itemPos.bottom > window.innerHeight ? 1 : 0 } function scrollToArrow () { const el = getASelected() while (1) { const pos = aboveBelowRightin(el) if (pos === -1) { scrollBy(0, -300) } else if (pos === 1) { scrollBy(0, 300) } else { break } } } function clearArrowSelected () { const arr = getArrowSelected() if (!arr) { return } arr.classList.remove('arrow-selected') } window.setCursorTo = setCursorTo function setCursorTo (where) { if (!where) return false clearArrowSelected() let a = allA.find(el => el.innerText === where || el.innerText === where + '/') if (!a) { if (allA[0].innerText === '../') { a = allA[1] || allA[0] } else { a = allA[0] } } const icon = a.parentElement.parentElement.querySelectorAll('.arrow-icon')[0] icon.classList.add('arrow-selected') scrollToArrow() storeArrow(where) return true } function moveArrow (down) { const all = Array.from(document.querySelectorAll('.arrow-icon')) let i = all.findIndex(el => el.classList.contains('arrow-selected')) clearArrowSelected() if (down) { i = all[i + 1] ? i + 1 : 0 } else { i = all[i - 1] ? i - 1 : all.length - 1 } all[i].classList.add('arrow-selected') storeArrow(getASelected().innerText) scrollToArrow() } const storeArrow = src => localStorage.setItem('last-selected' + window.extraPath + location.pathname, src) const isTop = () => window.scrollY === 0 const isBottom = () => (window.innerHeight + window.scrollY) >= document.body.offsetHeight const hasScroll = () => table.clientHeight > window.innerHeight function movePage (up) { const current = getASelected().href if (!hasScroll()) return