Updated npm packages
This commit is contained in:
parent
00fd6f5d52
commit
949df2d4c5
703
js/main.js
703
js/main.js
@ -20,706 +20,3 @@ window.onload = externalLinks;
|
|||||||
/*
|
/*
|
||||||
$('a[rel="external"]').attr('target', '_blank');
|
$('a[rel="external"]').attr('target', '_blank');
|
||||||
*/
|
*/
|
||||||
|
|
||||||
/* InstantClick 3.0.1 | (C) 2014 Alexandre Dieulot | http://instantclick.io/license.html */
|
|
||||||
|
|
||||||
var InstantClick = function(document, location) {
|
|
||||||
// Internal variables
|
|
||||||
var $ua = navigator.userAgent,
|
|
||||||
$hasTouch = 'createTouch' in document,
|
|
||||||
$currentLocationWithoutHash,
|
|
||||||
$urlToPreload,
|
|
||||||
$preloadTimer,
|
|
||||||
|
|
||||||
// Preloading-related variables
|
|
||||||
$history = {},
|
|
||||||
$xhr,
|
|
||||||
$url = false,
|
|
||||||
$title = false,
|
|
||||||
$mustRedirect = false,
|
|
||||||
$body = false,
|
|
||||||
$timing = {},
|
|
||||||
$isPreloading = false,
|
|
||||||
$isWaitingForCompletion = false,
|
|
||||||
$trackedAssets = [],
|
|
||||||
|
|
||||||
// Variables defined by public functions
|
|
||||||
$useWhitelist,
|
|
||||||
$preloadOnMousedown,
|
|
||||||
$delayBeforePreload,
|
|
||||||
$eventsCallbacks = {
|
|
||||||
fetch: [],
|
|
||||||
receive: [],
|
|
||||||
wait: [],
|
|
||||||
change: []
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
////////// HELPERS //////////
|
|
||||||
|
|
||||||
|
|
||||||
function removeHash(url) {
|
|
||||||
var index = url.indexOf('#')
|
|
||||||
if (index < 0) {
|
|
||||||
return url
|
|
||||||
}
|
|
||||||
return url.substr(0, index)
|
|
||||||
}
|
|
||||||
|
|
||||||
function getLinkTarget(target) {
|
|
||||||
while (target.nodeName != 'A') {
|
|
||||||
target = target.parentNode
|
|
||||||
}
|
|
||||||
return target
|
|
||||||
}
|
|
||||||
|
|
||||||
function isBlacklisted(elem) {
|
|
||||||
do {
|
|
||||||
if (!elem.hasAttribute) { // Parent of <html>
|
|
||||||
break
|
|
||||||
}
|
|
||||||
if (elem.hasAttribute('data-instant')) {
|
|
||||||
return false
|
|
||||||
}
|
|
||||||
if (elem.hasAttribute('data-no-instant')) {
|
|
||||||
return true
|
|
||||||
}
|
|
||||||
}
|
|
||||||
while (elem = elem.parentNode);
|
|
||||||
return false
|
|
||||||
}
|
|
||||||
|
|
||||||
function isWhitelisted(elem) {
|
|
||||||
do {
|
|
||||||
if (!elem.hasAttribute) { // Parent of <html>
|
|
||||||
break
|
|
||||||
}
|
|
||||||
if (elem.hasAttribute('data-no-instant')) {
|
|
||||||
return false
|
|
||||||
}
|
|
||||||
if (elem.hasAttribute('data-instant')) {
|
|
||||||
return true
|
|
||||||
}
|
|
||||||
}
|
|
||||||
while (elem = elem.parentNode);
|
|
||||||
return false
|
|
||||||
}
|
|
||||||
|
|
||||||
function triggerPageEvent(eventType, arg1) {
|
|
||||||
for (var i = 0; i < $eventsCallbacks[eventType].length; i++) {
|
|
||||||
$eventsCallbacks[eventType][i](arg1)
|
|
||||||
}
|
|
||||||
|
|
||||||
/* The `change` event takes one boolean argument: "isInitialLoad" */
|
|
||||||
}
|
|
||||||
|
|
||||||
function changePage(title, body, newUrl, scrollY) {
|
|
||||||
document.title = title
|
|
||||||
|
|
||||||
document.documentElement.replaceChild(body, document.body)
|
|
||||||
/* We cannot just use `document.body = doc.body`, it causes Safari (tested
|
|
||||||
5.1, 6.0 and Mobile 7.0) to execute script tags directly.
|
|
||||||
*/
|
|
||||||
|
|
||||||
if (newUrl) {
|
|
||||||
history.pushState(null, null, newUrl)
|
|
||||||
|
|
||||||
var hashIndex = newUrl.indexOf('#'),
|
|
||||||
hashElem = hashIndex > -1
|
|
||||||
&& document.getElementById(newUrl.substr(hashIndex + 1)),
|
|
||||||
offset = 0
|
|
||||||
|
|
||||||
if (hashElem) {
|
|
||||||
while (hashElem.offsetParent) {
|
|
||||||
offset += hashElem.offsetTop
|
|
||||||
|
|
||||||
hashElem = hashElem.offsetParent
|
|
||||||
}
|
|
||||||
}
|
|
||||||
scrollTo(0, offset)
|
|
||||||
|
|
||||||
$currentLocationWithoutHash = removeHash(newUrl)
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
scrollTo(0, scrollY)
|
|
||||||
}
|
|
||||||
instantanize()
|
|
||||||
bar.done()
|
|
||||||
triggerPageEvent('change', false)
|
|
||||||
}
|
|
||||||
|
|
||||||
function setPreloadingAsHalted() {
|
|
||||||
$isPreloading = false
|
|
||||||
$isWaitingForCompletion = false
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
////////// EVENT HANDLERS //////////
|
|
||||||
|
|
||||||
|
|
||||||
function mousedown(e) {
|
|
||||||
preload(getLinkTarget(e.target).href)
|
|
||||||
}
|
|
||||||
|
|
||||||
function mouseover(e) {
|
|
||||||
var a = getLinkTarget(e.target)
|
|
||||||
a.addEventListener('mouseout', mouseout)
|
|
||||||
|
|
||||||
if (!$delayBeforePreload) {
|
|
||||||
preload(a.href)
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
$urlToPreload = a.href
|
|
||||||
$preloadTimer = setTimeout(preload, $delayBeforePreload)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
function touchstart(e) {
|
|
||||||
var a = getLinkTarget(e.target)
|
|
||||||
if ($preloadOnMousedown) {
|
|
||||||
a.removeEventListener('mousedown', mousedown)
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
a.removeEventListener('mouseover', mouseover)
|
|
||||||
}
|
|
||||||
preload(a.href)
|
|
||||||
}
|
|
||||||
|
|
||||||
function click(e) {
|
|
||||||
if (e.which > 1 || e.metaKey || e.ctrlKey) { // Opening in new tab
|
|
||||||
return
|
|
||||||
}
|
|
||||||
e.preventDefault()
|
|
||||||
display(getLinkTarget(e.target).href)
|
|
||||||
}
|
|
||||||
|
|
||||||
function mouseout() {
|
|
||||||
if ($preloadTimer) {
|
|
||||||
clearTimeout($preloadTimer)
|
|
||||||
$preloadTimer = false
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!$isPreloading || $isWaitingForCompletion) {
|
|
||||||
return
|
|
||||||
}
|
|
||||||
$xhr.abort()
|
|
||||||
setPreloadingAsHalted()
|
|
||||||
}
|
|
||||||
|
|
||||||
function readystatechange() {
|
|
||||||
if ($xhr.readyState < 4) {
|
|
||||||
return
|
|
||||||
}
|
|
||||||
if ($xhr.status == 0) {
|
|
||||||
/* Request aborted */
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
$timing.ready = +new Date - $timing.start
|
|
||||||
triggerPageEvent('receive')
|
|
||||||
|
|
||||||
if ($xhr.getResponseHeader('Content-Type').match(/\/(x|ht|xht)ml/)) {
|
|
||||||
var doc = document.implementation.createHTMLDocument('')
|
|
||||||
doc.documentElement.innerHTML = $xhr.responseText
|
|
||||||
$title = doc.title
|
|
||||||
$body = doc.body
|
|
||||||
var urlWithoutHash = removeHash($url)
|
|
||||||
$history[urlWithoutHash] = {
|
|
||||||
body: $body,
|
|
||||||
title: $title,
|
|
||||||
scrollY: urlWithoutHash in $history ? $history[urlWithoutHash].scrollY : 0
|
|
||||||
}
|
|
||||||
|
|
||||||
var elems = doc.head.children,
|
|
||||||
found = 0,
|
|
||||||
elem,
|
|
||||||
data
|
|
||||||
|
|
||||||
for (var i = elems.length - 1; i >= 0; i--) {
|
|
||||||
elem = elems[i]
|
|
||||||
if (elem.hasAttribute('data-instant-track')) {
|
|
||||||
data = elem.getAttribute('href') || elem.getAttribute('src') || elem.innerHTML
|
|
||||||
for (var j = $trackedAssets.length - 1; j >= 0; j--) {
|
|
||||||
if ($trackedAssets[j] == data) {
|
|
||||||
found++
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if (found != $trackedAssets.length) {
|
|
||||||
$mustRedirect = true // Assets have changed
|
|
||||||
}
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
$mustRedirect = true // Not an HTML document
|
|
||||||
}
|
|
||||||
|
|
||||||
if ($isWaitingForCompletion) {
|
|
||||||
$isWaitingForCompletion = false
|
|
||||||
display($url)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
////////// MAIN FUNCTIONS //////////
|
|
||||||
|
|
||||||
|
|
||||||
function instantanize(isInitializing) {
|
|
||||||
var as = document.getElementsByTagName('a'),
|
|
||||||
a,
|
|
||||||
domain = location.protocol + '//' + location.host
|
|
||||||
|
|
||||||
for (var i = as.length - 1; i >= 0; i--) {
|
|
||||||
a = as[i]
|
|
||||||
if (a.target // target="_blank" etc.
|
|
||||||
|| a.hasAttribute('download')
|
|
||||||
|| a.href.indexOf(domain + '/') != 0 // Another domain, or no href attribute
|
|
||||||
|| (a.href.indexOf('#') > -1
|
|
||||||
&& removeHash(a.href) == $currentLocationWithoutHash) // Anchor
|
|
||||||
|| ($useWhitelist
|
|
||||||
? !isWhitelisted(a)
|
|
||||||
: isBlacklisted(a))
|
|
||||||
) {
|
|
||||||
continue
|
|
||||||
}
|
|
||||||
a.addEventListener('touchstart', touchstart)
|
|
||||||
if ($preloadOnMousedown) {
|
|
||||||
a.addEventListener('mousedown', mousedown)
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
a.addEventListener('mouseover', mouseover)
|
|
||||||
}
|
|
||||||
a.addEventListener('click', click)
|
|
||||||
}
|
|
||||||
if (!isInitializing) {
|
|
||||||
var scripts = document.body.getElementsByTagName('script'),
|
|
||||||
script,
|
|
||||||
copy,
|
|
||||||
parentNode,
|
|
||||||
nextSibling
|
|
||||||
|
|
||||||
for (i = 0, j = scripts.length; i < j; i++) {
|
|
||||||
script = scripts[i]
|
|
||||||
if (script.hasAttribute('data-no-instant')) {
|
|
||||||
continue
|
|
||||||
}
|
|
||||||
copy = document.createElement('script')
|
|
||||||
if (script.src) {
|
|
||||||
copy.src = script.src
|
|
||||||
}
|
|
||||||
if (script.innerHTML) {
|
|
||||||
copy.innerHTML = script.innerHTML
|
|
||||||
}
|
|
||||||
parentNode = script.parentNode
|
|
||||||
nextSibling = script.nextSibling
|
|
||||||
parentNode.removeChild(script)
|
|
||||||
parentNode.insertBefore(copy, nextSibling)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
function preload(url) {
|
|
||||||
if (!$preloadOnMousedown
|
|
||||||
&& 'display' in $timing
|
|
||||||
&& +new Date - ($timing.start + $timing.display) < 100) {
|
|
||||||
/* After a page is displayed, if the user's cursor happens to be above
|
|
||||||
a link a mouseover event will be in most browsers triggered
|
|
||||||
automatically, and in other browsers it will be triggered when the
|
|
||||||
user moves his mouse by 1px.
|
|
||||||
|
|
||||||
Here are the behavior I noticed, all on Windows:
|
|
||||||
- Safari 5.1: auto-triggers after 0 ms
|
|
||||||
- IE 11: auto-triggers after 30-80 ms (depends on page's size?)
|
|
||||||
- Firefox: auto-triggers after 10 ms
|
|
||||||
- Opera 18: auto-triggers after 10 ms
|
|
||||||
|
|
||||||
- Chrome: triggers when cursor moved
|
|
||||||
- Opera 12.16: triggers when cursor moved
|
|
||||||
|
|
||||||
To remedy to this, we do not start preloading if last display
|
|
||||||
occurred less than 100 ms ago. If they happen to click on the link,
|
|
||||||
they will be redirected.
|
|
||||||
*/
|
|
||||||
|
|
||||||
return
|
|
||||||
}
|
|
||||||
if ($preloadTimer) {
|
|
||||||
clearTimeout($preloadTimer)
|
|
||||||
$preloadTimer = false
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!url) {
|
|
||||||
url = $urlToPreload
|
|
||||||
}
|
|
||||||
|
|
||||||
if ($isPreloading && (url == $url || $isWaitingForCompletion)) {
|
|
||||||
return
|
|
||||||
}
|
|
||||||
$isPreloading = true
|
|
||||||
$isWaitingForCompletion = false
|
|
||||||
|
|
||||||
$url = url
|
|
||||||
$body = false
|
|
||||||
$mustRedirect = false
|
|
||||||
$timing = {
|
|
||||||
start: +new Date
|
|
||||||
}
|
|
||||||
triggerPageEvent('fetch')
|
|
||||||
$xhr.open('GET', url)
|
|
||||||
$xhr.send()
|
|
||||||
}
|
|
||||||
|
|
||||||
function display(url) {
|
|
||||||
if (!('display' in $timing)) {
|
|
||||||
$timing.display = +new Date - $timing.start
|
|
||||||
}
|
|
||||||
if ($preloadTimer) {
|
|
||||||
/* Happens when there’s a delay before preloading and that delay
|
|
||||||
hasn't expired (preloading didn't kick in).
|
|
||||||
*/
|
|
||||||
|
|
||||||
if ($url && $url != url) {
|
|
||||||
/* Happens when the user clicks on a link before preloading
|
|
||||||
kicks in while another link is already preloading.
|
|
||||||
*/
|
|
||||||
|
|
||||||
location.href = url
|
|
||||||
return
|
|
||||||
}
|
|
||||||
preload(url)
|
|
||||||
bar.start(0, true)
|
|
||||||
triggerPageEvent('wait')
|
|
||||||
$isWaitingForCompletion = true
|
|
||||||
return
|
|
||||||
}
|
|
||||||
if (!$isPreloading || $isWaitingForCompletion) {
|
|
||||||
/* If the page isn't preloaded, it likely means the user has focused
|
|
||||||
on a link (with his Tab key) and then pressed Return, which
|
|
||||||
triggered a click.
|
|
||||||
Because very few people do this, it isn't worth handling this case
|
|
||||||
and preloading on focus (also, focusing on a link doesn't mean it's
|
|
||||||
likely that you'll "click" on it), so we just redirect them when
|
|
||||||
they "click".
|
|
||||||
It could also mean the user hovered over a link less than 100 ms
|
|
||||||
after a page display, thus we didn't start the preload (see
|
|
||||||
comments in `preload()` for the rationale behind this.)
|
|
||||||
|
|
||||||
If the page is waiting for completion, the user clicked twice while
|
|
||||||
the page was preloading. Either on the same link or on another
|
|
||||||
link. If it's the same link something might have gone wrong (or he
|
|
||||||
could have double clicked), so we send him to the page the old way.
|
|
||||||
If it's another link, it hasn't been preloaded, so we redirect the
|
|
||||||
user the old way.
|
|
||||||
*/
|
|
||||||
|
|
||||||
location.href = url
|
|
||||||
return
|
|
||||||
}
|
|
||||||
if ($mustRedirect) {
|
|
||||||
location.href = $url
|
|
||||||
return
|
|
||||||
}
|
|
||||||
if (!$body) {
|
|
||||||
bar.start(0, true)
|
|
||||||
triggerPageEvent('wait')
|
|
||||||
$isWaitingForCompletion = true
|
|
||||||
return
|
|
||||||
}
|
|
||||||
$history[$currentLocationWithoutHash].scrollY = pageYOffset
|
|
||||||
setPreloadingAsHalted()
|
|
||||||
changePage($title, $body, $url)
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
////////// PROGRESS BAR FUNCTIONS //////////
|
|
||||||
|
|
||||||
|
|
||||||
var bar = function() {
|
|
||||||
var $barContainer,
|
|
||||||
$barElement,
|
|
||||||
$barTransformProperty,
|
|
||||||
$barProgress,
|
|
||||||
$barTimer
|
|
||||||
|
|
||||||
function init() {
|
|
||||||
$barContainer = document.createElement('div')
|
|
||||||
$barContainer.id = 'instantclick'
|
|
||||||
$barElement = document.createElement('div')
|
|
||||||
$barElement.id = 'instantclick-bar'
|
|
||||||
$barElement.className = 'instantclick-bar'
|
|
||||||
$barContainer.appendChild($barElement)
|
|
||||||
|
|
||||||
var vendors = ['Webkit', 'Moz', 'O']
|
|
||||||
|
|
||||||
$barTransformProperty = 'transform'
|
|
||||||
if (!($barTransformProperty in $barElement.style)) {
|
|
||||||
for (var i = 0; i < 3; i++) {
|
|
||||||
if (vendors[i] + 'Transform' in $barElement.style) {
|
|
||||||
$barTransformProperty = vendors[i] + 'Transform'
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
var transitionProperty = 'transition'
|
|
||||||
if (!(transitionProperty in $barElement.style)) {
|
|
||||||
for (var i = 0; i < 3; i++) {
|
|
||||||
if (vendors[i] + 'Transition' in $barElement.style) {
|
|
||||||
transitionProperty = '-' + vendors[i].toLowerCase() + '-' + transitionProperty
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
var style = document.createElement('style')
|
|
||||||
style.innerHTML = '#instantclick{position:' + ($hasTouch ? 'absolute' : 'fixed') + ';top:0;left:0;width:100%;pointer-events:none;z-index:2147483647;' + transitionProperty + ':opacity .25s .1s}'
|
|
||||||
+ '.instantclick-bar{background:#29d;width:100%;margin-left:-100%;height:2px;' + transitionProperty + ':all .25s}'
|
|
||||||
/* We set the bar's background in `.instantclick-bar` so that it can be
|
|
||||||
overriden in CSS with `#instantclick-bar`, as IDs have higher priority.
|
|
||||||
*/
|
|
||||||
document.head.appendChild(style)
|
|
||||||
|
|
||||||
if ($hasTouch) {
|
|
||||||
updatePositionAndScale()
|
|
||||||
addEventListener('resize', updatePositionAndScale)
|
|
||||||
addEventListener('scroll', updatePositionAndScale)
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
function start(at, jump) {
|
|
||||||
$barProgress = at
|
|
||||||
if (document.getElementById($barContainer.id)) {
|
|
||||||
document.body.removeChild($barContainer)
|
|
||||||
}
|
|
||||||
$barContainer.style.opacity = '1'
|
|
||||||
if (document.getElementById($barContainer.id)) {
|
|
||||||
document.body.removeChild($barContainer)
|
|
||||||
/* So there's no CSS animation if already done once and it goes from 1 to 0 */
|
|
||||||
}
|
|
||||||
update()
|
|
||||||
if (jump) {
|
|
||||||
setTimeout(jumpStart, 0)
|
|
||||||
/* Must be done in a timer, otherwise the CSS animation doesn't happen. */
|
|
||||||
}
|
|
||||||
clearTimeout($barTimer)
|
|
||||||
$barTimer = setTimeout(inc, 500)
|
|
||||||
}
|
|
||||||
|
|
||||||
function jumpStart() {
|
|
||||||
$barProgress = 10
|
|
||||||
update()
|
|
||||||
}
|
|
||||||
|
|
||||||
function inc() {
|
|
||||||
$barProgress += 1 + (Math.random() * 2)
|
|
||||||
if ($barProgress >= 98) {
|
|
||||||
$barProgress = 98
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
$barTimer = setTimeout(inc, 500)
|
|
||||||
}
|
|
||||||
update()
|
|
||||||
}
|
|
||||||
|
|
||||||
function update() {
|
|
||||||
$barElement.style[$barTransformProperty] = 'translate(' + $barProgress + '%)'
|
|
||||||
if (!document.getElementById($barContainer.id)) {
|
|
||||||
document.body.appendChild($barContainer)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
function done() {
|
|
||||||
if (document.getElementById($barContainer.id)) {
|
|
||||||
clearTimeout($barTimer)
|
|
||||||
$barProgress = 100
|
|
||||||
update()
|
|
||||||
$barContainer.style.opacity = '0'
|
|
||||||
/* If you're debugging, setting this to 0.5 is handy. */
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
/* The bar container hasn't been appended: It's a new page. */
|
|
||||||
start($barProgress == 100 ? 0 : $barProgress)
|
|
||||||
/* $barProgress is 100 on popstate, usually. */
|
|
||||||
setTimeout(done, 0)
|
|
||||||
/* Must be done in a timer, otherwise the CSS animation doesn't happen. */
|
|
||||||
}
|
|
||||||
|
|
||||||
function updatePositionAndScale() {
|
|
||||||
/* Adapted from code by Sam Stephenson and Mislav Marohnić
|
|
||||||
http://signalvnoise.com/posts/2407
|
|
||||||
*/
|
|
||||||
|
|
||||||
$barContainer.style.left = pageXOffset + 'px'
|
|
||||||
$barContainer.style.width = innerWidth + 'px'
|
|
||||||
$barContainer.style.top = pageYOffset + 'px'
|
|
||||||
|
|
||||||
var landscape = 'orientation' in window && Math.abs(orientation) == 90,
|
|
||||||
scaleY = innerWidth / screen[landscape ? 'height' : 'width'] * 2
|
|
||||||
/* We multiply the size by 2 because the progress bar is harder
|
|
||||||
to notice on a mobile device.
|
|
||||||
*/
|
|
||||||
$barContainer.style[$barTransformProperty] = 'scaleY(' + scaleY + ')'
|
|
||||||
}
|
|
||||||
|
|
||||||
return {
|
|
||||||
init: init,
|
|
||||||
start: start,
|
|
||||||
done: done
|
|
||||||
}
|
|
||||||
}()
|
|
||||||
|
|
||||||
|
|
||||||
////////// PUBLIC VARIABLE AND FUNCTIONS //////////
|
|
||||||
|
|
||||||
var supported = 'pushState' in history
|
|
||||||
&& (!$ua.match('Android') || $ua.match('Chrome/'))
|
|
||||||
&& location.protocol != "file:"
|
|
||||||
|
|
||||||
/* The state of Android's AOSP browsers:
|
|
||||||
|
|
||||||
2.3.7: pushState appears to work correctly, but
|
|
||||||
`doc.documentElement.innerHTML = body` is buggy.
|
|
||||||
See details here: http://stackoverflow.com/q/21918564
|
|
||||||
Note an issue anymore, but it may fail where 3.0 do, this needs
|
|
||||||
testing again.
|
|
||||||
|
|
||||||
3.0: pushState appears to work correctly (though the URL bar is only
|
|
||||||
updated on focus), but
|
|
||||||
`document.documentElement.replaceChild(doc.body, document.body)`
|
|
||||||
throws DOMException: WRONG_DOCUMENT_ERR.
|
|
||||||
|
|
||||||
4.0.2: Doesn't support pushState.
|
|
||||||
|
|
||||||
4.0.4,
|
|
||||||
4.1.1,
|
|
||||||
4.2,
|
|
||||||
4.3: pushState is here, but it doesn't update the URL bar.
|
|
||||||
(Great logic there.)
|
|
||||||
|
|
||||||
4.4: Works correctly. Claims to be 'Chrome/30.0.0.0'.
|
|
||||||
|
|
||||||
All androids tested with Android SDK's Emulator.
|
|
||||||
Version numbers are from the browser's user agent.
|
|
||||||
|
|
||||||
Because of this mess, the only whitelisted browser on Android is Chrome.
|
|
||||||
*/
|
|
||||||
|
|
||||||
function init() {
|
|
||||||
if ($currentLocationWithoutHash) {
|
|
||||||
/* Already initialized */
|
|
||||||
return
|
|
||||||
}
|
|
||||||
if (!supported) {
|
|
||||||
triggerPageEvent('change', true)
|
|
||||||
return
|
|
||||||
}
|
|
||||||
for (var i = arguments.length - 1; i >= 0; i--) {
|
|
||||||
var arg = arguments[i]
|
|
||||||
if (arg === true) {
|
|
||||||
$useWhitelist = true
|
|
||||||
}
|
|
||||||
else if (arg == 'mousedown') {
|
|
||||||
$preloadOnMousedown = true
|
|
||||||
}
|
|
||||||
else if (typeof arg == 'number') {
|
|
||||||
$delayBeforePreload = arg
|
|
||||||
}
|
|
||||||
}
|
|
||||||
$currentLocationWithoutHash = removeHash(location.href)
|
|
||||||
$history[$currentLocationWithoutHash] = {
|
|
||||||
body: document.body,
|
|
||||||
title: document.title,
|
|
||||||
scrollY: pageYOffset
|
|
||||||
}
|
|
||||||
|
|
||||||
var elems = document.head.children,
|
|
||||||
elem,
|
|
||||||
data
|
|
||||||
for (var i = elems.length - 1; i >= 0; i--) {
|
|
||||||
elem = elems[i]
|
|
||||||
if (elem.hasAttribute('data-instant-track')) {
|
|
||||||
data = elem.getAttribute('href') || elem.getAttribute('src') || elem.innerHTML
|
|
||||||
/* We can't use just `elem.href` and `elem.src` because we can't
|
|
||||||
retrieve `href`s and `src`s from the Ajax response.
|
|
||||||
*/
|
|
||||||
$trackedAssets.push(data)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
$xhr = new XMLHttpRequest()
|
|
||||||
$xhr.addEventListener('readystatechange', readystatechange)
|
|
||||||
|
|
||||||
instantanize(true)
|
|
||||||
|
|
||||||
bar.init()
|
|
||||||
|
|
||||||
triggerPageEvent('change', true)
|
|
||||||
|
|
||||||
addEventListener('popstate', function() {
|
|
||||||
var loc = removeHash(location.href)
|
|
||||||
if (loc == $currentLocationWithoutHash) {
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!(loc in $history)) {
|
|
||||||
location.href = location.href
|
|
||||||
/* Reloads the page while using cache for scripts, styles and images,
|
|
||||||
unlike `location.reload()` */
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
$history[$currentLocationWithoutHash].scrollY = pageYOffset
|
|
||||||
$currentLocationWithoutHash = loc
|
|
||||||
changePage($history[loc].title, $history[loc].body, false, $history[loc].scrollY)
|
|
||||||
})
|
|
||||||
}
|
|
||||||
|
|
||||||
function on(eventType, callback) {
|
|
||||||
$eventsCallbacks[eventType].push(callback)
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
/* The debug function isn't included by default to reduce file size.
|
|
||||||
To enable it, add a slash at the beginning of the comment englobing
|
|
||||||
the debug function, and uncomment "debug: debug," in the return
|
|
||||||
statement below the function. */
|
|
||||||
|
|
||||||
/*
|
|
||||||
function debug() {
|
|
||||||
return {
|
|
||||||
currentLocationWithoutHash: $currentLocationWithoutHash,
|
|
||||||
history: $history,
|
|
||||||
xhr: $xhr,
|
|
||||||
url: $url,
|
|
||||||
title: $title,
|
|
||||||
mustRedirect: $mustRedirect,
|
|
||||||
body: $body,
|
|
||||||
timing: $timing,
|
|
||||||
isPreloading: $isPreloading,
|
|
||||||
isWaitingForCompletion: $isWaitingForCompletion
|
|
||||||
}
|
|
||||||
}
|
|
||||||
//*/
|
|
||||||
|
|
||||||
|
|
||||||
////////////////////
|
|
||||||
|
|
||||||
|
|
||||||
return {
|
|
||||||
// debug: debug,
|
|
||||||
supported: supported,
|
|
||||||
init: init,
|
|
||||||
on: on
|
|
||||||
}
|
|
||||||
|
|
||||||
}(document, location);
|
|
||||||
|
|
||||||
/*
|
|
||||||
HTML5 Shiv v3.7.0 | @afarkas @jdalton @jon_neal @rem | MIT/GPL2 Licensed
|
|
||||||
*/
|
|
||||||
(function(l,f){function m(){var a=e.elements;return"string"==typeof a?a.split(" "):a}function i(a){var b=n[a[o]];b||(b={},h++,a[o]=h,n[h]=b);return b}function p(a,b,c){b||(b=f);if(g)return b.createElement(a);c||(c=i(b));b=c.cache[a]?c.cache[a].cloneNode():r.test(a)?(c.cache[a]=c.createElem(a)).cloneNode():c.createElem(a);return b.canHaveChildren&&!s.test(a)?c.frag.appendChild(b):b}function t(a,b){if(!b.cache)b.cache={},b.createElem=a.createElement,b.createFrag=a.createDocumentFragment,b.frag=b.createFrag();
|
|
||||||
a.createElement=function(c){return!e.shivMethods?b.createElem(c):p(c,a,b)};a.createDocumentFragment=Function("h,f","return function(){var n=f.cloneNode(),c=n.createElement;h.shivMethods&&("+m().join().replace(/[\w\-]+/g,function(a){b.createElem(a);b.frag.createElement(a);return'c("'+a+'")'})+");return n}")(e,b.frag)}function q(a){a||(a=f);var b=i(a);if(e.shivCSS&&!j&&!b.hasCSS){var c,d=a;c=d.createElement("p");d=d.getElementsByTagName("head")[0]||d.documentElement;c.innerHTML="x<style>article,aside,dialog,figcaption,figure,footer,header,hgroup,main,nav,section{display:block}mark{background:#FF0;color:#000}template{display:none}</style>";
|
|
||||||
c=d.insertBefore(c.lastChild,d.firstChild);b.hasCSS=!!c}g||t(a,b);return a}var k=l.html5||{},s=/^<|^(?:button|map|select|textarea|object|iframe|option|optgroup)$/i,r=/^(?:a|b|code|div|fieldset|h1|h2|h3|h4|h5|h6|i|label|li|ol|p|q|span|strong|style|table|tbody|td|th|tr|ul)$/i,j,o="_html5shiv",h=0,n={},g;(function(){try{var a=f.createElement("a");a.innerHTML="<xyz></xyz>";j="hidden"in a;var b;if(!(b=1==a.childNodes.length)){f.createElement("a");var c=f.createDocumentFragment();b="undefined"==typeof c.cloneNode||
|
|
||||||
"undefined"==typeof c.createDocumentFragment||"undefined"==typeof c.createElement}g=b}catch(d){g=j=!0}})();var e={elements:k.elements||"abbr article aside audio bdi canvas data datalist details dialog figcaption figure footer header hgroup main mark meter nav output progress section summary template time video",version:"3.7.0",shivCSS:!1!==k.shivCSS,supportsUnknownElements:g,shivMethods:!1!==k.shivMethods,type:"default",shivDocument:q,createElement:p,createDocumentFragment:function(a,b){a||(a=f);
|
|
||||||
if(g)return a.createDocumentFragment();for(var b=b||i(a),c=b.frag.cloneNode(),d=0,e=m(),h=e.length;d<h;d++)c.createElement(e[d]);return c}};l.html5=e;q(f)})(this,document);
|
|
||||||
|
2
js/main.min.js
vendored
2
js/main.min.js
vendored
File diff suppressed because one or more lines are too long
40
package.json
40
package.json
@ -4,7 +4,7 @@
|
|||||||
"version": "1.0.0",
|
"version": "1.0.0",
|
||||||
"author": "Jan Jastrow",
|
"author": "Jan Jastrow",
|
||||||
"license": "MIT",
|
"license": "MIT",
|
||||||
"homepage": "projecturl",
|
"homepage": "http://projecturl.skl",
|
||||||
"url" : "http://github.com/Gehirnfussel/project/",
|
"url" : "http://github.com/Gehirnfussel/project/",
|
||||||
"email" : "jan@schwerkraftlabor.de",
|
"email" : "jan@schwerkraftlabor.de",
|
||||||
"scripts": {},
|
"scripts": {},
|
||||||
@ -16,23 +16,23 @@
|
|||||||
"dependencies": {},
|
"dependencies": {},
|
||||||
"devDependencies": {
|
"devDependencies": {
|
||||||
"del": "^0.1.3",
|
"del": "^0.1.3",
|
||||||
"gulp": "^3.8.10",
|
"gulp": "^3.9",
|
||||||
"gulp-autoprefixer": "^2.0.0",
|
"gulp-autoprefixer": "^2.3",
|
||||||
"gulp-cache": "^0.2.4",
|
"gulp-cache": "^0.2.10",
|
||||||
"gulp-concat": "^2.4.2",
|
"gulp-concat": "^2.6",
|
||||||
"gulp-cssmin": "^0.1.6",
|
"gulp-cssmin": "^0.1.7",
|
||||||
"gulp-imagemin": "^2.0.0",
|
"gulp-imagemin": "^2.3.0",
|
||||||
"gulp-jshint": "^1.9.0",
|
"gulp-jshint": "^1.11.2",
|
||||||
"gulp-livereload": "^3.0.2",
|
"gulp-livereload": "^3.8",
|
||||||
"gulp-minify-css": "^0.3.11",
|
"gulp-minify-css": "^1.2",
|
||||||
"gulp-notify": "^2.1.0",
|
"gulp-notify": "^2.2.0",
|
||||||
"gulp-plumber": "^0.6.6",
|
"gulp-plumber": "^1.0.1",
|
||||||
"gulp-rename": "^1.2.0",
|
"gulp-rename": "^1.2.2",
|
||||||
"gulp-ruby-sass": "^0.7.1",
|
"gulp-ruby-sass": "^1.0.5",
|
||||||
"gulp-sass": "^1.2.4",
|
"gulp-sass": "^2.0.4",
|
||||||
"gulp-uglify": "^1.0.2",
|
"gulp-uglify": "^1.2",
|
||||||
"gulp-watch": "^3.0.0",
|
"gulp-watch": "^4.3.4",
|
||||||
"imagemin-jpegtran": "^4.0.0",
|
"imagemin-jpegtran": "^4.3.0",
|
||||||
"imagemin-pngcrush": "^4.0.0"
|
"imagemin-pngcrush": "^4.1.0"
|
||||||
},
|
}
|
||||||
}
|
}
|
||||||
|
Loading…
x
Reference in New Issue
Block a user