├── LICENSE.md ├── bower.json ├── daisy.jpg ├── demo.html ├── grab.cur ├── grabbed.cur ├── icon.png ├── jquery.zoom.js ├── jquery.zoom.min.js ├── package.json ├── readme.md └── roxy.jpg /LICENSE.md: -------------------------------------------------------------------------------- 1 | The MIT License (MIT) 2 | 3 | Copyright (c) 2015 Jack Moore 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. -------------------------------------------------------------------------------- /bower.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "jquery-zoom", 3 | "description": "Enlarge images on click or mouseover.", 4 | "dependencies": { 5 | "jquery": ">=1.7" 6 | }, 7 | "keywords": [ 8 | "zoom", 9 | "images", 10 | "ui", 11 | "jQuery", 12 | "jquery-plugin" 13 | ], 14 | "authors": [ 15 | { 16 | "name": "Jack Moore", 17 | "url": "http://www.jacklmoore.com", 18 | "email": "hello@jacklmoore.com" 19 | } 20 | ], 21 | "licenses": [ 22 | { 23 | "type": "MIT", 24 | "url": "http://www.opensource.org/licenses/mit-license.php" 25 | } 26 | ], 27 | "homepage": "http://www.jacklmoore.com/zoom", 28 | "main": "jquery.zoom.js" 29 | } -------------------------------------------------------------------------------- /daisy.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/jackmoore/zoom/aabcdc20e01228b096e8829ba88cb64b36dc13a5/daisy.jpg -------------------------------------------------------------------------------- /demo.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | jQuery Zoom Demo 6 | 38 | 39 | 40 | 48 | 49 | 50 | 51 | Daisy on the Ohoopee 52 |

Hover

53 |
54 | 55 | Roxy on the Ohoopee 56 |

Grab

57 |
58 | 59 | Daisy on the Ohoopee 60 |

Click to activate

61 |
62 | 63 | Roxy on the Ohoopee 64 |

Click to toggle

