This repository was archived by the owner on Feb 22, 2024. It is now read-only.
-
Notifications
You must be signed in to change notification settings - Fork 228
Expand file tree
/
Copy pathscroll_to_anchor.js
More file actions
99 lines (84 loc) · 2.82 KB
/
scroll_to_anchor.js
File metadata and controls
99 lines (84 loc) · 2.82 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
const isVisible = require('./common_functions').isVisible;
const Url = require('./url');
const createElement = require('./utility').createElement;
/*
adds anchor links to elements with data-anchor attribute
created anchors work similarly to native anchors,
but rely on URL params instead
HOW TO USE:
<h1 data-anchor>Some title</h1>
*/
const ScrollToAnchor = (() => {
let id_occurrence_count = {};
const init = () => {
addAnchorsToElements();
const target = getAnchorTargetElement();
// remove query param if loaded onto a page without target element
if (!target || !isVisible(target)) {
Url.updateParamsWithoutReload({
anchor: null,
}, true);
} else {
scrollToAnchorInQuery();
}
};
const encode = (str) => {
const encoded = str.trim().toLowerCase().replace(/[^a-z0-9]+/g, '-');
let appendix = '';
if (id_occurrence_count[encoded]) {
appendix = `-${++id_occurrence_count[encoded]}`;
} else {
id_occurrence_count[encoded] = 1;
}
return encodeURI(`${encoded}${appendix}`);
};
const makeAnchorLink = (id) => {
const url = new URL(window.location);
url.search = `anchor=${id}`;
return createElement('a', {
class: 'data-anchor-link',
href : url.href,
});
};
const addAnchorsToElements = () => {
const els = document.querySelectorAll('[data-anchor]');
els.forEach(el => {
if (el.querySelector('.data-anchor-link')) return;
const title = el.getAttribute('data-anchor') === 'true' ? el.innerText : el.getAttribute('data-anchor'); // use data-anchor value else use innerText
const id = encode(title);
el.dataset.anchor = id;
const anchor_link = makeAnchorLink(id);
el.appendChild(anchor_link);
anchor_link.addEventListener('click', (e) => {
e.preventDefault();
scrollToEl(el);
Url.updateParamsWithoutReload({
anchor: id,
}, true);
});
});
};
const scrollToEl = (el) => {
$.scrollTo(el, 500, { offset: -10 });
};
const getAnchorTargetElement = () => {
const id = Url.paramsHash().anchor;
if (!id) return null;
return document.querySelector(`[data-anchor="${id}"]`);
};
const scrollToAnchorInQuery = () => {
const el = getAnchorTargetElement();
if (!el) return;
window.setTimeout(() => {
scrollToEl(el);
}, 100);
};
const cleanup = () => {
id_occurrence_count = {};
};
return {
init,
cleanup,
};
})();
module.exports = ScrollToAnchor;