mkdocs-material/src/assets/javascripts/application.js

362 lines
11 KiB
JavaScript
Raw Normal View History

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
import FastClick from "fastclick"
import lunr from "lunr"
// import Expander from "./components/expander"
import GithubSourceFacts from "./components/GithubSourceFacts"
import Material from "./components/Material"
// 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
* ------------------------------------------------------------------------- */
class Application {
/**
* Constructor.
*
* @constructor
* @param {object} config Configuration object
* @return {void}
*/
constructor(config) {
this.config = config
}
/**
* @return {void}
*/
initialize() {
const material = new Material()
material.initialize()
if (this.hasGithubRepo()) {
const githubSource = new GithubSourceFacts(
this.config.storage,
this.config.repo.url
)
githubSource.initialize()
}
}
/**
* Is this application about a Github repository?
*
* @return {bool} - true if `repo.icon` or `repo.url` contains 'github'
*/
hasGithubRepo() {
return this.config.repo.icon === "github"
|| this.config.repo.url.includes("github")
}
}
export default Application
// TODO: wrap in function call
// application module export
2016-01-29 01:27:15 +03:00
/* Initialize application upon DOM ready */
document.addEventListener("DOMContentLoaded", () => {
2016-01-29 01:27:15 +03:00
/* Test for iOS */
Modernizr.addTest("ios", () => {
return !!navigator.userAgent.match(/(iPad|iPhone|iPod)/g)
})
2016-01-29 01:27:15 +03:00
/* Test for web application context */
Modernizr.addTest("standalone", () => {
return !!navigator.standalone
})
2016-01-29 01:27:15 +03:00
/* Attack FastClick to mitigate 300ms delay on touch devices */
FastClick.attach(document.body)
2016-01-29 01:27:15 +03:00
const query = document.getElementById("query")
2016-10-23 20:31:54 +03:00
// query.addEventListener("focus", () => {
// document.querySelector(".md-search").dataset.mdLocked = ""
// })
/* Intercept click on search mode toggle */
2016-10-23 20:31:54 +03:00
// const offset = 0
// const toggle = document.getElementById("search")
// toggle.addEventListener("click", () => {
// const list = document.body // classList md bla
// const lock = !matchMedia("only screen and (min-width: 960px)").matches
//
// /* Exiting search mode */
// if (list.dataset.mdLocked) {
// delete list.dataset.mdLocked
//
// /* Scroll to former position, but wait for 100ms to prevent flashes
// on iOS. A short timeout seems to do the trick */
// if (lock)
// setTimeout(() => {
// window.scrollTo(0, offset)
// }, 100)
//
// /* Entering search mode */
// } else {
// offset = window.scrollY
//
// /* First timeout: scroll to top after transition, to omit flickering */
// if (lock)
// setTimeout(() => {
// window.scrollTo(0, 0)
// }, 400)
//
// /* 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. */
// setTimeout(() => {
//
// /* This additional check is necessary to handle fast subsequent
// clicks on the toggle and the timeout to lock the body must be
// cancelled */
// // if (ev.target.checked) {
// if (lock)
// list.dataset.mdLocked = ""
// setTimeout(() => {
// document.getElementById("query").focus()
// }, 200)
// // }
// }, 450)
// }
// })
// TODO: only do this on MOBILE and TABLET
2016-10-23 20:31:54 +03:00
// const toggleSearchClose = document.querySelector(".md-search__icon")
// toggleSearchClose.setAttribute("for", "search") // TODO: override query with search, when on mobile!!!
document.getElementById("query").addEventListener("focus", () => {
document.getElementById("search").checked = true
})
// should be registered on body, but leads to problems
document.querySelector(".md-container").addEventListener("click", () => {
if (document.getElementById("search").checked)
document.getElementById("search").checked = false
})
// stop propagation, if search is active...
document.querySelector(".md-search").addEventListener("click", ev => {
ev.stopPropagation()
})
// toggleSearchClose.addEventListener("click", ev => {
// ev.preventDefault()
// // ev.target
//
// const search = document.getElementById("search")
// search.checked = false
// })
// var toc = new Sidebar('.md-sidebar--secondary');
// toc.listen();
const toggles =
document.querySelectorAll(".md-nav__item--nested > .md-nav__link");
[].forEach.call(toggles, togglex => {
const nav = togglex.nextElementSibling
// 1.
nav.style.maxHeight = `${nav.getBoundingClientRect().height}px`
togglex.addEventListener("click", () => {
const first = nav.getBoundingClientRect().height
if (first) {
// console.log('closing');
nav.style.maxHeight = `${first}px` // reset!
requestAnimationFrame(() => {
nav.classList.add("md-nav--transitioning")
nav.style.maxHeight = "0px"
})
} else {
// console.log('opening');
/* Toggle and read height */
nav.style.maxHeight = ""
nav.classList.add("md-nav--toggled")
const last = nav.getBoundingClientRect().height
nav.classList.remove("md-nav--toggled")
// Initial state
nav.style.maxHeight = "0px"
/* Enable animations */
requestAnimationFrame(() => {
nav.classList.add("md-nav--transitioning")
nav.style.maxHeight = `${last}px`
})
}
})
// Capture the end with transitionend
nav.addEventListener("transitionend", ev => {
ev.target.classList.remove("md-nav--transitioning")
if (ev.target.getBoundingClientRect().height > 0) {
ev.target.style.maxHeight = "100%"
}
})
})
2016-09-23 21:26:27 +03:00
2016-09-23 12:56:25 +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(function() {
/* eslint-disable no-invalid-this, lines-around-comment */
this.field("title", { boost: 10 })
this.field("text")
this.ref("location")
/* eslint-enable no-invalid-this, lines-around-comment */
})
/* 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 12:56:25 +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)
/* Truncate a string after the given number of characters */
const truncate = function(string, n) {
let i = n
if (string.length > i) {
while (string[i] !== " " && --i > 0);
return `${string.substring(0, i)}&hellip;`
}
return string
}
/* Create text element */
const text = document.createElement("p")
text.classList.add("md-search-result__description")
text.innerHTML = truncate(article.text) // .truncate(140);
text.innerHTML = truncate(article.text, 140) // .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
// setTimeout(function() {
// li.classList.remove('md-source__fact--hidden');
// }, 100);
2016-09-23 12:56:25 +03:00
})
.catch(() => {
// console.log("parsing failed", ex)
})
2016-09-23 12:56:25 +03:00
// }, 1000);
fetch(
"https://api.github.com/repos/squidfunk/mkdocs-material/releases/latest")
.then(response => {
return response.json()
})
// .then(data => {
// // console.log(data)
// })
})