'use strict' var listing = { selectMultiple: false } listing.reload = function (callback) { let request = new XMLHttpRequest() request.open('GET', window.location) request.setRequestHeader('Minimal', 'true') request.send() request.onreadystatechange = function () { if (request.readyState === 4) { if (request.status === 200) { document.querySelector('body main').innerHTML = request.responseText listing.addDoubleTapEvent() if (typeof callback === 'function') { callback() } } } } } listing.itemDragStart = function (event) { let el = event.target for (let i = 0; i < 5; i++) { if (!el.classList.contains('item')) { el = el.parentElement } } event.dataTransfer.setData('id', el.id) event.dataTransfer.setData('name', el.querySelector('.name').innerHTML) } listing.itemDragOver = function (event) { event.preventDefault() let el = event.target for (let i = 0; i < 5; i++) { if (!el.classList.contains('item')) { el = el.parentElement } } el.style.opacity = 1 } listing.itemDrop = function (e) { e.preventDefault() let el = e.target, id = e.dataTransfer.getData('id'), name = e.dataTransfer.getData('name') if (id == '' || name == '') return for (let i = 0; i < 5; i++) { if (!el.classList.contains('item')) { el = el.parentElement } } if (el.id === id) return let oldLink = document.getElementById(id).dataset.url, newLink = el.dataset.url + name webdav.move(oldLink, newLink) .then(() => listing.reload()) .catch(e => console.log(e)) } listing.documentDrop = function (event) { event.preventDefault() let dt = event.dataTransfer, files = dt.files, el = event.target, items = document.getElementsByClassName('item') for (let i = 0; i < 5; i++) { if (el != null && !el.classList.contains('item')) { el = el.parentElement } } if (files.length > 0) { if (el != null && el.classList.contains('item') && el.dataset.dir == 'true') { listing.handleFiles(files, el.querySelector('.name').innerHTML + '/') return } listing.handleFiles(files, '') } else { Array.from(items).forEach(file => { file.style.opacity = 1 }) } } listing.rename = function (event) { if (!selectedItems.length || selectedItems.length > 1) { return false } let item = document.getElementById(selectedItems[0]) if (item.classList.contains('disabled')) { return false } let link = item.dataset.url, field = item.querySelector('.name'), name = field.innerHTML let submit = (event) => { event.preventDefault() let newName = event.currentTarget.querySelector('input').value, newLink = removeLastDirectoryPartOf(link) + '/' + newName closePrompt(event) buttons.setLoading('rename') webdav.move(link, newLink).then(() => { listing.reload(() => { newName = btoa(newName) selectedItems = [newName] document.getElementById(newName).setAttribute('aria-selected', true) listing.handleSelectionChange() }) buttons.setDone('rename') }).catch(error => { field.innerHTML = name buttons.setDone('rename', false) console.log(error) }) return false } let clone = document.importNode(templates.question.content, true) clone.querySelector('h3').innerHTML = 'Rename' clone.querySelector('input').value = name clone.querySelector('.ok').innerHTML = 'Rename' clone.querySelector('form').addEventListener('submit', submit) document.querySelector('body').appendChild(clone) document.querySelector('.overlay').classList.add('active') document.querySelector('.prompt').classList.add('active') return false } listing.handleFiles = function (files, base) { buttons.setLoading('upload') let promises = [] for (let file of files) { promises.push(webdav.put(window.location.pathname + base + file.name, file)) } Promise.all(promises) .then(() => { listing.reload() buttons.setDone('upload') }) .catch(e => { console.log(e) buttons.setDone('upload', false) }) return false } listing.unselectAll = function () { let items = document.getElementsByClassName('item') Array.from(items).forEach(link => { link.setAttribute('aria-selected', false) }) selectedItems = [] listing.handleSelectionChange() return false } listing.handleSelectionChange = function (event) { listing.redefineDownloadURLs() let selectedNumber = selectedItems.length, fileAction = document.getElementById('file-only') if (selectedNumber) { fileAction.classList.remove('disabled') if (selectedNumber > 1) { buttons.open.classList.add('disabled') buttons.rename.classList.add('disabled') } if (selectedNumber == 1) { if (document.getElementById(selectedItems[0]).dataset.dir == 'true') { buttons.open.classList.add('disabled') } else { buttons.open.classList.remove('disabled') } buttons.rename.classList.remove('disabled') } return false } fileAction.classList.add('disabled') return false } listing.redefineDownloadURLs = function () { let files = '' for (let i = 0; i < selectedItems.length; i++) { let url = document.getElementById(selectedItems[i]).dataset.url files += url.replace(window.location.pathname, '') + ',' } files = files.substring(0, files.length - 1) files = encodeURIComponent(files) let links = document.querySelectorAll('#download ul a') Array.from(links).forEach(link => { link.href = '?download=' + link.dataset.format + '&files=' + files }) } listing.openItem = function (event) { window.location = event.currentTarget.dataset.url } listing.selectItem = function (event) { let el = event.currentTarget if (selectedItems.length != 0) event.preventDefault() if (selectedItems.indexOf(el.id) == -1) { if (!event.ctrlKey && !listing.selectMultiple) listing.unselectAll() el.setAttribute('aria-selected', true) selectedItems.push(el.id) } else { el.setAttribute('aria-selected', false) selectedItems.removeElement(el.id) } listing.handleSelectionChange() return false } listing.newFileButton = function (event) { event.preventDefault() let clone = document.importNode(templates.question.content, true) clone.querySelector('h3').innerHTML = 'New file' clone.querySelector('p').innerHTML = 'End with a trailing slash to create a dir.' clone.querySelector('.ok').innerHTML = 'Create' clone.querySelector('form').addEventListener('submit', listing.newFilePrompt) document.querySelector('body').appendChild(clone) document.querySelector('.overlay').classList.add('active') document.querySelector('.prompt').classList.add('active') } listing.newFilePrompt = function (event) { event.preventDefault() buttons.setLoading('new') let name = event.currentTarget.querySelector('input').value webdav.new(window.location.pathname + name) .then(() => { buttons.setDone('new') listing.reload() }) .catch(e => { console.log(e) buttons.setDone('new', false) }) closePrompt(event) return false } listing.updateColumns = function (event) { let columns = Math.floor(document.getElementById('listing').offsetWidth / 300), items = getCSSRule(['#listing.mosaic .item', '.mosaic#listing .item']) items.style.width = `calc(${100/columns}% - 1em)` } listing.addDoubleTapEvent = function () { let items = document.getElementsByClassName('item'), touches = { id: '', count: 0 } Array.from(items).forEach(file => { file.addEventListener('touchstart', event => { if (touches.id != file.id) { touches.id = file.id touches.count = 1 setTimeout(() => { touches.count = 0 }, 300) return } touches.count++ if (touches.count > 1) { window.location = file.dataset.url } }) }) } // Keydown events window.addEventListener('keydown', (event) => { if (event.keyCode == 27) { listing.unselectAll() if (document.querySelectorAll('.prompt').length) { closePrompt(event) } } if (event.keyCode == 113) { listing.rename() } if (event.ctrlKey || event.metaKey) { switch (String.fromCharCode(event.which).toLowerCase()) { case 's': event.preventDefault() window.location = '?download=true' } } }) window.addEventListener('resize', () => { listing.updateColumns() }) listing.selectMoveFolder = function (event) { if (event.target.getAttribute('aria-selected') === 'true') { event.target.setAttribute('aria-selected', false) return } else { if (document.querySelector('.file-list li[aria-selected=true]')) { document.querySelector('.file-list li[aria-selected=true]').setAttribute('aria-selected', false) } event.target.setAttribute('aria-selected', true) return } } listing.getJSON = function (link) { return new Promise((resolve, reject) => { let request = new XMLHttpRequest() request.open('GET', link) request.setRequestHeader('Accept', 'application/json') request.onload = () => { if (request.status == 200) { resolve(request.responseText) } else { reject(request.statusText) } } request.onerror = () => reject(request.statusText) request.send() }) } listing.moveMakeItem = function (url, name) { let node = document.createElement('li'), count = 0 node.dataset.url = url node.innerHTML = name node.setAttribute('aria-selected', false) node.addEventListener('dblclick', listing.moveDialogNext) node.addEventListener('click', listing.selectMoveFolder) node.addEventListener('touchstart', event => { count++ setTimeout(() => { count = 0 }, 300) if (count > 1) { listing.moveDialogNext(event) } }) return node } listing.moveDialogNext = function (event) { let request = new XMLHttpRequest(), prompt = document.querySelector('form.prompt.active'), list = prompt.querySelector('div.file-list ul') prompt.addEventListener('submit', listing.moveSelected) listing.getJSON(event.target.dataset.url) .then((data) => { let dirs = 0 prompt.querySelector('ul').innerHTML = '' prompt.querySelector('code').innerHTML = event.target.dataset.url if (event.target.dataset.url != baseURL + '/') { let node = listing.moveMakeItem(removeLastDirectoryPartOf(event.target.dataset.url) + '/', '..') list.appendChild(node) } if (JSON.parse(data) == null) { prompt.querySelector('p').innerHTML = `There aren't any folders in this directory.` return } for (let f of JSON.parse(data)) { if (f.IsDir === true) { dirs++ list.appendChild(listing.moveMakeItem(f.URL, f.Name)) } } if (dirs === 0) prompt.querySelector('p').innerHTML = `There aren't any folders in this directory.` }) .catch(e => console.log(e)) } listing.moveSelected = function (event) { event.preventDefault() let promises = [] buttons.setLoading('move') for (let file of selectedItems) { let fileElement = document.getElementById(file), destFolder = event.target.querySelector('p code').innerHTML if (event.currentTarget.querySelector('li[aria-selected=true]') != null) { destFolder = event.currentTarget.querySelector('li[aria-selected=true]').dataset.url } let destPath = '/' + destFolder + '/' + fileElement.querySelector('.name').innerHTML destPath = destPath.replace('//', '/') promises.push(webdav.move(fileElement.dataset.url, destPath)) } Promise.all(promises) .then(() => { closePrompt(event) buttons.setDone('move') listing.reload() }) .catch(e => { console.log(e) }) } listing.moveEvent = function (event) { if (event.currentTarget.classList.contains('disabled')) return listing.getJSON(window.location.pathname) .then((data) => { let prompt = document.importNode(templates.move.content, true), list = prompt.querySelector('div.file-list ul'), dirs = 0 prompt.querySelector('form').addEventListener('submit', listing.moveSelected) prompt.querySelector('code').innerHTML = window.location.pathname if (window.location.pathname !== baseURL + '/') { list.appendChild(listing.moveMakeItem(removeLastDirectoryPartOf(window.location.pathname) + '/', '..')) } for (let f of JSON.parse(data)) { if (f.IsDir === true) { dirs++ list.appendChild(listing.moveMakeItem(f.URL, f.Name)) } } if (dirs === 0) { prompt.querySelector('p').innerHTML = `There aren't any folders in this directory.` } document.body.appendChild(prompt) document.querySelector('.overlay').classList.add('active') document.querySelector('.prompt').classList.add('active') }) .catch(e => console.log(e)) } document.addEventListener('DOMContentLoaded', event => { listing.updateColumns() listing.addDoubleTapEvent() buttons.rename = document.getElementById('rename') buttons.upload = document.getElementById('upload') buttons.new = document.getElementById('new') buttons.download = document.getElementById('download') buttons.move = document.getElementById('move') buttons.move.addEventListener('click', listing.moveEvent) document.getElementById('multiple-selection-activate').addEventListener('click', event => { listing.selectMultiple = true clickOverlay.click() document.getElementById('multiple-selection').classList.add('active') document.querySelector('body').style.paddingBottom = '4em' }) document.getElementById('multiple-selection-cancel').addEventListener('click', event => { listing.selectMultiple = false document.querySelector('body').style.paddingBottom = '0' document.getElementById('multiple-selection').classList.remove('active') }) if (user.AllowEdit) { buttons.rename.addEventListener('click', listing.rename) } let items = document.getElementsByClassName('item') if (user.AllowNew) { buttons.upload.addEventListener('click', (event) => { document.getElementById('upload-input').click() }) buttons.new.addEventListener('click', listing.newFileButton) // Drag and Drop document.addEventListener('dragover', function (event) { event.preventDefault() }, false) document.addEventListener('dragenter', (event) => { Array.from(items).forEach(file => { file.style.opacity = 0.5 }) }, false) document.addEventListener('dragend', (event) => { Array.from(items).forEach(file => { file.style.opacity = 1 }) }, false) document.addEventListener('drop', listing.documentDrop, false) } })