65 |
66 | 67 | 68 | -------------------------------------------------------------------------------- /grab.cur: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/jackmoore/zoom/aabcdc20e01228b096e8829ba88cb64b36dc13a5/grab.cur -------------------------------------------------------------------------------- /grabbed.cur: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/jackmoore/zoom/aabcdc20e01228b096e8829ba88cb64b36dc13a5/grabbed.cur -------------------------------------------------------------------------------- /icon.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/jackmoore/zoom/aabcdc20e01228b096e8829ba88cb64b36dc13a5/icon.png -------------------------------------------------------------------------------- /jquery.zoom.js: -------------------------------------------------------------------------------- 1 | /*! 2 | Zoom 1.7.21 3 | license: MIT 4 | http://www.jacklmoore.com/zoom 5 | */ 6 | (function ($) { 7 | var defaults = { 8 | url: false, 9 | callback: false, 10 | target: false, 11 | duration: 120, 12 | on: 'mouseover', // other options: grab, click, toggle 13 | touch: true, // enables a touch fallback 14 | onZoomIn: false, 15 | onZoomOut: false, 16 | magnify: 1 17 | }; 18 | 19 | // Core Zoom Logic, independent of event listeners. 20 | $.zoom = function(target, source, img, magnify) { 21 | var targetHeight, 22 | targetWidth, 23 | sourceHeight, 24 | sourceWidth, 25 | xRatio, 26 | yRatio, 27 | offset, 28 | $target = $(target), 29 | position = $target.css('position'), 30 | $source = $(source); 31 | 32 | // The parent element needs positioning so that the zoomed element can be correctly positioned within. 33 | target.style.position = /(absolute|fixed)/.test(position) ? position : 'relative'; 34 | target.style.overflow = 'hidden'; 35 | img.style.width = img.style.height = ''; 36 | 37 | $(img) 38 | .addClass('zoomImg') 39 | .css({ 40 | position: 'absolute', 41 | top: 0, 42 | left: 0, 43 | opacity: 0, 44 | width: img.width * magnify, 45 | height: img.height * magnify, 46 | border: 'none', 47 | maxWidth: 'none', 48 | maxHeight: 'none' 49 | }) 50 | .appendTo(target); 51 | 52 | return { 53 | init: function() { 54 | targetWidth = $target.outerWidth(); 55 | targetHeight = $target.outerHeight(); 56 | 57 | if (source === target) { 58 | sourceWidth = targetWidth; 59 | sourceHeight = targetHeight; 60 | } else { 61 | sourceWidth = $source.outerWidth(); 62 | sourceHeight = $source.outerHeight(); 63 | } 64 | 65 | xRatio = (img.width - targetWidth) / sourceWidth; 66 | yRatio = (img.height - targetHeight) / sourceHeight; 67 | 68 | offset = $source.offset(); 69 | }, 70 | move: function (e) { 71 | var left = (e.pageX - offset.left), 72 | top = (e.pageY - offset.top); 73 | 74 | top = Math.max(Math.min(top, sourceHeight), 0); 75 | left = Math.max(Math.min(left, sourceWidth), 0); 76 | 77 | img.style.left = (left * -xRatio) + 'px'; 78 | img.style.top = (top * -yRatio) + 'px'; 79 | } 80 | }; 81 | }; 82 | 83 | $.fn.zoom = function (options) { 84 | return this.each(function () { 85 | var 86 | settings = $.extend({}, defaults, options || {}), 87 | //target will display the zoomed image 88 | target = settings.target && $(settings.target)[0] || this, 89 | //source will provide zoom location info (thumbnail) 90 | source = this, 91 | $source = $(source), 92 | img = document.createElement('img'), 93 | $img = $(img), 94 | mousemove = 'mousemove.zoom', 95 | clicked = false, 96 | touched = false; 97 | 98 | // If a url wasn't specified, look for an image element. 99 | if (!settings.url) { 100 | var srcElement = source.querySelector('img'); 101 | if (srcElement) { 102 | settings.url = srcElement.getAttribute('data-src') || srcElement.currentSrc || srcElement.src; 103 | } 104 | if (!settings.url) { 105 | return; 106 | } 107 | } 108 | 109 | $source.one('zoom.destroy', function(position, overflow){ 110 | $source.off(".zoom"); 111 | target.style.position = position; 112 | target.style.overflow = overflow; 113 | img.onload = null; 114 | $img.remove(); 115 | }.bind(this, target.style.position, target.style.overflow)); 116 | 117 | img.onload = function () { 118 | var zoom = $.zoom(target, source, img, settings.magnify); 119 | 120 | function start(e) { 121 | zoom.init(); 122 | zoom.move(e); 123 | 124 | // Skip the fade-in for IE8 and lower since it chokes on fading-in 125 | // and changing position based on mousemovement at the same time. 126 | $img.stop() 127 | .fadeTo($.support.opacity ? settings.duration : 0, 1, $.isFunction(settings.onZoomIn) ? settings.onZoomIn.call(img) : false); 128 | } 129 | 130 | function stop() { 131 | $img.stop() 132 | .fadeTo(settings.duration, 0, $.isFunction(settings.onZoomOut) ? settings.onZoomOut.call(img) : false); 133 | } 134 | 135 | // Mouse events 136 | if (settings.on === 'grab') { 137 | $source 138 | .on('mousedown.zoom', 139 | function (e) { 140 | if (e.which === 1) { 141 | $(document).one('mouseup.zoom', 142 | function () { 143 | stop(); 144 | 145 | $(document).off(mousemove, zoom.move); 146 | } 147 | ); 148 | 149 | start(e); 150 | 151 | $(document).on(mousemove, zoom.move); 152 | 153 | e.preventDefault(); 154 | } 155 | } 156 | ); 157 | } else if (settings.on === 'click') { 158 | $source.on('click.zoom', 159 | function (e) { 160 | if (clicked) { 161 | // bubble the event up to the document to trigger the unbind. 162 | return; 163 | } else { 164 | clicked = true; 165 | start(e); 166 | $(document).on(mousemove, zoom.move); 167 | $(document).one('click.zoom', 168 | function () { 169 | stop(); 170 | clicked = false; 171 | $(document).off(mousemove, zoom.move); 172 | } 173 | ); 174 | return false; 175 | } 176 | } 177 | ); 178 | } else if (settings.on === 'toggle') { 179 | $source.on('click.zoom', 180 | function (e) { 181 | if (clicked) { 182 | stop(); 183 | } else { 184 | start(e); 185 | } 186 | clicked = !clicked; 187 | } 188 | ); 189 | } else if (settings.on === 'mouseover') { 190 | zoom.init(); // Preemptively call init because IE7 will fire the mousemove handler before the hover handler. 191 | 192 | $source 193 | .on('mouseenter.zoom', start) 194 | .on('mouseleave.zoom', stop) 195 | .on(mousemove, zoom.move); 196 | } 197 | 198 | // Touch fallback 199 | if (settings.touch) { 200 | $source 201 | .on('touchstart.zoom', function (e) { 202 | e.preventDefault(); 203 | if (touched) { 204 | touched = false; 205 | stop(); 206 | } else { 207 | touched = true; 208 | start( e.originalEvent.touches[0] || e.originalEvent.changedTouches[0] ); 209 | } 210 | }) 211 | .on('touchmove.zoom', function (e) { 212 | e.preventDefault(); 213 | zoom.move( e.originalEvent.touches[0] || e.originalEvent.changedTouches[0] ); 214 | }) 215 | .on('touchend.zoom', function (e) { 216 | e.preventDefault(); 217 | if (touched) { 218 | touched = false; 219 | stop(); 220 | } 221 | }); 222 | } 223 | 224 | if ($.isFunction(settings.callback)) { 225 | settings.callback.call(img); 226 | } 227 | }; 228 | 229 | img.setAttribute('role', 'presentation'); 230 | img.alt = ''; 231 | img.src = settings.url; 232 | }); 233 | }; 234 | 235 | $.fn.zoom.defaults = defaults; 236 | }(window.jQuery)); 237 | -------------------------------------------------------------------------------- /jquery.zoom.min.js: -------------------------------------------------------------------------------- 1 | /*! 2 | Zoom 1.7.21 3 | license: MIT 4 | http://www.jacklmoore.com/zoom 5 | */ 6 | (function(o){var t={url:!1,callback:!1,target:!1,duration:120,on:"mouseover",touch:!0,onZoomIn:!1,onZoomOut:!1,magnify:1};o.zoom=function(t,n,e,i){var u,c,a,r,m,l,s,f=o(t),h=f.css("position"),d=o(n);return t.style.position=/(absolute|fixed)/.test(h)?h:"relative",t.style.overflow="hidden",e.style.width=e.style.height="",o(e).addClass("zoomImg").css({position:"absolute",top:0,left:0,opacity:0,width:e.width*i,height:e.height*i,border:"none",maxWidth:"none",maxHeight:"none"}).appendTo(t),{init:function(){c=f.outerWidth(),u=f.outerHeight(),n===t?(r=c,a=u):(r=d.outerWidth(),a=d.outerHeight()),m=(e.width-c)/r,l=(e.height-u)/a,s=d.offset()},move:function(o){var t=o.pageX-s.left,n=o.pageY-s.top;n=Math.max(Math.min(n,a),0),t=Math.max(Math.min(t,r),0),e.style.left=t*-m+"px",e.style.top=n*-l+"px"}}},o.fn.zoom=function(n){return this.each(function(){var e=o.extend({},t,n||{}),i=e.target&&o(e.target)[0]||this,u=this,c=o(u),a=document.createElement("img"),r=o(a),m="mousemove.zoom",l=!1,s=!1;if(!e.url){var f=u.querySelector("img");if(f&&(e.url=f.getAttribute("data-src")||f.currentSrc||f.src),!e.url)return}c.one("zoom.destroy",function(o,t){c.off(".zoom"),i.style.position=o,i.style.overflow=t,a.onload=null,r.remove()}.bind(this,i.style.position,i.style.overflow)),a.onload=function(){function t(t){f.init(),f.move(t),r.stop().fadeTo(o.support.opacity?e.duration:0,1,o.isFunction(e.onZoomIn)?e.onZoomIn.call(a):!1)}function n(){r.stop().fadeTo(e.duration,0,o.isFunction(e.onZoomOut)?e.onZoomOut.call(a):!1)}var f=o.zoom(i,u,a,e.magnify);"grab"===e.on?c.on("mousedown.zoom",function(e){1===e.which&&(o(document).one("mouseup.zoom",function(){n(),o(document).off(m,f.move)}),t(e),o(document).on(m,f.move),e.preventDefault())}):"click"===e.on?c.on("click.zoom",function(e){return l?void 0:(l=!0,t(e),o(document).on(m,f.move),o(document).one("click.zoom",function(){n(),l=!1,o(document).off(m,f.move)}),!1)}):"toggle"===e.on?c.on("click.zoom",function(o){l?n():t(o),l=!l}):"mouseover"===e.on&&(f.init(),c.on("mouseenter.zoom",t).on("mouseleave.zoom",n).on(m,f.move)),e.touch&&c.on("touchstart.zoom",function(o){o.preventDefault(),s?(s=!1,n()):(s=!0,t(o.originalEvent.touches[0]||o.originalEvent.changedTouches[0]))}).on("touchmove.zoom",function(o){o.preventDefault(),f.move(o.originalEvent.touches[0]||o.originalEvent.changedTouches[0])}).on("touchend.zoom",function(o){o.preventDefault(),s&&(s=!1,n())}),o.isFunction(e.callback)&&e.callback.call(a)},a.setAttribute("role","presentation"),a.alt="",a.src=e.url})},o.fn.zoom.defaults=t})(window.jQuery); -------------------------------------------------------------------------------- /package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "jquery-zoom", 3 | "description": "Enlarge images on click or mouseover.", 4 | "version": "1.7.21", 5 | "keywords": [ 6 | "zoom", 7 | "images", 8 | "ui", 9 | "jquery-plugin" 10 | ], 11 | "author": { 12 | "name": "Jack Moore", 13 | "url": "http://www.jacklmoore.com", 14 | "email": "hello@jacklmoore.com" 15 | }, 16 | "main": "jquery.zoom.js", 17 | "license": "MIT", 18 | "homepage": "http://www.jacklmoore.com/zoom", 19 | "demo": "http://www.jacklmoore.com/zoom", 20 | "repository": { 21 | "type": "git", 22 | "url": "http://github.com/jackmoore/zoom.git" 23 | }, 24 | "dependencies": { 25 | "jquery": ">=1.7" 26 | } 27 | } 28 | -------------------------------------------------------------------------------- /readme.md: -------------------------------------------------------------------------------- 1 | ## About Zoom 2 | 3 | A small jQuery plugin for zooming images on mouseover or mousedown. See the [project page](http://jacklmoore.com/zoom/) for documentation and a demonstration. Released under the [MIT license](http://www.opensource.org/licenses/mit-license.php). 4 | 5 | To compile the .min.js file, run: `uglifyjs --comments '/license:/' < jquery.zoom.js > jquery.zoom.min.js` 6 | 7 | ## Changelog: 8 | 9 | ##### v1.7.21 - 2018/4/26 10 | * Added empty alt attribute. Resolves #134 11 | 12 | ##### v1.7.20 - 2017/4/25 13 | * Replaced alt and aria-hidden with role attribute. Resolves #121 14 | 15 | ##### v1.7.19 - 2017/4/20 16 | * Added alt and aria-hidden attributes to the zoom layer img element. Merged #121 17 | 18 | ##### v1.7.18 - 2016/9/9 19 | * Fixed regression from 1.7.16 that occurred when the target option was passed a selector. Fixes #113 20 | 21 | ##### v1.7.17 - 2016/9/7 22 | * Detect src using element.currentSrc to support srcset. Fixes #82 23 | 24 | ##### v1.7.16 - 2016/9/7 25 | * Cancelled the onload event when calling destroy. Fixes #83 26 | 27 | ##### v1.7.15 - 2016/2/8 28 | * Added touchend event, might fix #97 #75 #62. Merges #100. 29 | 30 | ##### v1.7.14 - 2015/3/18 31 | * Fixes bug with passing the `target` property a selector, rather than a DOM node. Merges #73. 32 | 33 | ##### v1.7.13 - 2014/4/29 34 | * Destroy event does a better job of reseting back to the original state. 35 | 36 | ##### v1.7.12 - 2014/2/11 37 | * Set zoomed image's maxHeight to none, just in case a maxHeight has been defined for images in the CSS. 38 | 39 | ##### v1.7.11 - 2013/11/12 40 | * Added magnify property to allow scaling of the zoomed image. 41 | 42 | ##### v1.7.10 - 2013/10/16 43 | * Fixed bug relating to the size of the target element when using the target property (Fixes #35) 44 | 45 | ##### v1.7.9 - 2013/10/16 46 | * Added simple fallback for touch events (Fixes #37 #39) 47 | * Renamed minified file to jquery.zoom.min.js to match jQuery's convention. 48 | 49 | ##### v1.7.8 - 2013/7/30 50 | * Will use data-src attribute if present before checking for the presence of an src attribute. 51 | 52 | ##### v1.7.7 - 2013/7/14 53 | * Restricted grab to just the left-mouse-button on mousedown 54 | 55 | ##### v1.7.6 - 2013/6/24 56 | * Fixed misnamed onZoomOut callback 57 | 58 | ##### v1.7.5 - 2013/6/19 59 | * Fixed a bug with absolutely or fixed position target elements 60 | * Set the value of `this` to be zoom-image element for the onZoomIn and onZoomOut callbacks 61 | 62 | ##### v1.7.4 - 2013/6/18 63 | * Namespaced events to assist unbinding events. 64 | * Added destroy event to unbind zoom events & remove created img element. Example: 65 | $('.example').trigger('zoom.destroy'); 66 | * Added onZoomIn and onZoomOut callbacks 67 | 68 | ##### v1.7.3 - 2013/6/10 69 | * Fixing mistake made in previous commit 70 | 71 | ##### v1.7.2 - 2013/6/6 72 | * Replaced new Image() with document.createElement('img') to avoid a potential bug in Chrome 27. 73 | 74 | ##### v1.7.1 - 2013/3/12 75 | * Replaced jQuery shorthand methods with on() in anticipation of jQuery 2.0 76 | 77 | ##### v1.7.0 - 2013/1/31 78 | * Added 'toggle' behavior to zoom in/out on click. Example: $('#example').zoom({ on:'toggle' }); 79 | * Removed the icon property in favor of just using CSS. 80 | 81 | ##### v1.6.0 - 2013/1/22 82 | * Created $.zoom which contains the positioning logic, so that users can write custom controls or event handling. 83 | 84 | ##### v1.5.0 - 2012/11/19 85 | * Added 'target' property for specifying the element that displays the zoomed image. 86 | 87 | ##### v1.4.0 - 2012/9/29 88 | * Changed API & added option to activate on click. 89 | 90 | ##### v1.3.0 - 2011/12/21 91 | * Added 'callback' property that will execute a callback function once the image has loaded. 92 | * Fixed a bug relating to the 'grab' property 93 | 94 | ##### v1.2.0 - 2011/11/15 95 | * Fixed a positioning bug 96 | 97 | ##### v1.1.0 - 2011/11/15 98 | * Added 'grab' property 99 | 100 | ##### v1.0.0 - 2011/11/11 101 | * First release -------------------------------------------------------------------------------- /roxy.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/jackmoore/zoom/aabcdc20e01228b096e8829ba88cb64b36dc13a5/roxy.jpg --------------------------------------------------------------------------------