diff --git a/README.md b/README.md index 622bcb1..072cc20 100644 --- a/README.md +++ b/README.md @@ -5,11 +5,13 @@ ## Features - Fit mobile devices. -- Uses link's `href` attribute for large images. +- Uses CSS3 transform and transition for smooth touch sliding. +- Touch slide left or right opens next or previous image, touch slide up or down closes image. - Clicking image opens next one, clicking left side opens previous, clicking right side closes image. - Hotkeys for next, previous and close buttons. - Closing after viewing of all images. - Preloading of next and previous images. +- Uses link's `href` or `data-href` attribute for large images. - Fully customizable styles. - Customizable bottom area. - Customizable `onopen` event. @@ -26,18 +28,29 @@ Add jQuery and ABigImage scripts in head of page. Call plugin on selector of enlargeable images links. $(function() { + /* all links with class "myimgclass" */ + $('.myimgclass').abigimage(); + + /* or all links to "*.jpg" images */ $('a[href$=".jpg"]').abigimage(); + + /* or all links to images under dir "/my/images/dir/" */ + $('a[href^="/my/images/dir/"]').abigimage(); }); ### Options -- `fadeIn` - fade in duration or [options](http://api.jquery.com/fadein/). -- `fadeOut` - fade out duration or [options](http://api.jquery.com/fadeout/). -- `prevBtnHtml` - html of "previous" button. -- `closeBtnHtml` - html of "close" button. -- `keyNext` - hotkeys for "next" button (by default: 13 enter, 32 space, 39 right, 40 down). -- `keyPrev` - hotkeys for "previous" button (by default: 8 backspace, 37 left, 38 up). -- `keyNext` - hotkeys for "close" button (by default: 27 escape, 35 end, 36 home). +- `fadeIn` - fade in duration or [options](http://api.jquery.com/fadein/) (default: `fast`). +- `fadeOut` - fade out duration or [options](http://api.jquery.com/fadeout/) (default: `fast`). +- `slideWidth` - slide width to switch or close image (between 0 and 1, default: 0.4). +- `slideVelocity` - slide velocity to switch or close image (pixels per millisecond, default: 0.4). +- `zoomMin` - minimal zoom that will hold (default: 1.5). +- `zoomMax` - maximal zoom (default: 5). +- `prevBtnHtml` - html of "previous" button (default: `←`). +- `closeBtnHtml` - html of "close" button (default: `x`). +- `keyNext` - hotkeys for "next" button (default: 13 enter, 32 space, 39 right, 40 down). +- `keyPrev` - hotkeys for "previous" button (default: 8 backspace, 37 left, 38 up). +- `keyNext` - hotkeys for "close" button (default: 27 escape, 35 end, 36 home). - `onopen` - function called when image opens. - `*Attrs` - plugin elements attributes. - `*CSS` - plugin elements CSS. @@ -51,28 +64,31 @@ Plugin generates next html code:
- +
- +
- -
+ +
+ +
+
-
- -
- +
- -
+ +
+ +
+
+ + + + + +
- - - - - -
@@ -95,6 +111,14 @@ Function, defined as `onopen` handler, executes in context of plugin, and receiv }); }); +### Using custom links with data-href attribute + +If you want different link for plugin's big image and for non-javascript clients (search engines or browsers without javascript) - use `data-href` attribute: + + ... + +Also, you can use `data-href` attribute on any element, not only links. + ## License Copyright © 2014 Maksim Krylosov diff --git a/abigimage.jquery.js b/abigimage.jquery.js index 0eff1a3..6141a38 100644 --- a/abigimage.jquery.js +++ b/abigimage.jquery.js @@ -11,150 +11,441 @@ (function ($) { - $.fn.abigimage = function(options) { - - var opts = $.extend(true, $.fn.abigimage.defaults, options); - - this.overlay = $('
').attr(opts.overlayAttrs) .css(opts.overlayCSS) .appendTo('body'); - this.layout = $('
').attr(opts.layoutAttrs) .css(opts.layoutCSS) .appendTo('body'); - this.prevBtnWrapper = $('
').attr(opts.prevBtnWrapperAttrs) .css(opts.prevBtnWrapperCSS) .appendTo(this.layout); - this.prevBtnBox = $('
').attr(opts.prevBtnBoxAttrs) .css(opts.prevBtnBoxCSS) .appendTo(this.prevBtnWrapper); - this.prevBtn = $('
').attr(opts.prevBtnAttrs) .css(opts.prevBtnCSS) .appendTo(this.prevBtnBox) .html(opts.prevBtnHtml); - this.closeBtnWrapper = $('
').attr(opts.closeBtnWrapperAttrs) .css(opts.closeBtnWrapperCSS) .appendTo(this.layout); - this.closeBtnBox = $('
').attr(opts.closeBtnBoxAttrs) .css(opts.closeBtnBoxCSS) .appendTo(this.closeBtnWrapper); - this.closeBtn = $('
').attr(opts.closeBtnAttrs) .css(opts.closeBtnCSS) .appendTo(this.closeBtnBox) .html(opts.closeBtnHtml); - this.img = $('').attr(opts.imgAttrs) .css(opts.imgCSS) .appendTo(this.layout); - this.imgNext = $('').attr(opts.imgNextAttrs) .css(opts.imgNextCSS) .appendTo(this.layout); - this.imgPrev = $('').attr(opts.imgPrevAttrs) .css(opts.imgPrevCSS) .appendTo(this.layout); - this.bottom = $('
').attr(opts.bottomAttrs) .css(opts.bottomCSS) .appendTo(this.layout); - - var t = this, - d = 0, - i = null; - - function nextI() { - var j = i + 1; - if (j === t.length) { - j = 0; - } - return j; + var overlay = $('
').css({display: 'none'}).appendTo('body'), + layout = $('
').css({display: 'none'}).appendTo('body'), + box = $('
').appendTo(layout), + prevBtnWrapper = $('
').appendTo(box), + prevBtnBox = $('
').appendTo(prevBtnWrapper), + prevBtn = $('
').appendTo(prevBtnBox), + closeBtnWrapper = $('
').appendTo(box), + closeBtnBox = $('
').appendTo(closeBtnWrapper), + closeBtn = $('
').appendTo(closeBtnBox), + img = $('').appendTo(box), + imgNext = $('').appendTo(box), + imgPrev = $('').appendTo(box), + bottom = $('
').appendTo(layout); + + var opts = {}, + t = null, + i = null, + d = 0, + opened = false; + + function nextI() { + var j = i + 1; + if (j >= t.length) { + j = 0; } + return j; + } - function prevI() { - var j = i - 1; - if (j === -1) { - j = t.length - 1; - } - return j; + function prevI() { + var j = i - 1; + if (j < 0) { + j = t.length - 1; } + return j; + } - function next() { - if (d === t.length - 1) { - return close(); - } else { - ++d; - return open(nextI()); - } + function next() { + if (d === t.length - 1) { + return close(); + } else { + ++d; + return open(nextI()); } + } - function prev() { - if (d === 1 - t.length) { - return close(); - } else { - --d; - return open(prevI()); - } + function prev() { + if (d === 1 - t.length) { + return close(); + } else { + --d; + return open(prevI()); } + } + + function key(event) { + if (opts.keyNext.indexOf(event.which) !== -1) { + event.preventDefault(); + next(); + } else if (opts.keyPrev.indexOf(event.which) !== -1) { + event.preventDefault(); + prev(); + } else if (opts.keyClose.indexOf(event.which) !== -1) { + event.preventDefault(); + close(); + } + } - function key(event) { - if (opts.keyNext.indexOf(event.which) !== -1) { - event.preventDefault(); - next(); - } else if (opts.keyPrev.indexOf(event.which) !== -1) { - event.preventDefault(); - prev(); - } else if (opts.keyClose.indexOf(event.which) !== -1) { - event.preventDefault(); - close(); + function open(src, openI) { + if ('number' === typeof src) { + if (src === i || src < 0 || src > t.length - 1) { + return; + } + i = src; + var $t = $(t[i]); + src = $t.data('href') || $t.attr('href'); + } else { + if ('number' !== typeof openI) { + openI = -1; + } + if (i === openI) { + return; } + i = openI; } - function close() { - d = 0; - t.overlay.fadeOut(opts.fadeOut); - t.layout.fadeOut(opts.fadeOut); - $(document).unbind('keydown', key); - return false; + opened = true; + + // removeAttr to force image reloading instead of replacing on load + img.removeAttr('src').attr('src', src); + var $tn = $(t[nextI()]); + imgNext.removeAttr('src').attr('src', $tn.data('href') || $tn.attr('href')); + var $tp = $(t[prevI()]); + imgPrev.removeAttr('src').attr('src', $tp.data('href') || $tp.attr('href')); + + overlay.fadeIn(opts.fadeIn); + layout.fadeIn(opts.fadeIn); + + opts.onopen.call(t, t[i], i); + + $(document).unbind('keydown', key).bind('keydown', key); + + return false; + }; + + function close() { + if (!opened) { + return; } + opened = false; + i = null; + d = 0; + overlay.fadeOut(opts.fadeOut); + layout.fadeOut(opts.fadeOut); - function open(openI) { - if (openI < 0 || openI > t.length - 1) { - return; - } + opts.onclose.call(t); - i = openI; + $(document).unbind('keydown', key); + return false; + } - t.img - .removeAttr('src') // To re-fire load event if same image opened - .attr('src', $(t[i]).attr('href')); + prevBtnWrapper.click(function() { + return prev(); + }); - t.overlay.fadeIn(opts.fadeIn); - t.layout.fadeIn(opts.fadeIn); + closeBtnWrapper.click(function() { + return close(); + }); - opts.onopen.call(t, t[i]); + var prevent = function(e) { + e.preventDefault(); + }; - $(document).unbind('keydown', key).bind('keydown', key); + layout + .on('touchmove', prevent) + .on('wheel', prevent); + + + + var sx, + sy, + ss, + x, + y, + s, + k, + dx, + dy, + iw, + ih, + + start, + width, + height, + minD, + vert, + touches, + + slideAnimateNext, + slideEnd, + slideActive; + + touchReset(); + + function touchReset() { + x = 0; + y = 0; + s = 1; + vert = null; + if (opts.imgCSS) { + img.css({zIndex: opts.imgCSS.zIndex}); + } + } - return false; + function med(ts, c) { + var p = 0; + for (var t = 0, l = ts.length; t < l; t++) { + p += ts[t]['page' + c]; + } + return p / l; + } + + function dis(e) { + return Math.sqrt( + Math.pow(e.touches[0].pageX - e.touches[1].pageX, 2) + + Math.pow(e.touches[0].pageY - e.touches[1].pageY, 2) + ); + } + + img[0].addEventListener('touchstart', function(e) { + if (e.touches.length > 1) { + k = dis(e); + img.css({zIndex: opts.prevBtnBoxCSS.zIndex}); + } else { + vert = null; + start = (new Date()).getTime(); + width = box.width() * 0.34; + height = box.height(); + minD = opts.slideWidth * width; + iw = img.width(); + ih = img.height(); + } + sx = x; + sy = y; + ss = s; + dx = 0; + dy = 0; + touches = e.touches; + e.preventDefault(); + }); + + img[0].addEventListener('touchmove', function(e) { + dx = (med(e.touches, 'X') - med(touches, 'X')); + dy = (med(e.touches, 'Y') - med(touches, 'Y')); + x = sx + dx / s; + y = sy + dy / s; + if (e.touches.length > 1) { + s = Math.max(1, ss * (dis(e) / k)); + } + if (s > opts.zoomMin) { + var mx = 0.5 * (iw - (iw / s)); + var my = 0.5 * (ih - (ih / s)); + x = Math.max(-mx, Math.min(mx, x)); + y = Math.max(-my, Math.min(my, y)); + } else { + if (null === vert) { + vert = Math.abs(dy) > Math.abs(dx); + } + if (vert) { + x = 0; + } else { + y = 0; + } + } + slideAnimate(x, y, s); + e.preventDefault(); + }); + + img[0].addEventListener('touchend', function(e) { + var time = (new Date()).getTime() - start; + + if (!e.touches.length) { + if (s <= opts.zoomMin) { + if (time < 20 && dx <= 1 && dy <= 1) { + slideAnimate(0, 0, 1, false); + next(); + } else { + if (vert) { + var ady = Math.abs(dy); + if (ady > minD) { + slideQueue(slideClose); + } else { + if (ady / time > opts.slideVelocity) { + slideQueue(slideClose); + } else { + slideQueue(slideBack); + } + } + } else { + if (dx < -minD) { + slideNext(); + } else if (dx > minD) { + slidePrev(); + } else { + if (Math.abs(dx) / time > opts.slideVelocity) { + if (dx < 0) { + slideNext(); + } else { + slidePrev(); + } + } else { + slideQueue(slideBack); + } + } + } + } + touchReset(); + } else if (s > opts.zoomMax) { + s = opts.zoomMax; + + slideAnimate(x, y, s, true); + } } - this.img.load(function() { - // preload prev and next images after viewed images loaded - t.imgNext.attr('src', $(t[nextI()]).attr('href')); - t.imgPrev.attr('src', $(t[prevI()]).attr('href')); - }); + if (s <= opts.zoomMin) { + img.css({zIndex: opts.imgCSS.zIndex}); + } - this.img.click(function() { - return next(); + touches = e.touches; + e.preventDefault(); + }); + + box.on('transitionend webkitTransitionEnd msTransitionEnd oTransitionEnd', function() { + slideActive = false; + if (slideEnd) { + slideEnd(); + slideEnd = null; + slideAnimate(0, 0, 1, false); + } else if (slideAnimateNext) { + slideAnimateNext(); + slideAnimateNext = null; + } + }); + + img.click(function() { + return next(); + }); + + function slideNext() { + setTimeout(function() {slideEnd = next;}, 100); + slideAnimate(-width, 0, 1, true); + } + + function slidePrev() { + setTimeout(function() {slideEnd = prev;}, 100); + slideAnimate(width, 0, 1, true); + } + + function slideBack() { + slideAnimate(0, 0, 1, true); + } + + function slideClose() { + slideBack(); + close(); + } + + function slideQueue(fn) { + if (slideActive) { + slideAnimateNext = fn; + } else { + fn(); + } + } + + function slideAnimate(x, y, s, transition) { + slideActive = true; + if (true === transition) { + transition = 'all .2s ease-out'; + } else if (false === transition) { + transition = ''; + } else { + transition = 'all .02s linear'; + } + var transform = 'scale(' + s + ') translate(' + x + 'px, ' + y + 'px)'; + box.css({ + '-webkit-transform': transform, + '-moz-transform': transform, + '-ms-transform': transform, + '-o-transform': transform, + 'transform': transform, + transition: transition }); + } - this.prevBtnWrapper.click(function() { - return prev(); - }); + $.fn.abigimage = function(options) { - this.closeBtnWrapper.click(function() { - return close(); - }); + t = this; + + opts = $.extend(true, $.fn.abigimage.defaults, options); + + this.overlay = overlay .attr(opts.overlayAttrs) .css(opts.overlayCSS); + this.layout = layout .attr(opts.layoutAttrs) .css(opts.layoutCSS); + this.box = box .attr(opts.boxAttrs) .css(opts.boxCSS); + this.prevBtnWrapper = prevBtnWrapper .attr(opts.prevBtnWrapperAttrs) .css(opts.prevBtnWrapperCSS); + this.prevBtnBox = prevBtnBox .attr(opts.prevBtnBoxAttrs) .css(opts.prevBtnBoxCSS); + this.prevBtn = prevBtn .attr(opts.prevBtnAttrs) .css(opts.prevBtnCSS) .html(opts.prevBtnHtml); + this.closeBtnWrapper = closeBtnWrapper .attr(opts.closeBtnWrapperAttrs) .css(opts.closeBtnWrapperCSS); + this.closeBtnBox = closeBtnBox .attr(opts.closeBtnBoxAttrs) .css(opts.closeBtnBoxCSS); + this.closeBtn = closeBtn .attr(opts.closeBtnAttrs) .css(opts.closeBtnCSS) .html(opts.closeBtnHtml); + this.img = img .attr(opts.imgAttrs) .css(opts.imgCSS); + this.imgNext = imgNext .attr(opts.imgNextAttrs) .css(opts.imgNextCSS); + this.imgPrev = imgPrev .attr(opts.imgPrevAttrs) .css(opts.imgPrevCSS); + this.bottom = bottom .attr(opts.bottomAttrs) .css(opts.bottomCSS); + + var prevBtnUnHoverCSS = {}; + for (var p in opts.prevBtnHoverCSS) { + if (opts.prevBtnCSS) { + prevBtnUnHoverCSS[p] = opts.prevBtnCSS[p]; + } + } + var closeBtnUnHoverCSS = {}; + for (var p in opts.closeBtnHoverCSS) { + if (opts.closeBtnCSS) { + closeBtnUnHoverCSS[p] = opts.closeBtnCSS[p]; + } + } + var bottomUnHoverCSS = {}; + for (var p in opts.bottomHoverCSS) { + if (opts.bottomCSS) { + bottomUnHoverCSS[p] = opts.bottomCSS[p]; + } + } this.prevBtnWrapper.hover(function() { - t.prevBtn.stop().animate(opts.prevBtnHoverCSS, opts.fadeIn); + prevBtn.stop().animate(opts.prevBtnHoverCSS, opts.fadeIn); }, function() { - t.prevBtn.stop().animate(opts.prevBtnCSS, opts.fadeOut); + prevBtn.stop().animate(prevBtnUnHoverCSS, opts.fadeOut); }); this.closeBtnWrapper.hover(function() { - t.closeBtn.stop().animate(opts.closeBtnHoverCSS, opts.fadeIn); + closeBtn.stop().animate(opts.closeBtnHoverCSS, opts.fadeIn); }, function () { - t.closeBtn.stop().animate(opts.closeBtnCSS, opts.fadeOut); + closeBtn.stop().animate(closeBtnUnHoverCSS, opts.fadeOut); }); this.bottom.hover(function() { - t.bottom.stop().animate(opts.bottomHoverCSS, opts.fadeIn); + bottom.stop().animate(opts.bottomHoverCSS, opts.fadeIn); }, function () { - t.bottom.stop().animate(opts.bottomCSS, opts.fadeOut); + bottom.stop().animate(bottomUnHoverCSS, opts.fadeOut); }); return this.each(function(i) { - $(this).click(function() { + $(this).unbind('click.abigimage').bind('click.abigimage', function() { return open(i); }); }); }; + $.abigimage = { + open: open, + next: next, + prev: prev, + close: close + }; + $.fn.abigimage.defaults = { fadeIn: 'fast', fadeOut: 'fast', + slideWidth: .4, + slideVelocity: .4, + + zoomMin: 1.5, + zoomMax: 5, + prevBtnHtml: '←', closeBtnHtml: 'x', @@ -163,19 +454,21 @@ keyClose: [27 /* escape */, 35 /* end */, 36 /* home */], onopen: function() {}, + onclose: function() {}, - overlayCSS: {position: 'fixed', zIndex: 101, top: 0, right: 0, bottom: 0, left: 0, display: 'none', + overlayCSS: {position: 'fixed', zIndex: 101, top: 0, right: 0, bottom: 0, left: 0, backgroundColor: '#000', opacity: .9}, - layoutCSS: {position: 'fixed', zIndex: 101, top: 0, right: 0, bottom: 0, left: 0, display: 'none', + layoutCSS: {position: 'fixed', zIndex: 101, top: 0, right: 0, bottom: 0, left: 0, '-webkit-user-select': 'none', '-moz-user-select': 'none', 'user-select': 'none', '-webkit-tap-highlight-color': 'rgba(0, 0, 0, 0)', lineHeight: 2.5}, + boxCSS: {position: 'absolute', width: '312.5%', height: '100%', left: '-106.25%', top: 0}, prevBtnWrapperCSS: {cursor: 'pointer', position: 'absolute', top: 0, right: '50%', bottom: 0, left: 0}, - closeBtnWrapperCSS: {cursor: 'pointer', position: 'absolute', top: 0, right: 0, bottom: 0, left: '50%'}, + closeBtnWrapperCSS: {cursor: 'pointer', position: 'absolute', top: 0, right: 0, bottom: 0, left: '50%'}, - prevBtnBoxCSS: {position: 'absolute', zIndex: 104, top: 0, bottom: 0, left: 0}, - closeBtnBoxCSS: {position: 'absolute', zIndex: 104, top: 0, bottom: 0, right: 0}, + prevBtnBoxCSS: {position: 'absolute', zIndex: 103, top: 0, bottom: 0, left: '68%'}, + closeBtnBoxCSS: {position: 'absolute', zIndex: 103, top: 0, bottom: 0, right: '68%'}, prevBtnCSS: {color: '#fff', backgroundColor: '#000', opacity: .5, padding: '0 1em', borderRadius: '0 0 1ex 0'}, @@ -187,12 +480,15 @@ imgCSS: {position: 'absolute', zIndex: 102, margin: 'auto', width: 'auto', top: 0, right: 0, bottom: 0, left: 0, - display: 'block', cursor: 'pointer', maxWidth: '100%', maxHeight: '100%'}, - - imgNextCSS: {position: 'absolute', top: '-10000px', left: 0, width: '1px'}, - imgPrevCSS: {position: 'absolute', top: '-10000px', left: 0, width: '1px'}, - - bottomCSS: {position: 'absolute', zIndex: 103, right: 0, bottom: 0, left: 0, + display: 'block', cursor: 'pointer', maxWidth: '32%', maxHeight: '100%'}, + imgNextCSS: {position: 'absolute', margin: 'auto', width: 'auto', + top: 0, right: 0, bottom: 0, left: '68%', + display: 'block', maxWidth: '32%', maxHeight: '100%'}, + imgPrevCSS: {position: 'absolute', margin: 'auto', width: 'auto', + top: 0, right: '68%', bottom: 0, left: 0, + display: 'block', maxWidth: '32%', maxHeight: '100%'}, + + bottomCSS: {position: 'fixed', zIndex: 104, right: 0, bottom: 0, left: 0, '-webkit-user-select': 'text', '-moz-user-select': 'text', 'user-select': 'text', backgroundColor: '#000', color: '#fff', opacity: .5, padding: '0 1em', textAlign: 'center'}, @@ -200,6 +496,7 @@ overlayAttrs: {}, layoutAttrs: {}, + boxAttrs: {}, prevBtnWrapperAttrs: {}, prevBtnBoxAttrs: {}, prevBtnAttrs: {}, diff --git a/abigimage.jquery.json b/abigimage.jquery.json index 26121a4..9a0e9c9 100644 --- a/abigimage.jquery.json +++ b/abigimage.jquery.json @@ -1,6 +1,6 @@ { "name": "abigimage", - "version": "1.2.4", + "version": "1.2.5", "title": "ABigImage - view big versions of images", "author": { "name": "Maksim Krylosov", @@ -14,7 +14,7 @@ "dependencies": { "jquery": ">=1.9" }, - "description": "Fit mobile devices. Uses link's `href` attribute for large images. Clicking image opens next one, clicking left side opens previous, clicking right side closes image. Hotkeys for next, previous and close buttons. Closing after viewing of all images. Preloading of next and previous images. Fully customizable styles. Customizable bottom area. Customizable `onopen` event.", + "description": "Fit mobile devices. Uses CSS3 transform and transition for smooth touch sliding. Touch slide left or right opens next or previous image, touch slide up or down closes image. Clicking image opens next one, clicking left side opens previous, clicking right side closes image. Hotkeys for next, previous and close buttons. Closing after viewing of all images. Preloading of next and previous images. Uses link's `href` or `data-href` attribute for large images. Fully customizable styles. Customizable bottom area. Customizable `onopen` event.", "keywords": [ "image", "picture", @@ -29,6 +29,8 @@ "mobile", "desktop", "slideshow", + "touch", + "slide", "keyboard", "hotkey", "responsive", diff --git a/abigimage.jquery.min.js b/abigimage.jquery.min.js index a119b37..46a4d21 100644 --- a/abigimage.jquery.min.js +++ b/abigimage.jquery.min.js @@ -1 +1 @@ -(function(a){a.fn.abigimage=function(o){var b=a.extend(true,a.fn.abigimage.defaults,o);this.overlay=a("
").attr(b.overlayAttrs).css(b.overlayCSS).appendTo("body");this.layout=a("
").attr(b.layoutAttrs).css(b.layoutCSS).appendTo("body");this.prevBtnWrapper=a("
").attr(b.prevBtnWrapperAttrs).css(b.prevBtnWrapperCSS).appendTo(this.layout);this.prevBtnBox=a("
").attr(b.prevBtnBoxAttrs).css(b.prevBtnBoxCSS).appendTo(this.prevBtnWrapper);this.prevBtn=a("
").attr(b.prevBtnAttrs).css(b.prevBtnCSS).appendTo(this.prevBtnBox).html(b.prevBtnHtml);this.closeBtnWrapper=a("
").attr(b.closeBtnWrapperAttrs).css(b.closeBtnWrapperCSS).appendTo(this.layout);this.closeBtnBox=a("
").attr(b.closeBtnBoxAttrs).css(b.closeBtnBoxCSS).appendTo(this.closeBtnWrapper);this.closeBtn=a("
").attr(b.closeBtnAttrs).css(b.closeBtnCSS).appendTo(this.closeBtnBox).html(b.closeBtnHtml);this.img=a("").attr(b.imgAttrs).css(b.imgCSS).appendTo(this.layout);this.imgNext=a("").attr(b.imgNextAttrs).css(b.imgNextCSS).appendTo(this.layout);this.imgPrev=a("").attr(b.imgPrevAttrs).css(b.imgPrevCSS).appendTo(this.layout);this.bottom=a("
").attr(b.bottomAttrs).css(b.bottomCSS).appendTo(this.layout);var n=this,j=0,f=null;function k(){var d=f+1;if(d===n.length){d=0}return d}function c(){var d=f-1;if(d===-1){d=n.length-1}return d}function h(){if(j===n.length-1){return m()}else{++j;return g(k())}}function e(){if(j===1-n.length){return m()}else{--j;return g(c())}}function l(d){if(b.keyNext.indexOf(d.which)!==-1){d.preventDefault();h()}else{if(b.keyPrev.indexOf(d.which)!==-1){d.preventDefault();e()}else{if(b.keyClose.indexOf(d.which)!==-1){d.preventDefault();m()}}}}function m(){j=0;n.overlay.fadeOut(b.fadeOut);n.layout.fadeOut(b.fadeOut);a(document).unbind("keydown",l);return false}function g(d){if(d<0||d>n.length-1){return}f=d;n.img.removeAttr("src").attr("src",a(n[f]).attr("href"));n.overlay.fadeIn(b.fadeIn);n.layout.fadeIn(b.fadeIn);b.onopen.call(n,n[f]);a(document).unbind("keydown",l).bind("keydown",l);return false}this.img.load(function(){n.imgNext.attr("src",a(n[k()]).attr("href"));n.imgPrev.attr("src",a(n[c()]).attr("href"))});this.img.click(function(){return h()});this.prevBtnWrapper.click(function(){return e()});this.closeBtnWrapper.click(function(){return m()});this.prevBtnWrapper.hover(function(){n.prevBtn.stop().animate(b.prevBtnHoverCSS,b.fadeIn)},function(){n.prevBtn.stop().animate(b.prevBtnCSS,b.fadeOut)});this.closeBtnWrapper.hover(function(){n.closeBtn.stop().animate(b.closeBtnHoverCSS,b.fadeIn)},function(){n.closeBtn.stop().animate(b.closeBtnCSS,b.fadeOut)});this.bottom.hover(function(){n.bottom.stop().animate(b.bottomHoverCSS,b.fadeIn)},function(){n.bottom.stop().animate(b.bottomCSS,b.fadeOut)});return this.each(function(d){a(this).click(function(){return g(d)})})};a.fn.abigimage.defaults={fadeIn:"fast",fadeOut:"fast",prevBtnHtml:"←",closeBtnHtml:"x",keyNext:[13,32,39,40],keyPrev:[8,37,38],keyClose:[27,35,36],onopen:function(){},overlayCSS:{position:"fixed",zIndex:101,top:0,right:0,bottom:0,left:0,display:"none",backgroundColor:"#000",opacity:0.9},layoutCSS:{position:"fixed",zIndex:101,top:0,right:0,bottom:0,left:0,display:"none","-webkit-user-select":"none","-moz-user-select":"none","user-select":"none","-webkit-tap-highlight-color":"rgba(0, 0, 0, 0)",lineHeight:2.5},prevBtnWrapperCSS:{cursor:"pointer",position:"absolute",top:0,right:"50%",bottom:0,left:0},closeBtnWrapperCSS:{cursor:"pointer",position:"absolute",top:0,right:0,bottom:0,left:"50%"},prevBtnBoxCSS:{position:"absolute",zIndex:104,top:0,bottom:0,left:0},closeBtnBoxCSS:{position:"absolute",zIndex:104,top:0,bottom:0,right:0},prevBtnCSS:{color:"#fff",backgroundColor:"#000",opacity:0.5,padding:"0 1em",borderRadius:"0 0 1ex 0"},closeBtnCSS:{color:"#fff",backgroundColor:"#000",opacity:0.5,padding:"0 1em",borderRadius:"0 0 0 1ex"},prevBtnHoverCSS:{opacity:1},closeBtnHoverCSS:{opacity:1},imgCSS:{position:"absolute",zIndex:102,margin:"auto",width:"auto",top:0,right:0,bottom:0,left:0,display:"block",cursor:"pointer",maxWidth:"100%",maxHeight:"100%"},imgNextCSS:{position:"absolute",top:"-10000px",left:0,width:"1px"},imgPrevCSS:{position:"absolute",top:"-10000px",left:0,width:"1px"},bottomCSS:{position:"absolute",zIndex:103,right:0,bottom:0,left:0,"-webkit-user-select":"text","-moz-user-select":"text","user-select":"text",backgroundColor:"#000",color:"#fff",opacity:0.5,padding:"0 1em",textAlign:"center"},bottomHoverCSS:{opacity:1},overlayAttrs:{},layoutAttrs:{},prevBtnWrapperAttrs:{},prevBtnBoxAttrs:{},prevBtnAttrs:{},closeBtnWrapperAttrs:{},closeBtnBoxAttrs:{},closeBtnAttrs:{},imgAttrs:{},imgNextAttrs:{},imgPrevAttrs:{},bottomAttrs:{}}}(jQuery)); \ No newline at end of file +(function(R){var af=R("
").css({display:"none"}).appendTo("body"),O=R("
").css({display:"none"}).appendTo("body"),n=R("
").appendTo(O),T=R("
").appendTo(n),E=R("
").appendTo(T),v=R("
").appendTo(E),A=R("
").appendTo(n),K=R("
").appendTo(A),U=R("
").appendTo(K),p=R("").appendTo(n),z=R("").appendTo(n),X=R("").appendTo(n),b=R("
").appendTo(O);var L={},Y=null,ae=null,ah=0,C=false;function ac(){var d=ae+1;if(d>=Y.length){d=0}return d}function o(){var d=ae-1;if(d<0){d=Y.length-1}return d}function f(){if(ah===Y.length-1){return aa()}else{++ah;return I(ac())}}function N(){if(ah===1-Y.length){return aa()}else{--ah;return I(o())}}function F(d){if(L.keyNext.indexOf(d.which)!==-1){d.preventDefault();f()}else{if(L.keyPrev.indexOf(d.which)!==-1){d.preventDefault();N()}else{if(L.keyClose.indexOf(d.which)!==-1){d.preventDefault();aa()}}}}function I(k,d){if("number"===typeof k){if(k===ae||k<0||k>Y.length-1){return}ae=k;var t=R(Y[ae]);k=t.data("href")||t.attr("href")}else{if("number"!==typeof d){d=-1}if(ae===d){return}ae=d}C=true;p.removeAttr("src").attr("src",k);var s=R(Y[ac()]);z.removeAttr("src").attr("src",s.data("href")||s.attr("href"));var i=R(Y[o()]);X.removeAttr("src").attr("src",i.data("href")||i.attr("href"));af.fadeIn(L.fadeIn);O.fadeIn(L.fadeIn);L.onopen.call(Y,Y[ae],ae);R(document).unbind("keydown",F).bind("keydown",F);return false}function aa(){if(!C){return}C=false;ae=null;ah=0;af.fadeOut(L.fadeOut);O.fadeOut(L.fadeOut);L.onclose.call(Y);R(document).unbind("keydown",F);return false}T.click(function(){return N()});A.click(function(){return aa()});var h=function(d){d.preventDefault()};O.on("touchmove",h).on("wheel",h);var r,q,w,W,V,Z,ad,l,g,H,S,J,a,e,ai,B,ak,M,Q,ab;aj();function aj(){W=0;V=0;Z=1;B=null;if(L.imgCSS){p.css({zIndex:L.imgCSS.zIndex})}}function D(k,x){var s=0;for(var i=0,d=k.length;i1){ad=ag(d);p.css({zIndex:L.prevBtnBoxCSS.zIndex})}else{B=null;J=(new Date()).getTime();a=n.width()*0.34;e=n.height();ai=L.slideWidth*a;H=p.width();S=p.height()}r=W;q=V;w=Z;l=0;g=0;ak=d.touches;d.preventDefault()});p[0].addEventListener("touchmove",function(i){l=(D(i.touches,"X")-D(ak,"X"));g=(D(i.touches,"Y")-D(ak,"Y"));W=r+l/Z;V=q+g/Z;if(i.touches.length>1){Z=Math.max(1,w*(ag(i)/ad))}if(Z>L.zoomMin){var k=0.5*(H-(H/Z));var d=0.5*(S-(S/Z));W=Math.max(-k,Math.min(k,W));V=Math.max(-d,Math.min(d,V))}else{if(null===B){B=Math.abs(g)>Math.abs(l)}if(B){W=0}else{V=0}}u(W,V,Z);i.preventDefault()});p[0].addEventListener("touchend",function(i){var d=(new Date()).getTime()-J;if(!i.touches.length){if(Z<=L.zoomMin){if(d<20&&l<=1&&g<=1){u(0,0,1,false);f()}else{if(B){var k=Math.abs(g);if(k>ai){G(c)}else{if(k/d>L.slideVelocity){G(c)}else{G(j)}}}else{if(l<-ai){P()}else{if(l>ai){m()}else{if(Math.abs(l)/d>L.slideVelocity){if(l<0){P()}else{m()}}else{G(j)}}}}}aj()}else{if(Z>L.zoomMax){Z=L.zoomMax;u(W,V,Z,true)}}}if(Z<=L.zoomMin){p.css({zIndex:L.imgCSS.zIndex})}ak=i.touches;i.preventDefault()});n.on("transitionend webkitTransitionEnd msTransitionEnd oTransitionEnd",function(){ab=false;if(Q){Q();Q=null;u(0,0,1,false)}else{if(M){M();M=null}}});p.click(function(){return f()});function P(){setTimeout(function(){Q=f},100);u(-a,0,1,true)}function m(){setTimeout(function(){Q=N},100);u(a,0,1,true)}function j(){u(0,0,1,true)}function c(){j();aa()}function G(d){if(ab){M=d}else{d()}}function u(d,al,k,t){ab=true;if(true===t){t="all .2s ease-out"}else{if(false===t){t=""}else{t="all .02s linear"}}var i="scale("+k+") translate("+d+"px, "+al+"px)";n.css({"-webkit-transform":i,"-moz-transform":i,"-ms-transform":i,"-o-transform":i,transform:i,transition:t})}R.fn.abigimage=function(s){Y=this;L=R.extend(true,R.fn.abigimage.defaults,s);this.overlay=af.attr(L.overlayAttrs).css(L.overlayCSS);this.layout=O.attr(L.layoutAttrs).css(L.layoutCSS);this.box=n.attr(L.boxAttrs).css(L.boxCSS);this.prevBtnWrapper=T.attr(L.prevBtnWrapperAttrs).css(L.prevBtnWrapperCSS);this.prevBtnBox=E.attr(L.prevBtnBoxAttrs).css(L.prevBtnBoxCSS);this.prevBtn=v.attr(L.prevBtnAttrs).css(L.prevBtnCSS).html(L.prevBtnHtml);this.closeBtnWrapper=A.attr(L.closeBtnWrapperAttrs).css(L.closeBtnWrapperCSS);this.closeBtnBox=K.attr(L.closeBtnBoxAttrs).css(L.closeBtnBoxCSS);this.closeBtn=U.attr(L.closeBtnAttrs).css(L.closeBtnCSS).html(L.closeBtnHtml);this.img=p.attr(L.imgAttrs).css(L.imgCSS);this.imgNext=z.attr(L.imgNextAttrs).css(L.imgNextCSS);this.imgPrev=X.attr(L.imgPrevAttrs).css(L.imgPrevCSS);this.bottom=b.attr(L.bottomAttrs).css(L.bottomCSS);var k={};for(var t in L.prevBtnHoverCSS){if(L.prevBtnCSS){k[t]=L.prevBtnCSS[t]}}var d={};for(var t in L.closeBtnHoverCSS){if(L.closeBtnCSS){d[t]=L.closeBtnCSS[t]}}var i={};for(var t in L.bottomHoverCSS){if(L.bottomCSS){i[t]=L.bottomCSS[t]}}this.prevBtnWrapper.hover(function(){v.stop().animate(L.prevBtnHoverCSS,L.fadeIn)},function(){v.stop().animate(k,L.fadeOut)});this.closeBtnWrapper.hover(function(){U.stop().animate(L.closeBtnHoverCSS,L.fadeIn)},function(){U.stop().animate(d,L.fadeOut)});this.bottom.hover(function(){b.stop().animate(L.bottomHoverCSS,L.fadeIn)},function(){b.stop().animate(i,L.fadeOut)});return this.each(function(x){R(this).unbind("click.abigimage").bind("click.abigimage",function(){return I(x)})})};R.abigimage={open:I,next:f,prev:N,close:aa};R.fn.abigimage.defaults={fadeIn:"fast",fadeOut:"fast",slideWidth:0.4,slideVelocity:0.4,zoomMin:1.5,zoomMax:5,prevBtnHtml:"←",closeBtnHtml:"x",keyNext:[13,32,39,40],keyPrev:[8,37,38],keyClose:[27,35,36],onopen:function(){},onclose:function(){},overlayCSS:{position:"fixed",zIndex:101,top:0,right:0,bottom:0,left:0,backgroundColor:"#000",opacity:0.9},layoutCSS:{position:"fixed",zIndex:101,top:0,right:0,bottom:0,left:0,"-webkit-user-select":"none","-moz-user-select":"none","user-select":"none","-webkit-tap-highlight-color":"rgba(0, 0, 0, 0)",lineHeight:2.5},boxCSS:{position:"absolute",width:"312.5%",height:"100%",left:"-106.25%",top:0},prevBtnWrapperCSS:{cursor:"pointer",position:"absolute",top:0,right:"50%",bottom:0,left:0},closeBtnWrapperCSS:{cursor:"pointer",position:"absolute",top:0,right:0,bottom:0,left:"50%"},prevBtnBoxCSS:{position:"absolute",zIndex:103,top:0,bottom:0,left:"68%"},closeBtnBoxCSS:{position:"absolute",zIndex:103,top:0,bottom:0,right:"68%"},prevBtnCSS:{color:"#fff",backgroundColor:"#000",opacity:0.5,padding:"0 1em",borderRadius:"0 0 1ex 0"},closeBtnCSS:{color:"#fff",backgroundColor:"#000",opacity:0.5,padding:"0 1em",borderRadius:"0 0 0 1ex"},prevBtnHoverCSS:{opacity:1},closeBtnHoverCSS:{opacity:1},imgCSS:{position:"absolute",zIndex:102,margin:"auto",width:"auto",top:0,right:0,bottom:0,left:0,display:"block",cursor:"pointer",maxWidth:"32%",maxHeight:"100%"},imgNextCSS:{position:"absolute",margin:"auto",width:"auto",top:0,right:0,bottom:0,left:"68%",display:"block",maxWidth:"32%",maxHeight:"100%"},imgPrevCSS:{position:"absolute",margin:"auto",width:"auto",top:0,right:"68%",bottom:0,left:0,display:"block",maxWidth:"32%",maxHeight:"100%"},bottomCSS:{position:"fixed",zIndex:104,right:0,bottom:0,left:0,"-webkit-user-select":"text","-moz-user-select":"text","user-select":"text",backgroundColor:"#000",color:"#fff",opacity:0.5,padding:"0 1em",textAlign:"center"},bottomHoverCSS:{opacity:1},overlayAttrs:{},layoutAttrs:{},boxAttrs:{},prevBtnWrapperAttrs:{},prevBtnBoxAttrs:{},prevBtnAttrs:{},closeBtnWrapperAttrs:{},closeBtnBoxAttrs:{},closeBtnAttrs:{},imgAttrs:{},imgNextAttrs:{},imgPrevAttrs:{},bottomAttrs:{}}}(jQuery)); \ No newline at end of file diff --git a/img/1-big.jpg b/img/1-big.jpg index 74ad2ed..3d44f3e 100644 Binary files a/img/1-big.jpg and b/img/1-big.jpg differ diff --git a/img/1-small.jpg b/img/1-small.jpg index 3311838..bf050f3 100644 Binary files a/img/1-small.jpg and b/img/1-small.jpg differ diff --git a/img/2-big.jpg b/img/2-big.jpg index 1200ef8..a02ebb6 100644 Binary files a/img/2-big.jpg and b/img/2-big.jpg differ diff --git a/img/2-small.jpg b/img/2-small.jpg index bf905b6..ca2f24f 100644 Binary files a/img/2-small.jpg and b/img/2-small.jpg differ diff --git a/img/3-big.jpg b/img/3-big.jpg index d5a534f..97102c4 100644 Binary files a/img/3-big.jpg and b/img/3-big.jpg differ diff --git a/img/3-small.jpg b/img/3-small.jpg index 196dc2d..5c17598 100644 Binary files a/img/3-small.jpg and b/img/3-small.jpg differ diff --git a/img/4-big.jpg b/img/4-big.jpg index d9d220e..3b2e724 100644 Binary files a/img/4-big.jpg and b/img/4-big.jpg differ diff --git a/img/4-small.jpg b/img/4-small.jpg index b4010d7..4f6319a 100644 Binary files a/img/4-small.jpg and b/img/4-small.jpg differ diff --git a/index.html b/index.html index 28b9e22..77bb8ba 100644 --- a/index.html +++ b/index.html @@ -45,21 +45,17 @@ } @media (min-width: 700px) { - .features { + .coll { float: left; width: 50%; } - .ads { + .colr { float: right; + width: 300px; } } - .ads-title { - color: #000; - font-size: 1.3em; - } - .clearfix { clear: both; } @@ -78,34 +74,48 @@

