PageSourceSearch

https://www.samaterials.es/js/product-detail-tab.js?v=1788571303

js samaterials.es collected 2026-10-02 20:47:21 UTC 4,438 bytes, 144 lines download raw bytes

1$(document).ready(function () {
2  // ==================== 缓存选择器 ====================
3  const $tabContainer = $('.oc-maon-sam-product-detail-tab')
4  const $tabBtns = $tabContainer.find('.tab-btns .tab-btn')
5  const $contents = $('.content-div')
6  const $tabsWrapper = $tabContainer.find('.tab-btns')
7  const $box = $tabContainer.find('.tab-btns-content')
8  const $leftBtn = $tabContainer.find('.tab-btn-left')
9  const $rightBtn = $tabContainer.find('.tab-btn-right')
10
11  const $headerMobile = $('.oc-main-sam-header-mobile')
12  const $headerPC = $('.oc-main-sam-header-pc')
13
14  const step = 200 // 左右滑动步长,可根据实际 Tab 宽度调整
15
16  let isSticky = false
17  let ticking = false
18
19  // ==================== Tab 切换 ====================
20  function switchTab(target) {
21    $contents.hide()
22    $tabBtns.removeClass('active')
23
24    $('#' + target).show()
25    $tabBtns.filter(`[data-target="${target}"]`).addClass('active')
26
27    // 滚动到 Tab 区域顶部
28    const scrollTarget = $tabContainer.offset().top - getHeaderHeight()
29    $('html, body').animate({ scrollTop: scrollTarget }, 300)
30  }
31
32  $tabBtns.on('click', function () {
33    const target = $(this).data('target')
34    switchTab(target)
35    updateStickyBounds()
36
37  })
38
39  // 默认激活第一个 Tab
40  const $firstBtn = $tabBtns.first()
41  if ($firstBtn.length) {
42    $firstBtn.addClass('active')
43    $contents.first().show()
44  }
45
46  // ==================== 获取当前 Header 高度 ====================
47  function getHeaderHeight() {
48    if (window.innerWidth <= 1025) {
49      return $headerMobile.hasClass('hide') ? 0 : $headerMobile.outerHeight()
50    }
51    return $headerPC.height() || 0
52  }
53
54  // ==================== Sticky Tabs (移动端) ====================
55  function handleMobileSticky() {
56    const headerHeight = getHeaderHeight()
57    const tabRect = $tabsWrapper[0].getBoundingClientRect()
58
59    if (tabRect.top <= headerHeight) {
60      $tabsWrapper.css('top', headerHeight + 'px')
61    } else {
62      $tabsWrapper.css('top', '0')
63    }
64  }
65
66  // ==================== Sticky Tabs (PC端,使用原生更流畅) ====================
67  const tabsContainer = document.querySelector('.oc-maon-sam-product-detail-tab .tab-btns')
68  const contentArea = document.querySelector('.oc-maon-sam-product-detail-tab .tab-content')
69  const placeholder = document.querySelector('.oc-maon-sam-product-detail-tab .tab-placeholder')
70
71  let stickyTop = 0
72  let contentBottom = 0
73
74  function updateStickyBounds() {
75    if (placeholder) stickyTop = placeholder.offsetTop
76    if (contentArea) contentBottom = contentArea.offsetTop + contentArea.offsetHeight
77  }
78
79  function handlePCSticky() {
80    if (!tabsContainer) return
81    const scrollY = window.scrollY
82    const shouldSticky = scrollY > stickyTop + 5 && scrollY < contentBottom - 5
83
84    if (shouldSticky === isSticky) return
85
86    isSticky = shouldSticky
87    tabsContainer.classList.toggle('sticky', shouldSticky)
88  }
89
90  // ==================== Tab 左右箭头控制 ====================
91  function updateArrowStatus() {
92    if (window.innerWidth > 1025) return
93
94    const scrollLeft = $box.scrollLeft()
95    const clientWidth = $box.outerWidth()
96    const scrollWidth = $box[0].scrollWidth
97
98    $leftBtn.toggle(scrollLeft > 0)
99    $rightBtn.toggle(scrollLeft + clientWidth < scrollWidth - 1)
100  }
101
102  $rightBtn.on('click', function () {
103    $box.animate({ scrollLeft: $box.scrollLeft() + step }, 300, updateArrowStatus)
104  })
105
106  $leftBtn.on('click', function () {
107    $box.animate({ scrollLeft: $box.scrollLeft() - step }, 300, updateArrowStatus)
108  })
109
110  $box.on('scroll', updateArrowStatus)
111
112  // ==================== 滚动 & Resize 事件 ====================
113  function onScroll() {
114    if (window.innerWidth <= 1025) {
115      handleMobileSticky()
116    } else {
117      if (ticking) return
118      ticking = true
119      requestAnimationFrame(() => {
120        handlePCSticky()
121        ticking = false
122      })
123    }
124  }
125
126  $(window).on('scroll', onScroll)
127  $(window).on('resize', () => {
128    updateStickyBounds()
129    handleMobileSticky()
130    updateArrowStatus()
131  })
132
133  // 初始化
134  function init() {
135    updateStickyBounds()
136    updateArrowStatus()
137    // 首次加载时执行一次 sticky 判断
138    setTimeout(() => {
139      onScroll()
140    }, 100)
141  }
142
143  init()
144})

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.