1 2// ###### ######## ####### ###### ## ## ###### ###### 3// ## ## ## ## ## ## ## ## ## ## ## 4// ## ## ## ## ## ## ## ## ## 5// ## ###### ## ## ## ## ## ###### ## 6// ## ## ## ## ## ## ## ## ## 7// ## ## ## ## ## ## ## ## ## ## ## 8// ###### ## ####### ###### ####### ###### ###### 9 10function FocusFunction() { 11 12 let focusContext = this; 13 let observables = []; 14 15 /** 16 * 17 * @param target 18 * @return {*} 19 */ 20 function getObservable(target) { 21 22 for (let i=0; i < observables.length; i++) { 23 if (observables[i].target === target) { 24 return observables[i]; 25 } 26 } 27 } 28 29 let options = { 30 attributes: true, 31 attributeFilter: ['data-crop'] 32 // attributeFilter: ['data-focus-area'] 33 }; 34 35 let resizeObserver = new ResizeObserver(function (entries, observer) { 36 for (let i=0; i < entries.length; i++) { 37 focusContext.handleEvent(getObservable(entries[i].target)); 38 } 39 }); 40 41 let intersectionObserver = new IntersectionObserver(function (entries, observer) { 42 43 for (let i=0; i < entries.length; i++) { 44 45 let observable = getObservable(entries[i].target); 46 47 if (entries[i].isIntersecting) { 48 if (!observable.viewport) { 49 resizeObserver.observe(entries[i].target); 50 observable.mutationObserver = new MutationObserver(function () { 51 focusContext.handleEvent(observable); 52 }); 53 observable.mutationObserver.observe(observable.img, options); 54 observable.viewport = true; 55 } 56 } else { 57 if (observable.viewport) { 58 resizeObserver.unobserve(entries[i].target); 59 observable.mutationObserver.disconnect(); 60 observable.viewport = false; 61 } 62 } 63 } 64 }, {}); 65 66 focusContext.observe = function (img) { 67 68 let item = { 'img': img, 'target': img.parentNode, 'viewport': false, 'mutationObserver': null }; 69 70 while ( 71 (item.target.tagName.toLowerCase() !== 'body') && 72 ((item.target.offsetWidth === 0) || (item.target.offsetHeight === 0))) { 73 item.target = item.target.parentNode; 74 } 75 if (item.target.tagName.toLowerCase() !== 'body') { 76 let properties = window.getComputedStyle(item.target); 77 if (!properties.getPropertyValue('position')) { 78 item.target.style.position = 'relative'; 79 } 80 81 img.style.position = 'absolute'; 82 img.style.maxWidth = 'none'; 83 observables.push(item); 84 intersectionObserver.observe(item.target); 85 } 86 }; 87 88 this.handleEvent = function (item) { 89 90 let img = item.img, 91 target = item.target, 92 93 width = target.offsetWidth, // frame width 94 height = target.offsetHeight, // frame height 95 focusX = .50, // center 96 focusY = .50; // center 97 98 // let focusJson = JSON.parse(img.getAttribute('data-focus-area')); 99 if (img.getAttribute('data-crop')){ 100 let focusJson = JSON.parse(img.getAttribute('data-crop')); 101 focusJson = focusJson.default.focusArea; 102 if (focusJson != null){ 103 // overwrite focus coordinates and calc to % 104 if (focusJson.x != null) { 105 // focusX = parseFloat(focusJson.x / img.naturalWidth * 100) / 100; 106 focusX = parseFloat(focusJson.x + (focusJson.width / 2)); 107 } 108 if (focusJson.y != null) { 109 // focusY = parseFloat(focusJson.y / img.naturalHeight * 100) / 100; 110 focusY = parseFloat(focusJson.y + (focusJson.height / 2)); 111 } 112 } 113 } 114 115 let scaled, 116 value; 117
118 if ( (img.naturalWidth / img.naturalHeight) >= (width / height) ) { 119 img.style.width = 'auto'; 120 img.style.height = '100%'; 121 img.style.top = '0'; 122 scaled = img.naturalWidth * (height / img.naturalHeight); 123 value = - Math.floor((scaled * focusX) - (width / 2)); 124 125 if (value > 0) { 126 value = 0; 127 } else if (value < width - scaled) { 128 value = Math.floor(width - scaled); 129 } 130 131 img.style.left = value + 'px'; 132 } else { 133 img.style.width = '100%'; 134 img.style.height = 'auto'; 135 img.style.left = '0'; 136 scaled = img.naturalHeight * (width / img.naturalWidth); 137 value = - Math.floor((scaled * focusY) - (height / 2)); 138 139 if (value > 0) { 140 value = 0; 141 } else if (value < (height - scaled)) { 142 value = Math.floor(height - scaled); 143 } 144 145 img.style.top = value + 'px'; 146 } 147 } 148} 149 150/** 151 * @param {NodeListOf<HTMLImageElement>} imgElementsToFocus 152 * 153 * @return void 154 */ 155export function callFocusFunction(imgElementsToFocus){ 156 157 if (imgElementsToFocus.length > 0) { 158 159 let focus = new FocusFunction(); 160 161 for (let i=0; i < imgElementsToFocus.length; i++) { 162 if (!imgElementsToFocus[i].complete || (imgElementsToFocus[i].naturalWidth === 0)) { 163 imgElementsToFocus[i].addEventListener("load", function (e) { focus.observe(this); }, false); 164 } else { 165 focus.observe(imgElementsToFocus[i]); 166 } 167 } 168 } 169}
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.