summaryrefslogtreecommitdiff
path: root/javascript
diff options
context:
space:
mode:
authorspider@dev <spiderr@bitweaver.org>2017-10-17 17:23:27 -0400
committerspider@dev <spiderr@bitweaver.org>2017-10-17 17:23:27 -0400
commitfc444f43863abbe6bbd0102f7ed995df0f57ecf0 (patch)
tree674c542ea07022b62a11f17234e3074216bba315 /javascript
parent64e621c271529330c7716178180a126d3f30a441 (diff)
downloadutil-fc444f43863abbe6bbd0102f7ed995df0f57ecf0.tar.gz
util-fc444f43863abbe6bbd0102f7ed995df0f57ecf0.tar.bz2
util-fc444f43863abbe6bbd0102f7ed995df0f57ecf0.zip
add magnify jquery plugin
Diffstat (limited to 'javascript')
-rw-r--r--javascript/jquery/plugins/magnify/jquery.magnify-mobile.js101
-rw-r--r--javascript/jquery/plugins/magnify/jquery.magnify.js315
-rw-r--r--javascript/jquery/plugins/magnify/magnify.css60
3 files changed, 476 insertions, 0 deletions
diff --git a/javascript/jquery/plugins/magnify/jquery.magnify-mobile.js b/javascript/jquery/plugins/magnify/jquery.magnify-mobile.js
new file mode 100644
index 0000000..f54c52c
--- /dev/null
+++ b/javascript/jquery/plugins/magnify/jquery.magnify-mobile.js
@@ -0,0 +1,101 @@
+/*!
+ * Mobile plugin for jQuery Magnify (http://thdoan.github.io/magnify/)
+ *
+ * jQuery Magnify by T. H. Doan is licensed under the MIT License.
+ * Read a copy of the license in the LICENSE file or at http://choosealicense.com/licenses/mit
+ */
+
+(function($) {
+ // Ensure this is loaded after jquery.magnify.js
+ if (!$.fn.magnify) return;
+ // Add required CSS
+ $('<style>' +
+ '.lens-mobile {' +
+ 'position:fixed;' +
+ 'top:0;' +
+ 'left:0;' +
+ 'width:100%;' +
+ 'height:100%;' +
+ 'background:#ccc;' +
+ 'display:none;' +
+ 'overflow:scroll;' +
+ '-webkit-overflow-scrolling:touch;' +
+ 'z-index:9999;' +
+ '}' +
+ '.magnify-mobile>.close {' +
+ 'position:fixed;' +
+ 'top:10px;' +
+ 'right:10px;' +
+ 'width:32px;' +
+ 'height:32px;' +
+ 'background:#333;' +
+ 'border-radius:16px;' +
+ 'color:#fff;' +
+ 'display:inline-block;' +
+ 'font:normal bold 20px/32px sans-serif;' +
+ 'letter-spacing:0;' +
+ 'opacity:0.8;' +
+ 'text-align:center;' +
+ 'text-shadow:none;' +
+ 'z-index:9999;' +
+ '}' +
+ '@media only screen and (min-device-width:320px) and (max-device-width:773px) {' +
+ '/* Assume QHD (1440 x 2560) is highest mobile resolution */' +
+ '.lens-mobile { display:block; }' +
+ '}' +
+ '</style>').appendTo('head');
+ // Ensure .magnify is rendered
+ $(window).on('load', function() {
+ $('body').append('<div class="magnify-mobile"><div class="lens-mobile"></div></div>');
+ var $lensMobile = $('.lens-mobile');
+ // Only enable mobile zoom on smartphones
+ if ($lensMobile.is(':visible') && !!('ontouchstart' in window || (window.DocumentTouch && document instanceof DocumentTouch) || navigator.msMaxTouchPoints)) {
+ var $magnify = $('.magnify'),
+ $magnifyMobile = $('.magnify-mobile');
+ // Disable desktop magnifying lens
+ $magnify.off();
+ // Initiate mobile zoom
+ // NOTE: Fixed elements inside a scrolling div have issues in iOS, so we need to insert the
+ // close icon at the same level as the lens.
+ $magnifyMobile.hide().append('<i class="close">&times;</i>');
+ // Hook up event handlers
+ $magnifyMobile.children('.close').on('touchstart', function() {
+ $magnifyMobile.toggle();
+ });
+ $magnify.children('img').on({
+ 'touchend': function() {
+ // Only execute on tap
+ if ($(this).data('drag')) return;
+ var oScrollOffset = $(this).data('scrollOffset');
+ $magnifyMobile.toggle();
+ // Zoom into touch point
+ $lensMobile.scrollLeft(oScrollOffset.x);
+ $lensMobile.scrollTop(oScrollOffset.y);
+ },
+ 'touchmove': function() {
+ // Set drag state
+ $(this).data('drag', true);
+ },
+ 'touchstart': function(e) {
+ // Render zoom image
+ // NOTE: In iOS background-image is url(...), not url("...").
+ $lensMobile.html('<img src="' + $(this).prev('.magnify-lens').css('background-image').replace(/url\(["']?|["']?\)/g, '') + '" alt="">');
+ // Determine zoom position
+ var $magnifyImage = $(this),
+ oZoomSize = $magnifyImage.data('zoomSize'),
+ nX = e.originalEvent.touches[0].pageX - $magnifyImage.offset().left,
+ nXPct = nX / $magnifyImage.width(),
+ nY = e.originalEvent.touches[0].pageY - $magnifyImage.offset().top,
+ nYPct = nY / $magnifyImage.height();
+ // Store scroll offsets
+ $magnifyImage.data('scrollOffset', {
+ 'x': (oZoomSize.width*nXPct)-(window.innerWidth/2),
+ 'y': (oZoomSize.height*nYPct)-(window.innerHeight/2)
+ });
+ // Reset drag state
+ $(this).data('drag', false);
+ }
+ });
+ }
+ });
+}(jQuery));
diff --git a/javascript/jquery/plugins/magnify/jquery.magnify.js b/javascript/jquery/plugins/magnify/jquery.magnify.js
new file mode 100644
index 0000000..c1670e0
--- /dev/null
+++ b/javascript/jquery/plugins/magnify/jquery.magnify.js
@@ -0,0 +1,315 @@
+/*!
+ * jQuery Magnify Plugin v2.1.0 by T. H. Doan (http://thdoan.github.io/magnify/)
+ * Based on http://thecodeplayer.com/walkthrough/magnifying-glass-for-images-using-jquery-and-css3
+ *
+ * jQuery Magnify by T. H. Doan is licensed under the MIT License.
+ * Read a copy of the license in the LICENSE file or at http://choosealicense.com/licenses/mit
+ */
+
+(function($) {
+ $.fn.magnify = function(oOptions) {
+ // Default options
+ oOptions = $.extend({
+ 'src': '',
+ 'speed': 100,
+ 'timeout': -1,
+ 'finalWidth': null,
+ 'finalHeight': null,
+ 'magnifiedWidth': null,
+ 'magnifiedHeight': null,
+ 'limitBounds': false,
+ 'afterLoad': function(){}
+ }, oOptions);
+
+ var $that = this, // Preserve scope
+ $html = $('html'),
+
+ // Initiate
+ init = function(el) {
+ var $image = $(el),
+ $anchor = $image.closest('a'),
+ oDataAttr = {};
+
+ // Get data attributes
+ for (var i in oOptions) {
+ oDataAttr[i] = $image.attr('data-magnify-' + i.toLowerCase());
+ }
+
+ // Disable zooming if no valid large image source
+ var sZoomSrc = oDataAttr['src'] || oOptions['src'] || $anchor.attr('href') || '';
+ if (!sZoomSrc) return;
+
+ var $container,
+ $lens,
+ nImageWidth,
+ nImageHeight,
+ nMagnifiedWidth,
+ nMagnifiedHeight,
+ nLensWidth,
+ nLensHeight,
+ nBoundX = 0,
+ nBoundY = 0,
+ oContainerOffset, // Relative to document
+ oImageOffset, // Relative to container
+ // Get true offsets
+ getOffset = function() {
+ var o = $container.offset();
+ // Store offsets from container border to image inside
+ // NOTE: .offset() does NOT take into consideration image border and padding.
+ oImageOffset = {
+ 'top': ($image.offset().top-o.top) + parseInt($image.css('border-top-width')) + parseInt($image.css('padding-top')),
+ 'left': ($image.offset().left-o.left) + parseInt($image.css('border-left-width')) + parseInt($image.css('padding-left'))
+ };
+ o.top += oImageOffset['top'];
+ o.left += oImageOffset['left'];
+ return o;
+ },
+ // Hide the lens
+ hideLens = function() {
+ if ($lens.is(':visible')) $lens.fadeOut(oOptions['speed'], function() {
+ $html.removeClass('magnifying').trigger('magnifyend'); // Reset overflow-x
+ });
+ };
+
+ // Data attributes have precedence over options object
+ if (!isNaN(+oDataAttr['speed'])) oOptions['speed'] = +oDataAttr['speed'];
+ if (!isNaN(+oDataAttr['timeout'])) oOptions['timeout'] = +oDataAttr['timeout'];
+ if (!isNaN(+oDataAttr['finalWidth'])) oOptions['finalWidth'] = +oDataAttr['finalWidth'];
+ if (!isNaN(+oDataAttr['finalHeight'])) oOptions['finalHeight'] = +oDataAttr['finalHeight'];
+ if (!isNaN(+oDataAttr['magnifiedWidth'])) oOptions['magnifiedWidth'] = +oDataAttr['magnifiedWidth'];
+ if (!isNaN(+oDataAttr['magnifiedHeight'])) oOptions['magnifiedHeight'] = +oDataAttr['magnifiedHeight'];
+ if (oDataAttr['limitBounds']==='true') oOptions['limitBounds'] = true;
+ if (typeof window[oDataAttr['afterLoad']]==='function') oOptions.afterLoad = window[oDataAttr['afterLoad']];
+
+ // Save any inline styles for resetting
+ $image.data('originalStyle', $image.attr('style'));
+
+ // Activate magnification:
+ // 1. Try to get large image dimensions
+ // 2. Proceed only if able to get large image dimensions OK
+
+ // [1] Calculate the native (magnified) image dimensions. The zoomed version is only shown
+ // after the native dimensions are available. To get the actual dimensions we have to create
+ // this image object.
+ var elZoomImage = new Image();
+ $(elZoomImage).on({
+ 'load': function() {
+ // [2] Got image dimensions OK.
+
+ var nX, nY;
+
+ // Fix overlap bug at the edges during magnification
+ $image.css('display', 'block');
+ // Create container div if necessary
+ if (!$image.parent('.magnify').length) {
+ $image.wrap('<div class="magnify"></div>');
+ }
+ $container = $image.parent('.magnify');
+ // Create the magnifying lens div if necessary
+ if ($image.prev('.magnify-lens').length) {
+ $container.children('.magnify-lens').css('background-image', 'url(\'' + sZoomSrc + '\')');
+ } else {
+ $image.before('<div class="magnify-lens loading" style="background:url(\'' + sZoomSrc + '\') 0 0 no-repeat"></div>');
+ }
+ $lens = $container.children('.magnify-lens');
+ // Remove the "Loading..." text
+ $lens.removeClass('loading');
+ // Cache dimensions and offsets for improved performance
+ // NOTE: This code is inside the load() function, which is important. The width and
+ // height of the object would return 0 if accessed before the image is fully loaded.
+ nImageWidth = oOptions['finalWidth'] || $image.width();
+ nImageHeight = oOptions['finalHeight'] || $image.height();
+ nMagnifiedWidth = oOptions['magnifiedWidth'] || elZoomImage.width;
+ nMagnifiedHeight = oOptions['magnifiedHeight'] || elZoomImage.height;
+ nLensWidth = $lens.width();
+ nLensHeight = $lens.height();
+ oContainerOffset = getOffset(); // Required by refresh()
+ // Set zoom boundaries
+ if (oOptions['limitBounds']) {
+ nBoundX = (nLensWidth/2) / (nMagnifiedWidth/nImageWidth);
+ nBoundY = (nLensHeight/2) / (nMagnifiedHeight/nImageHeight);
+ }
+ // Enforce non-native large image size?
+ if (nMagnifiedWidth!==elZoomImage.width || nMagnifiedHeight!==elZoomImage.height) {
+ $lens.css('background-size', nMagnifiedWidth + 'px ' + nMagnifiedHeight + 'px');
+ }
+ // Store zoom dimensions for mobile plugin
+ $image.data('zoomSize', {
+ 'width': nMagnifiedWidth,
+ 'height': nMagnifiedHeight
+ });
+ // Clean up
+ elZoomImage = null;
+ // Execute callback
+ oOptions.afterLoad();
+ // Handle mouse movements
+ $container.off().on({
+ 'mousemove touchmove': function(e) {
+ e.preventDefault();
+ // Reinitialize if image initially hidden
+ if (!nImageHeight) {
+ refresh();
+ return;
+ }
+ // x/y coordinates of the mouse pointer or touch point. This is the position of
+ // .magnify relative to the document.
+ //
+ // We deduct the positions of .magnify from the mouse or touch positions relative to
+ // the document to get the mouse or touch positions relative to the container.
+ nX = (e.pageX || e.originalEvent.touches[0].pageX) - oContainerOffset['left'],
+ nY = (e.pageY || e.originalEvent.touches[0].pageY) - oContainerOffset['top'];
+ // Toggle magnifying lens
+ if (!$lens.is(':animated')) {
+ if (nX>nBoundX && nX<nImageWidth-nBoundX && nY>nBoundY && nY<nImageHeight-nBoundY) {
+ if ($lens.is(':hidden')) {
+ $html.addClass('magnifying').trigger('magnifystart'); // Hide overflow-x while zooming
+ $lens.fadeIn(oOptions['speed']);
+ }
+ } else {
+ hideLens();
+ }
+ }
+ if ($lens.is(':visible')) {
+ // Move the magnifying lens with the mouse
+ var sBgPos = '';
+ if (nMagnifiedWidth && nMagnifiedHeight) {
+ // Change the background position of .magnify-lens according to the position of
+ // the mouse over the .magnify-image image. This allows us to get the ratio of
+ // the pixel under the mouse pointer with respect to the image and use that to
+ // position the large image inside the magnifying lens.
+ var nRatioX = -Math.round(nX/nImageWidth*nMagnifiedWidth-nLensWidth/2),
+ nRatioY = -Math.round(nY/nImageHeight*nMagnifiedHeight-nLensHeight/2);
+ if (oOptions['limitBounds']) {
+ // Enforce bounds to ensure only image is visible in lens
+ var nBoundRight = -Math.round((nImageWidth-nBoundX)/nImageWidth*nMagnifiedWidth-nLensWidth/2),
+ nBoundBottom = -Math.round((nImageHeight-nBoundY)/nImageHeight*nMagnifiedHeight-nLensHeight/2);
+ // Left and right edges
+ if (nRatioX>0) nRatioX = 0;
+ else if (nRatioX<nBoundRight) nRatioX = nBoundRight;
+ // Top and bottom edges
+ if (nRatioY>0) nRatioY = 0;
+ else if (nRatioY<nBoundBottom) nRatioY = nBoundBottom;
+ }
+ sBgPos = nRatioX + 'px ' + nRatioY + 'px';
+ }
+ // Now the lens moves with the mouse. The logic is to deduct half of the lens's
+ // width and height from the mouse coordinates to place it with its center at the
+ // mouse coordinates. If you hover on the image now, you should see the magnifying
+ // lens in action.
+ $lens.css({
+ 'top': Math.round(nY-nLensHeight/2) + oImageOffset['top'] + 'px',
+ 'left': Math.round(nX-nLensWidth/2) + oImageOffset['left'] + 'px',
+ 'background-position': sBgPos
+ });
+ }
+ },
+ 'mouseenter': function() {
+ // Need to update offsets here to support accordions
+ oContainerOffset = getOffset();
+ },
+ 'mouseleave': hideLens
+ });
+
+ // Prevent magnifying lens from getting "stuck"
+ if (oOptions['timeout']>=0) {
+ $container.on('touchend', function() {
+ setTimeout(hideLens, oOptions['timeout']);
+ });
+ }
+ // Ensure lens is closed when tapping outside of it
+ $('body').not($container).on('touchstart', hideLens);
+
+ // Support image map click-throughs while zooming
+ var sUsemap = $image.attr('usemap');
+ if (sUsemap) {
+ var $map = $('map[name=' + sUsemap.slice(1) + ']');
+ // Image map needs to be on the same DOM level as image source
+ $image.after($map);
+ $container.click(function(e) {
+ // Trigger click on image below lens at current cursor position
+ if (e.clientX || e.clientY) {
+ $lens.hide();
+ var elPoint = document.elementFromPoint(
+ e.clientX || e.originalEvent.touches[0].clientX,
+ e.clientY || e.originalEvent.touches[0].clientY
+ );
+ if (elPoint.nodeName==='AREA') {
+ elPoint.click();
+ } else {
+ // Workaround for buggy implementation of elementFromPoint()
+ // See https://bugzilla.mozilla.org/show_bug.cgi?id=1227469
+ $('area', $map).each(function() {
+ var a = $(this).attr('coords').split(',');
+ if (nX>=a[0] && nX<=a[2] && nY>=a[1] && nY<=a[3]) {
+ this.click();
+ return false;
+ }
+ });
+ }
+ }
+ });
+ }
+
+ if ($anchor.length) {
+ // Make parent anchor inline-block to have correct dimensions
+ $anchor.css('display', 'inline-block');
+ // Disable parent anchor if it's sourcing the large image
+ if ($anchor.attr('href') && !(oDataAttr['src'] || oOptions['src'])) {
+ $anchor.click(function(e) {
+ e.preventDefault();
+ });
+ }
+ }
+
+ },
+ 'error': function() {
+ // Clean up
+ elZoomImage = null;
+ }
+ });
+
+ elZoomImage.src = sZoomSrc;
+ }, // END init()
+
+ // Simple debounce
+ nTimer = 0,
+ refresh = function() {
+ clearTimeout(nTimer);
+ nTimer = setTimeout(function() {
+ $that.destroy();
+ $that.magnify(oOptions);
+ }, 100);
+ };
+
+ /**
+ * Public Methods
+ */
+
+ // Turn off zoom and reset to original state
+ this.destroy = function() {
+ this.each(function() {
+ var $this = $(this),
+ $lens = $this.prev('div.magnify-lens'),
+ sStyle = $this.data('originalStyle');
+ if ($this.parent('div.magnify').length && $lens.length) {
+ if (sStyle) $this.attr('style', sStyle);
+ else $this.removeAttr('style');
+ $this.unwrap();
+ $lens.remove();
+ }
+ });
+ // Unregister event handler
+ $(window).off('resize', refresh);
+ return $that;
+ }
+
+ // Handle window resizing
+ $(window).resize(refresh);
+
+ return this.each(function() {
+ // Initiate magnification powers
+ init(this);
+ });
+
+ };
+}(jQuery));
diff --git a/javascript/jquery/plugins/magnify/magnify.css b/javascript/jquery/plugins/magnify/magnify.css
new file mode 100644
index 0000000..84b4c4f
--- /dev/null
+++ b/javascript/jquery/plugins/magnify/magnify.css
@@ -0,0 +1,60 @@
+html.magnifying > body {
+ overflow-x: hidden !important;
+}
+.magnify,
+.magnify > .magnify-lens,
+.magnify-mobile,
+.lens-mobile { /* Reset */
+ min-width: 0;
+ min-height: 0;
+ animation: none;
+ border: none;
+ float: none;
+ margin: 0;
+ opacity: 1;
+ outline: none;
+ overflow: visible;
+ padding: 0;
+ text-indent: 0;
+ transform: none;
+ transition: none;
+}
+.magnify {
+ position: relative;
+ width: auto;
+ height: auto;
+ box-shadow: none;
+ display: inline-block;
+ z-index: inherit;
+}
+.magnify > .magnify-lens { /* Magnifying lens */
+ position: absolute;
+ width: 200px;
+ height: 200px;
+ border-radius: 100%;
+ /* Multiple box shadows to achieve the glass lens effect */
+ box-shadow: 0 0 0 7px rgba(255, 255, 255, 0.85),
+ 0 0 7px 7px rgba(0, 0, 0, 0.25),
+ inset 0 0 40px 2px rgba(0, 0, 0, 0.25);
+ cursor: none;
+ display: none;
+ z-index: 99;
+}
+.magnify > .magnify-lens.loading {
+ background: #333 !important;
+ opacity: 0.8;
+}
+.magnify > .magnify-lens.loading:after { /* Loading text */
+ position: absolute;
+ top: 50%;
+ left: 0;
+ width: 100%;
+ color: #fff;
+ content: 'Loading...';
+ font: italic normal 16px/1 Calibri, sans-serif;
+ letter-spacing: 1px;
+ margin-top: -8px;
+ text-align: center;
+ text-shadow: 0 0 2px rgba(51, 51, 51, 0.8);
+ text-transform: none;
+}