3 * Zoomy v1.0 - for jQuery 1.7.1+
5 * Copyright 2012, James Louis Thompson
6 * http://codecanyon.net/user/jameslouiz
8 * You need to buy a license to use this script.
9 * http://codecanyon.net/wiki/buying/howto-buying/licensing/
16 //used to fix method calling issues on un-instantiated objects
17 $.bind = function (object, method) {
18 var args = Array.prototype.slice.call(arguments, 2);
20 var args2 = [this].concat(args, $.makeArray(arguments));
21 return method.apply(object, args2);
26 var zoomy = function () {};
32 * @param string e The element to turn into a zoomy
33 * @param obj config An object containing the configuration options for this instance of zoomify
36 init: function (e, config) {
39 var zoomy = this, //reference to object
42 //default configuration
44 popoverClassName: 'popover',
45 popoverHeight: $(e).find('img').height() * 1.5,
46 popoverWidth: $(e).find('img').width() * 1.5,
47 popoverPosition: 'right',
50 lensHeight: $(e).find('img').height() / 1.5,
51 lensWidth: $(e).find('img').width() / 1.5,
53 triggerEvent: 'hover',
60 this.dataOptions = this.e.data();
63 this.settings = $.extend(true, defaults, config);
65 if (typeof this.dataOptions == 'object' && !$.isEmptyObject(this.dataOptions)) {
66 this.settings = $.extend(true, this.settings, this.dataOptions);
70 this.body = $('html body');
71 this.popoverHtml = '<div class=' + this.settings.popoverClassName + '><img class=' + this.settings.popoverClassName + '_image' + ' src="" /></div>';
72 this.sandboxHtml = '<div class=' + this.settings.popoverClassName + '_sandbox' + '></div>';
73 this.lensHtml = '<div class="lens"></div>';
74 this.preloaderHtml = '<div class="preloader"></div>';
75 this.thumb = this.e.find('img');
76 this.id = Math.floor(Math.random() * 999999999);
77 this.zoomedImageSource = this.e.data('zoomed-image');
78 this.useSelf = !this.zoomedImageSource ? true : false;
79 this.loaded = false;//this.thumb.data('loaded');
82 this.popoverWidth = this.settings.popoverWidth;// || this.popoverHeight;
83 this.popoverHeight = this.settings.popoverHeight;// || this.popoverWidth;
84 this.lensWidth = this.settings.lensWidth;
85 this.lensHeight = this.settings.lensHeight;
90 //Setup vars of newly injected elements
91 this.lens = this.e.find('.lens');
92 this.popover = $('.' + this.settings.popoverClassName);
93 this.sandbox = $('.' + this.settings.popoverClassName + '_sandbox');
94 this.preloader = this.e.find('.preloader');
96 //Add CSS to the elements
100 position: 'absolute',
106 position: 'relative',
113 position: 'absolute',
121 this.lens.find('img').css({
128 position: 'absolute',
135 this.sandbox.find('img').css({
136 position: 'absolute',
144 'margin-left': -(this.preloader.outerWidth() / 2),
145 'margin-top': -(this.preloader.outerHeight() / 2),
152 //Makes the zoomed image source unique incase you want multipul instances of the same
153 //image on the page but with different zoom levels or other options specified.
155 src: this.thumb.attr('src') + '?' + this.id
159 'data-zoomed-image': this.e.attr('data-zoomed-image') + '?' + this.id
163 this.e.attr({'data-zoomed-image': this.thumb.attr('src')});
166 this.zoomedImageSource = this.e.attr('data-zoomed-image');
168 if (this.thumb.attr('data-status') !== 'error') {
169 if (this.settings.preload) {
172 this.eventBindings();
179 this.e.append(this.lensHtml);
180 this.e.append(this.preloaderHtml);
181 //inject Popover only once
182 if ($("." + this.settings.popoverClassName).length < 1) {
183 this.body.append(this.popoverHtml); //change container back to this.body
185 // inject sandbox only once
186 if ($('.' + this.settings.popoverClassName + '_sandbox').length < 1) {
187 this.body.append(this.sandboxHtml); //change container back to this.body
192 * loadImages - loads the zoomed images and appends to sandbox
195 loadImages: function ()
200 showPreloader = this.settings.showPreloader,
201 preloader = this.preloader,
202 zoomedImageSource = this.zoomedImageSource,
203 loaded = this.thumb.data('loaded'),
204 sandboxZoomedImageSource = this.sandbox.find('img').attr('src'),
208 if (!loaded && zoomedImageSource) {
210 if (this.settings.showPreloader) {
211 preloader.fadeIn(200);
215 $(img).load(function () {
216 var thisImg = $(this),
219 self.injectImages(thisImg);
222 src: zoomedImageSource
223 }).error(function () {
224 thumb.data('loaded', 'failed');
225 // Callbacks for when elements shown
226 self.callHook('loadFail');
236 * FetchImage - Gets the image from the sandbox and puts it in the popover
242 var zoomedImageSource = this.zoomedImageSource,
243 zoomedImage = this.sandbox.find('img[src="'+zoomedImageSource+'"]'),
250 source = this.thumb.attr('src');
251 el = this.sandbox.find('img[src="'+source+'"]');
254 source = zoomedImageSource;
257 if (this.settings.innerZoom) { // appends the large image to lens if the option is true
258 if (this.lens.find('img').length < 1) {
259 this.lens.append(el.clone());
261 } else { // else append to popover
262 if (zoomedImageSource !== this.popover.find('img').attr('src')) {
263 this.popover.html(el.clone());
268 //this.lensSize(this.sandbox.find('img[src="'+source+'"]')); //set size of lens for this thumb
275 * Event Bindings - Bind all the mouse vents to elements
278 eventBindings: function ()
282 popover = this.popover,
284 preloadOnInit = this.settings.preload,
287 switch (this.settings.triggerEvent) {
293 trigger = 'mouseenter';
297 elem.on(trigger, function () {
307 $('body').on('mousemove.zoomy', lens, function (e) {
313 elem.on('mouseleave', function () {
314 $('body').off('mousemove.zoomy');
320 * injectImages - Injects imagaes to the relevant container. If not innerzoom - append to snadbox.
322 * @param append - DOM Object you want to append to the lens or popover
325 injectImages: function(append)
328 var loaded = this.thumb.data('loaded'),
329 platform, freshImage;
331 if (this.settings.innerZoom) {
332 platform = this.lens;
334 platform = this.sandbox;
337 if (this.zoomedImageSource != platform.find('img').attr('src')) {
338 append.css({position:'absolute'});
339 platform.append(append);
342 this.magnify(append);
344 if (this.settings.preload && !loaded) {
345 this.eventBindings(); //if the zoomed image loads, bind the events to this
347 this.grabData(append);
350 this.preloader.fadeOut(200);
352 this.thumb.data('loaded', true);
357 * Lens Size - Sets the size of the lens
359 * @param zoomedImage - DOM Object of the large image you need to calcaulate lens with
362 lensSize: function (zoomedImage) {
365 var popover = this.popver,
368 popoverHeight = this.popoverHeight,
369 popoverWidth = this.popoverWidth,
370 thumbHeight = thumb.height(),
371 thumbWidth = thumb.width(),
372 lensHeight, lensWidth, lensHeight1, lensWidth1, ex, ey;
375 if (this.settings.innerZoom) {
376 lensHeight = this.lensHeight;
377 lensWidth = this.lensWidth;
379 //lensHeight1 = (popoverHeight / (zoomedImage.height() / thumbHeight)) ;
380 //lensWidth1 = (popoverWidth / (zoomedImage.width() / thumbWidth)) ;
382 //ey = thumbHeight / lensHeight1;
383 //ex = thumbWidth / lensWidth1;
387 //lensHeight = thumbHeight / ( (zoomedImage.height()+ey) / popoverHeight); //lensHeight + (lensHeight / 100 * 3.5);
388 //lensWidth = thumbWidth / ( (zoomedImage.width()+ex) / popoverWidth) ; //lensWidth + (lensWidth / 100 * 3.5);
390 lensHeight = popoverHeight / (zoomedImage.height() / thumbHeight);
391 lensWidth = popoverWidth / (zoomedImage.width() / thumbWidth);
396 //console.log(lensHeight);
399 height: lensHeight + 0,
407 * Lens Position - Sets the position of lens on mouse move
412 lensPos: function (e)
417 thumbLeft = thumb.offset().left,
418 thumbTop = thumb.offset().top,
421 lensWidth = lens.outerWidth(),
422 lensHeight = lens.outerHeight(),
427 lensTop = mouseY - lensHeight / 2;
428 lensLeft = mouseX - lensWidth / 2;
431 function limitLeft() {
432 return mouseX - (lensWidth) / 2 < thumbLeft;
435 function limitRight() {
436 return mouseX + (lensWidth) / 2 > (thumbLeft + thumb.width());
439 function limitTop() {
440 return mouseY - (lensHeight) / 2 < thumbTop;
443 function limitBottom() {
444 return mouseY + (lensHeight) / 2 > (thumbTop + thumb.height());
448 if (limitLeft(lens)) {
449 lensLeft = thumbLeft;
450 } else if (limitRight(lens)) {
451 lensLeft = thumbLeft + thumb.width() - lensWidth;
453 if (limitTop(lens)) {
455 } else if (limitBottom(lens)) {
456 lensTop = thumbTop + thumb.height() - lensHeight;
465 self.zoomedPosition();
470 * Popover Position - Sets the position of popover on mouse move
473 popoverPos: function ()
476 if (!this.settings.innerZoom){
479 element = this.thumb,
480 popover = this.popover;
483 var popoverTop, popoverLeft;
485 switch (this.settings.popoverPosition) {
487 popoverTop = element.offset().top + this.settings.popoverOffsetY;
488 popoverLeft = element.offset().left + element.outerWidth() + this.settings.popoverOffsetX;
492 popoverTop = element.offset().top - this.popoverHeight - this.settings.popoverOffsetY;
493 popoverLeft = element.offset().left + this.settings.popoverOffsetX;
497 popoverTop = element.offset().top + element.outerHeight() + this.settings.popoverOffsetY ;
498 popoverLeft = element.offset().left + this.settings.popoverOffsetX;
501 case 'left': // defaults fixed left
502 popoverTop = element.offset().top + this.settings.popoverOffsetY;
503 popoverLeft = element.offset().left - this.popoverWidth - this.settings.popoverOffsetX;
510 height: this.popoverHeight,
511 width: this.popoverWidth
519 popover.offset(popoverPos);
527 * Sets the position of the zoomed image in the popover in relation to the lens
530 zoomedPosition: function ()
533 var el = this.settings.innerZoom ? this.lens.find('img') : this.popover.find('img'),
536 borderTop = (lens.css('border-top-width') > 0) ? parseFloat(lens.css('border-top-width')) : 0,
537 borderLeft = (lens.css('border-left-width') > 0) ? parseFloat(lens.css('border-left-width')) : 0,
538 lensHeight = lens.outerHeight(),
539 lensWidth = lens.outerWidth(),
540 thumbHeight = thumb.height(),
541 thumbWidth = thumb.width(),
542 largeImgHeight = el.height(),
543 largeImgWidth = el.width(),
544 refYY = (thumb.offset().top) - (lens.offset().top + borderTop),
545 refXX = (thumb.offset().left) - (lens.offset().left + borderLeft);
548 if (this.settings.innerZoom) {
549 hr = (largeImgHeight - lensHeight) / (thumbHeight - lensHeight);
550 wr = (largeImgWidth - lensWidth) / (thumbWidth - lensWidth);
552 hr = largeImgHeight / thumbHeight;
553 wr = largeImgWidth / thumbWidth;
558 top: (refYY) * hr,//0(thumbHeight / lensHeight),
559 left: (refXX) * wr //(thumbWidth / lensWidth)
565 * maginify - Magnifies the large image
567 * @param img DOM Object - The image you want to magnify
570 magnify: function(img)
572 var imgHeight = img.height(),
573 imgWidth = img.width(),
574 magnify = this.settings.magnify;
577 //if (img.height != imgHeight * this.settings.magnify) {
579 height: imgHeight * magnify,
580 width: imgWidth * magnify
588 * showElems - Shows the popover and lens when required. Popover doesnt show if innerZoom is enabled
591 showElems: function()
595 if (!this.settings.innerZoom) {
596 // if ( this.popover.is(':hidden') || (this.popover.is(':visible') && popover.is(':animated')) ) {
598 this.popover.stop().fadeTo(this.settings.duration, 1);
602 // if ( this.lens.is(':hidden') || this.lens.css('opacity') < 1 || (this.lens.is(':visible') && this.lens.is(':animated')) ) {
603 this.lens.stop(true, true).fadeTo(this.settings.duration, 1);
609 * hideElems - Hides the popover and lens when required.
612 hideElems: function()
615 if ( this.popover.is(':visible') || (this.popover.is(':hidden') && this.popover.is(':animated')) ) {
616 this.popover.stop().fadeOut(this.settings.duration);
619 if ( this.lens.is(':visible') || (this.lens.is(':hidden') && this.lens.is(':animated')) ) {
620 this.lens.stop().fadeOut(this.settings.duration);
627 //jQuery function to access / instantiate zoomify
628 $.fn.zoomy = function (config) {
632 msie = (!document.documentMode || document.documentMode < 9) && window.attachEvent && !window.addEventListener; // IE < 9
636 //if nothing is passed to the function and this IS a Zoomy, return instance of Zoomy
637 if (!config && el[0].zoomy) {
638 return $el.get(0).zoomy;
640 //otherwise instantiate Zoomy
642 return el.each(function () {
645 this.zoomy = new zoomy();
646 this.zoomy.init(this, config);
648 $(this).get(0).zoomy;
658 var elems = el.find('img'),
660 blank = "data:image/gif;base64,R0lGODlhAQABAIAAAAAAAP///ywAAAAAAQABAAACAUwAOw==",
661 error = "data:image/gif;base64,R0lGODlhAQABAIAAAAAAAP///ywAAAAAAQABAAACAUwAOw==";
663 elems.bind('load.imgloaded',function(){
664 if ((--len <= 0 && this.src !== blank) || this.src == error){
665 elems.unbind('load.imgloaded');
669 var curSrc = $(this).attr('src');
670 // cached images don't fire load sometimes, so we reset src.
671 if (this.complete || this.complete === undefined){
677 $(this).error(function()
679 $(this).attr('data-status', 'error');