mirror of
https://github.com/filebrowser/filebrowser.git
synced 2024-06-07 23:00:43 +00:00
0a65393527
Former-commit-id: 2d19655aac80ec7033829b0b3d708bf86986252c [formerly b8bb006bd1a5492960c1d4793e15e80775ddc5fd] [formerly 4641277c14953bdb2ddab89ba866cf63f3dac0f9 [formerly 95b91a64a3
]]
Former-commit-id: 5a6e07758bbe67fd202effa5b2975c65227eaebd [formerly 9a161548d270750b8da949189ad6f3b641779bfc]
Former-commit-id: 84e0bbcbbead53c5e91987574d5c854a9792515f
567 lines
15 KiB
JavaScript
567 lines
15 KiB
JavaScript
'use strict'
|
|
|
|
var listing = {
|
|
selectMultiple: false,
|
|
reload: function (callback) {
|
|
let request = new window.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()
|
|
}
|
|
}
|
|
}
|
|
}
|
|
},
|
|
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)
|
|
},
|
|
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
|
|
},
|
|
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))
|
|
},
|
|
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
|
|
})
|
|
}
|
|
},
|
|
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
|
|
let field = item.querySelector('.name')
|
|
let name = field.innerHTML
|
|
|
|
let submit = (event) => {
|
|
event.preventDefault()
|
|
|
|
let newName = event.currentTarget.querySelector('input').value
|
|
let 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
|
|
},
|
|
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.rename.classList.add('disabled')
|
|
buttons.info.classList.add('disabled')
|
|
}
|
|
|
|
if (selectedNumber == 1) {
|
|
buttons.info.classList.remove('disabled')
|
|
buttons.rename.classList.remove('disabled')
|
|
}
|
|
|
|
return false
|
|
}
|
|
|
|
buttons.info.classList.remove('disabled')
|
|
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')
|
|
|
|
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.move.addEventListener('click', listing.moveEvent)
|
|
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)
|
|
}
|
|
})
|