PageSourceSearch

https://fanpla.jp/static/original/assets/js/jquery.vide.js

js fanpla.jp collected 2026-09-24 09:42:16 UTC 12,446 bytes, 493 lines download raw bytes

1!(function(root, factory) {
2  if (typeof define === 'function' && define.amd) {
3    define(['jquery'], factory);
4  } else if (typeof exports === 'object') {
5    factory(require('jquery'));
6  } else {
7    factory(root.jQuery);
8  }
9})(this, function($) {
10
11  'use strict';
12
13  /**
14   * Name of the plugin
15   * @private
16   * @const
17   * @type {String}
18   */
19  var PLUGIN_NAME = 'vide';
20
21  /**
22   * Default settings
23   * @private
24   * @const
25   * @type {Object}
26   */
27  var DEFAULTS = {
28    volume: 1,
29    playbackRate: 1,
30    muted: true,
31    loop: true,
32    autoplay: true,
33    position: '50% 50%',
34    posterType: 'detect',
35    resizing: true,
36    bgColor: 'transparent',
37    className: ''
38  };
39
40  /**
41   * Not implemented error message
42   * @private
43   * @const
44   * @type {String}
45   */
46  var NOT_IMPLEMENTED_MSG = 'Not implemented';
47
48  /**
49   * Parse a string with options
50   * @private
51   * @param {String} str
52   * @returns {Object|String}
53   */
54  function parseOptions(str) {
55    var obj = {};
56    var delimiterIndex;
57    var option;
58    var prop;
59    var val;
60    var arr;
61    var len;
62    var i;
63
64    // Remove spaces around delimiters and split
65    arr = str.replace(/\s*:\s*/g, ':').replace(/\s*,\s*/g, ',').split(',');
66
67    // Parse a string
68    for (i = 0, len = arr.length; i < len; i++) {
69      option = arr[i];
70
71      // Ignore urls and a string without colon delimiters
72      if (
73        option.search(/^(http|https|ftp):\/\//) !== -1 ||
74        option.search(':') === -1
75      ) {
76        break;
77      }
78
79      delimiterIndex = option.indexOf(':');
80      prop = option.substring(0, delimiterIndex);
81      val = option.substring(delimiterIndex + 1);
82
83      // If val is an empty string, make it undefined
84      if (!val) {
85        val = undefined;
86      }
87
88      // Convert a string value if it is like a boolean
89      if (typeof val === 'string') {
90        val = val === 'true' || (val === 'false' ? false : val);
91      }
92
93      // Convert a string value if it is like a number
94      if (typeof val === 'string') {
95        val = !isNaN(val) ? +val : val;
96      }
97
98      obj[prop] = val;
99    }
100
101    // If nothing is parsed
102    if (prop == null && val == null) {
103      return str;
104    }
105
106    return obj;
107  }
108
109  /**
110   * Parse a position option
111   * @private
112   * @param {String} str
113   * @returns {Object}
114   */
115  function parsePosition(str) {
116    str = '' + str;
117
118    // Default value is a center
119    var args = str.split(/\s+/);
120    var x = '50%';
121    var y = '50%';
122    var len;
123    var arg;
124    var i;
125
126    for (i = 0, len = args.length; i < len; i++) {
127      arg = args[i];
128
129      // Convert values
130      if (arg === 'left') {
131        x = '0%';
132      } else if (arg === 'right') {
133        x = '100%';
134      } else if (arg === 'top') {
135        y = '0%';
136      } else if (arg === 'bottom') {
137        y = '100%';
138      } else if (arg === 'center') {
139        if (i === 0) {
140          x = '50%';
141        } else {
142          y = '50%';
143        }
144      } else {
145        if (i === 0) {
146          x = arg;
147        } else {
148          y = arg;
149        }
150      }
151    }
152
153    return { x: x, y: y };
154  }
155
156  /**
157   * Search a poster
158   * @private
159   * @param {String} path
160   * @param {Function} callback
161   */
162  function findPoster(path, callback) {
163    var onLoad = function() {
164      callback(this.src);
165    };
166
167  //  $('<img src="' + path + '.gif">').on('load', onLoad);
168  //  $('<img src="' + path + '.jpg">').on('load', onLoad);
169  //  $('<img src="' + path + '.jpeg">').on('load', onLoad);
170  //  $('<img src="' + path + '.png">').on('load', onLoad);
171  }
172
173  /**
174   * Vide constructor
175   * @param {HTMLElement} element
176   * @param {Object|String} path
177   * @param {Object|String} options
178   * @constructor
179   */
180  function Vide(element, path, options) {
181    this.$element = $(element);
182
183    // Parse path
184    if (typeof path === 'string') {
185      path = parseOptions(path);
186    }
187
188    // Parse options
189    if (!options) {
190      options = {};
191    } else if (typeof options === 'string') {
192      options = parseOptions(options);
193    }
194
195    // Remove an extension
196    if (typeof path === 'string') {
197      path = path.replace(/\.\w*$/, '');
198    } else if (typeof path === 'object') {
199      for (var i in path) {
200        if (path.hasOwnProperty(i)) {
201          path[i] = path[i].replace(/\.\w*$/, '');
202        }
203      }
204    }
205
206    this.settings = $.extend({}, DEFAULTS, options);
207    this.path = path;
208
209    // https://github.com/VodkaBears/Vide/issues/110
210    try {
211      this.init();
212    } catch (e) {
213      if (e.message !== NOT_IMPLEMENTED_MSG) {
214        throw e;
215      }
216    }
217  }
218
219  /**
220   * Initialization
221   * @public
222   */
223  Vide.prototype.init = function() {
224    var vide = this;
225    var path = vide.path;
226    var poster = path;
227    var sources = '';
228    var $element = vide.$element;
229    var settings = vide.settings;
230    var position = parsePosition(settings.position);
231    var posterType = settings.posterType;
232    var $video;
233    var $wrapper;
234
235    // Set styles of a video wrapper
236    $wrapper = vide.$wrapper = $('<div>')
237      .addClass(settings.className)
238      .css({
239        position: 'absolute',
240        'z-index': -1,
241        top: 0,
242        left: 0,
243        bottom: 0,
244        right: 0,
245        overflow: 'hidden',
246        '-webkit-background-size': 'cover',
247        '-moz-background-size': 'cover',
248        '-o-background-size': 'cover',
249        'background-size': 'cover',
250        'background-color': settings.bgColor,
251        'background-repeat': 'no-repeat',
252        'background-position': position.x + ' ' + position.y
253      });
254
255    // Get a poster path
256    if (typeof path === 'object') {
257      if (path.poster) {
258        poster = path.poster;
259      } else {
260        if (path.mp4) {
261          poster = path.mp4;
262        } else if (path.webm) {
263          poster = path.webm;
264        } else if (path.ogv) {
265          poster = path.ogv;
266        }
267      }
268    }
269
270    // Set a video poster
271    if (posterType === 'detect') {
272      findPoster(poster, function(url) {
273        $wrapper.css('background-image', 'url(' + url + ')');
274      });
275    } else if (posterType !== 'none') {
276      $wrapper.css('background-image', 'url(' + poster + '.' + posterType + ')');
277    }
278
279    // If a parent element has a static position, make it relative
280    if ($element.css('position') === 'static') {
281      $element.css('position', 'relative');
282    }
283
284    $element.prepend($wrapper);
285
286    if (typeof path === 'object') {
287      if (path.mp4) {
288        sources += '<source src="' + path.mp4 + '.mp4" type="video/mp4">';
289      }
290
291      if (path.webm) {
292        sources += '<source src="' + path.webm + '.webm" type="video/webm">';
293      }
294
295      if (path.ogv) {
296        sources += '<source src="' + path.ogv + '.ogv" type="video/ogg">';
297      }
298
299      $video = vide.$video = $('<video webkit-playsinline playsinline>' + sources + '</video>');
300    } else {
301      $video = vide.$video = $('<video webkit-playsinline playsinline>' +
302        '<source src="' + path + '.mp4" type="video/mp4">' +
303        '<source src="' + path + '.webm" type="video/webm">' +
304        '<source src="' + path + '.ogv" type="video/ogg">' +
305        '</video>');
306    }
307
308    // https://github.com/VodkaBears/Vide/issues/110
309    try {
310      $video
311
312        // Set video properties
313        .prop({
314          autoplay: settings.autoplay,
315          loop: settings.loop,
316          volume: settings.volume,
317          muted: settings.muted,
318          defaultMuted: settings.muted,
319          playbackRate: settings.playbackRate,
320          defaultPlaybackRate: settings.playbackRate
321        });
322    } catch (e) {
323      throw new Error(NOT_IMPLEMENTED_MSG);
324    }
325
326    // Video alignment
327    $video.css({
328      margin: 'auto',
329      position: 'absolute',
330      'z-index': -1,
331      top: position.y,
332      left: position.x,
333      '-webkit-transform': 'translate(-' + position.x + ', -' + position.y + ')',
334      '-ms-transform': 'translate(-' + position.x + ', -' + position.y + ')',
335      '-moz-transform': 'translate(-' + position.x + ', -' + position.y + ')',
336      transform: 'translate(-' + position.x + ', -' + position.y + ')',
337
338      // Disable visibility, while loading
339      //visibility: 'hidden',
340      //opacity: 0
341    })
342
343    // Resize a video, when it's loaded
344    .one('canplaythrough.' + PLUGIN_NAME, function() {
345      vide.resize();
346    })
347
348    // Make it visible, when it's already playing
349    .one('playing.' + PLUGIN_NAME, function() {
350      $video.css({
351        visibility: 'visible',
352        opacity: 1
353      });
354      $wrapper.css('background-image', 'none');
355    });
356
357    // Resize event is available only for 'window'
358    // Use another code solutions to detect DOM elements resizing
359    $element.on('resize.' + PLUGIN_NAME, function() {
360      if (settings.resizing) {
361        vide.resize();
362      }
363    });
364
365    // Append a video
366    $wrapper.append($video);
367  };
368
369  /**
370   * Get a video element
371   * @public
372   * @returns {HTMLVideoElement}
373   */
374  Vide.prototype.getVideoObject = function() {
375    return this.$video[0];
376  };
377
378  /**
379   * Resize a video background
380   * @public
381   */
382  Vide.prototype.resize = function() {
383    if (!this.$video) {
384      return;
385    }
386
387    var $wrapper = this.$wrapper;
388    var $video = this.$video;
389    var video = $video[0];
390
391    // Get a native video size
392    var videoHeight = video.videoHeight;
393    var videoWidth = video.videoWidth;
394
395    // Get a wrapper size
396    var wrapperHeight = $wrapper.height();
397    var wrapperWidth = $wrapper.width();
398
399    if (wrapperWidth / videoWidth > wrapperHeight / videoHeight) {
400      $video.css({
401
402        // +2 pixels to prevent an empty space after transformation
403        width: wrapperWidth + 2,
404        height: 'auto'
405      });
406    } else {
407      $video.css({
408        width: 'auto',
409
410        // +2 pixels to prevent an empty space after transformation
411        height: wrapperHeight + 2
412      });
413    }
414  };
415
416  /**
417   * Destroy a video background
418   * @public
419   */
420  Vide.prototype.destroy = function() {
421    delete $[PLUGIN_NAME].lookup[this.index];
422    this.$video && this.$video.off(PLUGIN_NAME);
423    this.$element.off(PLUGIN_NAME).removeData(PLUGIN_NAME);
424    this.$wrapper.remove();
425  };
426
427  /**
428   * Special plugin object for instances.
429   * @public
430   * @type {Object}
431   */
432  $[PLUGIN_NAME] = {
433    lookup: []
434  };
435
436  /**
437   * Plugin constructor
438   * @param {Object|String} path
439   * @param {Object|String} options
440   * @returns {JQuery}
441   * @constructor
442   */
443  $.fn[PLUGIN_NAME] = function(path, options) {
444    var instance;
445
446    this.each(function() {
447      instance = $.data(this, PLUGIN_NAME);
448
449      // Destroy the plugin instance if exists
450      instance && instance.destroy();
451
452      // Create the plugin instance
453      instance = new Vide(this, path, options);
454      instance.index = $[PLUGIN_NAME].lookup.push(instance) - 1;
455      $.data(this, PLUGIN_NAME, instance);
456    });
457
458    return this;
459  };
460
461  $(document).ready(function() {
462    var $window = $(window);
463
464    // Window resize event listener
465    $window.on('resize.' + PLUGIN_NAME, function() {
466      for (var len = $[PLUGIN_NAME].lookup.length, i = 0, instance; i < len; i++) {
467        instance = $[PLUGIN_NAME].lookup[i];
468
469        if (instance && instance.settings.resizing) {
470          instance.resize();
471        }
472      }
473    });
474
475    // https://github.com/VodkaBears/Vide/issues/68
476    $window.on('unload.' + PLUGIN_NAME, function() {
477      return false;
478    });
479
480    // Auto initialization
481    // Add 'data-vide-bg' attribute with a path to the video without extension
482    // Also you can pass options throw the 'data-vide-options' attribute
483    // 'data-vide-options' must be like 'muted: false, volume: 0.5'
484    $(document).find('[data-' + PLUGIN_NAME + '-bg]').each(function(i, element) {
485      var $element = $(element);
486      var options = $element.data(PLUGIN_NAME + '-options');
487      var path = $element.data(PLUGIN_NAME + '-bg');
488
489      $element[PLUGIN_NAME](path, options);
490    });
491  });
492
493});

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.