PageSourceSearch

https://on-nuri.co.kr/wp-content/themes/onnuri/assets/js/cardstrip.js?ver=1790926266

js on-nuri.co.kr collected 2026-10-09 00:00:19 UTC 3,087 bytes, 88 lines download raw bytes

1/**
2 * cardstrip.js — 공통 next-only 순환 슬라이더
3 *
4 * 마크업 계약:
5 *   <div class="cardstrip" data-cardstrip data-visible="N">
6 *     <div class="cardstrip-viewport">
7 *       <ul class="cardstrip-track">
8 *         <li class="cardstrip-slide">…</li> × N+
9 *       </ul>
10 *     </div>
11 *     <button data-strip-next class="cardstrip-arrow">→</button>
12 *   </div>
13 *
14 * 동작:
15 *   - 데스크톱 (>1024): 화살표 클릭으로 한 칸씩 이동, 마지막에서 처음으로 순환.
16 *     매끄러운 순환 위해 처음 N개 슬라이드를 뒤에 클론.
17 *   - 태블릿↓ (≤1024): CSS 로 화살표 숨김 + 뷰포트 overflow-x scroll-snap.
18 *     JS 는 transform 초기화만 담당.
19 *   - 슬라이드 개수 ≤ visible → 버튼 숨김, 클론 안 함.
20 */
21(function(){
22  document.querySelectorAll('[data-cardstrip]').forEach(function(root){
23    var track = root.querySelector('.cardstrip-track');
24    var nextBtn = root.querySelector('[data-strip-next]');
25    if (!track || !nextBtn) return;
26    var visible = parseInt(root.dataset.visible, 10) || 5;
27    var originals = Array.prototype.slice.call(track.children);
28    var total = originals.length;
29    if (total <= visible) { nextBtn.hidden = true; return; }
30
31    // 매끄러운 순환을 위해 처음 visible 개 슬라이드를 뒤에 클론
32    for (var i = 0; i < visible; i++) {
33      var clone = originals[i].cloneNode(true);
34      clone.setAttribute('aria-hidden', 'true');
35      clone.classList.add('is-clone');
36      track.appendChild(clone);
37    }
38
39    var idx = 0;
40    var animating = false;
41    var mq = window.matchMedia('(max-width:1024px)');
42
43    function stepPx(){
44      var slide = track.children[0];
45      var g = parseFloat(getComputedStyle(track).gap) || 0;
46      return slide.getBoundingClientRect().width + g;
47    }
48
49    function go(){
50      if (animating || mq.matches) return;
51      animating = true;
52      idx += 1;
53      track.style.transition = 'transform .55s var(--ease)';
54      track.style.transform = 'translateX(-' + (idx * stepPx()) + 'px)';
55      var onEnd = function(e){
56        if (e.propertyName !== 'transform') return;
57        track.removeEventListener('transitionend', onEnd);
58        if (idx >= total) {
59          idx = 0;
60          track.style.transition = 'none';
61          track.style.transform = 'translateX(0px)';
62          void track.offsetWidth;
63        }
64        animating = false;
65      };
66      track.addEventListener('transitionend', onEnd);
67    }
68    nextBtn.addEventListener('click', go);
69
70    function sync(){
71      if (mq.matches) {
72        track.style.transition = 'none';
73        track.style.transform = '';
74      } else {
75        idx = 0;
76        track.style.transition = 'none';
77        track.style.transform = 'translateX(0px)';
78      }
79    }
80    if (mq.addEventListener) mq.addEventListener('change', sync);
81    window.addEventListener('resize', function(){
82      if (!mq.matches) {
83        track.style.transition = 'none';
84        track.style.transform = 'translateX(-' + (idx * stepPx()) + 'px)';
85      }
86    });
87  });
88})();

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.