1(function () { 2 var MOBILE_MAX = 992; 3 var DEBUG = false; 4 5 function log() { 6 if (!DEBUG) return; 7 var args = Array.prototype.slice.call(arguments); 8 args.unshift("[sf-features]"); 9 console.log.apply(console, args); 10 } 11 12 function setup(root) { 13 if (!root || root.dataset.carouselInit) { 14 return; 15 } 16 17 var viewport = root.querySelector(".sf-features__viewport"); 18 var track = root.querySelector(".sf-features__track"); 19 var prevBtn = root.querySelector(".sf-features__btn--prev"); 20 var nextBtn = root.querySelector(".sf-features__btn--next"); 21 22 if (!viewport || !track) { 23 return; 24 } 25 26 var baseItems = Array.prototype.slice.call(track.querySelectorAll(".sf-feature")); 27 if (!baseItems.length) { 28 return; 29 } 30 31 var isMobile = window.innerWidth <= MOBILE_MAX; 32 var index = 1; 33 var slideCount = baseItems.length; 34 var clonesMade = false; 35 var firstClone = null; 36 var lastClone = null; 37 var isAnimating = false; 38 39 root.dataset.carouselInit = "1"; 40 41 function applyTransform(i, opts) { 42 opts = opts || {}; 43 var noAnim = !!opts.noAnim; 44 var vw = viewport.clientWidth; 45 var x = -i * vw; 46 47 if (noAnim) { 48 var prevTransition = track.style.transition; 49 track.style.transition = "none"; 50 track.style.transform = "translate3d(" + x + "px,0,0)"; 51 void track.offsetHeight; 52 track.style.transition = prevTransition; 53 } else { 54 track.style.transform = "translate3d(" + x + "px,0,0)"; 55 } 56 } 57 58 function makeClones() { 59 if (clonesMade) return; 60 firstClone = baseItems[0].cloneNode(true); 61 lastClone = baseItems[slideCount - 1].cloneNode(true); 62 firstClone.dataset.clone = "1"; 63 lastClone.dataset.clone = "1"; 64 track.insertBefore(lastClone, track.firstChild); 65 track.appendChild(firstClone); 66 clonesMade = true; 67 } 68 69 function removeClones() { 70 if (!clonesMade) return; 71 try { 72 if (firstClone && firstClone.parentNode === track) track.removeChild(firstClone); 73 if (lastClone && lastClone.parentNode === track) track.removeChild(lastClone); 74 } catch (e) { 75 } 76 firstClone = lastClone = null; 77 clonesMade = false; 78 } 79 80 function ensureMobileMode() { 81 if (!clonesMade) makeClones(); 82 index = Math.min(Math.max(index, 1), slideCount); // sicherstellen 1..slideCount 83 applyTransform(index, { noAnim: true }); 84 } 85 86 function ensureDesktopMode() { 87 track.style.transform = ""; 88 removeClones(); 89 } 90 91 function onTransitionStart(ev) { 92 if (ev && ev.propertyName !== "transform") return; 93 isAnimating = true; 94 } 95 96 function onTransitionEnd(ev) { 97 if (ev && ev.propertyName !== "transform") return; 98 isAnimating = false; 99 100 if (!isMobile || !clonesMade) return; 101 102 if (index === 0) { 103 index = slideCount; 104 applyTransform(index, { noAnim: true }); 105 } else if (index === slideCount + 1) { 106 index = 1; 107 applyTransform(index, { noAnim: true }); 108 } 109 } 110 111 function step(delta) { 112 if (!isMobile) { 113 return; 114 } 115 if (!clonesMade) { 116 makeClones(); 117 } 118 if (isAnimating) { 119 return; 120 } 121 122 var before = index; 123 index += delta; 124 125 if (index < 0) index = 0; 126 if (index > slideCount + 1) index = slideCount + 1; 127 128 applyTransform(index); 129 } 130 131 function handleResize() { 132 var wasMobile = isMobile; 133 isMobile = window.innerWidth <= MOBILE_MAX; 134 135 if (wasMobile && !isMobile) { 136 ensureDesktopMode(); 137 } else if (!wasMobile && isMobile) { 138 makeClones(); 139 index = 1; 140 applyTransform(index, { noAnim: true }); 141 } else if (isMobile) { 142 applyTransform(index, { noAnim: true }); 143 } 144 } 145 146 if (prevBtn) prevBtn.addEventListener("click", function (ev) { 147 step(-1); 148 }); 149 if (nextBtn) nextBtn.addEventListener("click", function (ev) { 150 step(1); 151 }); 152 153 root.addEventListener("click", function (ev) { 154 var btn = ev.target.closest && ev.target.closest(".sf-features__btn"); 155 if (!btn) return; 156 if (btn === prevBtn || btn === nextBtn) return; 157 if (btn.classList.contains("sf-features__btn--prev")) { 158 step(-1); 159 } else if (btn.classList.contains("sf-features__btn--next")) { 160 step(1); 161 } 162 }); 163 164 track.addEventListener("transitionstart", onTransitionStart); 165 track.addEventListener("transitionend", onTransitionEnd); 166 167 window.addEventListener("resize", handleResize, { passive: true }); 168 169 if (isMobile) { 170 makeClones(); 171 index = 1; 172 applyTransform(index, { noAnim: true }); 173 } else { 174 ensureDesktopMode(); 175 } 176 177 root.__sfFeaturesDebug = { 178 next: function () { step(1); }, 179 prev: function () { step(-1); }, 180 goto: function (i) { 181 // Nur sinnvoll im Mobile-Modus auf echte Slides 1..slideCount 182 var ci = Math.max(1, Math.min(slideCount, i|0)); 183 index = ci; 184 applyTransform(index, { noAnim: true }); 185 }, 186 state: function () { 187 }, 188 remakeClones: function () { removeClones(); makeClones(); }, 189 removeClones: function () { removeClones(); } 190 }; 191 192 } 193 194 function initAll() { 195 var roots = document.querySelectorAll(".sf-features[data-carousel]");
196 roots.forEach(setup); 197 } 198 199 if (document.readyState === "loading") { 200 document.addEventListener("DOMContentLoaded", function () { 201 initAll(); 202 }); 203 } else { 204 initAll(); 205 } 206})();
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.