PageSourceSearch

https://www.chestnutparkprofessionals.com/themes/common/javascript…/imagescale/js/image-scale.js?v.c08368

js chestnutparkprofessionals.com collected 2026-10-05 01:01:10 UTC 15,345 bytes, 532 lines download raw bytes

1// ==========================================================================
2// Project:     Image Scale
3// Description: Scale images to fit or fill any target size via two simple properties: scale and align.
4// Copyright:   ©2012-2016 GestiXi
5// License:     Licensed under the MIT license (see LICENCE)
6// Version:     2.2
7// Author:      Nicolas BADIA
8// ==========================================================================
9
10// Uses CommonJS, AMD or browser globals to create a jQuery plugin.
11(function(factory) {
12  if (typeof define === 'function' && define.amd) {
13    // AMD. Register as an anonymous module.
14    define(['jquery'], factory);
15  } 
16  else if (typeof module === 'object' && module.exports) {
17    // Node/CommonJS
18    module.exports = function( root, jQuery ) {
19      if ( jQuery === undefined ) {
20        // require('jQuery') returns a factory that requires window to
21        // build a jQuery instance, we normalize how we use modules
22        // that require this pattern but the window provided is a noop
23        // if it's defined (how jquery works)
24        if (typeof window !== 'undefined') {
25          jQuery = require('jquery');
26        }
27        else {
28          jQuery = require('jquery')(root);
29        }
30      }
31      factory(jQuery);
32      return jQuery;
33    };
34  } 
35  else {
36    // Browser globals
37    factory(jQuery);
38  }
39}(function($) {
40
41  "use strict";
42
43  // ..........................................................
44  // IMAGE SCALE PLUGIN DEFINITION
45  //
46
47  $.fn.imageScale = function( options ) {
48
49    return this.each(function() {
50      var that = this,
51        $this = $(this),
52        data = $this.data('imageScale'),
53        $img = this.tagName === 'IMG' ? $this : $this.find("img");
54
55      if (!data) {
56        var didLoad = $img[0].complete,
57            formattedOpt = $.extend({}, $.fn.imageScale.defaults, typeof options == 'object' && options),
58
59            loadFunc = function() {
60              $this.data('imageScale', (data = new ImageScale(that, formattedOpt)));
61
62              data.scale(true, formattedOpt);
63            };
64
65        if (didLoad) {
66          loadFunc.apply($this[0]);
67        }
68        else {
69          $img.on("load", loadFunc).attr("src", $img.attr("src"));
70        }
71      }
72      else {
73        if (typeof options == 'string') data[options]();
74        else if (typeof options == 'object') {
75          var method = options.method || 'scale';
76          data[method](false, options);
77        }
78        else data.scale();
79      }
80    })
81  }
82
83  $.fn.imageScale.defaults = {
84    /**
85      Determines how the image will scale to fit within its containing space. Possible values:
86
87      * **fill** - stretches or compresses the source image to fill the target frame
88      * **best-fill** - fits the shortest side of the source image within the target frame while maintaining the original aspect ratio
89      * **best-fit** - fits the longest edge of the source image within the target frame while maintaining the original aspect ratio
90      * **best-fit-down** - same as *best-fit* but will not stretch the source if it is smaller than the target
91      * **none** - the source image is left unscaled
92
93      @type String
94      @default best-fill
95      @since Version 1.2
96    */
97    scale: 'best-fill',
98
99    /**
100      Align the image within its frame. Possible values:
101
102      * **left**
103      * **right**
104      * **center**
105      * **top**
106      * **bottom**
107      * **top-left**
108      * **top-right**
109      * **bottom-left**
110      * **bottom-right**
111
112      @type String
113      @default center
114      @since Version 1.2
115    */
116    align: 'center',
117
118    /**
119      A jQuery Object against which the image size will be calculated.
120      If null, the parent of the image will be used.
121
122      @type jQuery Object
123      @default null
124      @since Version 1.0
125    */
126    parent: null,
127
128    /**
129      A boolean determining if the parent should hide its overflow.
130
131      @type Boolean
132      @default true
133      @since Version 1.0
134    */
135    hideParentOverflow: true,
136
137    /**
138      A duration in milliseconds determining how long the fadeIn animation will run when your image is scale for the firstTime.
139
140      Set it to 0 if you don't want any animation.
141
142      @type Number|String
143      @default 0
144      @since Version 1.1
145    */
146    fadeInDuration: 0,
147
148    /**
149      A boolean indicating if the image size should be rescaled when the window is resized.
150
151      The window size is checked using requestAnimationFrame for good performance.
152
153      Example:
154
155          $images.imageScale({ 
156            rescaleOnResize: true
157          });
158      
159      @type Boolean
160      @default false
161      @since Version 1.0
162    */
163    rescaleOnResize: false,
164
165    /**
166      A function that will be call each time the receiver is scaled.
167
168      Example:
169
170          $images.imageScale({
171            didScale: function() {
172              console.log('did scale img: ', this.element);
173            }
174          });
175
176      @type Function
177      @param firstTime {Boolean} true if the image was scale for the first time.
178      @param options {Object} the options passed to the scale method.
179      @since Version 2.0
180    */
181    didScale: function(firstTime, options) {},
182
183    /**
184      A number indicating the log level :
185
186      0: silent
187      1: error
188      2: error & warning
189      3: error & warning & notice
190
191      @type Number
192      @default 0
193      @since Version 1.0
194    */
195    logLevel: 0
196  }
197
198  // ..........................................................
199  // IMAGE SCALE PUBLIC CLASS DEFINITION
200  //
201
202  var ImageScale = function(element, options) {
203    var that = this;
204    that.options = options;
205    that.element = element;
206
207    var $element = that.$element = $(element),
208      $img = that.$img = element.tagName === 'IMG' ? $element : $element.find("img"),
209      img = that.img = $img[0];
210
211    that.src = $img.attr('src');
212
213    that.imgWidth = img.naturalWidth || img.width;
214    that.imgHeight = img.naturalHeight || img.height;
215
216    var $parent = that.$parent = options.parent?options.parent:$($element.parent()[0]);
217    that.parent = $parent[0];
218
219    // Fixes: https://github.com/gestixi/image-scale/issues/1
220    if ($parent.css('position') === 'static') {
221      $parent.css('position', 'relative');
222    }
223
224    if (options.rescaleOnResize) {
225      $(window).resize(function(e) { that.scheduleScale(); });
226    }
227  }
228
229  $.fn.imageScale.Constructor = ImageScale;
230
231  ImageScale.prototype = {
232
233    NONE: "none",
234    FILL: "fill",
235    BEST_FILL: "best-fill",
236    BEST_FIT: "best-fit",
237    BEST_FIT_DOWN_ONLY: "best-fit-down",
238
239    ALIGN_LEFT: 'left',
240    ALIGN_RIGHT: 'right',
241    ALIGN_CENTER: 'center',
242    ALIGN_TOP: 'top',
243    ALIGN_BOTTOM: 'bottom',
244    ALIGN_TOP_LEFT: 'top-left',
245    ALIGN_TOP_RIGHT: 'top-right',
246    ALIGN_BOTTOM_LEFT: 'bottom-left',
247    ALIGN_BOTTOM_RIGHT: 'bottom-right',
248
249    constructor: ImageScale,
250
251    /**
252      The initial element.
253
254      @type DOM Element
255    */
256    element: null,
257
258    /**
259      The passed options.
260
261      @type Object
262    */
263    options: null,
264
265    /**
266      Main method. Used to scale the images.
267
268      When `rescaleOnResize` is set to true, this method is executed each time the
269      windows size changes.
270
271      If `rescaleOnResize` is set to false, you may want to call it manually. Here is an
272      example on how you should do it:
273
274          $image.imageScale('scale');
275
276
277      @param {Boolean} firstTime
278    */
279    scale: function(firstTime, opt) {
280      if (this._isDestroyed || this._canScale === false) return;
281
282      var that = this,
283          options = this.options,
284          $parent = this.$parent,
285          element = this.element,
286          $element = this.$element,
287          img = this.img,
288          $img = this.$img;
289
290      if (firstTime) {
291        if (options.hideParentOverflow) {
292          $parent.css({ overflow: 'hidden' });
293        }
294      }
295      else {
296        // If the source of the image has changed
297        if (this.src !== $img.attr('src')) {
298          this.destroy();
299          $element.data('imageScale', null);
300          $element.imageScale(options);
301          return;
302        }
303      }
304
305      this._didScheduleScale = false;
306
307      if (options.rescaleOnResize && !opt) {
308        if (!this._needUpdate(this.parent)) return;
309      }
310      opt = opt ? opt : {};
311
312      var transition = opt.transition;
313      if (transition) {
314        this._canScale = false;
315        $element.css('transition', 'all '+transition+'ms');
316
317        setTimeout(function() {
318          that._canScale = null;
319          $element.css('transition', 'null');
320        }, transition);
321      }
322
323      var destWidth = opt.destWidth ? opt.destWidth : $parent.outerWidth(),
324          destHeight = opt.destHeight ? opt.destHeight : $parent.outerHeight(),
325
326          destInnerWidth = opt.destWidth ? opt.destWidth : $parent.innerWidth(),
327          destInnerHeight = opt.destHeight ? opt.destHeight : $parent.innerHeight(),
328
329          widthOffset = destWidth - destInnerWidth,
330          heightOffset = destHeight - destInnerHeight,
331
332          scaleData = $element.attr('data-scale'),
333          alignData = $element.attr('data-align'),
334
335          scale = scaleData?scaleData:options.scale,
336          align = alignData?alignData:options.align,
337
338          fadeInDuration = options.fadeInDuration;
339
340      if (!scale) {
341        if (options.logLevel > 2) {
342          console.log("imageScale - DEBUG NOTICE: The scale property is null.", element);
343        }
344        return;
345      }
346
347      if (this._cacheDestWidth === destWidth && this._cacheDestHeight === destHeight) {
348        if (options.logLevel > 2) {
349          console.log("imageScale - DEBUG NOTICE: The parent size hasn't changed: dest width: '"+destWidth+"' - dest height: '"+destHeight+"'.", element);
350        }
351      }
352
353      var sourceWidth = this.imgWidth,
354          sourceHeight = this.imgHeight;
355
356      if (!(destWidth && destHeight && sourceWidth && sourceHeight)) {
357        if (options.logLevel > 0) {
358          console.error("imageScale - DEBUG ERROR: The dimensions are incorrect: source width: '"+sourceWidth+"' - source height: '"+sourceHeight+"' - dest width: '"+destWidth+"' - dest height: '"+destHeight+"'.", element);
359        }
360        return;
361      }
362
363      this._cacheDestWidth = destWidth;
364      this._cacheDestHeight = destHeight;
365
366      var layout = this._innerFrameForSize(scale, align, sourceWidth, sourceHeight, destWidth, destHeight);
367
368      if (widthOffset) layout.x -= widthOffset/2;
369      if (heightOffset) layout.y -= heightOffset/2;
370
371      $element.css({ position: 'absolute', top: layout.y+'px', left: layout.x+'px', width: layout.width+'px', height: layout.height+'px', 'max-width': 'none' });
372
373      if (firstTime && fadeInDuration) {
374        $element.css({ display: 'none' });
375        $element.fadeIn(fadeInDuration);
376      }
377
378      options.didScale.call(this, firstTime, opt);
379    },
380
381    /**
382      Removes the data from the element.
383
384      Here is an example on how you can call the destroy method:
385
386          $image.imageScale('destroy');
387
388    */
389    destroy: function() {
390      this._isDestroyed = true;
391      this.$element.removeData('imageScale');
392    },
393
394    /**
395      @private
396
397      Returns a frame (x, y, width, height) fitting the source size (sourceWidth & sourceHeight) within the
398      destination size (destWidth & destHeight) according to the align and scale properties.
399
400      @param {String} scale
401      @param {String} align
402      @param {Number}
402 sourceWidth
403      @param {Number} sourceHeight
404      @param {Number} destWidth
405      @param {Number} destHeight
406      @returns {Object} the inner frame with properties: { x: value, y: value, width: value, height: value }
407    */
408    _innerFrameForSize: function(scale, align, sourceWidth, sourceHeight, destWidth, destHeight) {
409      var scaleX,
410          scaleY,
411          result;
412
413      // Fast path
414      result = { x: 0, y: 0, width: destWidth, height: destHeight };
415      if (scale === this.FILL) return result;
416
417      // Determine the appropriate scale
418      scaleX = destWidth / sourceWidth;
419      scaleY = destHeight / sourceHeight;
420
421      switch (scale) {
422        case this.BEST_FIT_DOWN_ONLY:
423          if (scale !== this.BEST_FIT_DOWN_ONLY && this.options.logLevel > 1) {
424            console.warn("imageScale - DEBUG WARNING: The scale '"+scale+"' was not understood.");
425          }
426
427          if ((sourceWidth > destWidth) || (sourceHeight > destHeight)) {
428            scale = scaleX < scaleY ? scaleX : scaleY;
429          } else {
430            scale = 1.0;
431          }
432          break;
433        case this.BEST_FIT:
434          scale = scaleX < scaleY ? scaleX : scaleY;
435          break;
436        case this.NONE:
437          scale = 1.0;
438          break;
439        //case this.BEST_FILL:
440        default:
441          scale = scaleX > scaleY ? scaleX : scaleY;
442          break;
443      }
444
445      sourceWidth *= scale;
446      sourceHeight *= scale;
447      result.width = Math.round(sourceWidth);
448      result.height = Math.round(sourceHeight);
449
450      // Align the image within its frame
451      switch (align) {
452        case this.ALIGN_LEFT:
453          result.x = 0;
454          result.y = (destHeight / 2) - (sourceHeight / 2);
455          break;
456        case this.ALIGN_RIGHT:
457          result.x = destWidth - sourceWidth;
458          result.y = (destHeight / 2) - (sourceHeight / 2);
459          break;
460        case this.ALIGN_TOP:
461          result.x = (destWidth / 2) - (sourceWidth / 2);
462          result.y = 0;
463          break;
464        case this.ALIGN_BOTTOM:
465          result.x = (destWidth / 2) - (sourceWidth / 2);
466          result.y = destHeight - sourceHeight;
467          break;
468        case this.ALIGN_TOP_LEFT:
469          result.x = 0;
470          result.y = 0;
471          break;
472        case this.ALIGN_TOP_RIGHT:
473          result.x = destWidth - sourceWidth;
474          result.y = 0;
475          break;
476        case this.ALIGN_BOTTOM_LEFT:
477          result.x = 0;
478          result.y = destHeight - sourceHeight;
479          break;
480        case this.ALIGN_BOTTOM_RIGHT:
481          result.x = destWidth - sourceWidth;
482          result.y = destHeight - sourceHeight;
483          break;
484        default: // this.ALIGN_CENTER
485          if (align !== this.ALIGN_CENTER && this.options.logLevel > 1) {
486            console.warn("imageScale - DEBUG WARNING: The align '"+align+"' was not understood.");
487          }
488          result.x = (destWidth / 2) - (sourceWidth / 2);
489          result.y = (destHeight / 2) - (sourceHeight / 2);
490      }
491
492      return result;
493    },
494
495    /**
496      @private
497
498      Determines if the windows size has changed since the last update.
499
500      @returns {Boolean}
501    */
502    _needUpdate: function(parent) {
503      var size = parent.clientHeight + ' ' + parent.clientWidth;
504
505      if (this._lastParentSize !== size) {
506        this._lastParentSize = size;
507        return true;
508      }
509      return false;
510    },
511
512    /**
513      @private
514
515      Schedule a scale update.
516    */
517    scheduleScale: function() {
518      if (this._didScheduleScale) return;
519
520      if (window.requestAnimationFrame) {
521        var that = this;
522        this._didScheduleScale = true;
523        // setTimeout important when resizing down if the scrollbar were visible
524        requestAnimationFrame(function() { setTimeout(function() { that.scale(); }, 0); });
525      }
526      else {
527        this.scale();
528      }
529    }
530  }
531
532}));

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.