Moar changes
This commit is contained in:
parent
00487df5de
commit
b98abff03f
|
@ -0,0 +1,2 @@
|
|||
node_modules
|
||||
.sass-cache
|
|
@ -0,0 +1,4 @@
|
|||
#Design-Checklist
|
||||
|
||||
- Responsive Design – Mobile: 320, 360, 400px
|
||||
- Create Favicons (ICO!) with multiple sizes (16, 32, 48, 64px)
|
15
css/main.css
15
css/main.css
|
@ -152,7 +152,8 @@ figure {
|
|||
* Address differences between Firefox and other browsers.
|
||||
*/
|
||||
hr {
|
||||
box-sizing: content-box;
|
||||
-webkit-box-sizing: content-box;
|
||||
box-sizing: content-box;
|
||||
height: 0; }
|
||||
|
||||
/**
|
||||
|
@ -244,7 +245,8 @@ input {
|
|||
* 2. Remove excess padding in IE 8/9/10.
|
||||
*/
|
||||
input[type="checkbox"], input[type="radio"] {
|
||||
box-sizing: border-box;
|
||||
-webkit-box-sizing: border-box;
|
||||
box-sizing: border-box;
|
||||
/* 1 */
|
||||
padding: 0;
|
||||
/* 2 */ }
|
||||
|
@ -265,6 +267,7 @@ input[type="number"]::-webkit-inner-spin-button, input[type="number"]::-webkit-o
|
|||
input[type="search"] {
|
||||
-webkit-appearance: textfield;
|
||||
/* 1 */
|
||||
-webkit-box-sizing: content-box;
|
||||
/* 2 */
|
||||
box-sizing: content-box; }
|
||||
|
||||
|
@ -324,13 +327,15 @@ td, th {
|
|||
/* Reset
|
||||
--------------------------*/
|
||||
*, *:before, *:after {
|
||||
box-sizing: inherit;
|
||||
-webkit-box-sizing: inherit;
|
||||
box-sizing: inherit;
|
||||
padding: 0;
|
||||
margin: 0; }
|
||||
|
||||
html {
|
||||
height: 100%;
|
||||
box-sizing: border-box; }
|
||||
-webkit-box-sizing: border-box;
|
||||
box-sizing: border-box; }
|
||||
|
||||
/* Ideal Viewport-Fix for IE */
|
||||
@-ms-viewport {
|
||||
|
@ -448,7 +453,7 @@ ul li {
|
|||
a {
|
||||
color: #660000;
|
||||
-webkit-transition: color 0.2s ease;
|
||||
transition: color 0.2s ease; }
|
||||
transition: color 0.2s ease; }
|
||||
a:hover, a:active, a:focus {
|
||||
color: #b30000; }
|
||||
a:active {
|
||||
|
|
|
@ -1 +1 @@
|
|||
html{font-family:sans-serif;-ms-text-size-adjust:100%;-webkit-text-size-adjust:100%}body{margin:0}article,aside,details,figcaption,figure,footer,header,hgroup,main,nav,section,summary{display:block}audio,canvas,progress,video{display:inline-block;vertical-align:baseline}audio:not([controls]){display:none;height:0}[hidden],template{display:none}a{background:0 0}a:active,a:hover{outline:0}abbr[title]{border-bottom:1px dotted}b,strong{font-weight:700}dfn{font-style:italic}mark{background:#ff0;color:#000}small{font-size:80%}sub,sup{font-size:75%;line-height:0;position:relative;vertical-align:baseline}sup{top:-.5em}sub{bottom:-.25em}img{border:0}svg:not(:root){overflow:hidden}figure{margin:1em 40px}hr{box-sizing:content-box;height:0}pre{overflow:auto}code,kbd,pre,samp{font-family:monospace,monospace;font-size:1em}button,input,optgroup,select,textarea{color:inherit;font:inherit;margin:0}button{overflow:visible}button,select{text-transform:none}button,html input[type=button],input[type=reset],input[type=submit]{-webkit-appearance:button;cursor:pointer}button[disabled],html input[disabled]{cursor:default}button::-moz-focus-inner,input::-moz-focus-inner{border:0;padding:0}input{line-height:normal}input[type=checkbox],input[type=radio]{box-sizing:border-box;padding:0}input[type=number]::-webkit-inner-spin-button,input[type=number]::-webkit-outer-spin-button{height:auto}input[type=search]{-webkit-appearance:textfield;box-sizing:content-box}input[type=search]::-webkit-search-cancel-button,input[type=search]::-webkit-search-decoration{-webkit-appearance:none}fieldset{border:1px solid silver;margin:0 2px;padding:.35em .625em .75em}legend{border:0;padding:0}textarea{overflow:auto}optgroup{font-weight:700}table{border-collapse:collapse;border-spacing:0}td,th{padding:0}*,:after,:before{box-sizing:inherit;padding:0;margin:0}html{height:100%;box-sizing:border-box}@-ms-viewport{width:device-width}.clearfix::after,.clearfix::before{content:" ";display:table}.clearfix::after{clear:both}canvas,iframe,img,svg,video{max-width:100%}.video{position:relative;height:0;padding-bottom:56.25%}.video>*{position:absolute;top:0;left:0;height:100%;width:100%}.container{margin:0 auto}.row{overflow:hidden;max-width:960px;margin:0 auto}.fullrow{max-width:100%}.column{float:left;margin-left:5%}.column:first-child{margin-left:0}.column.full{width:100%}.column.three-fourth{width:63.75%}.column.two-thirds{width:65%}.column.half{width:47.5%}.column.one-third{width:30%}.column.one-fourth{width:21.25%}body{color:#000;font-family:Open Sans,Helvetica,Arial,sans-serif;font-size:12pt;-webkit-font-smoothing:subpixel-antialiased;-moz-osx-font-smoothing:auto}h1,h2,h3{font-family:Open Sans,Helvetica,Arial,sans-serif;font-weight:700;line-height:1.2em;margin:.4em 0}h1{font-size:2em;word-break:break-all}h2{font-size:1.5em}h3{font-size:1.25em}p{line-height:1.45em;padding:.5em 0}ul li{margin:.3em 0 .3em .5em;list-style-position:inside;list-style-type:square;font-size:1em}ul li p{padding-left:1em}a{color:#600;-webkit-transition:color .2s ease;transition:color .2s ease}a:active,a:focus,a:hover{color:#b30000}a:active{position:relative;top:1px}a.notdown:active{position:inherit}@media screen{a.external:after{content:"\00A0" "[" "\2197" "]"}}@media print{a[href]:after{content:" (" attr(href) ")"}}#instantclick-bar{background:red}.fa{margin-right:.3em;speak:none}.button{text-overflow:ellipsis}@media screen and (max-width:768px){.column.full,.column.half,.column.three-fourth,.column.two-thirds{float:none;margin:0;width:100%}.column.one-fourth,.column.one-third{float:left;margin:0;width:50%;padding:.4em}}@media screen and (max-width:568px){.column.one-third,.column.two-third{float:none;margin:0;width:100%}}@media screen and (max-width:480px){.column.full,.column.half,.column.one-fourth,.column.one-third,.column.three-fourth,.column.two-thirds{float:left;margin:0;width:100%}}
|
||||
html{font-family:sans-serif;-ms-text-size-adjust:100%;-webkit-text-size-adjust:100%}body{margin:0}article,aside,details,figcaption,figure,footer,header,hgroup,main,nav,section,summary{display:block}audio,canvas,progress,video{display:inline-block;vertical-align:baseline}audio:not([controls]){display:none;height:0}[hidden],template{display:none}a{background:0 0}a:active,a:hover{outline:0}abbr[title]{border-bottom:1px dotted}b,strong{font-weight:700}dfn{font-style:italic}mark{background:#ff0;color:#000}small{font-size:80%}sub,sup{font-size:75%;line-height:0;position:relative;vertical-align:baseline}sup{top:-.5em}sub{bottom:-.25em}img{border:0}svg:not(:root){overflow:hidden}figure{margin:1em 40px}hr{-webkit-box-sizing:content-box;box-sizing:content-box;height:0}pre{overflow:auto}code,kbd,pre,samp{font-family:monospace,monospace;font-size:1em}button,input,optgroup,select,textarea{color:inherit;font:inherit;margin:0}button{overflow:visible}button,select{text-transform:none}button,html input[type=button],input[type=reset],input[type=submit]{-webkit-appearance:button;cursor:pointer}button[disabled],html input[disabled]{cursor:default}button::-moz-focus-inner,input::-moz-focus-inner{border:0;padding:0}input{line-height:normal}input[type=checkbox],input[type=radio]{-webkit-box-sizing:border-box;box-sizing:border-box;padding:0}input[type=number]::-webkit-inner-spin-button,input[type=number]::-webkit-outer-spin-button{height:auto}input[type=search]{-webkit-appearance:textfield;-webkit-box-sizing:content-box;box-sizing:content-box}input[type=search]::-webkit-search-cancel-button,input[type=search]::-webkit-search-decoration{-webkit-appearance:none}fieldset{border:1px solid silver;margin:0 2px;padding:.35em .625em .75em}legend{border:0;padding:0}textarea{overflow:auto}optgroup{font-weight:700}table{border-collapse:collapse;border-spacing:0}td,th{padding:0}*,:after,:before{-webkit-box-sizing:inherit;box-sizing:inherit;padding:0;margin:0}html{height:100%;-webkit-box-sizing:border-box;box-sizing:border-box}@-ms-viewport{width:device-width}.clearfix::after,.clearfix::before{content:" ";display:table}.clearfix::after{clear:both}canvas,iframe,img,svg,video{max-width:100%}.video{position:relative;height:0;padding-bottom:56.25%}.video>*{position:absolute;top:0;left:0;height:100%;width:100%}.container{margin:0 auto}.row{overflow:hidden;max-width:960px;margin:0 auto}.fullrow{max-width:100%}.column{float:left;margin-left:5%}.column:first-child{margin-left:0}.column.full{width:100%}.column.three-fourth{width:63.75%}.column.two-thirds{width:65%}.column.half{width:47.5%}.column.one-third{width:30%}.column.one-fourth{width:21.25%}body{color:#000;font-family:Open Sans,Helvetica,Arial,sans-serif;font-size:12pt;-webkit-font-smoothing:subpixel-antialiased;-moz-osx-font-smoothing:auto}h1,h2,h3{font-family:Open Sans,Helvetica,Arial,sans-serif;font-weight:700;line-height:1.2em;margin:.4em 0}h1{font-size:2em;word-break:break-all}h2{font-size:1.5em}h3{font-size:1.25em}p{line-height:1.45em;padding:.5em 0}ul li{margin:.3em 0 .3em .5em;list-style-position:inside;list-style-type:square;font-size:1em}ul li p{padding-left:1em}a{color:#600;-webkit-transition:color .2s ease;transition:color .2s ease}a:active,a:focus,a:hover{color:#b30000}a:active{position:relative;top:1px}a.notdown:active{position:inherit}@media screen{a.external:after{content:"\00A0" "[" "\2197" "]"}}@media print{a[href]:after{content:" (" attr(href) ")"}}#instantclick-bar{background:red}.fa{margin-right:.3em;speak:none}.button{text-overflow:ellipsis}@media screen and (max-width:768px){.column.full,.column.half,.column.three-fourth,.column.two-thirds{float:none;margin:0;width:100%}.column.one-fourth,.column.one-third{float:left;margin:0;width:50%;padding:.4em}}@media screen and (max-width:568px){.column.one-third,.column.two-third{float:none;margin:0;width:100%}}@media screen and (max-width:480px){.column.full,.column.half,.column.one-fourth,.column.one-third,.column.three-fourth,.column.two-thirds{float:left;margin:0;width:100%}}
|
98
gulpfile.js
98
gulpfile.js
|
@ -1,24 +1,79 @@
|
|||
// include gulp
|
||||
var gulp = require('gulp');
|
||||
// Require all those npm-modules
|
||||
|
||||
// include plug-ins
|
||||
var jshint = require('gulp-jshint');
|
||||
var sass = require('gulp-sass');
|
||||
var prefix = require('gulp-autoprefixer');
|
||||
var rename = require('gulp-rename');
|
||||
var cssmin = require('gulp-cssmin');
|
||||
var watch = require('gulp-watch');
|
||||
var imagemin = require('gulp-imagemin');
|
||||
var pngcrush = require('imagemin-pngcrush');
|
||||
var gulp = require('gulp'),
|
||||
sass = require('gulp-sass'),
|
||||
autoprefixer = require('gulp-autoprefixer'),
|
||||
cssmin = require('gulp-cssmin'),
|
||||
jshint = require('gulp-jshint'),
|
||||
uglify = require('gulp-uglify'),
|
||||
imagemin = require('gulp-imagemin'),
|
||||
pngcrush = require('imagemin-pngcrush'),
|
||||
rename = require('gulp-rename'),
|
||||
clean = require('gulp-rimraf'),
|
||||
concat = require('gulp-concat'),
|
||||
notify = require('gulp-notify'),
|
||||
cache = require('gulp-cache'),
|
||||
livereload = require('gulp-livereload');
|
||||
|
||||
|
||||
// JS hint task
|
||||
gulp.task('jshint', function() {
|
||||
gulp.src('./scripts/*.js')
|
||||
.pipe(jshint())
|
||||
.pipe(jshint.reporter('default'));
|
||||
// render scss
|
||||
gulp.task('styles', function() {
|
||||
gulp.src('./src/scss/main.scss')
|
||||
.pipe(sass({ style: 'expanded' }))
|
||||
.pipe(autoprefixer('last 2 version', 'safari 5', 'ie 9', 'opera 12.1', 'ios 6', 'android 4'))
|
||||
.pipe(gulp.dest('./css'))
|
||||
.pipe(rename({suffix: '.min'}))
|
||||
.pipe(cssmin())
|
||||
.pipe(gulp.dest('./css'))
|
||||
.pipe(notify({ message: 'Styles task complete' }));
|
||||
});
|
||||
|
||||
// compress images
|
||||
gulp.task('images', function() {
|
||||
gulp.src('./src/img/*')
|
||||
.pipe(cache(imagemin({ optimizationLevel: 3, progressive: true, interlaced: true })))
|
||||
.pipe(gulp.dest('./img/'))
|
||||
.pipe(notify({ message: 'Images task complete' }));
|
||||
});
|
||||
|
||||
// clean the folders
|
||||
gulp.task('clean', function() {
|
||||
gulp.src(['./css/*', './js/*', './img/*'], {read: false})
|
||||
.pipe(clean());
|
||||
});
|
||||
|
||||
// do the javascript-dance
|
||||
gulp.task('scripts', function() {
|
||||
gulp.src('./src/js/**/*.js')
|
||||
.pipe(concat('main.js'))
|
||||
.pipe(gulp.dest('./js'))
|
||||
.pipe(rename({suffix: '.min'}))
|
||||
.pipe(uglify())
|
||||
.pipe(gulp.dest('./js'))
|
||||
.pipe(notify({ message: 'Scripts task complete' }));
|
||||
});
|
||||
|
||||
gulp.task('watch', function() {
|
||||
// Watch .scss files
|
||||
gulp.watch('src/scss/**/*.scss', ['styles']);
|
||||
|
||||
// Watch .js files
|
||||
gulp.watch('src/js/**/*.js', ['scripts']);
|
||||
|
||||
// Watch image files
|
||||
gulp.watch('src/img/**/*', ['images']);
|
||||
});
|
||||
|
||||
// default:
|
||||
gulp.task('default', ['clean'], function() {
|
||||
gulp.start('styles', 'scripts', 'images');
|
||||
});
|
||||
|
||||
|
||||
|
||||
/*
|
||||
//
|
||||
// OLD STUFF
|
||||
// ----------------------
|
||||
// sass + watch
|
||||
gulp.task('sass', function() {
|
||||
gulp.src('./scss/*.scss')
|
||||
|
@ -58,3 +113,12 @@ gulp.task('final', function() {
|
|||
}))
|
||||
.pipe(gulp.dest('./img/'))
|
||||
});
|
||||
|
||||
// JS hint task
|
||||
gulp.task('jshint', function() {
|
||||
gulp.src('./scripts/*.js')
|
||||
.pipe(jshint())
|
||||
.pipe(jshint.reporter('default'));
|
||||
});
|
||||
|
||||
*/
|
||||
|
|
|
@ -1,12 +0,0 @@
|
|||
/* InstantClick 3.0 | (C) 2014 Alexandre Dieulot | http://instantclick.io/license.html */
|
||||
var InstantClick=function(e,g){function v(a){var c=a.indexOf("#");return 0>c?a:a.substr(0,c)}function y(a){for(;"A"!=a.nodeName;)a=a.parentNode;return a}function t(a,c){for(var b=0;b<D[a].length;b++)D[a][b](c)}function G(a,c,b,l){e.title=a;e.documentElement.replaceChild(c,e.body);if(b){history.pushState(null,null,b);a=b.indexOf("#");a=-1<a&&e.getElementById(b.substr(a+1));c=0;if(a)for(;a.offsetParent;)c+=a.offsetTop,a=a.offsetParent;scrollTo(0,c);m=v(b)}else scrollTo(0,l);H();z.done();t("change",
|
||||
!1)}function I(a){w(y(a.target).href)}function J(a){a=y(a.target);a.addEventListener("mouseout",Q);E?(K=a.href,r=setTimeout(w,E)):w(a.href)}function R(a){a=y(a.target);A?a.removeEventListener("mousedown",I):a.removeEventListener("mouseover",J);w(a.href)}function S(a){1<a.which||a.metaKey||a.ctrlKey||(a.preventDefault(),L(y(a.target).href))}function Q(){r?(clearTimeout(r),r=!1):u&&!h&&(p.abort(),h=u=!1)}function T(){if(!(4>p.readyState)&&0!=p.status){q.ready=+new Date-q.start;t("receive");if(p.getResponseHeader("Content-Type").match(/\/(x|ht|xht)ml/)){var a=
|
||||
e.implementation.createHTMLDocument("");a.documentElement.innerHTML=p.responseText;F=a.title;x=a.body;var c=v(s);f[c]={body:x,title:F,scrollY:c in f?f[c].scrollY:0};for(var a=a.head.children,c=0,b,l=a.length-1;0<=l;l--)if(b=a[l],b.hasAttribute("data-instant-track")){b=b.getAttribute("href")||b.getAttribute("src")||b.innerHTML;for(var n=B.length-1;0<=n;n--)B[n]==b&&c++}c!=B.length&&(C=!0)}else C=!0;h&&(h=!1,L(s))}}function H(a){for(var c=e.getElementsByTagName("a"),b,l=g.protocol+"//"+g.host,n=c.length-
|
||||
1;0<=n;n--){b=c[n];var d;if(!((d=b.target)||(d=b.hasAttribute("download"))||(d=0!=b.href.indexOf(l+"/"))||(d=-1<b.href.indexOf("#")&&v(b.href)==m)))if(M){a:{d=b;do{if(!d.hasAttribute)break;if(d.hasAttribute("data-no-instant"))break;if(d.hasAttribute("data-instant")){d=!0;break a}}while(d=d.parentNode);d=!1}d=!d}else a:{d=b;do{if(!d.hasAttribute)break;if(d.hasAttribute("data-instant"))break;if(d.hasAttribute("data-no-instant")){d=!0;break a}}while(d=d.parentNode);d=!1}d||(b.addEventListener("touchstart",
|
||||
R),A?b.addEventListener("mousedown",I):b.addEventListener("mouseover",J),b.addEventListener("click",S))}if(!a)for(a=e.body.getElementsByTagName("script"),n=0,j=a.length;n<j;n++)c=a[n],c.hasAttribute("data-no-instant")||(b=e.createElement("script"),c.src&&(b.src=c.src),c.innerHTML&&(b.innerHTML=c.innerHTML),l=c.parentNode,d=c.nextSibling,l.removeChild(c),l.insertBefore(b,d))}function w(a){if(A||!("display"in q&&100>+new Date-(q.start+q.display)))if(r&&(clearTimeout(r),r=!1),a||(a=K),!u||a!=s&&!h)u=
|
||||
!0,h=!1,s=a,C=x=!1,q={start:+new Date},t("fetch"),p.open("GET",a),p.send()}function L(a){"display"in q||(q.display=+new Date-q.start);r?s&&s!=a?g.href=a:(w(a),z.start(0,!0),t("wait"),h=!0):!u||h?g.href=a:C?g.href=s:x?(f[m].scrollY=pageYOffset,h=u=!1,G(F,x,s)):(z.start(0,!0),t("wait"),h=!0)}var N=navigator.userAgent,O="createTouch"in e,m,K,r,f={},p,s=!1,F=!1,C=!1,x=!1,q={},u=!1,h=!1,B=[],M,A,E,D={fetch:[],receive:[],wait:[],change:[]},z=function(){function a(a,d){f=a;e.getElementById(k.id)&&e.body.removeChild(k);
|
||||
k.style.opacity="1";e.getElementById(k.id)&&e.body.removeChild(k);l();d&&setTimeout(c,0);clearTimeout(m);m=setTimeout(b,500)}function c(){f=10;l()}function b(){f+=1+2*Math.random();98<=f?f=98:m=setTimeout(b,500);l()}function l(){g.style[h]="translate("+f+"%)";e.getElementById(k.id)||e.body.appendChild(k)}function n(){e.getElementById(k.id)?(clearTimeout(m),f=100,l(),k.style.opacity="0"):(a(100==f?0:f),setTimeout(n,0))}function d(){k.style.left=pageXOffset+"px";k.style.width=innerWidth+"px";k.style.top=
|
||||
pageYOffset+"px";var a=innerWidth/screen[90==Math.abs(orientation)?"height":"width"]*2;k.style[h]="scaleY("+a+")"}var k,g,h,f,m;return{init:function(){k=e.createElement("div");k.id="instantclick";g=e.createElement("div");g.id="instantclick-bar";g.className="instantclick-bar";k.appendChild(g);var a=["Webkit","Moz","O"];h="transform";if(!(h in g.style))for(var b=0;3>b;b++)a[b]+"Transform"in g.style&&(h=a[b]+"Transform");var c="transition";if(!(c in g.style))for(b=0;3>b;b++)a[b]+"Transition"in g.style&&
|
||||
(c="-"+a[b].toLowerCase()+"-"+c);a=e.createElement("style");a.innerHTML="#instantclick{position:"+(O?"absolute":"fixed")+";top:0;left:0;width:100%;pointer-events:none;z-index:2147483647;"+c+":opacity .25s .1s}.instantclick-bar{background:#29d;width:100%;margin-left:-100%;height:2px;"+c+":all .25s}";e.head.appendChild(a);O&&(d(),addEventListener("resize",d),addEventListener("scroll",d))},start:a,done:n}}(),P="pushState"in history&&(!N.match("Android")||N.match("Chrome/"))&&"file:"!=g.protocol;return{supported:P,
|
||||
init:function(){if(!m)if(P){for(var a=arguments.length-1;0<=a;a--){var c=arguments[a];!0===c?M=!0:"mousedown"==c?A=!0:"number"==typeof c&&(E=c)}m=v(g.href);f[m]={body:e.body,title:e.title,scrollY:pageYOffset};for(var c=e.head.children,b,a=c.length-1;0<=a;a--)b=c[a],b.hasAttribute("data-instant-track")&&(b=b.getAttribute("href")||b.getAttribute("src")||b.innerHTML,B.push(b));p=new XMLHttpRequest;p.addEventListener("readystatechange",T);H(!0);z.init();t("change",!0);addEventListener("popstate",function(){var a=
|
||||
v(g.href);a!=m&&(a in f?(f[m].scrollY=pageYOffset,m=a,G(f[a].title,f[a].body,!1,f[a].scrollY)):g.href=g.href)})}else t("change",!0)},on:function(a,c){D[a].push(c)}}}(document,location);
|
|
@ -0,0 +1,725 @@
|
|||
/* Some scripts and stuff
|
||||
--------------------------*/
|
||||
|
||||
|
||||
/* Target-Blank for CSS-Class "external"
|
||||
--------------------------*/
|
||||
function externalLinks() {
|
||||
if (!document.getElementsByTagName) {return;}
|
||||
var anchors = document.getElementsByTagName("a");
|
||||
for (var i=0; i<anchors.length; i++) {
|
||||
var anchor = anchors[i];
|
||||
if (anchor.getAttribute("href") && anchor.getAttribute("class") === "external") {
|
||||
anchor.target = "_blank";
|
||||
}
|
||||
}
|
||||
}
|
||||
window.onload = externalLinks;
|
||||
|
||||
// or in jQuery
|
||||
/*
|
||||
$('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);
|
File diff suppressed because one or more lines are too long
|
@ -1 +0,0 @@
|
|||
function externalLinks(){if(document.getElementsByTagName)for(var e=document.getElementsByTagName("a"),t=0;t<e.length;t++){var n=e[t];n.getAttribute("href")&&"external"===n.getAttribute("class")&&(n.target="_blank")}}window.onload=externalLinks;
|
|
@ -0,0 +1,693 @@
|
|||
/* 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);
|
|
@ -6,8 +6,8 @@
|
|||
--------------------------*/
|
||||
|
||||
@import 'normalize';
|
||||
@import 'mixins';
|
||||
@import 'defaults';
|
||||
@import 'mixins';
|
||||
/* @import 'font-awesome'; */
|
||||
|
||||
/* Content
|
||||
|
@ -55,7 +55,7 @@ ul {
|
|||
}
|
||||
a {
|
||||
color: $linkcolor;
|
||||
@include transition(color 0.2s ease);
|
||||
transition: color 0.2s ease;
|
||||
&:hover, &:active, &:focus{
|
||||
color: lighten($linkcolor, 15%);
|
||||
}
|
Loading…
Reference in New Issue