ABigImage

ABigImage is jQuery plugin for viewing big versions of images.

+

Current version: 1.2.5 (2014-05-15).

- + +
+ +
+ +
+
+ + + + +
+
-
-

Features

+

Features

+
  • Fit mobile devices.
  • -
  • Uses link's href attribute for large images.
  • +
  • Uses CSS3 transform and transition for smooth touch sliding.
  • +
  • Touch slide left or right opens next or previous image, touch slide up or down closes image.
  • Clicking image opens next one, clicking left side opens previous, clicking right side closes image.
  • Hotkeys for next, previous and close buttons.
  • Closing after viewing of all images.
  • Preloading of next and previous images.
  • +
  • Uses link's href or data-href attribute for large images.
  • Fully customizable styles.
  • Customizable bottom area.
  • Customizable onopen event.
-
-
Sponsored links
+
Example Second image Third image Fourth image +

+ +

Live example, where I'm using and testing this plugin at the moment: kawaiinyan.com.

Usage

@@ -135,17 +148,28 @@

Basic

Call plugin on selector of enlargeable images links.

$(function() {
+    /* all links with class "myimgclass" */
+    $('.myimgclass').abigimage();
+
+    /* or all links to "*.jpg" images */
     $('a[href$=".jpg"]').abigimage();
+
+    /* or all links to images under dir "/my/images/dir/" */
+    $('a[href^="/my/images/dir/"]').abigimage();
 });
 

