1/** Created by: Udo Schmal | https://www.gocher.me/ */ 2(function() { 3 'use strict'; 4 // initialize focus object 5 function Focus (img) { 6 this.img = img; // image 7 this.wrapper = img.parentNode; // frame 8 this.focus_x = null; 9 this.focus_y = null; 10 this.focus_observe = false; 11 // find frame if it's not the parent 12 while ((this.wrapper.tagName.toLowerCase() !== 'div') && 13 (this.wrapper.tagName.toLowerCase() !== 'body')) { 14 this.wrapper = this.wrapper.parentNode; 15 } 16 if (this.wrapper.tagName.toLowerCase() !== 'body') { 17 if (this.img.hasAttribute('data-focus-observe')) { 18 this.focus_observe = this.img.getAttribute('data-focus-observe'); 19 } 20 // frame must have position attribute for focused content 21 if (!this.wrapper.style.position) { 22 this.wrapper.style.position = 'relative'; 23 } 24 // image must have a absolute position 25 img.style.position = 'absolute'; 26 img.style.maxWidth = 'none'; 27 this.handleEvent(); 28 29 var self = this; 30 // observe image for changes in focus attributes 31 if (this.focus_observe) { 32 this.imgObserver = new MutationObserver(function () { self.handleEvent(); }); 33 this.imgObserver.observe(self.img, { 34 attributes: true, 35 attributeFilter: ['data-focus', 'data-focus-x', 'data-focus-y'] 36 }); 37 } 38 39 // observe wrapper on resize 40 if ('ResizeObserver' in window) { 41 this.wrapperObserver = new ResizeObserver(function () { self.handleEvent(); }); 42 this.wrapperObserver.observe(self.wrapper); 43 } else { 44 // observe wrapper for changes in class and style attribute 45 this.wrapperObserver = new MutationObserver(function () { self.handleEvent(); }); 46 this.wrapperObserver.observe(self.wrapper, { 47 attributes: true, 48 attributeFilter: ['class', 'style'] 49 }); 50 // until ResizeObserver works on all devices 51 this.handleEvent.bind(this); 52 window.addEventListener("resize", this, false); 53 } 54 } 55 } 56 57 Focus.prototype = { 58 handleEvent: function () { 59 // get dependencies from attributes 60 var width = this.wrapper.offsetWidth, // frame width 61 height = this.wrapper.offsetHeight, // frame height 62 type = this.img.getAttribute('data-focus'); // full centered image else cover 63 if (this.focus_observe || this.focus_x == null) { 64 this.focus_x = .50; // center 65 this.focus_y = .50; // center 66 if (type !== 'contain') { 67 // overwrite focus x coortinate else center 68 if (this.img.getAttribute('data-focus-x')) { 69 this.focus_x = parseInt(this.img.getAttribute('data-focus-x')) / 100; 70 } 71 // overwrite focus y coordinate else center 72 if (this.img.getAttribute('data-focus-y')) { 73 this.focus_y = parseInt(this.img.getAttribute('data-focus-y')) / 100; 74 } 75 } 76 } 77 // concept: depending on the aspect ratio and the type of filling of the frame 78 // one side adapts to the frame and the other side is cut off or has a stub 79 var scaled, value; 80 if ((type !== 'contain') === ((this.img.width / this.img.height) >= (width / height))) { 81 this.img.style.width = 'auto'; 82 this.img.style.height = '100%'; // Internet Explorer fix : this.wrapper.offsetHeight 83 this.img.style.top = '0'; 84 scaled = this.img.width * (this.img.height / height); 85 value = - Math.floor((scaled * this.focus_x) - (width / 2)); 86 if (type !== 'contain') { 87 if (value > 0) { 88 value = 0; 89 } else if (value < width - scaled) { 90 value = Math.floor(width - scaled); 91 } 92 } 93 this.img.style.left = value + 'px'; 94 } else { 95 this.img.style.width = '100%'; // Internet Explorer fix : this.wrapper.offsetWidth 96 this.img.style.height = 'auto'; 97 this.img.style.left = '0'; 98 scaled = this.img.height * (this.img.width / width); 99 value = - Math.floor((scaled * this.focus_y) - (height / 2)); 100 if (type !== 'contain') { 101 if (value > 0) { 102 value = 0; 103 } else if (value < (height - scaled)) { 104 value = Math.floor(height - scaled); 105 } 106 } 107 this.img.style.top = value + 'px'; 108 } 109 } 110 }; 111 112 // get all images on page 113 var i, els = document.getElementsByTagName("img"), len = els.length; 114 for (i = 0; i < len; i++) { 115 // add a on load eventlistener to set the focus if the class list contains "focus" 116 // this don't breaks viewport (lazy loading) 117 if (els[i].classList.contains("focus")) {
118 if (!els[i].complete || (els[i].naturalWidth === 0)) { 119 els[i].addEventListener("load", function (e) { new Focus(this); }, false); 120 } else { 121 new Focus(els[i]); 122 } 123 } 124 } 125})();
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.