mirror of
https://github.com/squidfunk/mkdocs-material.git
synced 2026-07-28 00:32:42 -04:00
Implemented basic search modal functionality
This commit is contained in:
@@ -24,8 +24,7 @@
|
||||
* Definition
|
||||
* ------------------------------------------------------------------------- */
|
||||
|
||||
export default
|
||||
class Abstract {
|
||||
export default class Abstract {
|
||||
|
||||
/**
|
||||
* Dispatch update on next repaint
|
||||
@@ -33,8 +32,8 @@ class Abstract {
|
||||
* @constructor
|
||||
*/
|
||||
constructor() {
|
||||
// if (new.target === this.constructor)
|
||||
// throw new TypeError("Cannot construct abstract instance")
|
||||
if (this === Abstract)
|
||||
throw new TypeError("Cannot construct abstract instance")
|
||||
|
||||
/* Dispatch update on next repaint */
|
||||
this.handler_ = ev => {
|
||||
@@ -48,7 +47,6 @@ class Abstract {
|
||||
* Update state
|
||||
*
|
||||
* @abstract
|
||||
* @return {void}
|
||||
*/
|
||||
update() {
|
||||
throw new Error("update(): not implemented")
|
||||
@@ -58,7 +56,6 @@ class Abstract {
|
||||
* Reset state
|
||||
*
|
||||
* @abstract
|
||||
* @return {void}
|
||||
*/
|
||||
reset() {
|
||||
throw new Error("reset(): not implemented")
|
||||
@@ -66,8 +63,6 @@ class Abstract {
|
||||
|
||||
/**
|
||||
* Register listener for all relevant events
|
||||
*
|
||||
* @return {void}
|
||||
*/
|
||||
listen() {
|
||||
["scroll", "resize", "orientationchange"].forEach(name => {
|
||||
@@ -80,8 +75,6 @@ class Abstract {
|
||||
|
||||
/**
|
||||
* Unregister listener for all relevant events
|
||||
*
|
||||
* @return {void}
|
||||
*/
|
||||
unlisten() {
|
||||
["scroll", "resize", "orientationchange"].forEach(name => {
|
||||
|
||||
@@ -26,14 +26,13 @@ import Abstract from "./Abstract"
|
||||
* Definition
|
||||
* ------------------------------------------------------------------------- */
|
||||
|
||||
export default
|
||||
class Marker extends Abstract {
|
||||
export default class Marker extends Abstract {
|
||||
|
||||
/**
|
||||
* Mark anchors within the table of contents above current page y-offset
|
||||
*
|
||||
* @constructor
|
||||
* @param {(string|HTMLCollection)} els - Selector or HTML elements
|
||||
* @param {(string|NodeList<HTMLElement>)} els - Selector or HTML elements
|
||||
*/
|
||||
constructor(els) {
|
||||
super()
|
||||
@@ -57,16 +56,16 @@ class Marker extends Abstract {
|
||||
* Update anchor states
|
||||
*
|
||||
* @param {Event} ev - Event (omitted)
|
||||
* @return {void}
|
||||
*/
|
||||
update() {
|
||||
const offset = window.pageYOffset
|
||||
|
||||
/* Scroll direction is down */
|
||||
if (this.offset_ <= window.pageYOffset) {
|
||||
if (this.offset_ <= offset) {
|
||||
for (let i = this.index_ + 1; i < this.els_.length; i++) {
|
||||
if (this.anchors_[i].offsetTop <= window.pageYOffset) {
|
||||
if (this.anchors_[i].offsetTop <= offset) {
|
||||
if (i > 0)
|
||||
this.els_[i - 1].dataset.mdMarked = true
|
||||
this.els_[i - 1].dataset.mdMarked = ""
|
||||
this.index_ = i
|
||||
} else {
|
||||
break
|
||||
@@ -76,7 +75,7 @@ class Marker extends Abstract {
|
||||
/* Scroll direction is up */
|
||||
} else {
|
||||
for (let i = this.index_; i >= 0; i--) {
|
||||
if (this.anchors_[i].offsetTop > window.pageYOffset) {
|
||||
if (this.anchors_[i].offsetTop > offset) {
|
||||
if (i > 0)
|
||||
delete this.els_[i - 1].dataset.mdMarked
|
||||
} else {
|
||||
@@ -87,13 +86,11 @@ class Marker extends Abstract {
|
||||
}
|
||||
|
||||
/* Remember current offset for next iteration */
|
||||
this.offset_ = window.pageYOffset
|
||||
this.offset_ = offset
|
||||
}
|
||||
|
||||
/**
|
||||
* Reset anchor states
|
||||
*
|
||||
* @return {void}
|
||||
*/
|
||||
reset() {
|
||||
[].forEach.call(this.els_, el => {
|
||||
|
||||
@@ -26,8 +26,7 @@ import Abstract from "./Abstract"
|
||||
* Definition
|
||||
* ------------------------------------------------------------------------- */
|
||||
|
||||
export default
|
||||
class Position extends Abstract {
|
||||
export default class Position extends Abstract {
|
||||
|
||||
/**
|
||||
* Set sidebars to locked state and limit height to parent node
|
||||
@@ -44,8 +43,15 @@ class Position extends Abstract {
|
||||
: el
|
||||
|
||||
/* Index inner and outer container */
|
||||
this.inner_ = this.el_.parentNode
|
||||
this.outer_ = this.el_.parentNode.parentNode
|
||||
const inner = this.el_.parentNode
|
||||
const outer = this.el_.parentNode.parentNode
|
||||
|
||||
/* Get top and bottom bounds */
|
||||
this.offset_ = outer.offsetTop
|
||||
this.bounds_ = {
|
||||
top: inner.offsetTop,
|
||||
bottom: inner.offsetTop + inner.offsetHeight
|
||||
}
|
||||
|
||||
/* Initialize current height */
|
||||
this.height_ = 0
|
||||
@@ -55,45 +61,34 @@ class Position extends Abstract {
|
||||
* Update locked state and height
|
||||
*
|
||||
* @param {Event} ev - Event (omitted)
|
||||
* @return {void}
|
||||
*/
|
||||
update() {
|
||||
const bounds = this.inner_.getBoundingClientRect() // TODO: thresholds can be calculated as a function
|
||||
const parent = this.outer_.offsetTop
|
||||
|
||||
/* Determine top and bottom offsets */
|
||||
const top = bounds.top + window.pageYOffset,
|
||||
bottom = bounds.bottom + window.pageYOffset
|
||||
|
||||
/* Determine current y-offset at top and bottom of window */
|
||||
const upper = window.pageYOffset,
|
||||
lower = window.pageYOffset + window.innerHeight
|
||||
const scroll = window.pageYOffset
|
||||
const expand = window.innerHeight
|
||||
|
||||
/* Calculate new bounds */
|
||||
const offset = top - upper
|
||||
const height = window.innerHeight
|
||||
- Math.max(lower - bottom, 0)
|
||||
- Math.max(offset, parent)
|
||||
const offset = this.bounds_.top - scroll
|
||||
const height = expand
|
||||
- Math.max(0, scroll + expand - this.bounds_.bottom)
|
||||
- Math.max(offset, this.offset_)
|
||||
|
||||
/* If height changed, update element */
|
||||
if (height !== this.height_)
|
||||
this.el_.style.height = `${this.height_ = height}px`
|
||||
|
||||
/* Sidebar should be locked, as we're below parent offset */
|
||||
if (offset < parent) {
|
||||
if (offset < this.offset_) {
|
||||
if (!this.el_.dataset.mdLocked)
|
||||
this.el_.dataset.mdLocked = true
|
||||
this.el_.dataset.mdLocked = ""
|
||||
|
||||
/* Sidebar should be unlocked, if locked */
|
||||
} else if (this.el_.dataset.mdLocked) {
|
||||
} else if (typeof this.el_.dataset.mdLocked === "string") {
|
||||
delete this.el_.dataset.mdLocked
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Reset locked state and height
|
||||
*
|
||||
* @return {void}
|
||||
*/
|
||||
reset() {
|
||||
delete this.el_.dataset.mdLocked
|
||||
|
||||
@@ -21,71 +21,18 @@
|
||||
*/
|
||||
|
||||
/* ----------------------------------------------------------------------------
|
||||
* Navigation expander
|
||||
* Definition
|
||||
* ------------------------------------------------------------------------- */
|
||||
|
||||
class Expander {
|
||||
export default
|
||||
class Abstract {
|
||||
|
||||
/**
|
||||
* Constructor
|
||||
* Dispatch update on next repaint
|
||||
*
|
||||
* @constructor
|
||||
* @param {(string|HTMLElement)} el - Selector or HTML element
|
||||
*/
|
||||
constructor(el) {
|
||||
this.el_ = (typeof el === "string")
|
||||
? document.querySelector(el)
|
||||
: el
|
||||
|
||||
/* Event listener */
|
||||
this.handler_ = ev => {
|
||||
this.update(ev)
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Update state of expandable element
|
||||
*
|
||||
* @param {Event} ev - Event
|
||||
* @return {void}
|
||||
*/
|
||||
update() {}
|
||||
|
||||
/**
|
||||
* Reset state of expandable element
|
||||
*
|
||||
* @return {void}
|
||||
*/
|
||||
reset() {}
|
||||
|
||||
/**
|
||||
* Register listener for all relevant events
|
||||
*
|
||||
* @return {void}
|
||||
*/
|
||||
listen() {
|
||||
["click"].forEach(name => {
|
||||
window.addEventListener(name, this.handler_, false)
|
||||
})
|
||||
}
|
||||
|
||||
/**
|
||||
* Unregister listener for all relevant events
|
||||
*
|
||||
* @return {void}
|
||||
*/
|
||||
unlisten() {
|
||||
["click"].forEach(name => {
|
||||
window.removeEventListener(name, this.handler_, false)
|
||||
})
|
||||
|
||||
/* Perform reset */
|
||||
this.reset()
|
||||
}
|
||||
// constructor() {
|
||||
//
|
||||
// }
|
||||
}
|
||||
|
||||
/* ----------------------------------------------------------------------------
|
||||
* Exports
|
||||
* ------------------------------------------------------------------------- */
|
||||
|
||||
export default Expander
|
||||
@@ -1,131 +0,0 @@
|
||||
/*
|
||||
* 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.
|
||||
*/
|
||||
|
||||
/* ----------------------------------------------------------------------------
|
||||
* Sidebar scroll-spy
|
||||
* ------------------------------------------------------------------------- */
|
||||
|
||||
export default
|
||||
class ScrollSpy {
|
||||
|
||||
/**
|
||||
* Constructor
|
||||
*
|
||||
* @constructor
|
||||
* @param {(string|HTMLCollection)} els - Selector or HTML elements
|
||||
*/
|
||||
constructor(els) {
|
||||
this.els_ = (typeof els === "string")
|
||||
? document.querySelectorAll(els)
|
||||
: els
|
||||
|
||||
/* Initialize index for currently active element */
|
||||
this.index_ = 0
|
||||
this.offset_ = window.pageYOffset
|
||||
|
||||
/* Index anchor nodes for fast lookup */
|
||||
this.anchors_ = [].map.call(this.els_, el => {
|
||||
return document.querySelector(el.hash)
|
||||
})
|
||||
|
||||
/* Event listener */
|
||||
this.handler_ = ev => {
|
||||
this.update(ev)
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Update state of sidebar
|
||||
*
|
||||
* @param {Event} ev - Event (omitted)
|
||||
* @return {void}
|
||||
*/
|
||||
update() {
|
||||
|
||||
/* Scroll direction is down */
|
||||
if (this.offset_ <= window.pageYOffset) {
|
||||
for (let i = this.index_ + 1; i < this.els_.length; i++) {
|
||||
if (this.anchors_[i].offsetTop <= window.pageYOffset) {
|
||||
if (i > 0)
|
||||
this.els_[i - 1].dataset.mdMarked = true
|
||||
this.index_ = i
|
||||
} else {
|
||||
break
|
||||
}
|
||||
}
|
||||
|
||||
/* Scroll direction is up */
|
||||
} else {
|
||||
for (let i = this.index_; i >= 0; i--) {
|
||||
if (this.anchors_[i].offsetTop > window.pageYOffset) {
|
||||
if (i > 0)
|
||||
delete this.els_[i - 1].dataset.mdMarked
|
||||
} else {
|
||||
this.index_ = i
|
||||
break
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/* Remember current offset for next cycle */
|
||||
this.offset_ = window.pageYOffset
|
||||
}
|
||||
|
||||
/**
|
||||
* Reset state of sidebar
|
||||
*
|
||||
* @return {void}
|
||||
*/
|
||||
reset() {
|
||||
[].forEach.call(this.els_, el => {
|
||||
delete el.dataset.mdMarked
|
||||
})
|
||||
}
|
||||
|
||||
/**
|
||||
* Register listener for all relevant events
|
||||
*
|
||||
* @return {void}
|
||||
*/
|
||||
listen() {
|
||||
["scroll", "resize", "orientationchange"].forEach(name => {
|
||||
window.addEventListener(name, this.handler_, false)
|
||||
})
|
||||
|
||||
/* Initial update */
|
||||
this.update()
|
||||
}
|
||||
|
||||
/**
|
||||
* Unregister listener for all relevant events
|
||||
*
|
||||
* @return {void}
|
||||
*/
|
||||
unlisten() {
|
||||
["scroll", "resize", "orientationchange"].forEach(name => {
|
||||
window.removeEventListener(name, this.handler_, false)
|
||||
})
|
||||
|
||||
/* Perform reset */
|
||||
this.reset()
|
||||
}
|
||||
}
|
||||
@@ -1,96 +0,0 @@
|
||||
/*
|
||||
* 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.
|
||||
*/
|
||||
|
||||
/* ----------------------------------------------------------------------------
|
||||
* Search
|
||||
* ------------------------------------------------------------------------- */
|
||||
|
||||
class Search {
|
||||
|
||||
/**
|
||||
* Constructor
|
||||
*
|
||||
* @constructor
|
||||
* @param {(string|HTMLElement)} el - Selector or HTML element
|
||||
*/
|
||||
constructor(el) {
|
||||
this.el_ = (typeof el === "string") ? document.querySelector(el) : el
|
||||
|
||||
/* Event listener */
|
||||
this.handler_ = ev => {
|
||||
this.update(ev)
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Update state and height of sidebar
|
||||
*
|
||||
* @param {Event} ev - Event
|
||||
* @return {void}
|
||||
*/
|
||||
update() {
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* Reset state and height of sidebar
|
||||
*
|
||||
* @return {void}
|
||||
*/
|
||||
reset() {
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* Register listener for all relevant events
|
||||
*
|
||||
* @return {void}
|
||||
*/
|
||||
listen() {
|
||||
// ['scroll', 'resize', 'orientationchange'].forEach(name => {
|
||||
// window.addEventListener(name, this.handler_, false);
|
||||
// });
|
||||
|
||||
/* Initial update */
|
||||
this.update()
|
||||
}
|
||||
|
||||
/**
|
||||
* Unregister listener for all relevant events
|
||||
*
|
||||
* @return {void}
|
||||
*/
|
||||
unlisten() {
|
||||
// ['scroll', 'resize', 'orientationchange'].forEach(name => {
|
||||
// window.removeEventListener(name, this.handler_, false);
|
||||
// });
|
||||
|
||||
/* Perform reset */
|
||||
this.reset()
|
||||
}
|
||||
}
|
||||
|
||||
/* ----------------------------------------------------------------------------
|
||||
* Exports
|
||||
* ------------------------------------------------------------------------- */
|
||||
|
||||
export default Search
|
||||
@@ -1,142 +0,0 @@
|
||||
/*
|
||||
* 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.
|
||||
*/
|
||||
|
||||
/* ----------------------------------------------------------------------------
|
||||
* Sidebar sticky-scroll handler
|
||||
* ------------------------------------------------------------------------- */
|
||||
|
||||
class Sidebar {
|
||||
|
||||
/**
|
||||
* Constructor
|
||||
*
|
||||
* @constructor
|
||||
* @param {(string|HTMLElement)} el - Selector or HTML element
|
||||
*/
|
||||
constructor(el) {
|
||||
this.el_ = (typeof el === "string")
|
||||
? document.querySelector(el)
|
||||
: el
|
||||
|
||||
/* Grab inner and outer container */
|
||||
this.inner_ = this.el_.parentNode
|
||||
this.outer_ = this.el_.parentNode.parentNode
|
||||
|
||||
/* Initialize parameters */
|
||||
this.height_ = 0
|
||||
this.locked_ = false
|
||||
|
||||
/* Event listener */
|
||||
this.handler_ = ev => {
|
||||
this.update(ev)
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Update state and height of sidebar
|
||||
*
|
||||
* @param {Event} ev - Event
|
||||
* @return {void}
|
||||
*/
|
||||
update() {
|
||||
const bounds = this.inner_.getBoundingClientRect()
|
||||
const parent = this.outer_.offsetTop
|
||||
|
||||
/* Determine top and bottom offsets */
|
||||
const top = bounds.top + window.pageYOffset,
|
||||
bottom = bounds.bottom + window.pageYOffset
|
||||
|
||||
/* Determine current y-offset at top and bottom of window */
|
||||
const upper = window.pageYOffset,
|
||||
lower = window.pageYOffset + window.innerHeight
|
||||
|
||||
/* Calculate new bounds */
|
||||
const offset = top - upper
|
||||
const height = window.innerHeight - Math.max(lower - bottom, 0)
|
||||
- Math.max(offset, parent)
|
||||
|
||||
/* If height changed, update element */
|
||||
if (height !== this.height_)
|
||||
this.el_.style.height = `${this.height_ = height}px`
|
||||
|
||||
/* Sidebar should be locked, as we're below parent offset */
|
||||
if (offset < parent) {
|
||||
if (!this.locked_) {
|
||||
this.el_.classList.add("md-js__sidebar--locked")
|
||||
this.locked_ = true
|
||||
}
|
||||
|
||||
/* Sidebar should be unlocked, if locked */
|
||||
} else if (this.locked_) {
|
||||
this.el_.classList.remove("md-js__sidebar--locked")
|
||||
this.locked_ = false
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Reset state and height of sidebar
|
||||
*
|
||||
* @return {void}
|
||||
*/
|
||||
reset() {
|
||||
this.el_.classList.remove("md-js__sidebar--locked")
|
||||
this.el_.style.height = ""
|
||||
|
||||
/* Reset parameters */
|
||||
this.height_ = 0
|
||||
this.locked_ = false
|
||||
}
|
||||
|
||||
/**
|
||||
* Register listener for all relevant events
|
||||
*
|
||||
* @return {void}
|
||||
*/
|
||||
listen() {
|
||||
["scroll", "resize", "orientationchange"].forEach(name => {
|
||||
window.addEventListener(name, this.handler_, false)
|
||||
})
|
||||
|
||||
/* Initial update */
|
||||
this.update()
|
||||
}
|
||||
|
||||
/**
|
||||
* Unregister listener for all relevant events
|
||||
*
|
||||
* @return {void}
|
||||
*/
|
||||
unlisten() {
|
||||
["scroll", "resize", "orientationchange"].forEach(name => {
|
||||
window.removeEventListener(name, this.handler_, false)
|
||||
})
|
||||
|
||||
/* Perform reset */
|
||||
this.reset()
|
||||
}
|
||||
}
|
||||
|
||||
/* ----------------------------------------------------------------------------
|
||||
* Exports
|
||||
* ------------------------------------------------------------------------- */
|
||||
|
||||
export default Sidebar
|
||||
Reference in New Issue
Block a user