PageSourceSearch

https://www.swissbikepark.ch/extras/js/2020-06-19/interactive-map.js

js swissbikepark.ch collected 2026-10-06 04:50:01 UTC 5,436 bytes, 170 lines download raw bytes

1/**
2 * Swiss Bike Park - Interactive Map
3 * sbpim
4 * box: swissbikepark-2020
5 * author: sandra
6 * 
7 * description:
8 * this script adds interactivity to a inline svg map (in code part).
9 * there is no interactivity on mobile/tablet, only on desktop >1024.
10 * When clicked on a number on a map, the corresponding popup opens and the track
11 * is highlighted.
12 */
13sbpim = {
14
15  init: function() {
16    imContainer = document.querySelector('.interactiveMap')
17    if (!imContainer) {
18      return
19    }
20    imNumberContainer = imContainer.querySelector('.iM__background')
21    imNumbers = imContainer.querySelectorAll('.iM__background .num')
22    imPopupsContainer = imContainer.querySelector('.iM__popups')
23    imCloseLinks = imContainer.querySelectorAll('.iM__close')
24    activeClassName = 'is-active'
25    scrollbarOffset = imContainer.getBoundingClientRect().left
26    supportsNativeSmoothScroll = 'scrollBehavior' in document.documentElement.style
27
28    sbpim.addNumbersToPopup()
29    sbpim.setupListeners()
30  },
31
32  setupListeners: function() {
33    imNumbers.forEach(function(num){
34      num.addEventListener('click', sbpim.handleNumClick)
35    })
36
37    imCloseLinks.forEach(function(link){
38      link.addEventListener('click', sbpim.closeAll)
39    })
40
41    window.addEventListener('resize', function(event) {
42      if (sbpim.isInteractive()) {
43        sbpim.positionPopups()
44      }
45    })
46  
47    document.addEventListener('keyup', function (event) {
48      var key = event.key || event.keyCode
49      if (key === 'Escape' || key === 'Esc' || key === 27) {
50        sbpim.closeAll()
51      }
52    })
53  },
54
55  handleNumClick: function() {
56    var num = this
57    if (!sbpim.isInteractive()) {
58      var popup = imPopupsContainer.querySelector('.iM__popup--'+num.dataset.number)
59      var yOffset = document.querySelector('.section--header').getHeight()
60      const y = popup.getBoundingClientRect().top + window.pageYOffset - yOffset - 16
61
62      //window.scrollTo({top: y, behavior: 'smooth'});
63
64      if (supportsNativeSmoothScroll) {
65        console.log('nativeSmoothScrollTo')
66        sbpim.nativeSmoothScrollTo(y);
67      } else {
68        console.log('old scroll')
69        sbpim.smoothScrollTo(y, 600);
70      }
71      return
72    }
73    sbpim.closeAll()
74    imPopupsContainer.querySelector('.iM__popup--'+num.dataset.number).classList.add(activeClassName)
75    imContainer.querySelector('.track--'+num.dataset.number).classList.add(activeClassName)
76  },
77
78  positionPopups: function() {
79    var containerOffsetTop = imContainer.getBoundingClientRect().top
80    imNumbers.forEach(function(num){
81      var numBounding = num.getBoundingClientRect()
82      var popup = imPopupsContainer.querySelector('.iM__popup--'+num.dataset.number)
83      var popupNumber = imPopupsContainer.querySelector('.iM__number--'+num.dataset.number)
84      var top = numBounding.top + (numBounding.height * 0.5) - containerOffsetTop
85      var left = numBounding.left + (numBounding.width * 0.5) - scrollbarOffset
86      if(numBounding.left > (window.innerWidth / 2) && num.dataset.number != 11) {
87        popup.classList.add('iM__popup--right')
88      }
89      popup.style.top = top + 'px'
90      popup.style.left = left + 'px'
91
92      sbpim.setNodeDimensions(popupNumber, numBounding)
93    })
94  },
95
96  addNumbersToPopup: function() {
97    imPopupsContainer.children.forEach(function(popup) {
98      var id = popup.dataset.popup
99      var numBounding = imNumberContainer.querySelector('.num--'+ id).getBoundingClientRect()
100
101      var img = document.createElement('img')
102      img.setAttribute('src', '/images/nums/num-'+ id +'.svg')
103      img.setAttribute('alt', id)
104      img.classList.add('iM__number', 'iM__number--' + id)
105      if(numBounding.left > (window.innerWidth / 2) && id != 11) {
106        img.classList.add('iM__number--right')
107      }
108      sbpim.setNodeDimensions(img, numBounding)
109
110      img.addEventListener('click', sbpim.closeAll)
111      popup.appendChild(img)
112
113    })
114    sbpim.positionPopups()
115  },
116
117  closeAll: function() {
118    imContainer.querySelectorAll('.'+activeClassName).forEach(function(n) {n.classList.remove(activeClassName)})
119  },
120
121  setNodeDimensions: function(node, nodeBounding) {
122    node.style.height = nodeBounding.height+'px'
123    node.style.width = nodeBounding.width+'px'
124  },
125
126  isInteractive: function() {
127    return (window.innerWidth >= 1024)
128  },
129
130  // polyfilled smooth scrolling for IE, Edge & Safari
131  smoothScrollTo: function(to, duration) {
132    var element = document.scrollingElement || document.documentElement,
133        start = element.scrollTop,
134        change = to - start,
135        startDate = +new Date()
136
137    // t = current time
138    // b = start value
139    // c = change in value
140    // d = duration
141    var easeInOutQuad = function(t, b, c, d) {
142        t /= d/2
143        if (t < 1) return c/2*t*t + b
144        t--
145        return -c/2 * (t*(t-2) - 1) + b
146    };
147
148    var animateScroll = function() {
149        const currentDate = +new Date()
150        const currentTime = currentDate - startDate
151        element.scrollTop = parseInt(easeInOutQuad(currentTime, start, change, duration))
152        if(currentTime < duration) {
153            requestAnimationFrame(animateScroll)
154        }
155        else {
156            element.scrollTop = to
157        }
158    }
159    animateScroll();
160  },
161
162  nativeSmoothScrollTo: function(y) {
163    window.scroll({
164        behavior: 'smooth',
165        top: y
166    })
167  }
168}
169
170document.addEventListener("DOMContentLoaded", sbpim.init)

Line numbers count LF bytes from the start of the resource, as the search results do. Vendor segments are library code the classifier recognised; they are stored but not indexed. Bytes are shown as Latin1 characters, one per byte.