PageSourceSearch

https://evertz.com/js/lib.responsiveImageMap.js?039

js evertz.com collected 2026-10-02 03:45:36 UTC 5,974 bytes, 141 lines download raw bytes

1/* ********************************************************************
2 * responsiveImageMap w/ link highlight function
3 *   - By Brian Huisman (GreyWyvern)
4 *
5 * Adapted from Andriy Kuba's StackOverflow post:
6 *   - https://stackoverflow.com/a/48370297
7 *
8 */
9function responsiveImageMap(img, width) {
10  if (typeof img == 'string') img = document.getElementById(img);
11  if (!img) return console.log('Image not found');
12  if (!img.useMap) return console.log('Image does not reference a <map>.');
13
14  let map = document.getElementsByName(img.useMap.replace(/^#/, ''))[0];
15  if (!map) return console.log('Associated <map> element could not be found.');
16
17  img.link = !(arguments[2] === false);
18  img.origWidth = parseInt(width);
19  img.areas = [];
20  img.blur = img.parentNode.classList.contains('responsive-image-map-blur');
21
22  let area = map.getElementsByTagName('area');
23  for (let x = 0, a; x < area.length; x++, a = false) {
24    area[x].shape = area[x].shape.toLowerCase();
25    if (img.link && (
26          area[x].shape == 'rect' ||
27          area[x].shape == 'circle' ||
28          area[x].shape == 'poly')) {
29      a = document.createElement('a');
30      let attr, attributes = Array.prototype.slice.call(area[x].attributes);
31      while (attr = attributes.pop()) a.setAttribute(attr.nodeName, attr.nodeValue);
32      // a.href = area[x].href;
33      if (area[x].shape == 'circle')
34        a.style.borderRadius = '50%';
35      a.style.position = 'absolute';
36      if (img.blur) {
37        a.bkgImg = img;
38        a.style.backgroundImage = 'url(' + img.src + ')';
39        a.addEventListener('mouseover', function() {
40          this.bkgImg.classList.add('blur');
41          let sibs = this.parentNode.getElementsByTagName('a');
42          for (let y = 0; y < sibs.length; y++)
43            if (sibs[y] != this) sibs[y].classList.add('d-none');
44        }, false);
45        a.addEventListener('mouseout', function() {
46          this.bkgImg.classList.remove('blur');
47          let sibs = this.parentNode.getElementsByTagName('a');
48          for (let y = 0; y < sibs.length; y++)
49            sibs[y].classList.remove('d-none');
50        }, false);
51      }
52      map.appendChild(a);
53    }
54    img.areas.push({
55      element: area[x],
56      link: a,
57      coords: area[x].coords.split(',')
58    });
59  }
60
61  img.resize = function() {
62    clearInterval(this.check);
63    let ratio = this.offsetWidth / this.origWidth;
64    for (let x = 0, tArea; tArea = this.areas[x++];) {
65      let coords = [];
66      for (let y = 0; y < tArea.coords.length; y++)
67        coords.push(Math.round(tArea.coords[y] * ratio));
68      tArea.element.coords = coords.join(',');
69
70      if (this.link && tArea.link) {
71        switch (tArea.element.shape) {
72          case 'rect':
73            tArea.link.classList.add('shape-rect');
74            tArea.link.style.top = (this.offsetTop + coords[1]) + 'px';
75            tArea.link.style.left = (this.offsetLeft + coords[0]) + 'px';
76            tArea.link.style.width = (coords[2] - coords[0]) + 'px';
77            tArea.link.style.height = (coords[3] - coords[1]) + 'px';
78            break;
79          case 'circle':
80            tArea.link.classList.add('shape-circle');
81            tArea.link.style.top = (this.offsetTop + coords[1] - coords[2]) + 'px';
82            tArea.link.style.left = (this.offsetLeft + coords[0] - coords[2]) + 'px';
83            tArea.link.style.width = (coords[2] * 2) + 'px';
84            tArea.link.style.height = (coords[2] * 2) + 'px';
85            break;
86          case 'poly': // Doesn't work in IE11
87            let mx = [coords[0], coords[0]], my = [coords[1], coords[1]];
88            for (let i = 2; i < coords.length - 1; i += 2) {
89              mx = [Math.min(mx[0], coords[i]), Math.max(mx[1], coords[i])];
90              my = [Math.min(my[0], coords[i + 1]), Math.max(my[1], coords[i + 1])];
91            }
92            let final = [];
93            for (let i = 0; i < coords.length - 1; i += 2) {
94              final.push(
95                Math.round((coords[i] - mx[0]) / (mx[1] - mx[0]) * 1000) / 10 + '% ' +
96                Math.round((coords[i + 1] - my[0]) / (my[1] - my[0]) * 1000) / 10 + '%'
97              );
98            }
99            map.classList.add('contains-poly');
100            tArea.link.classList.add('shape-poly');
101            tArea.link.style.top = (this.offsetTop + my[0]) + 'px';
102            tArea.link.style.left = (this.offsetLeft + mx[0]) + 'px';
103            tArea.link.style.width = (mx[1] - mx[0]) + 'px';
104            tArea.link.style.height = (my[1] - my[0]) + 'px';
105            tArea.link.style.clipPath = 'polygon(' + final.join(',') + ')';
106        }
107        if (this.blur) {
108          tArea.link.style.backgroundSize = this.offsetWidth + 'px ' + this.offsetHeight + 'px';
109          tArea.link.style.backgroundPosition = '-' + tArea.link.style.left + ' -' + tArea.link.style.top;
110        }
111      }
112    } return true;
113  };
114
115  window.addEventListener('resize', function() { img.resize(); });
116  img.check = setInterval(function() {
117    if (img.complete) img.resize();
118  }, 10);
119}
120
121
122window.addEventListener('load', function() {
123  let respImgs = document.querySelectorAll('.responsive-image-map > img:first-of-type, .responsive-image-map-blur > img:first-of-type');
124  for (let x = 0; x < respImgs.length; x++) {
125    responsiveImageMap(respImgs[x], respImgs[x].naturalWidth);
126    respondToVisibility(respImgs[x], function() { respImgs[x].resize(); });
127  }
128}, false);
129
130
131// Start observing visbility of element. On change, the
132//   the callback is called with Boolean visibility as
133//   argument:
134function respondToVisibility(element, callback) {
135  let options = { root: document.documentElement };
136  let observer = new IntersectionObserver((entries, observer) => {
137    entries.forEach(entry => { callback(entry.intersectionRatio > 0); });
138  }, options);
139  observer.observe(element);
140}
141

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.