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
|
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 + (reverse ? -1 : 1)) % renderedList.length
const nextMap = renderedList.at(nextIndex)
nextMap.classList.add('focus')
nextMap.scrollIntoView({ behavior: 'smooth' })
}
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 + (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.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
}
}
|