PageSourceSearch

https://sib-life.com/static/js/main.js?v=1776084280979

js sib-life.com collected 2026-10-06 04:50:35 UTC 12,506 bytes, 437 lines download raw bytes

1/**
2 * 背景图懒加载类
3 * @param {Object} options 配置项
4 */
5function LazyBackgroundLoader(options) {
6  this.options = {
7    rootMargin: '50px 0px',
8    threshold: 0.01,
9    fallbackScrollCheck: true,
10    selector: '[data-bg]', // 默认选择器
11    ...options,
12  };
13
14  this.observers = null;
15  this.init();
16}
17
18LazyBackgroundLoader.prototype = {
19  init: function () {
20    // 检查是否支持 IntersectionObserver
21    if ('IntersectionObserver' in window) {
22      this.observers = new IntersectionObserver(this.observerCallback.bind(this), {
23        // threshold 表示目标元素和根元素相交的比例达到多少时触发回调
24        // 取值范围是 0 到 1
25        // 0 表示目标元素刚进入根元素就触发
26        // 1 表示目标元素完全进入根元素才触发
27        // 也可以是数组,比如 [0, 0.5, 1] 表示相交比例到达 0%、50%、100% 时都触发
28
29        // rootMargin 相当于在根元素外围加一个外边距,提前或延迟触发交叉检测
30        // threshold 则是控制目标元素进入可视区域的比例达到多少时触发回调
31        // 格式为 "上 右 下 左" 的边距值,类似 CSS margin
32        // 这里设置为 "50px 0px",表示在元素上下各增加 50px 的检测范围,左右不变
33        rootMargin: this.options.rootMargin,
34        threshold: this.options.threshold,
35      });
36    }
37  },
38
39  observerCallback: function (entries) {
40    var self = this;
41    entries.forEach(function (entry) {
42      if (entry.isIntersecting) {
43        self.loadImage(entry.target);
44        // 加载完成后取消观察
45        self.observers && self.observers.unobserve(entry.target);
46      }
47    });
48  },
49
50  loadImage: function (element) {
51    var bgUrl = element.getAttribute('data-bg');
52    if (!bgUrl) return;
53
54    // 1. 立即移除 data-bg 属性,防止任何并发逻辑重复触发
55    element.removeAttribute('data-bg');
56
57    // 2. 直接在元素的 style 属性中插入背景图,由浏览器引擎发起唯一的请求
58    // 不再使用 new Image() 预加载,彻底杜绝 common.js 发起的二次请求
59    element.style.backgroundImage = 'url("' + bgUrl + '")';
60
61    // 3. 立即标记为已加载
62    $(element).addClass('lazy-loaded');
63  },
64
65  isElementInViewport: function (el) {
66    var rect = el.getBoundingClientRect();
67    var windowHeight = window.innerHeight || document.documentElement.clientHeight;
68    var windowWidth = window.innerWidth || document.documentElement.clientWidth;
69
70    return (
71      rect.top <= windowHeight && rect.bottom >= 0 && rect.left <= windowWidth && rect.right >= 0
72    );
73  },
74
75  handleScrollCheck: function () {
76    var self = this;
77    var elements = document.querySelectorAll(
78      this.options.selector + ':not(.lazy-loaded):not(.lazy-error)',
79    );
80
81    Array.prototype.forEach.call(elements, function (element) {
82      if (self.isElementInViewport(element)) {
83        self.loadImage(element);
84      }
85    });
86  },
87
88  throttle: function (func, limit) {
89    var inThrottle;
90    var self = this;
91    return function () {
92      if (!inThrottle) {
93        func.apply(self);
94        inThrottle = true;
95        setTimeout(function () {
96          inThrottle = false;
97        }, limit);
98      }
99    };
100  },
101
102  observe: function (elements) {
103    var self = this;
104
105    // 如果传入的是选择器字符串
106    if (typeof elements === 'string') {
107      elements = document.querySelectorAll(elements);
108    }
109    // 如果是jQuery对象
110    else if (elements instanceof jQuery) {
111      elements = elements.get();
112    }
113    // 如果是单个DOM元素
114    else if (elements instanceof Element) {
115      elements = [elements];
116    }
117
118    if (this.observers) {
119      // 使用 IntersectionObserver
120      Array.prototype.forEach.call(elements, function (element) {
121        self.observers.observe(element);
122      });
123    } else if (this.options.fallbackScrollCheck) {
124      // 降级方案:使用滚动检测
125      var throttledScrollHandler = this.throttle(this.handleScrollCheck, 100);
126
127      $(window).on(
128        'scroll.lazyload resize.lazyload orientationchange.lazyload',
129        throttledScrollHandler,
130      );
131      // 初始检查
132      this.handleScrollCheck();
133    }
134  },
135
136  destroy: function () {
137    if (this.observers) {
138      this.observers.disconnect();
139    }
140    $(window).off('.lazyload');
141  },
142};
143var timer = null;
144var isScroll = false;
145function throttle(fn, delay = 20) {
146  let timer = null;
147  return function () {
148    if (timer) return;
149    timer = setTimeout(() => {
150      fn.apply(this, arguments);
151      timer = null;
152    }, delay);
153  };
154}
155function scrollHandler() {
156  var position = window.scrollY + 90;
157  if (timer) return;
158  timer = setTimeout(() => {
159    timer = null;
160  }, 20);
161  $('.nav-list .nav-link').each((index, navbarlink) => {
162    var href = $(navbarlink).find('.nav-link-item').attr('href')?.split('#')[1];
163    var section = $('#' + href);
164    if (!section) return;
165    if (
166      !isScroll &&
167      section.offset() &&
168      position >= section.offset().top &&
169      position <= section.offset().top + section.outerHeight()
170    ) {
171      $(navbarlink).addClass('active').siblings().removeClass('active');
172    }
173  });
174}
175function handler(event) {
176  event?.preventDefault?.();
177}
178
179function handleNavbar() {
180  if (window.innerWidth < 1200) {
181    return;
182  }
183  var moreHtml = '';
184  $('#nav .nav-list .should-hide').each(function () {
185    moreHtml += '<li class="nav-view-more-btn-item">' + $(this).html() + '</li>';
186  });
187  if (moreHtml) {
188    $('#nav .nav-view-more-btn .nav-view-more-btn-list').html(moreHtml);
189  }
190}
191function handleMobileNavbar() {
192  $('#nav .nav-view-more-btn-list').hide();
193  $('#nav .nav-list .nav-item').each(function () {
194    $(this).show();
195  });
196}
197
198$(document).ready(function () {
199  var lazyLoader = new LazyBackgroundLoader({
200    rootMargin: '50px 0px',
201    threshold: 0.01,
202    fallbackScrollCheck: true,
203    selector: '[data-bg]', // 可自定义选择器
204  });
205  lazyLoader.observe('[data-bg]');
206  // 方式2:传入jQuery对象
207  // lazyLoader.observe($('.lazy-bg'));
208  // 方式3:传入DOM元素或元素数组
209  // lazyLoader.observe(document.querySelectorAll('.lazy-bg'));
210  // 导航显示隐藏
211
212  window.addEventListener('contextmenu', handler);
213  window.addEventListener('selectstart', handler);
214  // 坚挺页面宽度,宽度大于1200px,调用频率节流
215  handleNavbar();
216  window.addEventListener(
217    'resize',
218    throttle(function () {
219      if (window.innerWidth >= 1200) {
220        $('#nav').css('height', 'auto');
221        $('#nav').css('overflow', 'initial');
222        $('.header-cover-click').css({
223          display: 'none',
224        });
225        $('body').css({
226          overflow: 'initial',
227        });
228        setTimeout(() => {
229          handleNavbar();
230        }, 0);
231      } else {
232        $('#nav').css('height', '0');
233        $('#nav').css('overflow', 'hidden');
234        $('.header-mobile-menu-icon')
235          .addClass('header-mobile-menu-close')
236          .removeClass('header-mobile-menu-show');
237        $('.header-cover-click').css({
238          display: 'none',
239        });
240        handleMobileNavbar();
241      }
242    }, 20),
243  );
244  if (window.location.pathname === '/') {
245    isScroll = true;
246    const maodian = sessionStorage.getItem('maodian');
247    if (maodian && $(maodian).length > 0) {
248      const targetOffset = maodian !== '#site' ? $(maodian).offset()?.top - 90 : 0;
249      window.scrollTo({
250        top: targetOffset,
251        behavior: 'smooth',
252      });
253      $('.nav-list .nav-link').each(function () {
254        const href = '#' + $(this).find('a').attr('href')?.split('#')[1];
255        if (href === maodian) {
256          $(this).addClass('active').siblings().find('a').removeClass('active');
257        }
258      });
259    } else {
260      $('.nav-list .nav-link').each(function () {
261        const href = '#' + $(this).find('a').attr('href')?.split('#')[1];
262        if (href === 'site' && window.scrollY === 0) {
263          $(this).addClass('active').siblings().find('a').removeClass('active');
264        } else {
265          $(this).removeClass('active');
266        }
267      });
268    }
269    setTimeout(() => {
270      isScroll = false;
271    }, 1000);
272    sessionStorage.removeItem('maodian');
273    window.addEventListener('scroll', scrollHandler);
274    scrollHandler();
275  } else {
276    $('.nav-list li').removeClass('active');
277  }
278
279  $('.sub-menu-icon').click(function (e) {
280    e.stopPropagation();
281    e.preventDefault();
282  });
283
284  $('.has-sub-menu').click(function (e) {
285    if (!$(this).attr('href')) {
286      e.stopPropagation();
287      e.preventDefault();
288    }
289  });
290
291  $('.has-sub-menu .sub-menu-icon').click(function () {
292    const height = $(this).parent().parent().find('.sub-menu').height();
293    const subMenuWrapper = $(this).parent().parent().find('.sub-menu-wrapper');
294    if (subMenuWrapper.height() === 0) {
295      subMenuWrapper.css('height', height);
296      var top = $(this).offset().top;
297
298      $(this).addClass('active');
299      setTimeout(() => {
300        document.getElementById('nav').scrollTo({
301          top: top + height,
302          behavior: 'smooth',
303        });
304      }, 100);
305    } else {
306      subMenuWrapper.css('height', 0);
307      $(this).removeClass('active');
308    }
309  });
310  $('.nav-list .nav-link .nav-link-item').click(function (e) {
311    e.preventDefault();
312  });
313  $('.sub-menu-link').click(function (e) {
314    e.stopPropagation();
315  });
316
317  $('.nav-list .nav-link').click(function (e) {
318    e.preventDefault();
319    isScroll = true;
320    $(this).addClass('active').siblings().removeClass('active');
321    const targetId = $(this).find('.nav-link-item').attr('data-target');
322    if (window.location.pathname !== '/') {
323      window.location.href = '/';
324      sessionStorage.setItem('maodian', '#' + targetId);
325      return;
326    }
327
328    const targetOffset = $('#' + targetId).offset()?.top - 80;
329    window.scrollTo({
330      top: targetOffset,
331      behavior: 'smooth',
332    });
333    setTimeout(() => {
334      isScroll = false;
335    }, 1000);
336
337    $('#header .header-mobile-menu-icon')
338      .removeClass('header-mobile-menu-show')
339      .addClass('header-mobile-menu-close');
340    $('.header-cover-click').css({
341      display: 'none',
342    });
343    if (window.innerWidth < 1200) {
344      $('#nav').css({
345        height: 0,
346        overflow: 'hidden',
347      });
348    }
349    $('body').css({
350      overflow: 'initial',
351    });
352  });
353  $('.header-cover-click').click(function () {
354    $('#header .header-mobile-menu-icon').click();
355  });
356  $('#header .header-mobile-menu-icon').click(function () {
357    if ($(this).hasClass('header-mobile-menu-close')) {
358      const height = $('.nav-list').height();
359      $(this).removeClass('header-mobile-menu-close').addClass('header-mobile-menu-show');
360      $('.header-cover-click').css({
361        display: 'block',
362      });
363      $('#nav').css({
364        height: height + 20,
365        overflow: 'auto',
366      });
367      $('.header-cover').css({
368        height: height + 20,
369        overflow: 'auto',
370      });
371
372      $('body').css({
373        overflow: 'hidden',
374      });
375    } else {
376      $(this).removeClass('header-mobile-menu-show').addClass('header-mobile-menu-close');
377      $('.header-cover-click').css({
378        display: 'none',
379      });
380      $('#nav').css({
381        height: 0,
382        overflow: 'hidden',
383      });
384      $('.header-cover').css({
385        height: 0,
386        overflow: 'hidden',
387      });
388      $('body').css({
389        overflow: 'initial',
390      });
391    }
392  });
393
394  $('.link-btn').click(function () {
395    const tgk = $(this).data('tgk');
396    if (tgk) {
397      window.open(tgk);
398    }
399  });
400
401  $(' .posts-trigger .posts-item, .posts-trigger .sidebar-item').on('click', function (e) {
402    if (e.target.tagName === 'A') {
403      return;
404    }
405    const url = $(this).find('h3').find('a').attr('href');
406    if (url) {
407      window.location.href = url;
408    }
409  });
410
411  $('.posts-list-trigger').on('click', function (e) {
412    if (e.target.className.includes('posts-list-trigger')) {
413      return;
414    }
415    if (e.target.tagName === 'A') {
416      e.stopPropagation();
417    } else {
418      try {
419        window.location.href = $(e.target)
420          .closest('.posts-item-wrap')
421          .find('.posts-title-link')
422          .attr('href');
423      } catch (error) {
424        console.log(error);
425      }
426    }
427  });
428
429  $('.footer-follow-nav-link').on('click', function (e) {
430    e.preventDefault();
431    e.stopPropagation();
432    var href = $(this).attr('href');
433    if (href) {
434      window.open(href, '_blank');
435    }
436  });
437});

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.