PageSourceSearch

https://myml666.github.io/js/src/utils.js?v=5.1.4

js myml666.github.io collected 2026-10-03 09:39:24 UTC 10,822 bytes, 339 lines download raw bytes

1/* global NexT: true */
2
3NexT.utils = NexT.$u = {
4  /**
5   * Wrap images with fancybox support.
6   */
7  wrapImageWithFancyBox: function () {
8    $('.content img')
9      .not('[hidden]')
10      .not('.group-picture img, .post-gallery img')
11      .each(function () {
12        var $image = $(this);
13        var imageTitle = $image.attr('title');
14        var $imageWrapLink = $image.parent('a');
15
16        if ($imageWrapLink.size() < 1) {
17	        var imageLink = ($image.attr('data-original')) ? this.getAttribute('data-original') : this.getAttribute('src');
18          $imageWrapLink = $image.wrap('<a href="' + imageLink + '"></a>').parent('a');
19        }
20
21        $imageWrapLink.addClass('fancybox fancybox.image');
22        $imageWrapLink.attr('rel', 'group');
23
24        if (imageTitle) {
25          $imageWrapLink.append('<p class="image-caption">' + imageTitle + '</p>');
26
27          //make sure img title tag will show correctly in fancybox
28          $imageWrapLink.attr('title', imageTitle);
29        }
30      });
31
32    $('.fancybox').fancybox({
33      helpers: {
34        overlay: {
35          locked: false
36        }
37      }
38    });
39  },
40
41  lazyLoadPostsImages: function () {
42    $('#posts').find('img').lazyload({
43      //placeholder: '/images/loading.gif',
44      effect: 'fadeIn',
45      threshold : 0
46    });
47  },
48
49  /**
50   * Tabs tag listener (without twitter bootstrap).
51   */
52  registerTabsTag: function () {
53    var tNav = '.tabs ul.nav-tabs ';
54
55    // Binding `nav-tabs` & `tab-content` by real time permalink changing.
56    $(function() {
57      $(window).bind('hashchange', function() {
58        var tHash = location.hash;
59        if (tHash !== '') {
60          $(tNav + 'li:has(a[href="' + tHash + '"])').addClass('active').siblings().removeClass('active');
61          $(tHash).addClass('active').siblings().removeClass('active');
62        }
63      }).trigger('hashchange');
64    });
65
66    $(tNav + '.tab').on('click', function (href) {
67      href.preventDefault();
68      // Prevent selected tab to select again.
69      if(!$(this).hasClass('active')){
70
71        // Add & Remove active class on `nav-tabs` & `tab-content`.
72        $(this).addClass('active').siblings().removeClass('active');
73        var tActive = $(this).find('a').attr('href');
74        $(tActive).addClass('active').siblings().removeClass('active');
75
76        // Clear location hash in browser if #permalink exists.
77        if (location.hash !== '') {
78          history.pushState('', document.title, window.location.pathname + window.location.search);
79        }
80      }
81    });
82
83  },
84
85  registerESCKeyEvent: function () {
86    $(document).on('keyup', function (event) {
87      var shouldDismissSearchPopup = event.which === 27 &&
88        $('.search-popup').is(':visible');
89      if (shouldDismissSearchPopup) {
90        $('.search-popup').hide();
91        $('.search-popup-overlay').remove();
92        $('body').css('overflow', '');
93      }
94    });
95  },
96
97  registerBackToTop: function () {
98    var THRESHOLD = 50;
99    var $top = $('.back-to-top');
100
101    $(window).on('scroll', function () {
102      $top.toggleClass('back-to-top-on', window.pageYOffset > THRESHOLD);
103
104      var scrollTop = $(window).scrollTop();
105      var contentVisibilityHeight = NexT.utils.getContentVisibilityHeight();
106      var scrollPercent = (scrollTop) / (contentVisibilityHeight);
107      var scrollPercentRounded = Math.round(scrollPercent*100);
108      var scrollPercentMaxed = (scrollPercentRounded > 100) ? 100 : scrollPercentRounded;
109      $('#scrollpercent>span').html(scrollPercentMaxed);
110    });
111
112    $top.on('click', function () {
113      $('body').velocity('scroll');
114    });
115  },
116
117  /**
118   * Transform embedded video to support responsive layout.
119   * @see http://toddmotto.com/fluid-and-responsive-youtube-and-vimeo-videos-with-fluidvids-js/
120   */
121  embeddedVideoTransformer: function () {
122    var $iframes = $('iframe');
123
124    // Supported Players. Extend this if you need more players.
125    var SUPPORTED_PLAYERS = [
126      'www.youtube.com',
127      'player.vimeo.com',
128      'player.youku.com',
129      'music.163.com',
130      'www.tudou.com'
131    ];
132    var pattern = new RegExp( SUPPORTED_PLAYERS.join('|') );
133
134    $iframes.each(function () {
135      var iframe = this;
136      var $iframe = $(this);
137      var oldDimension = getDimension($iframe);
138      var newDimension;
139
140      if (this.src.search(pattern) > 0) {
141
142        // Calculate the video ratio based on the iframe's w/h dimensions
143        var videoRatio = getAspectRadio(oldDimension.width, oldDimension.height);
144
145        // Replace the iframe's dimensions and position the iframe absolute
146        // This is the trick to emulate the video ratio
147        $iframe.width('100%').height('100%')
148          .css({
149            position: 'absolute',
150            top: '0',
151            left: '0'
152          });
153
154
155        // Wrap the iframe in a new <div> which uses a dynamically fetched padding-top property
156        // based on the video's w/h dimensions
157        var wrap = document.createElement('div');
158        wrap.className = 'fluid-vids';
159        wrap.style.position = 'relative';
160        wrap.style.marginBottom = '20px';
161        wrap.style.width = '100%';
162        wrap.style.paddingTop = videoRatio + '%';
163        // Fix for appear inside tabs tag.
164        (wrap.style.paddingTop === '') && (wrap.style.paddingTop = '50%');
165
166        // Add the iframe inside our newly created <div>
167        var iframeParent = iframe.parentNode;
168        iframeParent.insertBefore(wrap, iframe);
169        wrap.appendChild(iframe);
170
171        // Additional adjustments for 163 Music
172        if (this.src.search('music.163.com') > 0) {
173          newDimension = getDimension($iframe);
174          var shouldRecalculateAspect = newDimension.width > oldDimension.width ||
175                                        newDimension.height < oldDimension.height;
176
177          // 163 Music Player has a fixed height, so we need to reset the aspect radio
178          if (shouldRecalculateAspect) {
179            wrap.style.paddingTop = getAspectRadio(newDimension.width, oldDimension.height) + '%';
180          }
181        }
182      }
183    });
184
185    function getDimension($element) {
186      return {
187        width: $element.width(),
188        height: $element.height()
189      };
190    }
191
192    function getAspectRadio(width, height) {
193      return height / width * 100;
194    }
195  },
196
197  /**
198   * Add `menu-item-active` class name to menu item
199   * via comparing location.path with menu item's href.
200   */
201  addActiveClassToMenuItem: function () {
202    var path = window.location.pathname;
203    path = path === '/' ? path : path.substring(0, path.length - 1);
204    $('.menu-item a[href^="' + path + '"]:first').parent().addClass('menu-item-active');
205  },
206
207  hasMobileUA: function () {
208    var nav = window.navigator;
209    var ua = nav.userAgent;
210    var pa = /iPad|iPhone|Android|Opera Mini|BlackBerry|webOS|UCWEB|Blazer|PSP|IEMobile|Symbian/g;
211
212    return pa.test(ua);
213  },
214
215  isTablet: function () {
216    return window.screen.width < 992 && window.screen.width > 767 && this.hasMobileUA();
217  },
218
219  isMobile: function () {
220    return window.screen.width < 767 && this.hasMobileUA();
221  },
222
223  isDesktop: function () {
224    return !this.isTablet() && !this.isMobile();
225  },
226
227  /**
228   * Escape meta symbols in jQuery selectors.
229   *
230   * @param selector
231   * @returns {string|void|XML|*}
232   */
233  escapeSelector: function (selector) {
234    return selector.replace(/[!"$%&'()*+,.\/:;<=>?@[\\\]^`{|}~]/g, '\\$&');
235  },
236
237  displaySidebar: function () {
238    if (!this.isDesktop() || this.isPisces() || this.isGemini()) {
239      return;
240    }
241    $('.sidebar-toggle').trigger('click');
242  },
243
244  isMist: function () {
245    return CONFIG.scheme === 'Mist';
246  },
247
248  isPisces: function () {
249    return CONFIG.scheme === 'Pisces';
250  },
251
252  isGemini: function () {
253    return CONFIG.scheme === 'Gemini';
254  },
255
256  getScrollbarWidth: function () {
257    var $div = $('<div />').addClass('scrollbar-measure').prependTo('body');
258    var div = $div[0];
259    var scrollbarWidth = div.offsetWidth - div.clientWidth;
260
261    $div.remove();
262
263    return scrollbarWidth;
264  },
265
266  getContentVisibilityHeight: function () {
267    var docHeight = $('#content').height(),
268        winHeight = $(window).height(),
269        contentVisibilityHeight = (docHeight > winHeight) ? (docHeight - winHeight) : ($(document).height() - winHeight);
270    return contentVisibilityHeight;
271  },
272
273  getSidebarb2tHeight: function () {
274    //var sidebarb2tHeight = (CONFIG.sidebar.b2t) ? document.getElementsByClassName('back-to-top')[0].clientHeight : 0;
275    var sidebarb2tHeight = (CONFIG.sidebar.b2t) ? $('.back-to-top').height() : 0;
276    //var sidebarb2tHeight = (CONFIG.sidebar.b2t) ? 24 : 0;
277    return sidebarb2tHeight;
278  },
279
280  getSidebarSchemePadding: function () {
281    var sidebarNavHeight = ($('.sidebar-nav').css('display') == 'block') ? $('.sidebar-nav').outerHeight(true) : 0,
282        sidebarInner = $('.sidebar-inner'),
283        sidebarPadding = sidebarInner.innerWidth() - sidebarInner.width(),
284        sidebarSchemePadding = this.isPisces() || this.isGemini() ?
285          ((sidebarPadding * 2) + sidebarNavHeight + (CONFIG.sidebar.offset * 2) + this.getSidebarb2tHeight()) :
286          ((sidebarPadding * 2) + (sidebarNavHeight / 2));
287    return sidebarSchemePadding;
288  }
289
290  /**
291   * Affix behaviour for Sidebar.
292   *
293   * @returns {Boolean}
294   */
295//  needAffix: function () {
296//    return this.isPisces() || this.isGemini();
297//  }
298};
299
300$(document).ready(function () {
301
302  initSidebarDimension();
303
304  /**
305   * Init Sidebar & TOC inner dimensions on all pages and for all schemes.
306   * Need for Sidebar/TOC inner scrolling if content taller then viewport.
307   */
308  function initSidebarDimension () {
309    var updateSidebarHeightTimer;
310
311    $(window).on('resize', function () {
312      updateSidebarHeightTimer && clearTimeout(updateSidebarHeightTimer);
313
314      updateSidebarHeightTimer = setTimeout(function () {
315        var sidebarWrapperHeight = document.body.clientHeight - NexT.utils.getSidebarSchemePadding();
316
317        updateSidebarHeight(sidebarWrapperHeight);
318      }, 0);
319    });
320
321    // Initialize Sidebar & TOC Width.
322    var scrollbarWidth = NexT.utils.getScrollbarWidth();
323      if ($('.site-overview-wrap').height() > (document.body.clientHeight - NexT.utils.getSidebarSchemePadding())) {
324        $('.site-overview').css('width', 'calc(100% + ' + scrollbarWidth + 'px)');
325      }
326      if ($('.post-toc-wrap').height() > (document.body.clientHeight - NexT.utils.getSidebarSchemePadding())) {
327        $('.post-toc').css('width', 'calc(100% + ' + scrollbarWidth + 'px)');
328      }
329
330    // Initialize Sidebar & TOC Height.
331    updateSidebarHeight(document.body.clientHeight - NexT.utils.getSidebarSchemePadding());
332  }
333
334  function updateSidebarHeight (height) {
335    height = height || 'auto';
336    $('.site-overview, .post-toc').css('max-height', height);
337  }
338
339});

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.