2016-01-29 01:27:15 +03:00
|
|
|
/*
|
|
|
|
* Copyright (c) 2016 Martin Donath <martin.donath@squidfunk.com>
|
|
|
|
*
|
|
|
|
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
|
|
* of this software and associated documentation files (the "Software"), to
|
|
|
|
* deal in the Software without restriction, including without limitation the
|
|
|
|
* rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
|
|
|
|
* sell copies of the Software, and to permit persons to whom the Software is
|
|
|
|
* furnished to do so, subject to the following conditions:
|
|
|
|
*
|
|
|
|
* The above copyright notice and this permission notice shall be included in
|
|
|
|
* all copies or substantial portions of the Software.
|
|
|
|
*
|
|
|
|
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
|
|
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
|
|
* FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. IN NO EVENT SHALL THE
|
|
|
|
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
|
|
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
|
|
|
|
* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
|
|
|
|
* IN THE SOFTWARE.
|
|
|
|
*/
|
|
|
|
|
2016-08-07 19:01:56 +03:00
|
|
|
/* ----------------------------------------------------------------------------
|
|
|
|
* Imports
|
|
|
|
* ------------------------------------------------------------------------- */
|
2016-01-29 01:27:15 +03:00
|
|
|
|
2016-09-30 14:29:45 +03:00
|
|
|
import FastClick from "fastclick"
|
|
|
|
import lunr from "lunr"
|
|
|
|
|
|
|
|
// import Expander from "./components/expander"
|
2016-10-06 13:14:33 +03:00
|
|
|
|
|
|
|
import Material from "./components/Material"
|
2016-09-30 14:29:45 +03:00
|
|
|
|
|
|
|
// import Search from './components/search';
|
2016-01-29 01:27:15 +03:00
|
|
|
|
|
|
|
/* ----------------------------------------------------------------------------
|
2016-08-07 19:01:56 +03:00
|
|
|
* Application
|
2016-01-29 01:27:15 +03:00
|
|
|
* ------------------------------------------------------------------------- */
|
|
|
|
|
2016-10-06 13:14:33 +03:00
|
|
|
class Application {
|
|
|
|
|
|
|
|
/**
|
|
|
|
* @return {void}
|
|
|
|
*/
|
|
|
|
initialize() {
|
|
|
|
const material = new Material()
|
|
|
|
material.initialize()
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
export default Application
|
|
|
|
|
|
|
|
// TODO: wrap in function call
|
|
|
|
// application module export
|
|
|
|
|
2016-01-29 01:27:15 +03:00
|
|
|
/* Initialize application upon DOM ready */
|
2016-09-30 14:29:45 +03:00
|
|
|
document.addEventListener("DOMContentLoaded", () => {
|
2016-01-29 01:27:15 +03:00
|
|
|
|
|
|
|
/* Test for iOS */
|
2016-09-30 14:29:45 +03:00
|
|
|
Modernizr.addTest("ios", () => {
|
|
|
|
return !!navigator.userAgent.match(/(iPad|iPhone|iPod)/g)
|
|
|
|
})
|
2016-01-29 01:27:15 +03:00
|
|
|
|
|
|
|
/* Test for web application context */
|
2016-09-30 14:29:45 +03:00
|
|
|
Modernizr.addTest("standalone", () => {
|
|
|
|
return !!navigator.standalone
|
|
|
|
})
|
2016-01-29 01:27:15 +03:00
|
|
|
|
|
|
|
/* Attack FastClick to mitigate 300ms delay on touch devices */
|
2016-09-30 14:29:45 +03:00
|
|
|
FastClick.attach(document.body)
|
2016-01-29 01:27:15 +03:00
|
|
|
|
2016-09-30 14:29:45 +03:00
|
|
|
const query = document.getElementById("query")
|
|
|
|
query.addEventListener("focus", () => {
|
|
|
|
document.querySelector(".md-search").classList.add("md-js__search--locked")
|
|
|
|
})
|
2016-09-02 01:33:45 +03:00
|
|
|
|
|
|
|
/* Intercept click on search mode toggle */
|
2016-09-30 14:29:45 +03:00
|
|
|
let offset = 0
|
|
|
|
const toggle = document.getElementById("search")
|
|
|
|
toggle.addEventListener("click", ev => {
|
|
|
|
const list = document.body.classList
|
|
|
|
const lock = !matchMedia("only screen and (min-width: 960px)").matches
|
2016-09-02 01:33:45 +03:00
|
|
|
|
|
|
|
/* Exiting search mode */
|
2016-09-30 14:29:45 +03:00
|
|
|
if (list.contains("md-js__body--locked")) {
|
|
|
|
list.remove("md-js__body--locked")
|
2016-09-02 01:33:45 +03:00
|
|
|
|
|
|
|
/* Scroll to former position, but wait for 100ms to prevent flashes
|
|
|
|
on iOS. A short timeout seems to do the trick */
|
|
|
|
if (lock)
|
2016-09-30 14:29:45 +03:00
|
|
|
setTimeout(() => {
|
|
|
|
window.scrollTo(0, offset)
|
|
|
|
}, 100)
|
2016-09-02 01:33:45 +03:00
|
|
|
|
|
|
|
/* Entering search mode */
|
|
|
|
} else {
|
2016-09-30 14:29:45 +03:00
|
|
|
offset = window.scrollY
|
2016-09-02 01:33:45 +03:00
|
|
|
|
|
|
|
/* First timeout: scroll to top after transition, to omit flickering */
|
|
|
|
if (lock)
|
2016-09-30 14:29:45 +03:00
|
|
|
setTimeout(() => {
|
|
|
|
window.scrollTo(0, 0)
|
|
|
|
}, 400)
|
2016-09-02 01:33:45 +03:00
|
|
|
|
|
|
|
/* Second timeout: Lock body after finishing transition and scrolling to
|
|
|
|
top and focus input field. Sadly, the focus event is not dispatched
|
|
|
|
on iOS Safari and there's nothing we can do about it. */
|
2016-09-30 14:29:45 +03:00
|
|
|
setTimeout(() => {
|
2016-09-02 01:33:45 +03:00
|
|
|
|
|
|
|
/* This additional check is necessary to handle fast subsequent clicks
|
|
|
|
on the toggle and the timeout to lock the body must be cancelled */
|
2016-09-30 14:29:45 +03:00
|
|
|
if (ev.target.checked) {
|
2016-09-02 01:33:45 +03:00
|
|
|
if (lock)
|
2016-09-30 14:29:45 +03:00
|
|
|
list.add("md-js__body--locked")
|
|
|
|
setTimeout(() => {
|
|
|
|
document.getElementById("md-search").focus()
|
|
|
|
}, 200)
|
2016-09-02 01:33:45 +03:00
|
|
|
}
|
2016-09-30 14:29:45 +03:00
|
|
|
}, 450)
|
2016-09-02 01:33:45 +03:00
|
|
|
}
|
2016-09-30 14:29:45 +03:00
|
|
|
})
|
2016-09-02 01:33:45 +03:00
|
|
|
|
2016-09-24 19:52:37 +03:00
|
|
|
// var toc = new Sidebar('.md-sidebar--secondary');
|
|
|
|
// toc.listen();
|
|
|
|
|
2016-09-30 14:29:45 +03:00
|
|
|
const toggles =
|
|
|
|
document.querySelectorAll(".md-nav__item--nested > .md-nav__link");
|
|
|
|
[].forEach.call(toggles, togglex => {
|
|
|
|
const nav = togglex.nextElementSibling
|
2016-09-24 19:52:37 +03:00
|
|
|
|
|
|
|
// 1.
|
|
|
|
|
2016-09-30 14:29:45 +03:00
|
|
|
nav.style.maxHeight = `${nav.getBoundingClientRect().height}px`
|
2016-09-24 19:52:37 +03:00
|
|
|
|
2016-09-30 14:29:45 +03:00
|
|
|
togglex.addEventListener("click", () => {
|
|
|
|
const first = nav.getBoundingClientRect().height
|
2016-09-24 19:52:37 +03:00
|
|
|
if (first) {
|
2016-09-30 14:29:45 +03:00
|
|
|
// console.log('closing');
|
|
|
|
nav.style.maxHeight = `${first}px` // reset!
|
2016-09-24 19:52:37 +03:00
|
|
|
requestAnimationFrame(() => {
|
|
|
|
|
2016-09-30 14:29:45 +03:00
|
|
|
nav.classList.add("md-nav--transitioning")
|
|
|
|
nav.style.maxHeight = "0px"
|
|
|
|
})
|
2016-09-24 19:52:37 +03:00
|
|
|
} else {
|
2016-09-30 14:29:45 +03:00
|
|
|
// console.log('opening');
|
2016-09-24 19:52:37 +03:00
|
|
|
|
|
|
|
/* Toggle and read height */
|
2016-09-30 14:29:45 +03:00
|
|
|
nav.style.maxHeight = ""
|
2016-09-24 19:52:37 +03:00
|
|
|
|
2016-09-30 14:29:45 +03:00
|
|
|
nav.classList.add("md-nav--toggled")
|
|
|
|
const last = nav.getBoundingClientRect().height
|
|
|
|
nav.classList.remove("md-nav--toggled")
|
2016-09-24 19:52:37 +03:00
|
|
|
|
|
|
|
// Initial state
|
2016-09-30 14:29:45 +03:00
|
|
|
nav.style.maxHeight = "0px"
|
2016-09-24 19:52:37 +03:00
|
|
|
|
|
|
|
/* Enable animations */
|
|
|
|
requestAnimationFrame(() => {
|
2016-09-30 14:29:45 +03:00
|
|
|
nav.classList.add("md-nav--transitioning")
|
|
|
|
nav.style.maxHeight = `${last}px`
|
|
|
|
})
|
2016-09-24 19:52:37 +03:00
|
|
|
}
|
|
|
|
|
2016-09-30 14:29:45 +03:00
|
|
|
})
|
2016-09-24 19:52:37 +03:00
|
|
|
|
|
|
|
// Capture the end with transitionend
|
2016-09-30 14:29:45 +03:00
|
|
|
nav.addEventListener("transitionend", ev => {
|
|
|
|
ev.target.classList.remove("md-nav--transitioning")
|
|
|
|
if (ev.target.getBoundingClientRect().height > 0) {
|
|
|
|
ev.target.style.maxHeight = "100%"
|
2016-09-24 19:52:37 +03:00
|
|
|
}
|
2016-09-30 14:29:45 +03:00
|
|
|
})
|
|
|
|
})
|
2016-09-23 21:26:27 +03:00
|
|
|
|
2016-09-23 12:56:25 +03:00
|
|
|
// setTimeout(function() {
|
2016-09-30 14:29:45 +03:00
|
|
|
fetch("https://api.github.com/repos/squidfunk/mkdocs-material")
|
|
|
|
.then(response => {
|
2016-09-23 12:56:25 +03:00
|
|
|
return response.json()
|
2016-09-30 14:29:45 +03:00
|
|
|
})
|
|
|
|
.then(data => {
|
|
|
|
const stars = data.stargazers_count
|
|
|
|
const forks = data.forks_count
|
2016-09-23 12:56:25 +03:00
|
|
|
// store in session!!!
|
2016-09-30 14:29:45 +03:00
|
|
|
const lists = document.querySelectorAll(".md-source__facts"); // TODO 2x list in drawer and header
|
|
|
|
[].forEach.call(lists, list => {
|
|
|
|
|
|
|
|
let li = document.createElement("li")
|
|
|
|
li.className = "md-source__fact md-source__fact--hidden"
|
|
|
|
li.innerText = `${stars} Stars`
|
|
|
|
list.appendChild(li)
|
|
|
|
|
|
|
|
setTimeout(lix => {
|
|
|
|
lix.classList.remove("md-source__fact--hidden")
|
|
|
|
}, 100, li)
|
|
|
|
|
|
|
|
li = document.createElement("li")
|
|
|
|
li.className = "md-source__fact md-source__fact--hidden"
|
|
|
|
li.innerText = `${forks} Forks`
|
|
|
|
list.appendChild(li)
|
|
|
|
|
|
|
|
setTimeout(lix => {
|
|
|
|
lix.classList.remove("md-source__fact--hidden")
|
|
|
|
}, 500, li)
|
|
|
|
})
|
2016-09-23 12:56:25 +03:00
|
|
|
|
2016-09-30 14:29:45 +03:00
|
|
|
// setTimeout(function() {
|
|
|
|
// li.classList.remove('md-source__fact--hidden');
|
|
|
|
// }, 100);
|
2016-09-23 12:56:25 +03:00
|
|
|
|
2016-09-30 14:29:45 +03:00
|
|
|
})
|
|
|
|
.catch(() => {
|
|
|
|
// console.log("parsing failed", ex)
|
2016-09-23 12:56:25 +03:00
|
|
|
|
2016-09-30 14:29:45 +03:00
|
|
|
})
|
2016-09-23 12:56:25 +03:00
|
|
|
|
2016-09-30 14:29:45 +03:00
|
|
|
// setTimeout(function() {
|
|
|
|
fetch("/mkdocs/search_index.json") // TODO: prepend BASE URL!!!
|
|
|
|
.then(response => {
|
|
|
|
return response.json()
|
|
|
|
})
|
|
|
|
.then(data => {
|
|
|
|
// console.log(data)
|
|
|
|
|
|
|
|
/* Create index */
|
|
|
|
const index = lunr(() => {
|
|
|
|
/* eslint-disable no-invalid-this, lines-around-comment */
|
2016-10-06 13:14:33 +03:00
|
|
|
this.field("title", { boost: 10 })
|
2016-09-30 14:29:45 +03:00
|
|
|
this.field("text")
|
|
|
|
this.ref("location")
|
|
|
|
/* eslint-enable no-invalid-this, lines-around-comment */
|
|
|
|
})
|
2016-09-23 18:46:16 +03:00
|
|
|
|
2016-09-30 14:29:45 +03:00
|
|
|
/* Index articles */
|
|
|
|
const articles = {}
|
|
|
|
data.docs.forEach(article => {
|
|
|
|
|
|
|
|
// TODO: match for two whitespaces, then replace unnecessary whitespace after string
|
|
|
|
article.text = article.text.replace(/\s(\.,\:)\s/gi, (string, g1) => {
|
|
|
|
return `${g1} `
|
|
|
|
})
|
|
|
|
// TODO: window.baseUrl sucks...
|
|
|
|
article.location = window.baseUrl + article.location
|
|
|
|
articles[article.location] = article
|
|
|
|
index.add(article)
|
2016-09-23 18:46:16 +03:00
|
|
|
})
|
2016-09-23 12:56:25 +03:00
|
|
|
|
2016-09-30 14:29:45 +03:00
|
|
|
/* Register keyhandler to execute search on key up */
|
|
|
|
const queryx = document.getElementById("query")
|
|
|
|
queryx.addEventListener("keyup", () => {
|
|
|
|
const container = document.querySelector(".md-search-result__list")
|
|
|
|
while (container.firstChild)
|
|
|
|
container.removeChild(container.firstChild)
|
|
|
|
|
|
|
|
// /* Abort, if the query is empty */
|
|
|
|
// var bar = document.querySelector('.bar.search');
|
|
|
|
// if (!query.value.length) {
|
|
|
|
// while (meta.firstChild)
|
|
|
|
// meta.removeChild(meta.firstChild);
|
|
|
|
//
|
|
|
|
// /* Restore state */
|
|
|
|
// bar.classList.remove('non-empty');
|
|
|
|
// return;
|
|
|
|
// }
|
|
|
|
|
|
|
|
/* Show reset button */
|
|
|
|
// bar.classList.add('non-empty');
|
|
|
|
|
|
|
|
/* Execute search */
|
|
|
|
const results = index.search(query.value)
|
|
|
|
results.forEach(result => {
|
|
|
|
const article = articles[result.ref]
|
|
|
|
|
|
|
|
/* Create a link referring to the article */
|
|
|
|
const link = document.createElement("a")
|
|
|
|
link.classList.add("md-search-result__link")
|
|
|
|
link.href = article.location
|
|
|
|
|
|
|
|
// /* Create article container */
|
|
|
|
const li = document.createElement("li")
|
|
|
|
li.classList.add("md-search-result__item")
|
|
|
|
li.appendChild(link)
|
|
|
|
|
|
|
|
/* Create title element */
|
|
|
|
const title = document.createElement("div")
|
|
|
|
title.classList.add("md-search-result__title")
|
|
|
|
|
|
|
|
// article.title.split(//)
|
|
|
|
|
|
|
|
title.innerHTML = article.title
|
|
|
|
link.appendChild(title)
|
|
|
|
|
|
|
|
/* Create text element */
|
|
|
|
const text = document.createElement("p")
|
|
|
|
text.classList.add("md-search-result__description")
|
|
|
|
text.innerHTML = article.text // .truncate(140);
|
|
|
|
link.appendChild(text)
|
|
|
|
|
|
|
|
container.appendChild(li)
|
|
|
|
})
|
|
|
|
|
|
|
|
/* Show number of search results */
|
|
|
|
// var number = document.createElement('strong');
|
|
|
|
|
|
|
|
const meta = document.querySelector(".md-search-result__meta")
|
|
|
|
meta.innerHTML = `${results.length} search result${
|
|
|
|
results.length !== 1
|
|
|
|
? "s"
|
|
|
|
: ""}`
|
|
|
|
|
|
|
|
/* Update number */
|
|
|
|
// while (meta.firstChild)
|
|
|
|
// meta.removeChild(meta.firstChild);
|
|
|
|
// meta.appendChild(number);
|
|
|
|
})
|
2016-09-23 12:56:25 +03:00
|
|
|
|
2016-09-30 14:29:45 +03:00
|
|
|
// setTimeout(function() {
|
|
|
|
// li.classList.remove('md-source__fact--hidden');
|
|
|
|
// }, 100);
|
2016-09-23 12:56:25 +03:00
|
|
|
|
2016-09-30 14:29:45 +03:00
|
|
|
})
|
|
|
|
.catch(() => {
|
|
|
|
// console.log("parsing failed", ex)
|
|
|
|
})
|
2016-09-23 12:56:25 +03:00
|
|
|
// }, 1000);
|
2016-09-02 01:33:45 +03:00
|
|
|
|
2016-09-30 14:29:45 +03:00
|
|
|
})
|