Options

    -
  • fadeIn - fade in duration or options.
  • -
  • fadeOut - fade out duration or options.
  • -
  • prevBtnHtml - html of "previous" button.
  • -
  • closeBtnHtml - html of "close" button.
  • +
  • fadeIn - fade in duration or options (default: fast).
  • +
  • fadeOut - fade out duration or options (default: fast).
  • +
  • slideWidth - slide width to switch or close image (between 0 and 1, default: 0.4).
  • +
  • slideVelocity - slide velocity to switch or close image (pixels per millisecond, default: 0.4).
  • +
  • zoomMin - minimal zoom that will hold (default: 1.5).
  • +
  • zoomMax - maximal zoom (default: 5).
  • +
  • prevBtnHtml - html of "previous" button (default: ).
  • +
  • closeBtnHtml - html of "close" button (default: x).
  • keyNext - hotkeys for "next" button (by default: 13 enter, 32 space, 39 right, 40 down).
  • keyPrev - hotkeys for "previous" button (by default: 8 backspace, 37 left, 38 up).
  • keyClose - hotkeys for "close" button (by default: 27 escape, 35 end, 36 home).
  • @@ -163,28 +187,31 @@

    Options

    <div></div> <!-- layout --> <div> - <!-- prevBtnWrapper (clickable behind the image, width 50%) --> + <!-- box --> <div> - <!-- prevBtnBox (clickable above the image, button width) --> + <!-- prevBtnWrapper (clickable behind the image, width 50%) --> <div> - <!-- prevBtn --> - <div><!-- prevBtnHtml --></div> + <!-- prevBtnBox (clickable above the image, button width) --> + <div> + <!-- prevBtn --> + <div><!-- prevBtnHtml --></div> + </div> </div> - </div> - <!-- closeBtnWrapper (clickable behind the image, width 50%) --> - <div> - <!-- closeBtnBox (clickable above the image, button width) --> + <!-- closeBtnWrapper (clickable behind the image, width 50%) --> <div> - <!-- closeBtn --> - <div><!-- closeBtnHtml --></div> + <!-- closeBtnBox (clickable above the image, button width) --> + <div> + <!-- closeBtn --> + <div><!-- closeBtnHtml --></div> + </div> </div> + <!-- img --> + <img> + <!-- imgNext --> + <img> + <!-- imgPrev --> + <img> </div> - <!-- img --> - <img> - <!-- imgNext --> - <img> - <!-- imgPrev --> - <img> <!-- bottom --> <div></div> </div> @@ -208,7 +235,17 @@

    Using onopen handler

    }); +

    Using data-href attribute

    + +

    If you want different link for plugin's big image and for non-javascript clients (search engines or browsers without javascript) - use data-href attribute:

    + +
    <a href="/non_javascript_link.html" data-href="/images/big/myimage.jpg"> ... </a>
    + +

    Also, you can use data-href attribute on any element, not only links.

    + + +

    P. S.

    I WANT your comments, feature requests, bug reports, suggestions, thoughts... on GitHub.

    @@ -221,7 +258,7 @@

    Using onopen handler

    - +