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.