PageSourceSearch

https://iaiuse.com/js/utils.js?v=5.5.3

js iaiuse.com collected 2026-10-07 19:06:12 UTC 10,155 bytes, 338 lines download raw bytes

1(() => {
2  const btfFn = {
3    debounce: (func, wait = 0, immediate = false) => {
4      let timeout
5      return (...args) => {
6        const later = () => {
7          timeout = null
8          if (!immediate) func(...args)
9        }
10        const callNow = immediate && !timeout
11        clearTimeout(timeout)
12        timeout = setTimeout(later, wait)
13        if (callNow) func(...args)
14      }
15    },
16
17    throttle: (func, wait, options = {}) => {
18      let timeout, args
19      let previous = 0
20
21      const later = () => {
22        previous = options.leading === false ? 0 : new Date().getTime()
23        timeout = null
24        func(...args)
25        if (!timeout) args = null
26      }
27
28      return (...params) => {
29        const now = new Date().getTime()
30        if (!previous && options.leading === false) previous = now
31        const remaining = wait - (now - previous)
32        args = params
33
34        if (remaining <= 0 || remaining > wait) {
35          if (timeout) {
36            clearTimeout(timeout)
37            timeout = null
38          }
39          previous = now
40          func(...args)
41          if (!timeout) args = null
42        } else if (!timeout && options.trailing !== false) {
43          timeout = setTimeout(later, remaining)
44        }
45      }
46    },
47
48    overflowPaddingR: {
49      add: () => {
50        const paddingRight = window.innerWidth - document.body.clientWidth
51
52        if (paddingRight > 0) {
53          document.body.style.paddingRight = `${paddingRight}px`
54          document.body.style.overflow = 'hidden'
55          const menuElement = document.querySelector('#page-header.nav-fixed #menus')
56          if (menuElement) {
57            menuElement.style.paddingRight = `${paddingRight}px`
58          }
59        }
60      },
61      remove: () => {
62        document.body.style.paddingRight = ''
63        document.body.style.overflow = ''
64        const menuElement = document.querySelector('#page-header.nav-fixed #menus')
65        if (menuElement) {
66          menuElement.style.paddingRight = ''
67        }
68      }
69    },
70
71    snackbarShow: (text, showAction = false, duration = 2000) => {
72      const { position, bgLight, bgDark } = GLOBAL_CONFIG.Snackbar
73      const bg = document.documentElement.getAttribute('data-theme') === 'light' ? bgLight : bgDark
74      Snackbar.show({
75        text,
76        backgroundColor: bg,
77        showAction,
78        duration,
79        pos: position,
80        customClass: 'snackbar-css'
81      })
82    },
83
84    diffDate: (inputDate, more = false) => {
85      const dateNow = new Date()
86      const datePost = new Date(inputDate)
87      const diffMs = dateNow - datePost
88      const diffSec = diffMs / 1000
89      const diffMin = diffSec / 60
90      const diffHour = diffMin / 60
91      const diffDay = diffHour / 24
92      const diffMonth = diffDay / 30
93      const { dateSuffix } = GLOBAL_CONFIG
94
95      if (!more) return Math.floor(diffDay)
96
97      if (diffMonth > 12) return datePost.toISOString().slice(0, 10)
98      if (diffMonth >= 1) return `${Math.floor(diffMonth)} ${dateSuffix.month}`
99      if (diffDay >= 1) return `${Math.floor(diffDay)} ${dateSuffix.day}`
100      if (diffHour >= 1) return `${Math.floor(diffHour)} ${dateSuffix.hour}`
101      if (diffMin >= 1) return `${Math.floor(diffMin)} ${dateSuffix.min}`
102      return dateSuffix.just
103    },
104
105    loadComment: (dom, callback) => {
106      if ('IntersectionObserver' in window) {
107        const observerItem = new IntersectionObserver(entries => {
108          if (entries[0].isIntersecting) {
109            callback()
110            observerItem.disconnect()
111          }
112        }, { threshold: [0] })
113        observerItem.observe(dom)
114      } else {
115        callback()
116      }
117    },
118
119    scrollToDest: (pos, time = 500) => {
120      const currentPos = window.scrollY
121      const isNavFixed = document.getElementById('page-header').classList.contains('fixed')
122      if (currentPos > pos || isNavFixed) pos = pos - 70
123
124      if ('scrollBehavior' in document.documentElement.style) {
125        window.scrollTo({
126          top: pos,
127          behavior: 'smooth'
128        })
129        return
130      }
131
132      const startTime = performance.now()
133      const animate = currentTime => {
134        const timeElapsed = currentTime - startTime
135        const progress = Math.min(timeElapsed / time, 1)
136        window.scrollTo(0, currentPos + (pos - currentPos) * progress)
137        if (progress < 1) {
138          requestAnimationFrame(animate)
139        }
140      }
141      requestAnimationFrame(animate)
142    },
143
144    animateIn: (ele, animation) => {
145      ele.style.display = 'block'
146      ele.style.animation = animation
147    },
148
149    animateOut: (ele, animation) => {
150      const handleAnimationEnd = () => {
151        ele.style.display = ''
152        ele.style.animation = ''
153        ele.removeEventListener('animationend', handleAnimationEnd)
154      }
155      ele.addEventListener('animationend', handleAnimationEnd)
156      ele.style.animation = animation
157    },
158
159    wrap: (selector, eleType, options) => {
160      const createEle = document.createElement(eleType)
161      for (const [key, value] of Object.entries(options)) {
162        createEle.setAttribute(key, value)
163      }
164      selector.parentNode.insertBefore(createEle, selector)
165      createEle.appendChild(selector)
166    },
167
168    isHidden: ele => ele.offsetHeight === 0 && ele.offsetWidth === 0,
169
170    getEleTop: ele => ele.getBoundingClientRect().top + window.scrollY,
171
172    loadLightbox: ele => {
173      const service = GLOBAL_CONFIG.lightbox
174
175      if (service === 'medium_zoom') {
176        mediumZoom(ele, { background: 'var(--zoom-bg)' })
177        return
178      }
179
180      if (service === 'fancybox') {
181        ele.forEach(i => {
182          if (i.parentNode.tagName !== 'A') {
183            const dataSrc = i.dataset.lazySrc || i.src
184            const dataCaption = i.title || i.alt || ''
185            btf.wrap(i, 'a', { href: dataSrc, 'data-fancybox': 'gallery', 'data-caption': dataCaption, 'data-thumb'
185: dataSrc })
186          }
187        })
188
189        if (!window.fancyboxRun) {
190          let options = ''
191          if (Fancybox.version < '6') {
192            options = {
193              Hash: false,
194              Thumbs: {
195                showOnStart: false
196              },
197              Images: {
198                Panzoom: {
199                  maxScale: 4
200                }
201              },
202              Carousel: {
203                transition: 'slide'
204              },
205              Toolbar: {
206                display: {
207                  left: ['infobar'],
208                  middle: [
209                    'zoomIn',
210                    'zoomOut',
211                    'toggle1to1',
212                    'rotateCCW',
213                    'rotateCW',
214                    'flipX',
215                    'flipY'
216                  ],
217                  right: ['slideshow', 'thumbs', 'close']
218                }
219              }
220            }
221          } else {
222            options = {
223              Hash: false,
224              Carousel: {
225                transition: 'slide',
226                Thumbs: {
227                  showOnStart: false
228                },
229                Toolbar: {
230                  display: {
231                    left: ['counter'],
232                    middle: [
233                      'zoomIn',
234                      'zoomOut',
235                      'toggle1to1',
236                      'rotateCCW',
237                      'rotateCW',
238                      'flipX',
239                      'flipY',
240                      'reset'
241                    ],
242                    right: ['autoplay', 'thumbs', 'close']
243                  }
244                },
245                Zoomable: {
246                  Panzoom: {
247                    maxScale: 4
248                  }
249                }
250              }
251            }
252          }
253
254          Fancybox.bind('[data-fancybox]', options)
255          window.fancyboxRun = true
256        }
257      }
258    },
259
260    setLoading: {
261      add: ele => {
262        const html = `
263        <div class="loading-container">
264          <div class="loading-item">
265            <div></div><div></div><div></div><div></div><div></div>
266          </div>
267        </div>
268      `
269        ele.insertAdjacentHTML('afterend', html)
270      },
271      remove: ele => {
272        ele.nextElementSibling.remove()
273      }
274    },
275
276    updateAnchor: anchor => {
277      if (anchor !== window.location.hash) {
278        if (!anchor) anchor = location.pathname
279        const title = GLOBAL_CONFIG_SITE.title
280        window.history.replaceState({
281          url: location.href,
282          title
283        }, title, anchor)
284      }
285    },
286
287    getScrollPercent: (() => {
288      let docHeight, winHeight, headerHeight, contentMath
289
290      return (currentTop, ele) => {
291        if (!docHeight || ele.clientHeight !== docHeight) {
292          docHeight = ele.clientHeight
293          winHeight = window.innerHeight
294          headerHeight = ele.offsetTop
295          contentMath = Math.max(docHeight - winHeight, document.documentElement.scrollHeight - winHeight)
296        }
297
298        const scrollPercent = (currentTop - headerHeight) / contentMath
299        return Math.max(0, Math.min(100, Math.round(scrollPercent * 100)))
300      }
301    })(),
302
303    addEventListenerPjax: (ele, event, fn, option = false) => {
304      ele.addEventListener(event, fn, option)
305      btf.addGlobalFn('pjaxSendOnce', () => {
306        ele.removeEventListener(event, fn, option)
307      })
308    },
309
310    removeGlobalFnEvent: (key, parent = window) => {
311      const globalFn = parent.globalFn || {}
312      const keyObj = globalFn[key]
313      if (!keyObj) return
314
315      Object.keys(keyObj).forEach(i => keyObj[i]())
316
317      delete globalFn[key]
318    },
319
320    switchComments: (el = document, path) => {
321      const switchBtn = el.querySelector('#switch-btn')
322      if (!switchBtn) return
323
324      let switchDone = false
325      const postComment = el.querySelector('#post-comment')
326      const handleSwitchBtn = () => {
327        postComment.classList.toggle('move')
328        if (!switchDone && typeof loadOtherComment === 'function') {
329          switchDone = true
330          loadOtherComment(el, path)
331        }
332      }
333      btf.addEventListenerPjax(switchBtn, 'click', handleSwitchBtn)
334    }
335  }
336
337  window.btf = { ...window.btf, ...btfFn }
338})()

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.