PageSourceSearch

https://dtpia.co.kr/common/v2/js/jquery.magnify.js

js dtpia.co.kr collected 2026-10-06 03:26:41 UTC 14,961 bytes, 343 lines download raw bytes

vendor: 14,961 bytes, lines 1-343
1/*!
2 * jQuery Magnify Plugin v2.3.3 by T. H. Doan (https://thdoan.github.io/magnify/)
3 * Based on http://thecodeplayer.com/walkthrough/magnifying-glass-for-images-using-jquery-and-css3
4 *
5 * jQuery Magnify by T. H. Doan is licensed under the MIT License.
6 * Read a copy of the license in the LICENSE file or at https://choosealicense.com/licenses/mit/
7 */
8
9(function($) {
10  $.fn.magnify = function(oOptions) {
11    // Default options
12    oOptions = $.extend({
13      'src': '',
14      'speed': 100,
15      'timeout': -1,
16      'touchBottomOffset': 0,
17      'finalWidth': null,
18      'finalHeight': null,
19      'magnifiedWidth': null,
20      'magnifiedHeight': null,
21      'limitBounds': false,
22      'mobileCloseEvent': 'touchstart',
23      'afterLoad': function(){}
24    }, oOptions);
25
26    var $that = this, // Preserve scope
27      $html = $('html'),
28
29      // Initiate
30      init = function(el) {
31        var $image = $(el),
32          $anchor = $image.closest('a'),
33          oDataAttr = {};
34
35        // Get data attributes
36        for (var i in oOptions) {
37          oDataAttr[i] = $image.attr('data-magnify-' + i.toLowerCase());
38        }
39
40        // Disable zooming if no valid large image source
41        var sZoomSrc = oDataAttr['src'] || oOptions['src'] || $anchor.attr('href') || '';
42        if (!sZoomSrc) return;
43
44        var $container,
45          $lens,
46          nImageWidth,
47          nImageHeight,
48          nMagnifiedWidth,
49          nMagnifiedHeight,
50          nLensWidth,
51          nLensHeight,
52          nBoundX = 0,
53          nBoundY = 0,
54          nPosX, nPosY,     // Absolute cursor position
55          nX, nY,           // Relative cursor position
56          oContainerOffset, // Relative to document
57          oImageOffset,     // Relative to container
58          // Get true offsets
59          getOffset = function() {
60            var o = $container.offset();
61            // Store offsets from container border to image inside
62            // NOTE: .offset() does NOT take into consideration image border and padding.
63            oImageOffset = {
64              'top': ($image.offset().top-o.top) + parseInt($image.css('border-top-width')) + parseInt($image.css('padding-top')),
65              'left': ($image.offset().left-o.left) + parseInt($image.css('border-left-width')) + parseInt($image.css('padding-left'))
66            };
67            o.top += oImageOffset['top'];
68            o.left += oImageOffset['left'];
69            return o;
70          },
71          // Hide the lens
72          hideLens = function() {
73            if ($lens.is(':visible')) $lens.fadeOut(oOptions['speed'], function() {
74              $html.removeClass('magnifying').trigger('magnifyend'); // Reset overflow-x
75            });
76          },
77          moveLens = function(e) {
78            // Reinitialize if image initially hidden
79            if (!nImageHeight) {
80              refresh();
81              return;
82            }
83            if (e) {
84              e.preventDefault();
85              // Save last coordinates in case we need to call this function directly (required when
86              // updating magnifiedWidth/magnifiedHeight while the lens is visible).
87              nPosX = e.pageX || e.originalEvent.touches[0].pageX;
88              nPosY = e.pageY || e.originalEvent.touches[0].pageY;
89              $image.data('lastPos', {
90                'x': nPosX,
91                'y': nPosY
92              });
93            } else {
94              nPosX = $image.data('lastPos').x;
95              nPosY = $image.data('lastPos').y;
96            }
97            // x/y coordinates of the mouse pointer or touch point. This is the position of
98            // .magnify relative to the document.
99            //
100            // We deduct the positions of .magnify from the mouse or touch positions relative to
101            // the document to get the mouse or touch positions relative to the container.
102            nX = nPosX - oContainerOffset['left'],
103            nY = (nPosY - oContainerOffset['top']) - oOptions['touchBottomOffset'];
104            // Toggle magnifying lens
105            if (!$lens.is(':animated')) {
106              if (nX>nBoundX && nX<nImageWidth-nBoundX && nY>nBoundY && nY<nImageHeight-nBoundY) {
107                if ($lens.is(':hidden')) {
108                  $html.addClass('magnifying').trigger('magnifystart'); // Hide overflow-x while zooming
109                  $lens.fadeIn(oOptions['speed']);
110                }
111              } else {
112                hideLens();
113              }
114            }
115            if ($lens.is(':visible')) {
116              // Move the magnifying lens with the mouse
117              var sBgPos = '';
118              if (nMagnifiedWidth && nMagnifiedHeight) {
119                // Change the background position of .magnify-lens according to the position of
120                // the mouse over the .magnify-image image. This allows us to get the ratio of
121                // the pixel under the mouse pointer with respect to the image and use that to
122                // position the large image inside the magnifying lens.
123                var nRatioX = -Math.round(nX/nImageWidth*nMagnifiedWidth-nLensWidth/2),
124                  nRatioY = -Math.round(nY/nImageHeight*nMagnifiedHeight-nLensHeight/2);
125                if (oOptions['limitBounds']) {
126                  // Enforce bounds to ensure only image is visible in lens
127                  var nBoundRight = -Math.round((nImageWidth-nBoundX)/nImageWidth*nMagnifiedWidth-nLensWidth/2),
128                    nBoundBottom = -Math.round((nImageHeight-nBoundY)/nImageHeight*nMagnifiedHeight-nLensHeight/2);
129                  // Left and right edges
130                  if (nRatioX>0) nRatioX = 0;
131                  else if (nRatioX<nBoundRight) nRatioX = nBoundRight;
132                  // Top and bottom edges
133                  if (nRatioY>0) nRatioY = 0;
134                  else if (nRatioY<nBoundBottom) nRatioY = nBoundBottom;
135                }
136                sBgPos = nRatioX + 'px ' + nRatioY + 'px';
137              }
138              // Now the lens moves with the mouse. The logic is to deduct half of the lens's
139              // width and height from the mouse coordinates to place it with its center at the
140              // mouse coordinates. If you hover on the image now, you should see the magnifying
141              // lens in action.
142              $lens.css({
143                'top': Math.round(nY-nLensHeight/2) + oImageOffset['top'] + 'px',
144                'left': Math.round(nX-nLensWidth/2) + oImageOffset['left'] + 'px',
145                'background-position': sBgPos
146              });
147            }
148          };
149
150        // Data attributes have precedence over options object
151        if (!isNaN(+oDataAttr['speed'])) oOptions['speed'] = +oDataAttr['speed'];
152        if (!isNaN(+oDataAttr['timeout'])) oOptions['timeout'] = +oDataAttr['timeout'];
153        if (!isNaN(+oDataAttr['finalWidth'])) oOptions['finalWidth'] = +oDataAttr['finalWidth'];
154        if (!isNaN(+oDataAttr['finalHeight'])) oOptions['finalHeight'] = +oDataAttr['finalHeight'];
155        if (!isNaN(+oDataAttr['magnifiedWidth'])) oOptions['magnifiedWidth'] = +oDataAttr['magnifiedWidth'];
156        if (!isNaN(+oDataAttr['magnifiedHeight'])) oOptions['magnifiedHeight'] = +oDataAttr['magnifiedHeight'];
157        if (oDataAttr['limitBounds']==='true') oOptions['limitBounds'] = true;
158        if (typeof window[oDataAttr['afterLoad']]==='function') oOptions.afterLoad = window[oDataAttr['afterLoad']];
159
160        // Implement touch point bottom offset only on mobile devices
161        if (/\b(Android|BlackBerry|IEMobile|iPad|iPhone|Mobile|Opera Mini)\b/.test(navigator.userAgent)) {
162          if (!isNaN(+oDataAttr['touchBottomOffset'])) oOptions['touchBottomOffset'] = +oDataAttr['touchBottomOffset'];
163        } else {
164          oOptions['touchBottomOffset'] = 0;
165        }
166
167        // Save any inline styles for resetting
168        $image.data('originalStyle', $image.attr('style'));
169
170        // Activate magnification:
171        // 1. Try to get large image dimensions
172        // 2. Proceed only if able to get large image dimensions OK
173
174        // [1] Calculate the native (magnified) image dimensions. The zoomed version is only shown
175        // after the native dimensions are available. To get the actual dimensions we have to create
176        // this image object.
177        var elZoomImage = new Image();
178        $(elZoomImage).on({
179          'load': function() {
180            // [2] Got image dimensions OK.
181
182            // Fix overlap bug at the edges during magnification
183            $image.css('display', 'block');
184            // Create container div if necessary
185            if (!$image.parent('.magnify').length) {
186              $image.wrap('<div class="magnify"></div>');
187            }
188            $container = $image.parent('.magnify');
189            // Create the magnifying lens div if necessary
190            if ($image.prev('.magnify-lens').length) {
191              $container.children('.magnify-lens').css('background-image', 'url(\'' + sZoomSrc + '\')');
192            } else {
193              $image.before('<div class="magnify-lens loading" style="background:url(\'' + sZoomSrc + '\') 0 0 no-repeat"></div>');
194            }
195            $lens = $container.children('.magnify-lens');
196            // Remove the "Loading..." text
197            $lens.removeClass('loading');
198            // Cache dimensions and offsets for improved performance
199            // NOTE: This code is inside the load() function, which is important. The width and
200            // height of the object would return 0 if accessed before the image is fully loaded.
201            nImageWidth = oOptions['finalWidth'] || $image.width();
202            nImageHeight = oOptions['finalHeight'] || $image.height();
203            nMagnifiedWidth = oOptions['magnifiedWidth'] || elZoomImage.width;
204            nMagnifiedHeight = oOptions['magnifiedHeight'] || elZoomImage.height;
205            nLensWidth = $lens.width();
206            nLensHeight = $lens.height();
207            oContainerOffset = getOffset(); // Required by refresh()
208            // Set zoom boundaries
209            if (oOptions['limitBounds']) {
210              nBoundX = (nLensWidth/2) / (nMagnifiedWidth/nImageWidth);
211              nBoundY = (nLensHeight/2) / (nMagnifiedHeight/nImageHeight);
212            }
213            // Enforce non-native large image size?
214            if (nMagnifiedWidth!==elZoomImage.width || nMagnifiedHeight!==elZoomImage.height) {
215              $lens.css('background-size', nMagnifiedWidth + 'px ' + nMagnifiedHeight + 'px');
216            }
217            // Store zoom dimensions for mobile plugin
218            $image.data('zoomSize', {
219              'width': nMagnifiedWidth,
220              'height': nMagnifiedHeight
221            });
222            // Store mobile close event for mobile plugin
223            $container.data('mobileCloseEvent', oDataAttr['mobileCloseEvent'] || oOptions['mobileCloseEvent']);
224            // Clean up
225            elZoomImage = null;
226            // Execute callback
227            oOptions.afterLoad();
228            // Simulate a lens move to update positioning if magnifiedWidth/magnifiedHeight is
229            // updated while the lens is visible
230            if ($lens.is(':visible')) moveLens();
231            // Handle mouse movements
232            $container.off().on({
233              'mousemove touchmove': moveLens,
234              'mouseenter': function() {
235                // Need to update offsets here to support accordions
236                oContainerOffset = getOffset();
237              },
238              'mouseleave': hideLens
239            });
240
241            // Prevent magnifying lens from getting "stuck"
242            if (oOptions['timeout']>=0) {
243              $container.on('touchend', function() {
244                setTimeout(hideLens, oOptions['timeout']);
245              });
246            }
247            // Ensure lens is closed when tapping outside of it
248            $('body').not($container).on('touchstart', hideLens);
249
250            // Support image map click-throughs while zooming
251            var sUsemap = $image.attr('usemap');
252            if (sUsemap) {
253              var $map = $('map[name=' + sUsemap.slice(1) + ']');
254              // Image map needs to be on the same DOM level as image source
255              $image.after($map);
256              $container.click(function(e) {
257                // Trigger click on image below lens at current cursor position
258                if (e.clientX || e.clientY) {
259                  $lens.hide();
260                  var elPoint = document.elementFromPoint(
261                      e.clientX || e.originalEvent.touches[0].clientX,
262                      e.clientY || e.originalEvent.touches[0].clientY
263                    );
264                  if (elPoint.nodeName==='AREA') {
265                    elPoint.click();
266                  } else {
267                    // Workaround for buggy implementation of elementFromPoint()
268                    // See https://bugzilla.mozilla.org/show_bug.cgi?id=1227469
269                    $('area', $map).each(function() {
270                      var a = $(this).attr('coords').split(',');
271                      if (nX>=a[0] && nX<=a[2] && nY>=a[1] && nY<=a[3]) {
272                        this.click();
273                        return false;
274                      }
275                    });
276                  }
277                }
278              });
279            }
280
281            if ($anchor.length) {
282              // Make parent anchor inline-block to have correct dimensions
283              $anchor.css('display', 'inline-block');
284              // Disable parent anchor if it's sourcing the large image
285              if ($anchor.attr('href') && !(oDataAttr['src'] || oOptions['src'])) {
286                $anchor.click(function(e) {
287                  e.preventDefault();
288                });
289              }
290            }
291
292          },
293          'error': function() {
294            // Clean up
295            elZoomImage = null;
296          }
297        });
298
299        elZoomImage.src = sZoomSrc;
300      }, // END init()
301
302      // Simple debounce
303      nTimer = 0,
304      refresh = function() {
305        clearTimeout(nTimer);
306        nTimer = setTimeout(function() {
307          $that.destroy();
308          $that.magnify(oOptions);
309        }, 100);
310      };
311
312    /**
313     * Public Methods
314     */
315
316    // Turn off zoom and reset to original state
317    this.destroy = function() {
318      this.each(function() {
319        var $this = $(this),
320          $lens = $this.prev('div.magnify-lens'),
321          sStyle = $this.data('originalStyle');
322        if ($this.parent('div.magnify').length && $lens.length) {
323          if (sStyle) $this.attr('style', sStyle);
324          else $this.removeAttr('style');
325          $this.unwrap();
326          $lens.remove();
327        }
328      });
329      // Unregister event handler
330      $(window).off('resize', refresh);
331      return $that;
332    }
333
334    // Handle window resizing
335    $(window).resize(refresh);
336
337    return this.each(function() {
338      // Initiate magnification powers
339      init(this);
340    });
341
342  };
343}(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.