132 lines
4.0 KiB
JavaScript
132 lines
4.0 KiB
JavaScript
/*
|
|
* Copyright (c) 2016-2019 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.
|
|
*/
|
|
|
|
/* ----------------------------------------------------------------------------
|
|
* Class
|
|
* ------------------------------------------------------------------------- */
|
|
|
|
export default class Blur {
|
|
|
|
/**
|
|
* Blur links within the table of contents above current page y-offset
|
|
*
|
|
* @constructor
|
|
*
|
|
* @property {NodeList<HTMLElement>} els_ - Table of contents links
|
|
* @property {Array<HTMLElement>} anchors_ - Referenced anchor nodes
|
|
* @property {number} index_ - Current link index
|
|
* @property {number} offset_ - Current page y-offset
|
|
* @property {boolean} dir_ - Scroll direction change
|
|
*
|
|
* @param {(string|NodeList<HTMLElement>)} els - Selector or HTML elements
|
|
*/
|
|
constructor(els) {
|
|
this.els_ = (typeof els === "string")
|
|
? document.querySelectorAll(els)
|
|
: els
|
|
|
|
/* Initialize index and page y-offset */
|
|
this.index_ = 0
|
|
this.offset_ = window.pageYOffset
|
|
|
|
/* Necessary state to correctly reset the index */
|
|
this.dir_ = false
|
|
|
|
/* Index anchor node offsets for fast lookup */
|
|
this.anchors_ = [].reduce.call(this.els_, (anchors, el) => {
|
|
return anchors.concat(
|
|
document.getElementById(el.hash.substring(1)) || [])
|
|
}, [])
|
|
}
|
|
|
|
/**
|
|
* Initialize blur states
|
|
*/
|
|
setup() {
|
|
this.update()
|
|
}
|
|
|
|
/**
|
|
* Update blur states
|
|
*
|
|
* Deduct the static offset of the header (56px) and sidebar offset (24px),
|
|
* see _permalinks.scss for more information.
|
|
*/
|
|
update() {
|
|
const offset = window.pageYOffset
|
|
const dir = this.offset_ - offset < 0
|
|
|
|
/* Hack: reset index if direction changed to catch very fast scrolling,
|
|
because otherwise we would have to register a timer and that sucks */
|
|
if (this.dir_ !== dir)
|
|
this.index_ = dir
|
|
? this.index_ = 0
|
|
: this.index_ = this.els_.length - 1
|
|
|
|
/* Exit when there are no anchors */
|
|
if (this.anchors_.length === 0)
|
|
return
|
|
|
|
/* Scroll direction is down */
|
|
if (this.offset_ <= offset) {
|
|
for (let i = this.index_ + 1; i < this.els_.length; i++) {
|
|
if (this.anchors_[i].offsetTop - (56 + 24) <= offset) {
|
|
if (i > 0)
|
|
this.els_[i - 1].dataset.mdState = "blur"
|
|
this.index_ = i
|
|
} else {
|
|
break
|
|
}
|
|
}
|
|
|
|
/* Scroll direction is up */
|
|
} else {
|
|
for (let i = this.index_; i >= 0; i--) {
|
|
if (this.anchors_[i].offsetTop - (56 + 24) > offset) {
|
|
if (i > 0)
|
|
this.els_[i - 1].dataset.mdState = ""
|
|
} else {
|
|
this.index_ = i
|
|
break
|
|
}
|
|
}
|
|
}
|
|
|
|
/* Remember current offset and direction for next iteration */
|
|
this.offset_ = offset
|
|
this.dir_ = dir
|
|
}
|
|
|
|
/**
|
|
* Reset blur states
|
|
*/
|
|
reset() {
|
|
Array.prototype.forEach.call(this.els_, el => {
|
|
el.dataset.mdState = ""
|
|
})
|
|
|
|
/* Reset index and page y-offset */
|
|
this.index_ = 0
|
|
this.offset_ = window.pageYOffset
|
|
}
|
|
}
|