Skip to content

Instantly share code, notes, and snippets.

@audinue
Created September 2, 2020 14:58
Show Gist options
  • Select an option

  • Save audinue/cbe872fd95efc0f372138ed21d42036c to your computer and use it in GitHub Desktop.

Select an option

Save audinue/cbe872fd95efc0f372138ed21d42036c to your computer and use it in GitHub Desktop.
var respond = function () {
var responders = []
var post
addEventListener('DOMContentLoaded', domContentLoaded)
addEventListener('hashchange', hashchange)
addEventListener('submit', submit)
function domContentLoaded () {
removeEventListener('DOMContentLoaded', domContentLoaded)
if (location.hash === '') {
location.hash = '/'
} else {
hashchange()
}
}
function hashchange () {
var url = new URL('http://localhost' + location.hash.substr(1))
var request = {
method: 'GET',
path: url.pathname,
get: toObject(url.searchParams),
post: {}
}
if (post !== undefined) {
Object.assign(request, {
method: 'POST',
post: post
})
post = undefined
}
var responder = responders.find(function (responder) {
return responder.accept(request)
})
var body = document.body
if (responder) {
var response = responder.respond(request)
if (response instanceof Node) {
body.innerHTML = ''
body.appendChild(response)
} else {
body.innerHTML = response
}
} else {
body.innerHTML = '<pre>Unable to ' + request.method + ' ' + request.path + '</pre>'
}
}
function submit (e) {
var form = e.target
var action = form.getAttribute('action')
if (!action) {
return
}
if (action.substr(0, 2) !== '#/') {
return
}
var url = new URL('http://localhost' + action.substr(1))
var data = new FormData(form)
if (form.method === 'get') {
data.forEach(function (value, key) {
url.searchParams.append(key, value)
})
} else {
post = toObject(data)
}
var hash = '#' + url.pathname + url.search
if (location.hash !== hash) {
if (post !== undefined) {
location.replace(hash)
} else {
location.hash = hash
}
} else {
hashchange()
}
e.preventDefault()
}
function toObject (data) {
return Array.from(data).reduce(function (object, entry) {
var key = entry[0]
var value = entry[1]
if (object.hasOwnProperty(key)) {
if (!Array.isArray(object[key])) {
object[key] = [object[key]]
}
object[key].push(value)
} else {
object[key] = value
}
return object
}, {})
}
return function (method, path, callback) {
responders.push({
accept: function (request) {
return request.method === method && request.path === path
},
respond: callback
})
}
}()
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment