PageSourceSearch

https://moshicom.com/assets/js/jquery.bgswitcher.js

js moshicom.com collected 2026-09-24 10:04:25 UTC 11,714 bytes, 559 lines download raw bytes

1/*!
2 * jQuery.BgSwitcher
3 *
4 * @version  0.4.3
5 * @author   rewish <[email protected]>
6 * @license  MIT License (https://github.com/rewish/jquery-bgswitcher/blob/master/LICENSE.md)
7 * @link     https://github.com/rewish/jquery-bgswitcher
8 */
9(function($) {
10  'use strict';
11
12  var loadedImages = {},
13
14      slice = Array.prototype.slice,
15      toString = Object.prototype.toString,
16
17      corners = ['Top', 'Right', 'Bottom', 'Left'],
18      backgroundProperties = [
19        'Attachment', 'Color', 'Image', 'Repeat',
20        'Position', 'Size', 'Clip', 'Origin'
21      ];
22
23  $.fn.bgswitcher = function() {
24    var args = arguments,
25        instanceKey = BgSwitcher.keys.instance;
26
27    return this.each(function() {
28      var instance = $.data(this, instanceKey);
29
30      if (!instance) {
31        instance = new BgSwitcher(this);
32        $.data(this, instanceKey, instance);
33      }
34
35      instance.dispatch.apply(instance, args);
36    });
37  };
38
39  // Backward Compatibility
40  $.fn.bgSwitcher = $.fn.bgswitcher;
41
42  /**
43   * BgSwitcher
44   *
45   * @param {HTMLElement} el
46   * @constructor
47   */
48  function BgSwitcher(el) {
49    this.$el = $(el);
50    this.index = 0;
51    this.config = $.extend({}, BgSwitcher.defaultConfig);
52
53    this._setupBackgroundElement();
54    this._listenToResize();
55  }
56
57  $.extend(BgSwitcher.prototype, {
58    /**
59     * Dispatch
60     *
61     * @param {string|Array} one
62     */
63    dispatch: function(one) {
64      switch (toString.call(one)) {
65        case '[object Object]':
66          this.setConfig(one);
67          break;
68        case '[object String]':
69          this[one].apply(this, slice.call(arguments, 1));
70          break;
71        default:
72          throw new Error('Please specify a Object or String');
73      }
74    },
75
76    /**
77     * Set config
78     *
79     * @param {Object} config
80     */
81    setConfig: function(config) {
82      this.config = $.extend(this.config, config);
83
84      if (typeof this.config.random !== 'undefined') {
85        this.config.shuffle = this.config.random;
86      }
87
88      this.refresh();
89    },
90
91    /**
92     * Set images
93     *
94     * @param {Array} images
95     */
96    setImages: function(images) {
97      this.imageList = new this.constructor.ImageList(images);
98
99      if (this.config.shuffle) {
100        this.imageList.shuffle();
101      }
102    },
103
104    /**
105     * Set switch handler
106     *
107     * @param {Function} fn
108     */
109    setSwitchHandler: function(fn) {
110      this.switchHandler = $.proxy(fn, this);
111    },
112
113    /**
114     * Default switch handler
115     *
116     * @param {string} type
117     * @returns {Function}
118     */
119    getBuiltInSwitchHandler: function(type) {
120      return this.constructor.switchHandlers[type || this.config.effect];
121    },
122
123    /**
124     * Refresh
125     */
126    refresh: function() {
127      this.setImages(this.config.images);
128      this.setSwitchHandler(this.getBuiltInSwitchHandler());
129      this._prepareSwitching();
130
131      if (this.config.start) {
132        this.start();
133      }
134    },
135
136    /**
137     * Start switching
138     */
139    start: function() {
140      if (!this._timerID) {
141        this._timerID = setTimeout($.proxy(this, 'next'), this.config.interval);
142      }
143    },
144
145    /**
146     * Stop switching
147     */
148    stop: function() {
149      if (this._timerID) {
150        clearTimeout(this._timerID);
151        this._timerID = null;
152      }
153    },
154
155    /**
156     * Toggle between start/stop
157     */
158    toggle: function() {
159      if (this._timerID) {
160        this.stop();
161      } else {
162        this.start();
163      }
164    },
165
166    /**
167     * Reset switching
168     */
169    reset: function() {
170      this.index = 0;
171      this._prepareSwitching();
172    },
173
174    /**
175     * Go to next switching
176     */
177    next: function() {
178      var max = this.imageList.count();
179
180      if (!this.config.loop && this.index + 1 === max) {
181        return;
182      }
183
184      if (++this.index === max) {
185        this.index = 0;
186      }
187
188      this.switching();
189    },
190
191    /**
192     * Go to previous switching
193     */
194    prev: function() {
195      if (!this.config.loop && this.index === 0) {
196        return;
197      }
198
199      if (--this.index === -1) {
200        this.index = this.imageList.count() - 1;
201      }
202
203      this.switching();
204    },
205
206    /**
207     * Select the switching at index
208     *
209     * @param {number} index
210     */
211    select: function(index) {
212      if (index === -1) {
213        index = this.imageList.count() - 1;
214      }
215
216      this.index = index;
217      this.switching();
218    },
219
220    /**
221     * Switching the background image
222     */
223    switching: function() {
224      var started = !!this._timerID;
225
226      if (started) {
227        this.stop();
228      }
229
230      this._createSwitchableElement();
231      this._prepareSwitching();
232      this.switchHandler(this.$switchable);
233
234      if (started) {
235        this.start();
236      }
237    },
238
239    /**
240     * Destroy...
241     */
242    destroy: function() {
243      this.stop();
244      this._stopListeningToResize();
245
246      if (this.$switchable) {
247        this.$switchable.stop();
248        this.$switchable.remove();
249        this.$switchable = null;
250      }
251
252      if (this.$bg) {
253        this.$bg.remove();
254        this.$bg = null;
255      }
256
257      this.$el.removeAttr('style');
258      this.$el.removeData(this.constructor.keys.instance);
259      this.$el = null;
260    },
261
262    /**
263     * Adjust rectangle
264     */
265    _adjustRectangle: function() {
266      var corner,
267          i = 0,
268          length = corners.length,
269          offset = this.$el.position(),
270          copiedStyles = {
271            top: offset.top,
272            left: offset.left,
273            width: this.$el.innerWidth(),
274            height: this.$el.innerHeight()
275          };
276
277      for (; i < length; i++) {
278        corner = corners[i];
279        copiedStyles['margin' + corner] = this.$el.css('margin' + corner);
280        copiedStyles['border' + corner] = this.$el.css('border' + corner);
281      }
282
283      this.$bg.css(copiedStyles);
284    },
285
286    /**
287     * Setup background element
288     */
289    _setupBackgroundElement: function() {
290      this.$bg = $(document.createElement('div'));
291      this.$bg.css({
292        position: 'absolute',
293        zIndex: (parseInt(this.$el.css('zIndex'), 10) || 0) - 1,
294        overflow: 'hidden'
295      });
296
297      this._copyBackgroundStyles();
298      this._adjustRectangle();
299
300      if (this.$el[0].tagName === 'BODY') {
301        this.$el.prepend(this.$bg);
302      } else {
303        this.$el.before(this.$bg);
304        this.$el.css('background', 'none');
305      }
306    },
307
308    /**
309     * Create switchable element
310     */
311    _createSwitchableElement: function() {
312      if (this.$switchable) {
313        this.$switchable.remove();
314      }
315
316      this.$switchable = this.$bg.clone();
317      this.$switchable.css({top: 0, left: 0, margin: 0, border: 'none'});
318      this.$switchable.appendTo(this.$bg);
319    },
320
321    /**
322     * Copy background styles
323     */
324    _copyBackgroundStyles: function () {
325      var prop,
326          copiedStyle = {},
327          i = 0,
328          length = backgroundProperties.length,
329          backgroundPosition = 'backgroundPosition';
330
331      for (; i < length; i++) {
332        prop = 'background' + backgroundProperties[i];
333        copiedStyle[prop] = this.$el.css(prop);
334      }
335
336      // For IE<=9
337      if (copiedStyle[backgroundPosition] === undefined) {
338        copiedStyle[backgroundPosition] = [
339          this.$el.css(backgroundPosition + 'X'),
340          this.$el.css(backgroundPosition + 'Y')
341        ].join(' ');
342      }
343
344      this.$bg.css(copiedStyle);
345    },
346
347    /**
348     * Listen to the resize event
349     */
350    _listenToResize: function() {
351      var that = this;
352      this._resizeHandler = function() {
353        that._adjustRectangle();
354      };
355      $(window).on('resize', this._resizeHandler);
356    },
357
358    /**
359     * Stop listening to the resize event
360     */
361    _stopListeningToResize: function() {
362      $(window).off('resize', this._resizeHandler);
363      this._resizeHandler = null;
364    },
365
366    /**
367     * Prepare the Switching
368     */
369    _prepareSwitching: function() {
370      this.$bg.css('backgroundImage', this.imageList.url(this.index));
371    }
372  });
373
374  /**
375   * Data Keys
376   * @type {Object}
377   */
378  BgSwitcher.keys = {
379    instance: 'bgSwitcher'
380  };
381
382  /**
383   * Default Config
384   * @type {Object}
385   */
386  BgSwitcher.defaultConfig = {
387    images: [],
388    interval: 5000,
389    start: true,
390    loop: true,
391    shuffle: false,
392    effect: 'fade',
393    duration: 1000,
394    easing: 'swing'
395  };
396
397  /**
398   * Built-In switch handlers (effects)
399   * @type {Object}
400   */
401  BgSwitcher.switchHandlers = {
402    fade: function($el) {
403      $el.animate({opacity: 0}, this.config.duration, this.config.easing);
404    },
405
406    blind: function($el) {
407      $el.animate({height: 0}, this.config.duration, this.config.easing);
408    },
409
410    clip: function($el) {
411      $el.animate({
412        top: parseInt($el.css('top'), 10) + $el.height() / 2,
413        height: 0
414      }, this.config.duration, this.config.easing);
415    },
416
417    slide: function($el) {
418      $el.animate({top: -$el.height()}, this.config.duration, this.config.easing);
419    },
420
421    drop: function($el) {
422      $el.animate({
423        left: -$el.width(),
424        opacity: 0
425      }, this.config.duration, this.config.easing);
426    },
427
428    hide: function($el) {
429      $el.hide();
430    }
431  };
432
433  /**
434   * Define effect
435   *
436   * @param {String} name
437   * @param {Function} fn
438   */
439  BgSwitcher.defineEffect = function(name, fn) {
440    this.switchHandlers[name] = fn;
441  };
442
443  /**
444   * BgSwitcher.ImageList
445   *
446   * @param {Array} images
447   * @constructor
448   */
449  BgSwitcher.ImageList = function(images) {
450    this.images = images;
451    this.createImagesBySequence();
452    this.preload();
453  };
454
455  $.extend(BgSwitcher.ImageList.prototype, {
456    /**
457     * Images is sequenceable
458     *
459     * @returns {boolean}
460     */
461    isSequenceable: function() {
462      return typeof this.images[0] === 'string' &&
463          typeof this.images[1] === 'number' &&
464          typeof this.images[2] === 'number';
465    },
466
467    /**
468     * Create an images by sequence
469     */
470    createImagesBySequence: function() {
471      if (!this.isSequenceable()) {
472        return;
473      }
474
475      var images = [],
476          base = this.images[0],
477          min = this.images[1],
478          max = this.images[2];
479
480      do {
481        images.push(base.replace(/\.\w+$/, min + '$&'));
482      } while (++min <= max);
483
484      this.images = images;
485    },
486
487    /**
488     * Preload an images
489     */
490    preload: function() {
491      var path,
492          length = this.images.length,
493          i = 0;
494
495      for (; i < length; i++) {
496        path = this.images[i];
497        if (!loadedImages[path]) {
498          loadedImages[path] = new Image();
499          loadedImages[path].src = path;
500        }
501      }
502    },
503
504    /**
505     * Shuffle an images
506     */
507    shuffle: function() {
508      var j, t,
509          i = this.images.length,
510          original = this.images.join();
511
512      if (!i) {
513        return;
514      }
515
516      while (i) {
517        j = Math.floor(Math.random() * i);
518        t = this.images[--i];
519        this.images[i] = this.images[j];
520        this.images[j] = t;
521      }
522
523      if (this.images.join() === original) {
524        this.shuffle();
525      }
526    },
527
528    /**
529     * Get the image from index
530     *
531     * @param {number} index
532     * @returns {string}
533     */
534    get: function(index) {
535      return this.images[index];
536    },
537
538    /**
539     * Get the URL with function of CSS
540     *
541     * @param {number} index
542     * @returns {string}
543     */
544    url: function(index) {
545      return 'url(' + this.get(index) + ')';
546    },
547
548    /**
549     * Count of images
550     *
551     * @returns {number}
552     */
553    count: function() {
554      return this.images.length;
555    }
556  });
557
558  $.BgSwitcher = BgSwitcher;
559}(jQuery));

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.