PageSourceSearch

https://leowang721.github.io/js/src/utils.js?v=5.1.0

js leowang721.github.io collected 2026-10-03 09:30:31 UTC 6,529 bytes, 230 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          $imageWrapLink = $image.wrap('<a href="' + this.getAttribute('src') + '"></a>').parent('a');
18        }
19
20        $imageWrapLink.addClass('fancybox fancybox.image');
21        $imageWrapLink.attr('rel', 'group');
22
23        if (imageTitle) {
24          $imageWrapLink.append('<p class="image-caption">' + imageTitle + '</p>');
25
26          //make sure img title tag will show correctly in fancybox
27          $imageWrapLink.attr('title', imageTitle);
28        }
29      });
30
31    $('.fancybox').fancybox({
32      helpers: {
33        overlay: {
34          locked: false
35        }
36      }
37    });
38  },
39
40  lazyLoadPostsImages: function () {
41    $('#posts').find('img').lazyload({
42      placeholder: '/images/loading.gif',
43      effect: 'fadeIn'
44    });
45  },
46
47  registerESCKeyEvent: function () {
48    $(document).on('keyup', function (event) {
49      var shouldDismissSearchPopup = event.which === 27 &&
50        $('.search-popup').is(':visible');
51      if (shouldDismissSearchPopup) {
52        $('.search-popup').hide();
53        $('.search-popup-overlay').remove();
54        $('body').css('overflow', '');
55      }
56    });
57  },
58
59  registerBackToTop: function () {
60    var THRESHOLD = 50;
61    var $top = $('.back-to-top');
62
63    $(window).on('scroll', function () {
64      $top.toggleClass('back-to-top-on', window.pageYOffset > THRESHOLD);
65
66      var scrollTop = $(window).scrollTop();
67      var docHeight = $(document).height();
68      var winHeight = $(window).height();
69      var scrollPercent = (scrollTop) / (docHeight - winHeight);
70      var scrollPercentRounded = Math.round(scrollPercent*100);
71      $('#scrollpercent>span').html(scrollPercentRounded);
72    });
73
74    $top.on('click', function () {
75      $('body').velocity('scroll');
76    });
77  },
78
79  /**
80   * Transform embedded video to support responsive layout.
81   * @see http://toddmotto.com/fluid-and-responsive-youtube-and-vimeo-videos-with-fluidvids-js/
82   */
83  embeddedVideoTransformer: function () {
84    var $iframes = $('iframe');
85
86    // Supported Players. Extend this if you need more players.
87    var SUPPORTED_PLAYERS = [
88      'www.youtube.com',
89      'player.vimeo.com',
90      'player.youku.com',
91      'music.163.com',
92      'www.tudou.com'
93    ];
94    var pattern = new RegExp( SUPPORTED_PLAYERS.join('|') );
95
96    $iframes.each(function () {
97      var iframe = this;
98      var $iframe = $(this);
99      var oldDimension = getDimension($iframe);
100      var newDimension;
101
102      if (this.src.search(pattern) > 0) {
103
104        // Calculate the video ratio based on the iframe's w/h dimensions
105        var videoRatio = getAspectRadio(oldDimension.width, oldDimension.height);
106
107        // Replace the iframe's dimensions and position the iframe absolute
108        // This is the trick to emulate the video ratio
109        $iframe.width('100%').height('100%')
110          .css({
111            position: 'absolute',
112            top: '0',
113            left: '0'
114          });
115
116
117        // Wrap the iframe in a new <div> which uses a dynamically fetched padding-top property
118        // based on the video's w/h dimensions
119        var wrap = document.createElement('div');
120        wrap.className = 'fluid-vids';
121        wrap.style.position = 'relative';
122        wrap.style.marginBottom = '20px';
123        wrap.style.width = '100%';
124        wrap.style.paddingTop = videoRatio + '%';
125
126        // Add the iframe inside our newly created <div>
127        var iframeParent = iframe.parentNode;
128        iframeParent.insertBefore(wrap, iframe);
129        wrap.appendChild(iframe);
130
131        // Additional adjustments for 163 Music
132        if (this.src.search('music.163.com') > 0) {
133          newDimension = getDimension($iframe);
134          var shouldRecalculateAspect = newDimension.width > oldDimension.width ||
135                                        newDimension.height < oldDimension.height;
136
137          // 163 Music Player has a fixed height, so we need to reset the aspect radio
138          if (shouldRecalculateAspect) {
139            wrap.style.paddingTop = getAspectRadio(newDimension.width, oldDimension.height) + '%';
140          }
141        }
142      }
143    });
144
145    function getDimension($element) {
146      return {
147        width: $element.width(),
148        height: $element.height()
149      };
150    }
151
152    function getAspectRadio(width, height) {
153      return height / width * 100;
154    }
155  },
156
157  /**
158   * Add `menu-item-active` class name to menu item
159   * via comparing location.path with menu item's href.
160   */
161  addActiveClassToMenuItem: function () {
162    var path = window.location.pathname;
163    path = path === '/' ? path : path.substring(0, path.length - 1);
164    $('.menu-item a[href="' + path + '"]').parent().addClass('menu-item-active');
165  },
166
167  hasMobileUA: function () {
168    var nav = window.navigator;
169    var ua = nav.userAgent;
170    var pa = /iPad|iPhone|Android|Opera Mini|BlackBerry|webOS|UCWEB|Blazer|PSP|IEMobile|Symbian/g;
171
172    return pa.test(ua);
173  },
174
175  isTablet: function () {
176    return window.screen.width < 992 && window.screen.width > 767 && this.hasMobileUA();
177  },
178
179  isMobile: function () {
180    return window.screen.width < 767 && this.hasMobileUA();
181  },
182
183  isDesktop: function () {
184    return !this.isTablet() && !this.isMobile();
185  },
186
187  /**
188   * Escape meta symbols in jQuery selectors.
189   *
190   * @param selector
191   * @returns {string|void|XML|*}
192   */
193  escapeSelector: function (selector) {
194    return selector.replace(/[!"$%&'()*+,.\/:;<=>?@[\\\]^`{|}~]/g, '\\$&');
195  },
196
197  displaySidebar: function () {
198    if (!this.isDesktop() || this.isPisces()) {
199      return;
200    }
201    $('.sidebar-toggle').trigger('click');
202  },
203
204  isMist: function () {
205    return CONFIG.scheme === 'Mist';
206  },
207
208  isPisces: function () {
209    return CONFIG.scheme === 'Pisces';
210  },
211
212  getScrollbarWidth: function () {
213    var $div = $('<div />').addClass('scrollbar-measure').prependTo('body');
214    var div = $div[0];
215    var scrollbarWidth = div.offsetWidth - div.clientWidth;
216
217    $div.remove();
218
219    return scrollbarWidth;
220  },
221
222  /**
223   * Affix behaviour for Sidebar.
224   *
225   * @returns {Boolean}
226   */
227  needAffix: function () {
228    return this.isPisces();
229  }
230};

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.