PageSourceSearch

https://www.astragon.de/typo3conf/ext/lns_sitepackage/Resources/Public/JavaScript/focus.js

js astragon.de collected 2026-10-09 21:54:18 UTC 4,898 bytes, 125 lines download raw bytes

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.