PageSourceSearch

https://www.mejiro-mcqueen.com/common/js/jquery.backstretch.js

js mejiro-mcqueen.com collected 2026-10-06 20:12:42 UTC 12,560 bytes, 377 lines download raw bytes

1/*! Backstretch - v2.0.4 - 2013-06-19
2* http://srobbin.com/jquery-plugins/backstretch/
3* Copyright (c) 2013 Scott Robbin; Licensed MIT */
4
5;(function ($, window, undefined) {
6  'use strict';
7
8  /* PLUGIN DEFINITION
9   * ========================= */
10
11  $.fn.backstretch = function (images, options) {
12    // We need at least one image or method name
13    if (images === undefined || images.length === 0) {
14      $.error("No images were supplied for Backstretch");
15    }
16
17    /*
18     * Scroll the page one pixel to get the right window height on iOS
19     * Pretty harmless for everyone else
20    */
21    if ($(window).scrollTop() === 0 ) {
22      window.scrollTo(0, 0);
23    }
24
25    return this.each(function () {
26      var $this = $(this)
27        , obj = $this.data('backstretch');
28
29      // Do we already have an instance attached to this element?
30      if (obj) {
31
32        // Is this a method they're trying to execute?
33        if (typeof images == 'string' && typeof obj[images] == 'function') {
34          // Call the method
35          obj[images](options);
36
37          // No need to do anything further
38          return;
39        }
40
41        // Merge the old options with the new
42        options = $.extend(obj.options, options);
43
44        // Remove the old instance
45        obj.destroy(true);
46      }
47
48      obj = new Backstretch(this, images, options);
49      $this.data('backstretch', obj);
50    });
51  };
52
53  // If no element is supplied, we'll attach to body
54  $.backstretch = function (images, options) {
55    // Return the instance
56    return $('body')
57            .backstretch(images, options)
58            .data('backstretch');
59  };
60
61  // Custom selector
62  $.expr[':'].backstretch = function(elem) {
63    return $(elem).data('backstretch') !== undefined;
64  };
65
66  /* DEFAULTS
67   * ========================= */
68
69  $.fn.backstretch.defaults = {
70      centeredX: true   // Should we center the image on the X axis?
71    , centeredY: true   // Should we center the image on the Y axis?
72    , duration: 5000    // Amount of time in between slides (if slideshow)
73    , fade: 0           // Speed of fade transition between slides
74  };
75
76  /* STYLES
77   * 
78   * Baked-in styles that we'll apply to our elements.
79   * In an effort to keep the plugin simple, these are not exposed as options.
80   * That said, anyone can override these in their own stylesheet.
81   * ========================= */
82  var styles = {
83      wrap: {
84          left: 0
85        , top: 0
86        , overflow: 'hidden'
87        , margin: 0
88        , padding: 0
89        , height: '100%'
90        , width: '100%'
91        , zIndex: -999999
92      }
93    , img: {
94          position: 'absolute'
95        , display: 'none'
96        , margin: 0
97        , padding: 0
98        , border: 'none'
99        , width: 'auto'
100        , height: 'auto'
101        , maxHeight: 'none'
102        , maxWidth: 'none'
103        , zIndex: -999999
104      }
105  };
106
107  /* CLASS DEFINITION
108   * ========================= */
109  var Backstretch = function (container, images, options) {
110    this.options = $.extend({}, $.fn.backstretch.defaults, options || {});
111
112    /* In its simplest form, we allow Backstretch to be called on an image path.
113     * e.g. $.backstretch('/path/to/image.jpg')
114     * So, we need to turn this back into an array.
115     */
116    this.images = $.isArray(images) ? images : [images];
117
118    // Preload images
119    $.each(this.images, function () {
120      $('<img />')[0].src = this;
121    });    
122
123    // Convenience reference to know if the container is body.
124    this.isBody = container === document.body;
125
126    /* We're keeping track of a few different elements
127     *
128     * Container: the element that Backstretch was called on.
129     * Wrap: a DIV that we place the image into, so we can hide the overflow.
130     * Root: Convenience reference to help calculate the correct height.
131     */
132    this.$container = $(container);
133    this.$root = this.isBody ? supportsFixedPosition ? $(window) : $(document) : this.$container;
134
135    // Don't create a new wrap if one already exists (from a previous instance of Backstretch)
136    var $existing = this.$container.children(".backstretch").first();
137    this.$wrap = $existing.length ? $existing : $('<div class="backstretch"></div>').css(styles.wrap).appendTo(this.$container);
138
139    // Non-body elements need some style adjustments
140    if (!this.isBody) {
141      // If the container is statically positioned, we need to make it relative,
142      // and if no zIndex is defined, we should set it to zero.
143      var position = this.$container.css('position')
144        , zIndex = this.$container.css('zIndex');
145
146      this.$container.css({
147          position: position === 'static' ? 'relative' : position
148        , zIndex: zIndex === 'auto' ? 0 : zIndex
149        , background: 'none'
150      });
151      
152      // Needs a higher z-index
153      this.$wrap.css({zIndex: -999998});
154    }
155
156    // Fixed or absolute positioning?
157    this.$wrap.css({
158      position: this.isBody && supportsFixedPosition ? 'fixed' : 'absolute'
159    });
160
161    // Set the first image
162    this.index = 0;
163    this.show(this.index);
164
165    // Listen for resize
166    $(window).on('resize.backstretch', $.proxy(this.resize, this))
167             .on('orientationchange.backstretch', $.proxy(function () {
168                // Need to do this in order to get the right window height
169                if (this.isBody && window.pageYOffset === 0) {
170                  window.scrollTo(0, 1);
171                  this.resize();
172                }
173             }, this));
174  };
175
176  /* PUBLIC METHODS
177   * ========================= */
178  Backstretch.prototype = {
179      resize: function () {
180        try {
181          var bgCSS = {left: 0, top: 0}
182            , rootWidth = this.isBody ? this.$root.width() : this.$root.innerWidth()
183            , bgWidth = rootWidth
184            , rootHeight = this.isBody ? ( window.innerHeight ? window.innerHeight : this.$root.height() ) : this.$root.innerHe
184ight()
185            , bgHeight = bgWidth / this.$img.data('ratio')
186            , bgOffset;
187
188            // Make adjustments based on image ratio
189            if (bgHeight >= rootHeight) {
190                bgOffset = (bgHeight - rootHeight) / 2;
191                if(this.options.centeredY) {
192                  bgCSS.top = '-' + bgOffset + 'px';
193                }
194            } else {
195                bgHeight = rootHeight;
196                bgWidth = bgHeight * this.$img.data('ratio');
197                bgOffset = (bgWidth - rootWidth) / 2;
198                if(this.options.centeredX) {
199                  bgCSS.left = '-' + bgOffset + 'px';
200                }
201            }
202
203            this.$wrap.css({width: rootWidth, height: rootHeight})
204                      .find('img:not(.deleteable)').css({width: bgWidth, height: bgHeight}).css(bgCSS);
205        } catch(err) {
206            // IE7 seems to trigger resize before the image is loaded.
207            // This try/catch block is a hack to let it fail gracefully.
208        }
209
210        return this;
211      }
212
213      // Show the slide at a certain position
214    , show: function (newIndex) {
215
216        // Validate index
217        if (Math.abs(newIndex) > this.images.length - 1) {
218          return;
219        }
220
221        // Vars
222        var self = this
223          , oldImage = self.$wrap.find('img').addClass('deleteable')
224          , evtOptions = { relatedTarget: self.$container[0] };
225
226        // Trigger the "before" event
227        self.$container.trigger($.Event('backstretch.before', evtOptions), [self, newIndex]); 
228
229        // Set the new index
230        this.index = newIndex;
231
232        // Pause the slideshow
233        clearInterval(self.interval);
234
235        // New image
236        self.$img = $('<img />')
237                      .css(styles.img)
238                      .bind('load', function (e) {
239                        var imgWidth = this.width || $(e.target).width()
240                          , imgHeight = this.height || $(e.target).height();
241                        
242                        // Save the ratio
243                        $(this).data('ratio', imgWidth / imgHeight);
244
245                        // Show the image, then delete the old one
246                        // "speed" option has been deprecated, but we want backwards compatibilty
247                        $(this).fadeIn(self.options.speed || self.options.fade, function () {
248                          oldImage.remove();
249
250                          // Resume the slideshow
251                          if (!self.paused) {
252                            self.cycle();
253                          }
254
255                          // Trigger the "after" and "show" events
256                          // "show" is being deprecated
257                          $(['after', 'show']).each(function () {
258                            self.$container.trigger($.Event('backstretch.' + this, evtOptions), [self, newIndex]);
259                          });
260                        });
261
262                        // Resize
263                        self.resize();
264                      })
265                      .appendTo(self.$wrap);
266
267        // Hack for IE img onload event
268        self.$img.attr('src', self.images[newIndex]);
269        return self;
270      }
271
272    , next: function () {
273        // Next slide
274        return this.show(this.index < this.images.length - 1 ? this.index + 1 : 0);
275      }
276
277    , prev: function () {
278        // Previous slide
279        return this.show(this.index === 0 ? this.images.length - 1 : this.index - 1);
280      }
281
282    , pause: function () {
283        // Pause the slideshow
284        this.paused = true;
285        return this;
286      }
287
288    , resume: function () {
289        // Resume the slideshow
290        this.paused = false;
291        this.next();
292        return this;
293      }
294
295    , cycle: function () {
296        // Start/resume the slideshow
297        if(this.images.length > 1) {
298          // Clear the interval, just in case
299          clearInterval(this.interval);
300
301          this.interval = setInterval($.proxy(function () {
302            // Check for paused slideshow
303            if (!this.paused) {
304              this.next();
305            }
306          }, this), this.options.duration);
307        }
308        return this;
309      }
310
vendor: 2,463 bytes, lines 311-377
311    , destroy: function (preserveBackground) {
312        // Stop the resize events
313        $(window).off('resize.backstretch orientationchange.backstretch');
314
315        // Clear the interval
316        clearInterval(this.interval);
317
318        // Remove Backstretch
319        if(!preserveBackground) {
320          this.$wrap.remove();          
321        }
322        this.$container.removeData('backstretch');
323      }
324  };
325
326  /* SUPPORTS FIXED POSITION?
327   *
328   * Based on code from jQuery Mobile 1.1.0
329   * http://jquerymobile.com/
330   *
331   * In a nutshell, we need to figure out if fixed positioning is supported.
332   * Unfortunately, this is very difficult to do on iOS, and usually involves
333   * injecting content, scrolling the page, etc.. It's ugly.
334   * jQuery Mobile uses this workaround. It's not ideal, but works.
335   *
336   * Modified to detect IE6
337   * ========================= */
338
339  var supportsFixedPosition = (function () {
340    var ua = navigator.userAgent
341      , platform = navigator.platform
342        // Rendering engine is Webkit, and capture major version
343      , wkmatch = ua.match( /AppleWebKit\/([0-9]+)/ )
344      , wkversion = !!wkmatch && wkmatch[ 1 ]
345      , ffmatch = ua.match( /Fennec\/([0-9]+)/ )
346      , ffversion = !!ffmatch && ffmatch[ 1 ]
347      , operammobilematch = ua.match( /Opera Mobi\/([0-9]+)/ )
348      , omversion = !!operammobilematch && operammobilematch[ 1 ]
349      , iematch = ua.match( /MSIE ([0-9]+)/ )
350      , ieversion = !!iematch && iematch[ 1 ];
351
352    return !(
353      // iOS 4.3 and older : Platform is iPhone/Pad/Touch and Webkit version is less than 534 (ios5)
354      ((platform.indexOf( "iPhone" ) > -1 || platform.indexOf( "iPad" ) > -1  || platform.indexOf( "iPod" ) > -1 ) && wkversion && wkversion < 534) ||
355      
356      // Opera Mini
357      (window.operamini && ({}).toString.call( window.operamini ) === "[object OperaMini]") ||
358      (operammobilematch && omversion < 7458) ||
359      
360      //Android lte 2.1: Platform is Android and Webkit version is less than 533 (Android 2.2)
361      (ua.indexOf( "Android" ) > -1 && wkversion && wkversion < 533) ||
362      
363      // Firefox Mobile before 6.0 -
364      (ffversion && ffversion < 6) ||
365      
366      // WebOS less than 3
367      ("palmGetResource" in window && wkversion && wkversion < 534) ||
368      
369      // MeeGo
370      (ua.indexOf( "MeeGo" ) > -1 && ua.indexOf( "NokiaBrowser/8.5.0" ) > -1) ||
371      
372      // IE6
373      (ieversion && ieversion <= 6)
374    );
375  }());
376
377}(jQuery, window));

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.