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
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
|
import LeaderLine from 'leader-line';
export function focusNextMap(reverse = false) {
const renderedList = this.utils.renderedMaps();
const index = renderedList.findIndex(e => e.classList.contains('focus'));
const nextIndex =
index === -1 ? 0 : (index + (reverse ? -1 : 1)) % renderedList.length;
const nextMap = renderedList.at(nextIndex);
nextMap.classList.add('focus');
}
export function focusNextBlock(reverse = false) {
const blocks = this.blocks.filter(b =>
b.checkVisibility({
contentVisibilityAuto: true,
opacityProperty: true,
visibilityProperty: true,
}),
);
const index = blocks.findIndex(e => e.classList.contains('focus'));
const nextIndex =
index === -1 ? 0 : (index + (reverse ? -1 : 1)) % blocks.length;
blocks.forEach(b => b.classList.remove('focus'));
const nextBlock = blocks.at(nextIndex);
nextBlock?.classList?.add('focus');
scrollToBlock(nextBlock);
}
// Consider block is bigger then viewport height
export const scrollToBlock = block => {
const parentRect = block.parentElement.getBoundingClientRect();
const scrollBlock =
block.getBoundingClientRect().height > parentRect.height * 0.8
? 'nearest'
: 'center';
block.scrollIntoView({ behavior: 'smooth', block: scrollBlock });
};
export function focusDelay() {
return window.getComputedStyle(this.showcase).display === 'none' ? 50 : 300;
}
export function switchToNextLayout(reverse = false) {
const layouts = this.layouts;
const currentLayoutName = this.container.getAttribute('data-layout');
const currentIndex = layouts.map(l => l.name).indexOf(currentLayoutName);
const padding = reverse ? -1 : 1;
const nextIndex =
currentIndex === -1
? 0
: (currentIndex + padding + layouts.length) % layouts.length;
const nextLayout = layouts[nextIndex];
this.container.setAttribute('data-layout', nextLayout.name);
}
export function removeBlockFocus() {
this.blocks.forEach(b => b.classList.remove('focus'));
}
/**
* Create geolinks, which points to map by geo schema and id
*
* @param {HTMLElement} Elements contains anchor elements for doclinks
* @returns {Boolean} ture is link is created, false if coordinates are invalid
*/
export const createGeoLink = (link, callback = null) => {
const url = new URL(link.href);
const xyInParams = url.searchParams.get('xy');
const xy = xyInParams
? xyInParams.split(',')?.map(Number)
: url?.href
?.match(/^geo:([0-9.,]+)/)
?.at(1)
?.split(',')
?.reverse()
?.map(Number);
if (!xy || isNaN(xy[0]) || isNaN(xy[1])) return false;
// Geo information in link
link.url = url;
link.xy = xy;
link.classList.add('with-leader-line', 'geolink');
link.targets = link.url.searchParams.get('id')?.split(',') ?? null;
// LeaderLine
link.lines = [];
callback?.call(this, link);
return true;
};
/**
* CreateDocLink.
*
* @param {HTMLElement} Elements contains anchor elements for doclinks
*/
export const createDocLink = link => {
link.classList.add('with-leader-line', 'doclink');
link.lines = [];
link.onmouseover = () => {
const label = decodeURIComponent(link.href.split('#')[1]);
const selector = link.title.split('=>')[1] ?? '#' + label;
const target = document.querySelector(selector);
if (!target?.checkVisibility()) return;
const line = new LeaderLine({
start: link,
end: target,
middleLabel: LeaderLine.pathLabel({
text: label,
fontWeight: 'bold',
}),
hide: true,
path: 'magnet',
});
link.lines.push(line);
line.show('draw', { duration: 300 });
};
link.onmouseout = () => {
link.lines.forEach(line => line.remove());
link.lines.length = 0;
};
};
|