remove gitignore
Former-commit-id: 1c703e0364c90481dac2a218892907fca2a66963
This commit is contained in:
685
_embed/public/js/common.js
Normal file
685
_embed/public/js/common.js
Normal file
@@ -0,0 +1,685 @@
|
||||
'use strict'
|
||||
|
||||
var tempID = '_fm_internal_temporary_id'
|
||||
var ssl = (window.location.protocol === 'https:')
|
||||
var templates = {}
|
||||
var selectedItems = []
|
||||
var overlay
|
||||
var clickOverlay
|
||||
|
||||
// Removes an element, if exists, from an array
|
||||
Array.prototype.removeElement = function (element) {
|
||||
var i = this.indexOf(element)
|
||||
if (i !== -1) {
|
||||
this.splice(i, 1)
|
||||
}
|
||||
}
|
||||
|
||||
// Replaces an element inside an array by another
|
||||
Array.prototype.replaceElement = function (oldElement, newElement) {
|
||||
var i = this.indexOf(oldElement)
|
||||
if (i !== -1) {
|
||||
this[i] = newElement
|
||||
}
|
||||
}
|
||||
|
||||
// Sends a costum event to itself
|
||||
Document.prototype.sendCostumEvent = function (text) {
|
||||
this.dispatchEvent(new window.CustomEvent(text))
|
||||
}
|
||||
|
||||
// Gets the content of a cookie
|
||||
Document.prototype.getCookie = function (name) {
|
||||
var re = new RegExp('(?:(?:^|.*;\\s*)' + name + '\\s*\\=\\s*([^;]*).*$)|^.*$')
|
||||
return document.cookie.replace(re, '$1')
|
||||
}
|
||||
|
||||
// Remove the last directory of an url
|
||||
var removeLastDirectoryPartOf = function (url) {
|
||||
var arr = url.split('/')
|
||||
if (arr.pop() === '') {
|
||||
arr.pop()
|
||||
}
|
||||
return (arr.join('/'))
|
||||
}
|
||||
|
||||
function getCSSRule (rules) {
|
||||
for (let i = 0; i < rules.length; i++) {
|
||||
rules[i] = rules[i].toLowerCase()
|
||||
}
|
||||
|
||||
let result = null
|
||||
let find = Array.prototype.find
|
||||
|
||||
find.call(document.styleSheets, styleSheet => {
|
||||
result = find.call(styleSheet.cssRules, cssRule => {
|
||||
let found = false
|
||||
|
||||
if (cssRule instanceof CSSStyleRule) {
|
||||
for (let i = 0; i < rules.length; i++) {
|
||||
if (cssRule.selectorText.toLowerCase() === rules[i]) {
|
||||
found = true
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return found
|
||||
})
|
||||
|
||||
return result != null
|
||||
})
|
||||
|
||||
return result
|
||||
}
|
||||
|
||||
/* * * * * * * * * * * * * * * *
|
||||
* *
|
||||
* BUTTONS *
|
||||
* *
|
||||
* * * * * * * * * * * * * * * */
|
||||
var buttons = {
|
||||
previousState: {}
|
||||
}
|
||||
|
||||
buttons.setLoading = function (name) {
|
||||
if (typeof this[name] === 'undefined') return
|
||||
let i = this[name].querySelector('i')
|
||||
|
||||
this.previousState[name] = i.innerHTML
|
||||
i.style.opacity = 0
|
||||
|
||||
setTimeout(function () {
|
||||
i.classList.add('spin')
|
||||
i.innerHTML = 'autorenew'
|
||||
i.style.opacity = 1
|
||||
}, 200)
|
||||
}
|
||||
|
||||
// Changes an element to done animation
|
||||
buttons.setDone = function (name, success = true) {
|
||||
let i = this[name].querySelector('i')
|
||||
|
||||
i.style.opacity = 0
|
||||
|
||||
let thirdStep = () => {
|
||||
i.innerHTML = this.previousState[name]
|
||||
i.style.opacity = null
|
||||
|
||||
if (selectedItems.length === 0 && document.getElementById('listing')) {
|
||||
document.sendCostumEvent('changed-selected')
|
||||
}
|
||||
}
|
||||
|
||||
let secondStep = () => {
|
||||
i.style.opacity = 0
|
||||
setTimeout(thirdStep, 200)
|
||||
}
|
||||
|
||||
let firstStep = () => {
|
||||
i.classList.remove('spin')
|
||||
i.innerHTML = success
|
||||
? 'done'
|
||||
: 'close'
|
||||
i.style.opacity = 1
|
||||
setTimeout(secondStep, 1000)
|
||||
}
|
||||
|
||||
setTimeout(firstStep, 200)
|
||||
return false
|
||||
}
|
||||
|
||||
/* * * * * * * * * * * * * * * *
|
||||
* *
|
||||
* WEBDAV *
|
||||
* *
|
||||
* * * * * * * * * * * * * * * */
|
||||
var webdav = {}
|
||||
|
||||
webdav.convertURL = function (url) {
|
||||
return window.location.origin + url.replace(baseURL + '/', webdavURL + '/')
|
||||
}
|
||||
|
||||
webdav.move = function (oldLink, newLink) {
|
||||
return new Promise((resolve, reject) => {
|
||||
let request = new window.XMLHttpRequest()
|
||||
let destination = newLink.replace(baseURL + '/', webdavURL + '/')
|
||||
|
||||
destination = window.location.origin + destination.substring(prefixURL.length)
|
||||
|
||||
request.open('MOVE', webdav.convertURL(oldLink), true)
|
||||
request.setRequestHeader('Destination', destination)
|
||||
request.onload = () => {
|
||||
if (request.status === 201 || request.status === 204) {
|
||||
resolve()
|
||||
} else {
|
||||
reject(request.statusText)
|
||||
}
|
||||
}
|
||||
request.onerror = () => reject(request.statusText)
|
||||
request.send()
|
||||
})
|
||||
}
|
||||
|
||||
webdav.put = function (link, body, headers = {}) {
|
||||
return new Promise((resolve, reject) => {
|
||||
let request = new window.XMLHttpRequest()
|
||||
request.open('PUT', webdav.convertURL(link), true)
|
||||
|
||||
for (let key in headers) {
|
||||
request.setRequestHeader(key, headers[key])
|
||||
}
|
||||
|
||||
request.onload = () => {
|
||||
if (request.status == 201) {
|
||||
resolve()
|
||||
} else {
|
||||
reject(request.statusText)
|
||||
}
|
||||
}
|
||||
request.onerror = () => reject(request.statusText)
|
||||
request.send(body)
|
||||
})
|
||||
}
|
||||
|
||||
webdav.propfind = function (link, body, headers = {}) {
|
||||
return new Promise((resolve, reject) => {
|
||||
let request = new window.XMLHttpRequest()
|
||||
request.open('PROPFIND', webdav.convertURL(link), true)
|
||||
|
||||
for (let key in headers) {
|
||||
request.setRequestHeader(key, headers[key])
|
||||
}
|
||||
|
||||
request.onload = () => {
|
||||
if (request.status < 300) {
|
||||
resolve(request.responseText)
|
||||
} else {
|
||||
reject(request.statusText)
|
||||
}
|
||||
}
|
||||
request.onerror = () => reject(request.statusText)
|
||||
request.send(body)
|
||||
})
|
||||
}
|
||||
|
||||
webdav.delete = function (link) {
|
||||
return new Promise((resolve, reject) => {
|
||||
let request = new window.XMLHttpRequest()
|
||||
request.open('DELETE', webdav.convertURL(link), true)
|
||||
request.onload = () => {
|
||||
if (request.status === 204) {
|
||||
resolve()
|
||||
} else {
|
||||
reject(request.statusText)
|
||||
}
|
||||
}
|
||||
request.onerror = () => reject(request.statusText)
|
||||
request.send()
|
||||
})
|
||||
}
|
||||
|
||||
webdav.new = function (link) {
|
||||
return new Promise((resolve, reject) => {
|
||||
let request = new window.XMLHttpRequest()
|
||||
request.open((link.endsWith('/') ? 'MKCOL' : 'PUT'), webdav.convertURL(link), true)
|
||||
request.onload = () => {
|
||||
if (request.status === 201) {
|
||||
resolve()
|
||||
} else {
|
||||
reject(request.statusText)
|
||||
}
|
||||
}
|
||||
request.onerror = () => reject(request.statusText)
|
||||
request.send()
|
||||
})
|
||||
}
|
||||
|
||||
/* * * * * * * * * * * * * * * *
|
||||
* *
|
||||
* EVENTS *
|
||||
* *
|
||||
* * * * * * * * * * * * * * * */
|
||||
function closePrompt (event) {
|
||||
let prompt = document.querySelector('.prompt')
|
||||
|
||||
if (!prompt) return
|
||||
|
||||
if (typeof event !== 'undefined') {
|
||||
event.preventDefault()
|
||||
}
|
||||
|
||||
document.querySelector('.overlay').classList.remove('active')
|
||||
prompt.classList.remove('active')
|
||||
|
||||
setTimeout(() => {
|
||||
prompt.remove()
|
||||
}, 100)
|
||||
}
|
||||
|
||||
function notImplemented (event) {
|
||||
event.preventDefault()
|
||||
clickOverlay.click()
|
||||
|
||||
let clone = document.importNode(templates.message.content, true)
|
||||
clone.querySelector('h3').innerHTML = 'Not implemented'
|
||||
clone.querySelector('p').innerHTML = "Sorry, but this feature wasn't implemented yet."
|
||||
|
||||
document.querySelector('body').appendChild(clone)
|
||||
document.querySelector('.overlay').classList.add('active')
|
||||
document.querySelector('.prompt').classList.add('active')
|
||||
}
|
||||
|
||||
// Prevent Default event
|
||||
var preventDefault = function (event) {
|
||||
event.preventDefault()
|
||||
}
|
||||
|
||||
function logoutEvent (event) {
|
||||
let request = new window.XMLHttpRequest()
|
||||
request.open('GET', window.location.pathname, true, 'username', 'password')
|
||||
request.send()
|
||||
request.onreadystatechange = function () {
|
||||
if (request.readyState === 4) {
|
||||
window.location = '/'
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
function openEvent (event) {
|
||||
if (event.currentTarget.classList.contains('disabled')) {
|
||||
return false
|
||||
}
|
||||
|
||||
let link = '?raw=true'
|
||||
|
||||
if (selectedItems.length) {
|
||||
link = document.getElementById(selectedItems[0]).dataset.url + link
|
||||
} else {
|
||||
link = window.location.pathname + link
|
||||
}
|
||||
|
||||
window.open(link)
|
||||
return false
|
||||
}
|
||||
|
||||
function getHash (event, hash) {
|
||||
event.preventDefault()
|
||||
|
||||
let request = new window.XMLHttpRequest()
|
||||
let link
|
||||
|
||||
if (selectedItems.length) {
|
||||
link = document.getElementById(selectedItems[0]).dataset.url
|
||||
} else {
|
||||
link = window.location.pathname
|
||||
}
|
||||
|
||||
request.open('GET', `${link}?checksum=${hash}`, true)
|
||||
|
||||
request.onload = () => {
|
||||
if (request.status >= 300) {
|
||||
console.log(request.statusText)
|
||||
return
|
||||
}
|
||||
event.target.parentElement.innerHTML = request.responseText
|
||||
}
|
||||
request.onerror = (e) => console.log(e)
|
||||
request.send()
|
||||
}
|
||||
|
||||
function infoEvent (event) {
|
||||
event.preventDefault()
|
||||
if (event.currentTarget.classList.contains('disabled')) {
|
||||
return
|
||||
}
|
||||
|
||||
let dir = false
|
||||
let link
|
||||
|
||||
if (selectedItems.length) {
|
||||
link = document.getElementById(selectedItems[0]).dataset.url
|
||||
dir = document.getElementById(selectedItems[0]).dataset.dir
|
||||
} else {
|
||||
if (document.getElementById('listing') !== null) {
|
||||
dir = true
|
||||
}
|
||||
|
||||
link = window.location.pathname
|
||||
}
|
||||
|
||||
buttons.setLoading('info', false)
|
||||
|
||||
webdav.propfind(link)
|
||||
.then((text) => {
|
||||
let parser = new window.DOMParser()
|
||||
let xml = parser.parseFromString(text, 'text/xml')
|
||||
let clone = document.importNode(templates.info.content, true)
|
||||
|
||||
let value = xml.getElementsByTagName('displayname')
|
||||
if (value.length > 0) {
|
||||
clone.getElementById('display_name').innerHTML = value[0].innerHTML
|
||||
} else {
|
||||
clone.getElementById('display_name').innerHTML = xml.getElementsByTagName('D:displayname')[0].innerHTML
|
||||
}
|
||||
|
||||
value = xml.getElementsByTagName('getcontentlength')
|
||||
if (value.length > 0) {
|
||||
clone.getElementById('content_length').innerHTML = value[0].innerHTML
|
||||
} else {
|
||||
clone.getElementById('content_length').innerHTML = xml.getElementsByTagName('D:getcontentlength')[0].innerHTML
|
||||
}
|
||||
|
||||
value = xml.getElementsByTagName('getlastmodified')
|
||||
if (value.length > 0) {
|
||||
clone.getElementById('last_modified').innerHTML = value[0].innerHTML
|
||||
} else {
|
||||
clone.getElementById('last_modified').innerHTML = xml.getElementsByTagName('D:getlastmodified')[0].innerHTML
|
||||
}
|
||||
|
||||
if (dir === true || dir === 'true') {
|
||||
clone.querySelector('.file-only').style.display = 'none'
|
||||
}
|
||||
|
||||
document.querySelector('body').appendChild(clone)
|
||||
document.querySelector('.overlay').classList.add('active')
|
||||
document.querySelector('.prompt').classList.add('active')
|
||||
buttons.setDone('info', true)
|
||||
})
|
||||
.catch(e => {
|
||||
buttons.setDone('info', false)
|
||||
console.log(e)
|
||||
})
|
||||
}
|
||||
|
||||
function deleteOnSingleFile () {
|
||||
closePrompt()
|
||||
buttons.setLoading('delete')
|
||||
|
||||
webdav.delete(window.location.pathname)
|
||||
.then(() => {
|
||||
window.location.pathname = removeLastDirectoryPartOf(window.location.pathname)
|
||||
})
|
||||
.catch(e => {
|
||||
buttons.setDone('delete', false)
|
||||
console.log(e)
|
||||
})
|
||||
}
|
||||
|
||||
function deleteOnListing () {
|
||||
closePrompt()
|
||||
buttons.setLoading('delete')
|
||||
|
||||
let promises = []
|
||||
|
||||
for (let id of selectedItems) {
|
||||
promises.push(webdav.delete(document.getElementById(id).dataset.url))
|
||||
}
|
||||
|
||||
Promise.all(promises)
|
||||
.then(() => {
|
||||
listing.reload()
|
||||
buttons.setDone('delete')
|
||||
})
|
||||
.catch(e => {
|
||||
console.log(e)
|
||||
buttons.setDone('delete', false)
|
||||
})
|
||||
}
|
||||
|
||||
// Handles the delete button event
|
||||
function deleteEvent (event) {
|
||||
let single = false
|
||||
|
||||
if (!selectedItems.length) {
|
||||
selectedItems = ['placeholder']
|
||||
single = true
|
||||
}
|
||||
|
||||
let clone = document.importNode(templates.question.content, true)
|
||||
clone.querySelector('h3').innerHTML = 'Delete files'
|
||||
|
||||
if (single) {
|
||||
clone.querySelector('form').addEventListener('submit', deleteOnSingleFile)
|
||||
clone.querySelector('p').innerHTML = `Are you sure you want to delete this file/folder?`
|
||||
} else {
|
||||
clone.querySelector('form').addEventListener('submit', deleteOnListing)
|
||||
clone.querySelector('p').innerHTML = `Are you sure you want to delete ${selectedItems.length} file(s)?`
|
||||
}
|
||||
|
||||
clone.querySelector('input').remove()
|
||||
clone.querySelector('.ok').innerHTML = 'Delete'
|
||||
|
||||
document.body.appendChild(clone)
|
||||
document.querySelector('.overlay').classList.add('active')
|
||||
document.querySelector('.prompt').classList.add('active')
|
||||
|
||||
return false
|
||||
}
|
||||
|
||||
function resetSearchText () {
|
||||
let box = document.querySelector('#search > div div')
|
||||
|
||||
if (user.AllowCommands) {
|
||||
box.innerHTML = `Search or use one of your supported commands: ${user.Commands.join(", ")}.`
|
||||
} else {
|
||||
box.innerHTML = 'Type and press enter to search.'
|
||||
}
|
||||
}
|
||||
|
||||
function searchEvent (event) {
|
||||
if (this.value.length === 0) {
|
||||
resetSearchText()
|
||||
return
|
||||
}
|
||||
|
||||
let value = this.value,
|
||||
search = document.getElementById('search'),
|
||||
scrollable = document.querySelector('#search > div'),
|
||||
box = document.querySelector('#search > div div'),
|
||||
pieces = value.split(' '),
|
||||
supported = false
|
||||
|
||||
user.Commands.forEach(function (cmd) {
|
||||
if (cmd == pieces[0]) {
|
||||
supported = true
|
||||
}
|
||||
})
|
||||
|
||||
if (!supported || !user.AllowCommands) {
|
||||
box.innerHTML = 'Press enter to search.'
|
||||
} else {
|
||||
box.innerHTML = 'Press enter to execute.'
|
||||
}
|
||||
|
||||
if (event.keyCode === 13) {
|
||||
box.innerHTML = ''
|
||||
search.classList.add('ongoing')
|
||||
|
||||
let url = window.location.host + window.location.pathname
|
||||
|
||||
if (document.getElementById('editor')) {
|
||||
url = removeLastDirectoryPartOf(url)
|
||||
}
|
||||
|
||||
let protocol = ssl ? 'wss:' : 'ws:'
|
||||
|
||||
if (supported && user.AllowCommands) {
|
||||
let conn = new window.WebSocket(`${protocol}//${url}?command=true`)
|
||||
|
||||
conn.onopen = function () {
|
||||
conn.send(value)
|
||||
}
|
||||
|
||||
conn.onmessage = function (event) {
|
||||
box.innerHTML = event.data
|
||||
scrollable.scrollTop = scrollable.scrollHeight
|
||||
}
|
||||
|
||||
conn.onclose = function (event) {
|
||||
search.classList.remove('ongoing')
|
||||
listing.reload()
|
||||
}
|
||||
|
||||
return
|
||||
}
|
||||
|
||||
box.innerHTML = '<ul></ul>'
|
||||
|
||||
let ul = box.querySelector('ul')
|
||||
let conn = new window.WebSocket(`${protocol}//${url}?search=true`)
|
||||
|
||||
conn.onopen = function () {
|
||||
conn.send(value)
|
||||
}
|
||||
|
||||
conn.onmessage = function (event) {
|
||||
ul.innerHTML += '<li><a href="' + event.data + '">' + event.data + '</a></li>'
|
||||
scrollable.scrollTop = scrollable.scrollHeight
|
||||
}
|
||||
|
||||
conn.onclose = function (event) {
|
||||
search.classList.remove('ongoing')
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
function setupSearch () {
|
||||
let search = document.getElementById('search')
|
||||
let searchInput = search.querySelector('input')
|
||||
let searchDiv = search.querySelector('div')
|
||||
let hover = false
|
||||
let focus = false
|
||||
|
||||
resetSearchText()
|
||||
|
||||
searchInput.addEventListener('focus', event => {
|
||||
focus = true
|
||||
search.classList.add('active')
|
||||
})
|
||||
|
||||
searchDiv.addEventListener('mouseover', event => {
|
||||
hover = true
|
||||
search.classList.add('active')
|
||||
})
|
||||
|
||||
searchInput.addEventListener('blur', event => {
|
||||
focus = false
|
||||
if (hover) return
|
||||
search.classList.remove('active')
|
||||
})
|
||||
|
||||
search.addEventListener('mouseleave', event => {
|
||||
hover = false
|
||||
if (focus) return
|
||||
search.classList.remove('active')
|
||||
})
|
||||
|
||||
search.addEventListener('click', event => {
|
||||
search.classList.add('active')
|
||||
search.querySelector('input').focus()
|
||||
})
|
||||
|
||||
searchInput.addEventListener('keyup', searchEvent)
|
||||
}
|
||||
|
||||
function closeHelp (event) {
|
||||
event.preventDefault()
|
||||
|
||||
document.querySelector('.help').classList.remove('active')
|
||||
document.querySelector('.overlay').classList.remove('active')
|
||||
}
|
||||
|
||||
function openHelp (event) {
|
||||
closePrompt(event)
|
||||
|
||||
document.querySelector('.help').classList.add('active')
|
||||
document.querySelector('.overlay').classList.add('active')
|
||||
}
|
||||
|
||||
window.addEventListener('keydown', (event) => {
|
||||
if (event.keyCode === 27) {
|
||||
if (document.querySelector('.help.active')) {
|
||||
closeHelp(event)
|
||||
}
|
||||
}
|
||||
|
||||
if (event.keyCode === 46) {
|
||||
deleteEvent(event)
|
||||
}
|
||||
|
||||
if (event.keyCode === 112) {
|
||||
event.preventDefault()
|
||||
openHelp(event)
|
||||
}
|
||||
})
|
||||
|
||||
/* * * * * * * * * * * * * * * *
|
||||
* *
|
||||
* BOOTSTRAP *
|
||||
* *
|
||||
* * * * * * * * * * * * * * * */
|
||||
|
||||
document.addEventListener('DOMContentLoaded', function (event) {
|
||||
overlay = document.querySelector('.overlay')
|
||||
clickOverlay = document.querySelector('#click-overlay')
|
||||
|
||||
buttons.logout = document.getElementById('logout')
|
||||
buttons.open = document.getElementById('open')
|
||||
buttons.delete = document.getElementById('delete')
|
||||
buttons.previous = document.getElementById('previous')
|
||||
buttons.info = document.getElementById('info')
|
||||
|
||||
// Attach event listeners
|
||||
buttons.logout.addEventListener('click', logoutEvent)
|
||||
buttons.open.addEventListener('click', openEvent)
|
||||
buttons.info.addEventListener('click', infoEvent)
|
||||
|
||||
templates.question = document.querySelector('#question-template')
|
||||
templates.info = document.querySelector('#info-template')
|
||||
templates.message = document.querySelector('#message-template')
|
||||
templates.move = document.querySelector('#move-template')
|
||||
|
||||
if (user.AllowEdit) {
|
||||
buttons.delete.addEventListener('click', deleteEvent)
|
||||
}
|
||||
|
||||
let dropdownButtons = document.querySelectorAll('.action[data-dropdown]')
|
||||
Array.from(dropdownButtons).forEach(button => {
|
||||
button.addEventListener('click', event => {
|
||||
button.querySelector('ul').classList.toggle('active')
|
||||
clickOverlay.classList.add('active')
|
||||
|
||||
clickOverlay.addEventListener('click', event => {
|
||||
button.querySelector('ul').classList.remove('active')
|
||||
clickOverlay.classList.remove('active')
|
||||
})
|
||||
})
|
||||
})
|
||||
|
||||
overlay.addEventListener('click', event => {
|
||||
if (document.querySelector('.help.active')) {
|
||||
closeHelp(event)
|
||||
return
|
||||
}
|
||||
|
||||
closePrompt(event)
|
||||
})
|
||||
|
||||
let mainActions = document.getElementById('main-actions')
|
||||
|
||||
document.getElementById('more').addEventListener('click', event => {
|
||||
event.preventDefault()
|
||||
event.stopPropagation()
|
||||
|
||||
clickOverlay.classList.add('active')
|
||||
mainActions.classList.add('active')
|
||||
|
||||
clickOverlay.addEventListener('click', event => {
|
||||
mainActions.classList.remove('active')
|
||||
clickOverlay.classList.remove('active')
|
||||
})
|
||||
})
|
||||
|
||||
setupSearch()
|
||||
return false
|
||||
})
|
||||
278
_embed/public/js/editor.js
Normal file
278
_embed/public/js/editor.js
Normal file
@@ -0,0 +1,278 @@
|
||||
'use strict'
|
||||
|
||||
var editor = {}
|
||||
|
||||
editor.textareaAutoGrow = function () {
|
||||
let autogrow = function () {
|
||||
console.log(this.style.height)
|
||||
this.style.height = 'auto'
|
||||
this.style.height = (this.scrollHeight) + 'px'
|
||||
}
|
||||
|
||||
let textareas = document.getElementsByTagName('textarea')
|
||||
|
||||
let addAutoGrow = () => {
|
||||
Array.from(textareas).forEach(textarea => {
|
||||
autogrow.bind(textarea)()
|
||||
textarea.addEventListener('keyup', autogrow)
|
||||
})
|
||||
}
|
||||
|
||||
addAutoGrow()
|
||||
window.addEventListener('resize', addAutoGrow)
|
||||
}
|
||||
|
||||
editor.toggleSourceEditor = function (event) {
|
||||
event.preventDefault()
|
||||
|
||||
if (document.querySelector('[data-kind="content-only"]')) {
|
||||
window.location = window.location.pathname + '?visual=true'
|
||||
return
|
||||
}
|
||||
|
||||
window.location = window.location.pathname + '?visual=false'
|
||||
}
|
||||
|
||||
function deleteFrontMatterItem (event) {
|
||||
event.preventDefault()
|
||||
document.getElementById(this.dataset.delete).remove()
|
||||
}
|
||||
|
||||
function makeFromBaseTemplate (id, type, name, parent) {
|
||||
let clone = document.importNode(templates.base.content, true)
|
||||
clone.querySelector('fieldset').id = id
|
||||
clone.querySelector('fieldset').dataset.type = type
|
||||
clone.querySelector('h3').innerHTML = name
|
||||
clone.querySelector('.delete').dataset.delete = id
|
||||
clone.querySelector('.delete').addEventListener('click', deleteFrontMatterItem)
|
||||
clone.querySelector('.add').addEventListener('click', addFrontMatterItem)
|
||||
|
||||
if (parent.classList.contains('frontmatter')) {
|
||||
parent.insertBefore(clone, document.querySelector('div.button.add'))
|
||||
return
|
||||
}
|
||||
|
||||
parent.appendChild(clone)
|
||||
}
|
||||
|
||||
function makeFromArrayItemTemplate (id, number, parent) {
|
||||
let clone = document.importNode(templates.arrayItem.content, true)
|
||||
clone.querySelector('[data-type="array-item"]').id = `${id}-${number}`
|
||||
clone.querySelector('input').name = id
|
||||
clone.querySelector('input').id = id
|
||||
clone.querySelector('div.action').dataset.delete = `${id}-${number}`
|
||||
clone.querySelector('div.action').addEventListener('click', deleteFrontMatterItem)
|
||||
parent.querySelector('.group').appendChild(clone)
|
||||
document.getElementById(`${id}-${number}`).querySelector('input').focus()
|
||||
}
|
||||
|
||||
function makeFromObjectItemTemplate (id, name, parent) {
|
||||
let clone = document.importNode(templates.objectItem.content, true)
|
||||
clone.querySelector('.block').id = `block-${id}`
|
||||
clone.querySelector('.block').dataset.content = id
|
||||
clone.querySelector('label').for = id
|
||||
clone.querySelector('label').innerHTML = name
|
||||
clone.querySelector('input').name = id
|
||||
clone.querySelector('input').id = id
|
||||
clone.querySelector('.action').dataset.delete = `block-${id}`
|
||||
clone.querySelector('.action').addEventListener('click', deleteFrontMatterItem)
|
||||
|
||||
parent.appendChild(clone)
|
||||
document.getElementById(id).focus()
|
||||
}
|
||||
|
||||
function addFrontMatterItemPrompt (parent) {
|
||||
return function (event) {
|
||||
event.preventDefault()
|
||||
|
||||
let value = event.currentTarget.querySelector('input').value
|
||||
if (value === '') {
|
||||
return true
|
||||
}
|
||||
|
||||
closePrompt(event)
|
||||
|
||||
let name = value.substring(0, value.lastIndexOf(':')),
|
||||
type = value.substring(value.lastIndexOf(':') + 1, value.length)
|
||||
|
||||
if (type !== '' && type !== 'array' && type !== 'object') {
|
||||
name = value
|
||||
}
|
||||
|
||||
name = name.replace(' ', '_')
|
||||
|
||||
let id = name
|
||||
|
||||
if (parent.id != '') {
|
||||
id = parent.id + '.' + id
|
||||
}
|
||||
|
||||
if (type == 'array' || type == 'object') {
|
||||
if (parent.dataset.type == 'parent') {
|
||||
makeFromBaseTemplate(id, type, name, document.querySelector('.frontmatter'))
|
||||
return
|
||||
}
|
||||
|
||||
makeFromBaseTemplate(id, type, name, block)
|
||||
return
|
||||
}
|
||||
|
||||
let group = parent.querySelector('.group')
|
||||
|
||||
if (group == null) {
|
||||
parent.insertAdjacentHTML('afterbegin', '<div class="group"></div>')
|
||||
group = parent.querySelector('.group')
|
||||
}
|
||||
|
||||
makeFromObjectItemTemplate(id, name, group)
|
||||
}
|
||||
}
|
||||
|
||||
function addFrontMatterItem (event) {
|
||||
event.preventDefault()
|
||||
|
||||
let parent = event.currentTarget.parentNode,
|
||||
type = parent.dataset.type
|
||||
|
||||
// If the block is an array
|
||||
if (type === 'array') {
|
||||
let id = parent.id + '[]',
|
||||
count = parent.querySelectorAll('.group > div').length,
|
||||
fieldsets = parent.getElementsByTagName('fieldset')
|
||||
|
||||
if (fieldsets.length > 0) {
|
||||
let itemType = fieldsets[0].dataset.type,
|
||||
itemID = parent.id + '[' + fieldsets.length + ']',
|
||||
itemName = fieldsets.length
|
||||
|
||||
makeFromBaseTemplate(itemID, itemType, itemName, parent)
|
||||
} else {
|
||||
makeFromArrayItemTemplate(id, count, parent)
|
||||
}
|
||||
|
||||
return
|
||||
}
|
||||
|
||||
if (type == 'object' || type == 'parent') {
|
||||
let clone = document.importNode(templates.question.content, true)
|
||||
clone.querySelector('form').id = tempID
|
||||
clone.querySelector('h3').innerHTML = 'New field'
|
||||
clone.querySelector('p').innerHTML = 'Write the field name and then press enter. If you want to create an array or an object, end the name with <code>:array</code> or <code>:object.</code>'
|
||||
clone.querySelector('.ok').innerHTML = 'Create'
|
||||
clone.querySelector('form').addEventListener('submit', addFrontMatterItemPrompt(parent))
|
||||
clone.querySelector('form').classList.add('active')
|
||||
document.querySelector('body').appendChild(clone)
|
||||
|
||||
document.querySelector('.overlay').classList.add('active')
|
||||
document.getElementById(tempID).classList.add('active')
|
||||
}
|
||||
|
||||
return false
|
||||
}
|
||||
|
||||
document.addEventListener('DOMContentLoaded', (event) => {
|
||||
if (!document.getElementById('editor')) return
|
||||
|
||||
editor.textareaAutoGrow()
|
||||
|
||||
templates.arrayItem = document.getElementById('array-item-template')
|
||||
templates.base = document.getElementById('base-template')
|
||||
templates.objectItem = document.getElementById('object-item-template')
|
||||
templates.temporary = document.getElementById('temporary-template')
|
||||
|
||||
buttons.save = document.querySelector('#save')
|
||||
buttons.editSource = document.querySelector('#edit-source')
|
||||
|
||||
if (buttons.editSource) {
|
||||
buttons.editSource.addEventListener('click', editor.toggleSourceEditor)
|
||||
}
|
||||
|
||||
let container = document.getElementById('editor'),
|
||||
kind = container.dataset.kind,
|
||||
rune = container.dataset.rune
|
||||
|
||||
if (kind != 'frontmatter-only') {
|
||||
let editor = document.querySelector('.content #ace'),
|
||||
mode = editor.dataset.mode,
|
||||
textarea = document.querySelector('textarea[name="content"]'),
|
||||
aceEditor = ace.edit('ace'),
|
||||
options = {
|
||||
wrap: true,
|
||||
maxLines: Infinity,
|
||||
theme: 'ace/theme/github',
|
||||
showPrintMargin: false,
|
||||
fontSize: '1em',
|
||||
minLines: 20
|
||||
}
|
||||
|
||||
aceEditor.getSession().setMode('ace/mode/' + mode)
|
||||
aceEditor.getSession().setValue(textarea.value)
|
||||
aceEditor.getSession().on('change', function () {
|
||||
textarea.value = aceEditor.getSession().getValue()
|
||||
})
|
||||
|
||||
if (mode == 'markdown') options.showGutter = false
|
||||
aceEditor.setOptions(options)
|
||||
}
|
||||
|
||||
let deleteFrontMatterItemButtons = document.getElementsByClassName('delete')
|
||||
Array.from(deleteFrontMatterItemButtons).forEach(button => {
|
||||
button.addEventListener('click', deleteFrontMatterItem)
|
||||
})
|
||||
|
||||
let addFrontMatterItemButtons = document.getElementsByClassName('add')
|
||||
Array.from(addFrontMatterItemButtons).forEach(button => {
|
||||
button.addEventListener('click', addFrontMatterItem)
|
||||
})
|
||||
|
||||
let saveContent = function () {
|
||||
let data = form2js(document.querySelector('form'))
|
||||
|
||||
if (typeof data.content === 'undefined' && kind !== 'frontmatter-only') {
|
||||
data.content = ''
|
||||
}
|
||||
|
||||
if (typeof data.content === 'number') {
|
||||
data.content = data.content.toString()
|
||||
}
|
||||
|
||||
let request = new XMLHttpRequest()
|
||||
|
||||
buttons.setLoading('save')
|
||||
|
||||
webdav.put(window.location.pathname, JSON.stringify(data), {
|
||||
'Kind': kind,
|
||||
'Rune': rune
|
||||
})
|
||||
.then(() => {
|
||||
buttons.setDone('save')
|
||||
})
|
||||
.catch(e => {
|
||||
console.log(e)
|
||||
buttons.setDone('save', false)
|
||||
})
|
||||
}
|
||||
|
||||
document.querySelector('#save').addEventListener('click', event => {
|
||||
event.preventDefault()
|
||||
saveContent()
|
||||
})
|
||||
|
||||
document.querySelector('form').addEventListener('submit', (event) => {
|
||||
event.preventDefault()
|
||||
saveContent()
|
||||
})
|
||||
|
||||
window.addEventListener('keydown', (event) => {
|
||||
if (event.ctrlKey || event.metaKey) {
|
||||
switch (String.fromCharCode(event.which).toLowerCase()) {
|
||||
case 's':
|
||||
event.preventDefault()
|
||||
saveContent()
|
||||
break
|
||||
}
|
||||
}
|
||||
})
|
||||
|
||||
return false
|
||||
})
|
||||
580
_embed/public/js/listing.js
Normal file
580
_embed/public/js/listing.js
Normal file
@@ -0,0 +1,580 @@
|
||||
'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')
|
||||
buttons.info.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.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)
|
||||
}
|
||||
})
|
||||
356
_embed/public/js/vendor/form2js.js
vendored
Normal file
356
_embed/public/js/vendor/form2js.js
vendored
Normal file
@@ -0,0 +1,356 @@
|
||||
/**
|
||||
* Copyright (c) 2010 Maxim Vasiliev
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
* of this software and associated documentation files (the "Software"), to deal
|
||||
* in the Software without restriction, including without limitation the rights
|
||||
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
* copies of the Software, and to permit persons to whom the Software is
|
||||
* furnished to do so, subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included in
|
||||
* all copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||
* THE SOFTWARE.
|
||||
*
|
||||
* @author Maxim Vasiliev
|
||||
* Date: 09.09.2010
|
||||
* Time: 19:02:33
|
||||
*/
|
||||
|
||||
|
||||
(function (root, factory)
|
||||
{
|
||||
if (typeof exports !== 'undefined' && typeof module !== 'undefined' && module.exports) {
|
||||
// NodeJS
|
||||
module.exports = factory();
|
||||
}
|
||||
else if (typeof define === 'function' && define.amd)
|
||||
{
|
||||
// AMD. Register as an anonymous module.
|
||||
define(factory);
|
||||
}
|
||||
else
|
||||
{
|
||||
// Browser globals
|
||||
root.form2js = factory();
|
||||
}
|
||||
}(this, function ()
|
||||
{
|
||||
"use strict";
|
||||
|
||||
/**
|
||||
* Returns form values represented as Javascript object
|
||||
* "name" attribute defines structure of resulting object
|
||||
*
|
||||
* @param rootNode {Element|String} root form element (or it's id) or array of root elements
|
||||
* @param delimiter {String} structure parts delimiter defaults to '.'
|
||||
* @param skipEmpty {Boolean} should skip empty text values, defaults to true
|
||||
* @param nodeCallback {Function} custom function to get node value
|
||||
* @param useIdIfEmptyName {Boolean} if true value of id attribute of field will be used if name of field is empty
|
||||
*/
|
||||
function form2js(rootNode, delimiter, skipEmpty, nodeCallback, useIdIfEmptyName, getDisabled)
|
||||
{
|
||||
getDisabled = getDisabled ? true : false;
|
||||
if (typeof skipEmpty == 'undefined' || skipEmpty == null) skipEmpty = true;
|
||||
if (typeof delimiter == 'undefined' || delimiter == null) delimiter = '.';
|
||||
if (arguments.length < 5) useIdIfEmptyName = false;
|
||||
|
||||
rootNode = typeof rootNode == 'string' ? document.getElementById(rootNode) : rootNode;
|
||||
|
||||
var formValues = [],
|
||||
currNode,
|
||||
i = 0;
|
||||
|
||||
/* If rootNode is array - combine values */
|
||||
if (rootNode.constructor == Array || (typeof NodeList != "undefined" && rootNode.constructor == NodeList))
|
||||
{
|
||||
while(currNode = rootNode[i++])
|
||||
{
|
||||
formValues = formValues.concat(getFormValues(currNode, nodeCallback, useIdIfEmptyName, getDisabled));
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
formValues = getFormValues(rootNode, nodeCallback, useIdIfEmptyName, getDisabled);
|
||||
}
|
||||
|
||||
return processNameValues(formValues, skipEmpty, delimiter);
|
||||
}
|
||||
|
||||
/**
|
||||
* Processes collection of { name: 'name', value: 'value' } objects.
|
||||
* @param nameValues
|
||||
* @param skipEmpty if true skips elements with value == '' or value == null
|
||||
* @param delimiter
|
||||
*/
|
||||
function processNameValues(nameValues, skipEmpty, delimiter)
|
||||
{
|
||||
var result = {},
|
||||
arrays = {},
|
||||
i, j, k, l,
|
||||
value,
|
||||
nameParts,
|
||||
currResult,
|
||||
arrNameFull,
|
||||
arrName,
|
||||
arrIdx,
|
||||
namePart,
|
||||
name,
|
||||
_nameParts;
|
||||
|
||||
for (i = 0; i < nameValues.length; i++)
|
||||
{
|
||||
value = nameValues[i].value;
|
||||
|
||||
if (skipEmpty && (value === '' || value === null)) continue;
|
||||
|
||||
name = nameValues[i].name;
|
||||
_nameParts = name.split(delimiter);
|
||||
nameParts = [];
|
||||
currResult = result;
|
||||
arrNameFull = '';
|
||||
|
||||
for(j = 0; j < _nameParts.length; j++)
|
||||
{
|
||||
namePart = _nameParts[j].split('][');
|
||||
if (namePart.length > 1)
|
||||
{
|
||||
for(k = 0; k < namePart.length; k++)
|
||||
{
|
||||
if (k == 0)
|
||||
{
|
||||
namePart[k] = namePart[k] + ']';
|
||||
}
|
||||
else if (k == namePart.length - 1)
|
||||
{
|
||||
namePart[k] = '[' + namePart[k];
|
||||
}
|
||||
else
|
||||
{
|
||||
namePart[k] = '[' + namePart[k] + ']';
|
||||
}
|
||||
|
||||
arrIdx = namePart[k].match(/([a-z_]+)?\[([a-z_][a-z0-9_]+?)\]/i);
|
||||
if (arrIdx)
|
||||
{
|
||||
for(l = 1; l < arrIdx.length; l++)
|
||||
{
|
||||
if (arrIdx[l]) nameParts.push(arrIdx[l]);
|
||||
}
|
||||
}
|
||||
else{
|
||||
nameParts.push(namePart[k]);
|
||||
}
|
||||
}
|
||||
}
|
||||
else
|
||||
nameParts = nameParts.concat(namePart);
|
||||
}
|
||||
|
||||
for (j = 0; j < nameParts.length; j++)
|
||||
{
|
||||
namePart = nameParts[j];
|
||||
|
||||
if (namePart.indexOf('[]') > -1 && j == nameParts.length - 1)
|
||||
{
|
||||
arrName = namePart.substr(0, namePart.indexOf('['));
|
||||
arrNameFull += arrName;
|
||||
|
||||
if (!currResult[arrName]) currResult[arrName] = [];
|
||||
currResult[arrName].push(value);
|
||||
}
|
||||
else if (namePart.indexOf('[') > -1)
|
||||
{
|
||||
arrName = namePart.substr(0, namePart.indexOf('['));
|
||||
arrIdx = namePart.replace(/(^([a-z_]+)?\[)|(\]$)/gi, '');
|
||||
|
||||
/* Unique array name */
|
||||
arrNameFull += '_' + arrName + '_' + arrIdx;
|
||||
|
||||
/*
|
||||
* Because arrIdx in field name can be not zero-based and step can be
|
||||
* other than 1, we can't use them in target array directly.
|
||||
* Instead we're making a hash where key is arrIdx and value is a reference to
|
||||
* added array element
|
||||
*/
|
||||
|
||||
if (!arrays[arrNameFull]) arrays[arrNameFull] = {};
|
||||
if (arrName != '' && !currResult[arrName]) currResult[arrName] = [];
|
||||
|
||||
if (j == nameParts.length - 1)
|
||||
{
|
||||
if (arrName == '')
|
||||
{
|
||||
currResult.push(value);
|
||||
arrays[arrNameFull][arrIdx] = convertValue(currResult[currResult.length - 1]);
|
||||
}
|
||||
else
|
||||
{
|
||||
currResult[arrName].push(value);
|
||||
arrays[arrNameFull][arrIdx] = convertValue(currResult[arrName][currResult[arrName].length - 1]);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
if (!arrays[arrNameFull][arrIdx])
|
||||
{
|
||||
if ((/^[0-9a-z_]+\[?/i).test(nameParts[j+1])) currResult[arrName].push({});
|
||||
else currResult[arrName].push([]);
|
||||
|
||||
arrays[arrNameFull][arrIdx] = convertValue(currResult[arrName][currResult[arrName].length - 1]);
|
||||
}
|
||||
}
|
||||
|
||||
currResult = convertValue(arrays[arrNameFull][arrIdx]);
|
||||
}
|
||||
else
|
||||
{
|
||||
arrNameFull += namePart;
|
||||
|
||||
if (j < nameParts.length - 1) /* Not the last part of name - means object */
|
||||
{
|
||||
if (!currResult[namePart]) currResult[namePart] = {};
|
||||
currResult = convertValue(currResult[namePart]);
|
||||
}
|
||||
else
|
||||
{
|
||||
currResult[namePart] = convertValue(value);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
function convertValue(value) {
|
||||
if (value == "true") return true;
|
||||
if (value == "false") return false;
|
||||
if (!isNaN(value)) return parseInt(value);
|
||||
return value;
|
||||
}
|
||||
|
||||
function getFormValues(rootNode, nodeCallback, useIdIfEmptyName, getDisabled)
|
||||
{
|
||||
var result = extractNodeValues(rootNode, nodeCallback, useIdIfEmptyName, getDisabled);
|
||||
return result.length > 0 ? result : getSubFormValues(rootNode, nodeCallback, useIdIfEmptyName, getDisabled);
|
||||
}
|
||||
|
||||
function getSubFormValues(rootNode, nodeCallback, useIdIfEmptyName, getDisabled)
|
||||
{
|
||||
var result = [],
|
||||
currentNode = rootNode.firstChild;
|
||||
|
||||
while (currentNode)
|
||||
{
|
||||
result = result.concat(extractNodeValues(currentNode, nodeCallback, useIdIfEmptyName, getDisabled));
|
||||
currentNode = currentNode.nextSibling;
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
function extractNodeValues(node, nodeCallback, useIdIfEmptyName, getDisabled) {
|
||||
if (node.disabled && !getDisabled) return [];
|
||||
|
||||
var callbackResult, fieldValue, result, fieldName = getFieldName(node, useIdIfEmptyName);
|
||||
|
||||
callbackResult = nodeCallback && nodeCallback(node);
|
||||
|
||||
if (callbackResult && callbackResult.name) {
|
||||
result = [callbackResult];
|
||||
}
|
||||
else if (fieldName != '' && node.nodeName.match(/INPUT|TEXTAREA/i)) {
|
||||
fieldValue = getFieldValue(node, getDisabled);
|
||||
if (null === fieldValue) {
|
||||
result = [];
|
||||
} else {
|
||||
result = [ { name: fieldName, value: fieldValue} ];
|
||||
}
|
||||
}
|
||||
else if (fieldName != '' && node.nodeName.match(/SELECT/i)) {
|
||||
fieldValue = getFieldValue(node, getDisabled);
|
||||
result = [ { name: fieldName.replace(/\[\]$/, ''), value: fieldValue } ];
|
||||
}
|
||||
else {
|
||||
result = getSubFormValues(node, nodeCallback, useIdIfEmptyName, getDisabled);
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
function getFieldName(node, useIdIfEmptyName)
|
||||
{
|
||||
if (node.name && node.name != '') return node.name;
|
||||
else if (useIdIfEmptyName && node.id && node.id != '') return node.id;
|
||||
else return '';
|
||||
}
|
||||
|
||||
|
||||
function getFieldValue(fieldNode, getDisabled)
|
||||
{
|
||||
if (fieldNode.disabled && !getDisabled) return null;
|
||||
|
||||
switch (fieldNode.nodeName) {
|
||||
case 'INPUT':
|
||||
case 'TEXTAREA':
|
||||
switch (fieldNode.type.toLowerCase()) {
|
||||
case 'radio':
|
||||
if (fieldNode.checked && fieldNode.value === "false") return false;
|
||||
case 'checkbox':
|
||||
if (fieldNode.checked && fieldNode.value === "true") return true;
|
||||
if (!fieldNode.checked && fieldNode.value === "true") return false;
|
||||
if (fieldNode.checked) return fieldNode.value;
|
||||
break;
|
||||
|
||||
case 'button':
|
||||
case 'reset':
|
||||
case 'submit':
|
||||
case 'image':
|
||||
return '';
|
||||
break;
|
||||
|
||||
default:
|
||||
return fieldNode.value;
|
||||
break;
|
||||
}
|
||||
break;
|
||||
|
||||
case 'SELECT':
|
||||
return getSelectedOptionValue(fieldNode);
|
||||
break;
|
||||
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
function getSelectedOptionValue(selectNode)
|
||||
{
|
||||
var multiple = selectNode.multiple,
|
||||
result = [],
|
||||
options,
|
||||
i, l;
|
||||
|
||||
if (!multiple) return selectNode.value;
|
||||
|
||||
for (options = selectNode.getElementsByTagName("option"), i = 0, l = options.length; i < l; i++)
|
||||
{
|
||||
if (options[i].selected) result.push(options[i].value);
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
return form2js;
|
||||
|
||||
}));
|
||||
Reference in New Issue
Block a user