litejs
Version:
Single-page application framework
154 lines (127 loc) • 4.03 kB
JavaScript
xhr.logErrors = function(unsentErrors) {
xhr("POST", "/errlog").send(JSON.stringify(unsentErrors))
unsentErrors.length = 0
}
// Clickjacking defense, break out of frames.
// If JavaScript is disabled, the site will not display at all.
if (self !== top) {
xhr.logErrors(["Framed in " + top.location])
throw top.location = self.location
}
!function(window, document, navigator, View, i18n) {
i18n.def({
"en": "In English"
})
var timezone
, html = document.documentElement
, body = document.body
, standalone = "standalone" in navigator ?
navigator.standalone :
window.matchMedia && matchMedia("(display-mode:standalone)").matches
// Detect first available language
, lang = i18n.use([].concat(
navigator.languages, navigator.language, navigator.userLanguage,
"en" // Default language
).filter(i18n.get)[0])
// Detect base from HTML <base> element
, base = (html.getElementsByTagName("base")[0] || i18n).href
history.scrollRestoration = "manual"
if (standalone) {
El.addClass(html, "is-app")
}
try {
timezone = Intl.DateTimeFormat().resolvedOptions().timezone
} catch(e) {}
i18n.setLang = function(lang) {
html.lang = lang = i18n.use(lang)
xhr.load("lang/" + lang + ".js", function() {
Date.names = i18n("__date").split(" ")
String.alphabet = i18n("__alphabet")
String.ordinal = i18n("__ordinal")
String.plural = i18n("__plural")
Object.assign(Date.masks, i18n("__dateMasks"))
body.dir = i18n("dir")
El.render(body)
})
}
// Define `#body` view, it is a starting point for us.
// It could be any element on page but we want to start from `BODY`.
View("#body", body)
View.on("show", function(params, view) {
// Re-render all .js-viewHook elements on each View change
El.findAll(body, ".js-viewRender").render()
scroll(0, 1)
})
xhr.load(El.findAll(body, "script[type='litejs/view']").pluck("src"), function() {
// Start a router to show views
history.start(View.show)
})
El.on(body, "click", function(e) {
var el = e.target
, link = !(e.altKey || e.shiftKey) && el.tagName == "A" && el.href.split("#")
if (link && link[0] == (base || location.href.split("#")[0])) {
if (e[El.kbMod] ? window.open(el.href, "_blank") : !history.setUrl(link[1])) {
return Event.stop(e)
}
}
})
/*** worker ***/
var worker = navigator.serviceWorker
if (worker) {
worker.addEventListener("message", function(event) {
View.emit(event.data.op || event.data, event.data)
})
View.one("show", function() {
worker.register("worker.js").then(function(reg) {
var forcedReload
, active = !!reg.active
reg.addEventListener("updatefound", function() {
reg.installing.addEventListener("statechange", statechange)
})
View.on("update", reg.update, reg)
View.on("reload", function() {
if (reg.waiting) reg.waiting.postMessage("reload")
})
function statechange(event) {
if (event.target.state === "installed") {
if (active) View.emit("updateready")
} else if (event.target.state === "activated") {
if (!active) active = true
else if (!forcedReload) location.reload(forcedReload = true)
}
}
})
})
}
View.on("updateready", function() {
View.emit("confirm", "Update ready", {
body: "A new version became available.",
actions: [
{ title: "Cancel" },
{ action: "ok", title: "Reload to activate it", key: "enter" }
]
}, {
ok: "reload"
})
})
/**/
/*** self-xss ***/
try {
console.log(
"%cStop!\n" +
"%cThis developer tool lets you hack and give others access only to your own account.\n" +
"See more: https://en.wikipedia.org/wiki/Self-XSS",
"font:bold 50px monospace;color:red;text-shadow:3px 3px #000,-1px -1px #fff",
"font:20px sans-serif"
)
var now = RegExp(Date())
, img = new Image()
now.toString = function() {
console.log("see")
}
console.log(now)
Object.defineProperty(img,"id",{get:now.toString})
console.log(img)
} catch(e) {}
/**/
}(this, document, navigator, View, El.i18n)