PageSourceSearch

https://tbtb.biz/static/js/main.js?v=1778258719876

js tbtb.biz collected 2026-10-07 06:29:10 UTC 15,651 bytes, 500 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};
143
144var timer = null;
145var isScroll = false;
146function throttle(fn, delay = 20) {
147  let timer = null;
148  return function () {
149    if (timer) return;
150    timer = setTimeout(() => {
151      fn.apply(this, arguments);
152      timer = null;
153    }, delay);
154  };
155}
156function scrollHandler() {
157  var position = window.scrollY + 90;
158  if (timer) return;
159  timer = setTimeout(() => {
160    timer = null;
161  }, 20);
162  $('.nav-list .nav-link').each((index, navbarlink) => {
163    var href = $(navbarlink).find('.nav-link-item').attr('href')?.split('#')[1];
164    var section = $('#' + href);
165    if (!section) return;
166    if (
167      !isScroll &&
168      section.offset() &&
169      position >= section.offset().top &&
170      position <= section.offset().top + section.outerHeight()
171    ) {
172      $(navbarlink).addClass('active').siblings().removeClass('active');
173    }
174  });
175}
176function handler(event) {
177  event?.preventDefault?.();
178}
179
180function handleNavbar() {
181  if (window.innerWidth < 1200) {
182    return;
183  }
184  var moreHtml = '';
185  $('#nav .nav-list .should-hide').each(function () {
186    moreHtml += '<li class="nav-view-more-btn-item">' + $(this).html() + '</li>';
187  });
188  if (moreHtml) {
189    $('#nav .nav-view-more-btn .nav-view-more-btn-list').html(moreHtml);
190  }
191}
192function handleMobileNavbar() {
193  $('#nav .nav-view-more-btn-list').hide();
194  $('#nav .nav-list .nav-item').each(function () {
195    $(this).show();
196  });
197}
198
199$(document).ready(function () {
200  var lazyLoader = new LazyBackgroundLoader({
201    rootMargin: '50px 0px',
202    threshold: 0.01,
203    fallbackScrollCheck: true,
204    selector: '[data-bg]', // 可自定义选择器
205  });
206  lazyLoader.observe('[data-bg]');
207  // 方式2:传入jQuery对象
208  // lazyLoader.observe($('.lazy-bg'));
209  // 方式3:传入DOM元素或元素数组
210  // lazyLoader.observe(document.querySelectorAll('.lazy-bg'));
211  // 导航显示隐藏
212
213  window.addEventListener('contextmenu', handler);
214  window.addEventListener('selectstart', handler);
215  // 坚挺页面宽度,宽度大于1200px,调用频率节流
216  handleNavbar();
217  window.addEventListener(
218    'resize',
219    throttle(function () {
220      if (window.innerWidth >= 1200) {
221        $('#nav').css('height', 'auto');
222        $('#nav').css('overflow', 'initial');
223        $('.header-cover-click').css({
224          display: 'none',
225        });
226        $('body').css({
227          overflow: 'initial',
228        });
229        setTimeout(() => {
230          handleNavbar();
231        }, 0);
232      } else {
233        $('#nav').css('height', '0');
234        $('#nav').css('overflow', 'hidden');
235        $('.header-mobile-menu-icon')
236          .addClass('header-mobile-menu-close')
237          .removeClass('header-mobile-menu-show');
238        $('.header-cover-click').css({
239          display: 'none',
240        });
241        handleMobileNavbar();
242      }
243    }, 20),
244  );
245  if (window.location.pathname === '/') {
246    isScroll = true;
247    const maodian = sessionStorage.getItem('maodian');
248    if (maodian && $(maodian).length > 0) {
249      const targetOffset = maodian !== '#site' ? $(maodian).offset()?.top - 90 : 0;
250      window.scrollTo({
251        top: targetOffset,
252        behavior: 'smooth',
253      });
254      $('.nav-list .nav-link').each(function () {
255        const href = '#' + $(this).find('a').attr('href')?.split('#')[1];
256        if (href === maodian) {
257          $(this).addClass('active').siblings().find('a').removeClass('active');
258        }
259      });
260    } else {
261      $('.nav-list .nav-link').each(function () {
262        const href = '#' + $(this).find('a').attr('href')?.split('#')[1];
263        if (href === 'site' && window.scrollY === 0) {
264          $(this).addClass('active').siblings().find('a').removeClass('active');
265        } else {
266          $(this).removeClass('active');
267        }
268      });
269    }
270    setTimeout(() => {
271      isScroll = false;
272    }, 1000);
273    sessionStorage.removeItem('maodian');
274    window.addEventListener('scroll', scrollHandler);
275    scrollHandler();
276  } else {
277    $('.nav-list li').removeClass('active');
278  }
279
280  $('.sub-menu-icon').click(function (e) {
281    e.stopPropagation();
282    e.preventDefault();
283  });
284
285  $('.has-sub-menu').click(function (e) {
286    if (!$(this).attr('href')) {
287      e.stopPropagation();
288      e.preventDefault();
289    }
290  });
291
292  $('.has-sub-menu .sub-menu-icon').click(function () {
293    const height = $(this).parent().parent().find('.sub-menu').height();
294    const subMenuWrapper = $(this).parent().parent().find('.sub-menu-wrapper');
295    if (subMenuWrapper.height() === 0) {
296      subMenuWrapper.css('height', height);
297      var top = $(this).offset().top;
298
299      $(this).addClass('active');
300      setTimeout(() => {
301        document.getElementById('nav').scrollTo({
302          top: top + height,
303          behavior: 'smooth',
304        });
305      }, 100);
306    } else {
307      subMenuWrapper.css('height', 0);
308      $(this).removeClass('active');
309    }
310  });
311  $('.nav-list .nav-link .nav-link-item').click(function (e) {
312    e.preventDefault();
313  });
314  $('.sub-menu-link').click(function (e) {
315    e.stopPropagation();
316  });
317
318  $('.nav-list .nav-link').click(function (e) {
319    e.preventDefault();
320    isScroll = true;
321    $(this).addClass('active').siblings().removeClass('active');
322    const targetId = $(this).find('.nav-link-item').attr('data-target');
323    if (!targetId) {
324      return;
325    }
326    if (window.location.pathname !== '/') {
327      window.location.href = '/';
328      sessionStorage.setItem('maodian', '#' + targetId);
329      return;
330    }
331
332    const targetOffset = $('#' + targetId).offset()?.top - 80;
333
334    if (isNaN(targetOffset)) {
335      return;
336    }
337
338    window.scrollTo({
339      top: targetOffset,
340      behavior: 'smooth',
341    });
342    setTimeout(() => {
343      isScroll = false;
344    }, 1000);
345
346    $('#header .header-mobile-menu-icon')
347      .removeClass('header-mobile-menu-show')
348      .addClass('header-mobile-menu-close');
349    $('.header-cover-click').css({
350      display: 'none',
351    });
352    if (window.innerWidth < 1200) {
353      $('#nav').css({
354        height: 0,
355        overflow: 'hidden',
356      });
357    }
358    $('body').css({
359      overflow: 'initial',
360    });
361  });
362  $('.header-cover-click').click(function () {
363    $('#header .header-mobile-menu-icon').click();
364  });
365  $('#header .header-mobile-menu-icon').click(function () {
366    if ($(this).hasClass('header-mobile-menu-close')) {
367      const height = $('.nav-list').height();
368      $(this).removeClass('header-mobile-menu-close').addClass('header-mobile-menu-show');
369      $('.header-cover-click').css({
370        display: 'block',
371      });
372      $('#nav').css({
373        height: height + 20,
374        overflow: 'auto',
375      });
376      $('.header-cover').css({
377        height: height + 20,
378        overflow: 'auto',
379      });
380
381      $('body').css({
382        overflow: 'hidden',
383      });
384    } else {
385      $(this).removeClass('header-mobile-menu-show').addClass('header-mobile-menu-close');
386      $('.header-cover-click').css({
387        display: 'none',
388      });
389      $('#nav').css({
390        height: 0,
391        overflow: 'hidden',
392      });
393      $('.header-cover').css({
394        height: 0,
395        overflow: 'hidden',
396      });
397      $('body').css({
398        overflow: 'initial',
399      });
400    }
401  });
402
403  $('.link-btn').click(function () {
404    const tgk = $(this).data('tgk');
405    if (tgk) {
406      window.open(tgk);
407    }
408  });
409
410  $(' .posts-trigger .posts-item, .posts-trigger .sidebar-item').on('click', function (e) {
411    if (e.target.tagName === 'A') {
412      return;
413    }
414    const url = $(this).find('h3').find('a').attr('href');
415    if (url) {
416      window.location.href = url;
417    }
418  });
419
420  $('.post-list-trigger').on('click', function (e) {
421    if (e.target.className.includes('post-list-trigger')) {
422      return;
423    }
424    if (e.target.tagName === 'A') {
425      e.stopPropagation();
426    } else {
427      try {
428        var url = $(e.target).closest('.posts-item').find('.posts-item-title a').attr('href');
429        if (url) {
430          window.location.href = url;
431        }
432      } catch (error) {
433        console.log(error);
434      }
435    }
436  });
437
438  $('.footer-follow-nav-link').on('click', function (e) {
439    e.preventDefault();
440    e.stopPropagation();
441    var href = $(this).attr('href');
442    if (href) {
443      window.open(href, '_blank');
444    }
445  });
446
447  $('.open-lines-dialog').on('click', function () {
448    // $('.dialog-lines').addClass('open').removeClass('close');
449    $('#header').append(`<div class="dialog-lines" id="dialog-lines">
450    <div class="dialog-lines-container">
451      <div class="dialog-lines-header">
452        平台入口
453        <i class="dialog-header-close-icon">
454          <svg style="width: 1em; height: 1em; fill: currentColor" viewBox="0 0 1024 1024" version="1.1" xmlns="http://www.w3.org/2000/svg">
455            <path d="M585.412525 512.594747L973.601616 124.418586c19.600808-19.600808 19.600808-51.898182 0-71.49899l-2.120404-2.120404c-19.600808-19.600808-51.898182-19.600808-71.49899 0L511.793131 439.518384 123.61697 50.799192c-19.600808-19.600808-51.898182-19.600808-71.49899 0l-2.120404 2.120404c-20.11798 19.600808-20.11798 51.898182 0 71.49899l388.189091 388.189091L49.997576 900.783838c-19.587879 19.600808-19.587879 51.898182 0 71.49899l2.120404 2.120404c19.600808 19.600808 51.898182 19.600808 71.49899 0L511.793131 586.214141l388.189091 388.176162c19.600808 19.600808 51.898182 19.600808 71.49899 0l2.120404-2.120404c19.600808-19.600808 19.600808-51.898182 0-71.49899L585.412525 512.594747z m0 0"></path>
456          </svg>
457        </i>
458      </div>
459      <div class="site-tips">
460        <i class="dialog-header-close-icon">
461          <svg style="width: 1em; height: 1em; fill: currentColor" viewBox="0 0 1024 1024" version="1.1" xmlns="http://www.w3.org/2000/svg">
462            <path d="M510.983345 63.599504c246.331291 0 447.87554 201.544249 447.87554 447.87554 0 246.332315-201.544249 447.87554-447.87554 447.87554S63.108828 757.806335 63.108828 511.474021C63.108828 265.143753 264.652054 63.599504 510.983345 63.599504L510.983345 63.599504zM575.273581 639.544885l-127.913275 0 0 127.913275 127.913275 0L575.273581 639.544885zM575.273581 255.42132l-127.913275 0 0 320.67858 127.913275 0L575.273581 255.42132z"></path>
463          </svg>
464        </i>
465        温馨提示:如遇IP限制,请先下载VPN软件
466      </div>
467      <div class="dialog-lines-content">
468        ${zhLineList
469          .map(
470            (item) => `
471        <div tgk-url="${desktopDevice ? item?.webUrl : item?.h5Url}" target="_blank" class="link-card">
472          <div class="card-left">
473            <div class="card-logo">
474              <img src="${item?.logo}" alt="${item?.title}">
475            </div>
476            <div class="card-text">
477              <div class="card-title">${item?.title}</div>
478              <div class="card-desc">${item?.desc}</div>
479            </div>
480          </div>
481          <button class="card-btn">立即进入</button>
482        </div>
483        `,
484          )
485          .join('')}
486      </div>
487    </div>
488  </div>`);
489    $('[tgk-url]').click(function () {
490      const url = $(this).attr('tgk-url');
491      if (url) {
492        window.open(url, '_blank');
493      }
494    });
495    $('.dialog-header-close-icon').on('click', function () {
496      // $('.dialog-lines').addClass('close').removeClass('open');
497      $('#dialog-lines').remove();
498    });
499  });
500});

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.