2 * jQzoom Evolution Library v2.3 - Javascript Image magnifier
3 * http://www.mind-projects.it
5 * Copyright 2011, Engineer Marco Renzi
6 * Licensed under the BSD license.
8 * Redistribution and use in source and binary forms, with or without
9 * modification, are permitted provided that the following conditions are met:
10 * * Redistributions of source code must retain the above copyright
11 * notice, this list of conditions and the following disclaimer.
12 * * Redistributions in binary form must reproduce the above copyright
13 * notice, this list of conditions and the following disclaimer in the
14 * documentation and/or other materials provided with the distribution.
15 * * Neither the name of the organization nor the
16 * names of its contributors may be used to endorse or promote products
17 * derived from this software without specific prior written permission.
19 * Date: 03 May 2011 22:16:00
23 var isIE6 = ($.browser.msie && $.browser.version < 7);
24 var body = $(document.body);
25 var window = $(window);
26 var jqzoompluging_disabled = false; //disabilita globalmente il plugin
27 $.fn.jqzoom = function (options) {
28 return this.each(function () {
29 var node = this.nodeName.toLowerCase();
31 new jqzoom(this, options);
35 jqzoom = function (el, options) {
37 api = $(el).data("jqzoom");
40 var settings = $.extend({}, $.jqzoom.defaults, options || {});
42 el.rel = $(el).attr('rel');
44 el.zoom_active = false;
45 el.zoom_disabled = false; //to disable single zoom instance
46 el.largeimageloading = false; //tell us if large image is loading
47 el.largeimageloaded = false; //tell us if large image is loaded
53 'outline-style': 'none',
54 'text-decoration': 'none'
57 var img = $("img:eq(0)", el);
58 el.title = $(el).attr('title');
59 el.imagetitle = img.attr('title');
60 var zoomtitle = ($.trim(el.title).length > 0) ? el.title : el.imagetitle;
61 var smallimage = new Smallimage(img);
62 var lens = new Lens();
63 var stage = new Stage();
64 var largeimage = new Largeimage();
65 var loader = new Loader();
66 //preventing default click,allowing the onclick event [exmple: lightbox]
67 $(el).bind('click', function (e) {
71 //setting the default zoomType if not in settings
72 var zoomtypes = ['standard', 'drag', 'innerzoom', 'reverse'];
73 if ($.inArray($.trim(settings.zoomType), zoomtypes) < 0) {
74 settings.zoomType = 'standard';
77 create: function () { //create the main objects
79 if ($(".zoomPad", el).length == 0) {
80 el.zoomPad = $('<div/>').addClass('zoomPad');
83 if(settings.zoomType == 'innerzoom'){
84 settings.zoomWidth = smallimage.w;
85 settings.zoomHeight = smallimage.h;
88 if ($(".zoomPup", el).length == 0) {
92 if ($(".zoomWindow", el).length == 0) {
96 if ($(".zoomPreload", el).length == 0) {
100 if (settings.preloadImages || settings.zoomType == 'drag' || settings.alwaysOn) {
107 if (settings.zoomType == 'drag') {
108 $(".zoomPad", el).mousedown(function () {
111 $(".zoomPad", el).mouseup(function () {
112 el.mouseDown = false;
114 document.body.ondragstart = function () {
117 $(".zoomPad", el).css({
120 $(".zoomPup", el).css({
124 if (settings.zoomType == 'innerzoom') {
125 $(".zoomWrapper", el).css({
129 $(".zoomPad", el).bind('mouseenter mouseover', function (event) {
130 img.attr('title', '');
131 $(el).attr('title', '');
132 el.zoom_active = true;
133 //if loaded then activate else load large image
134 smallimage.fetchdata();
135 if (el.largeimageloaded) {
141 $(".zoomPad", el).bind('mouseleave', function (event) {
144 $(".zoomPad", el).bind('mousemove', function (e) {
146 //prevent fast mouse mevements not to fire the mouseout event
147 if (e.pageX > smallimage.pos.r || e.pageX < smallimage.pos.l || e.pageY < smallimage.pos.t || e.pageY > smallimage.pos.b) {
151 el.zoom_active = true;
152 if (el.largeimageloaded && !$('.zoomWindow', el).is(':visible')) {
155 if (el.largeimageloaded && (settings.zoomType != 'drag' || (settings.zoomType == 'drag' && el.mouseDown))) {
159 var thumb_preload = new Array();
161 //binding click event on thumbnails
162 var thumblist = new Array();
163 thumblist = $('a').filter(function () {
164 var regex = new RegExp("gallery[\\s]*:[\\s]*'" + $.trim(el.rel) + "'", "i");
165 var rel = $(this).attr('rel');
166 if (regex.test(rel)) {
170 if (thumblist.length > 0) {
171 //getting the first to the last
172 var first = thumblist.splice(0, 1);
173 thumblist.push(first);
175 thumblist.each(function () {
177 if (settings.preloadImages) {
178 var thumb_options = $.extend({}, eval("(" + $.trim($(this).attr('rel')) + ")"));
179 thumb_preload[i] = new Image();
180 thumb_preload[i].src = thumb_options.largeimage;
183 $(this).click(function (e) {
184 if($(this).hasClass('zoomThumbActive')){
187 thumblist.each(function () {
188 $(this).removeClass('zoomThumbActive');
197 if (el.largeimageloaded == false && el.largeimageloading == false) {
198 var url = $(el).attr('href');
199 el.largeimageloading = true;
200 largeimage.loadimage(url);
203 activate: function (e) {
204 clearTimeout(el.timer);
205 //show lens and zoomWindow
209 deactivate: function (e) {
210 switch (settings.zoomType) {
212 //nothing or lens.setcenter();
215 img.attr('title', el.imagetitle);
216 $(el).attr('title', el.title);
217 if (settings.alwaysOn) {
225 el.zoom_active = false;
227 swapimage: function (link) {
228 el.largeimageloading = false;
229 el.largeimageloaded = false;
230 var options = new Object();
231 options = $.extend({}, eval("(" + $.trim($(link).attr('rel')) + ")"));
232 if (options.smallimage && options.largeimage) {
233 var smallimage = options.smallimage;
234 var largeimage = options.largeimage;
235 $(link).addClass('zoomThumbActive');
236 $(el).attr('href', largeimage);
237 img.attr('src', smallimage);
242 alert('ERROR :: Missing parameter for largeimage or smallimage.');
243 throw 'ERROR :: Missing parameter for largeimage or smallimage.';
248 //sometimes image is already loaded and onload will not fire
249 if (img[0].complete) {
250 //fetching data from sallimage if was previously loaded
251 smallimage.fetchdata();
252 if ($(".zoomPad", el).length == 0) obj.create();
254 /*========================================================,
256 |---------------------------------------------------------:
257 | Base image into the anchor element
258 `========================================================*/
260 function Smallimage(image) {
262 this.node = image[0];
263 this.findborder = function () {
265 bordertop = image.css('border-top-width');
268 borderleft = image.css('border-left-width');
271 for (i = 0; i < 3; i++) {
273 x = bordertop.substr(i, 1);
274 if (isNaN(x) == false) {
275 btop = btop + '' + bordertop.substr(i, 1);
282 for (i = 0; i < 3; i++) {
283 if (!isNaN(borderleft.substr(i, 1))) {
284 bleft = bleft + borderleft.substr(i, 1)
290 $obj.btop = (btop.length > 0) ? eval(btop) : 0;
291 $obj.bleft = (bleft.length > 0) ? eval(bleft) : 0;
293 this.fetchdata = function () {
295 $obj.w = image.width();
296 $obj.h = image.height();
297 $obj.ow = image.outerWidth();
298 $obj.oh = image.outerHeight();
299 $obj.pos = image.offset();
300 $obj.pos.l = image.offset().left + $obj.bleft;
301 $obj.pos.t = image.offset().top + $obj.btop;
302 $obj.pos.r = $obj.w + $obj.pos.l;
303 $obj.pos.b = $obj.h + $obj.pos.t;
304 $obj.rightlimit = image.offset().left + $obj.ow;
305 $obj.bottomlimit = image.offset().top + $obj.oh;
308 this.node.onerror = function () {
309 alert('Problems while loading image.');
310 throw 'Problems while loading image.';
312 this.node.onload = function () {
314 if ($(".zoomPad", el).length == 0) obj.create();
318 /*========================================================,
320 |---------------------------------------------------------:
321 | Show that the large image is loading
322 `========================================================*/
326 this.append = function () {
327 this.node = $('<div/>').addClass('zoomPreload').css('visibility', 'hidden').html(settings.preloadText);
328 $('.zoomPad', el).append(this.node);
330 this.show = function () {
331 this.node.top = (smallimage.oh - this.node.height()) / 2;
332 this.node.left = (smallimage.ow - this.node.width()) / 2;
336 left: this.node.left,
337 position: 'absolute',
338 visibility: 'visible'
341 this.hide = function () {
342 this.node.css('visibility', 'hidden');
346 /*========================================================,
348 |---------------------------------------------------------:
349 | Lens over the image
350 `========================================================*/
354 this.node = $('<div/>').addClass('zoomPup');
355 //this.nodeimgwrapper = $("<div/>").addClass('zoomPupImgWrapper');
356 this.append = function () {
357 $('.zoomPad', el).append($(this.node).hide());
358 if (settings.zoomType == 'reverse') {
359 this.image = new Image();
360 this.image.src = smallimage.node.src; // fires off async
361 $(this.node).empty().append(this.image);
364 this.setdimensions = function () {
365 this.node.w = (parseInt((settings.zoomWidth) / el.scale.x) > smallimage.w ) ? smallimage.w : (parseInt(settings.zoomWidth / el.scale.x));
366 this.node.h = (parseInt((settings.zoomHeight) / el.scale.y) > smallimage.h ) ? smallimage.h : (parseInt(settings.zoomHeight / el.scale.y));
367 this.node.top = (smallimage.oh - this.node.h - 2) / 2;
368 this.node.left = (smallimage.ow - this.node.w - 2) / 2;
373 width: this.node.w + 'px',
374 height: this.node.h + 'px',
375 position: 'absolute',
377 borderWidth: 1 + 'px'
382 if (settings.zoomType == 'reverse') {
383 this.image.src = smallimage.node.src;
389 position: 'absolute',
391 left: -(this.node.left + 1 - smallimage.bleft) + 'px',
392 top: -(this.node.top + 1 - smallimage.btop) + 'px'
397 this.setcenter = function () {
398 //calculating center position
399 this.node.top = (smallimage.oh - this.node.h - 2) / 2;
400 this.node.left = (smallimage.ow - this.node.w - 2) / 2;
406 if (settings.zoomType == 'reverse') {
408 position: 'absolute',
410 left: -(this.node.left + 1 - smallimage.bleft) + 'px',
411 top: -(this.node.top + 1 - smallimage.btop) + 'px'
415 //centering large image
416 largeimage.setposition();
418 this.setposition = function (e) {
419 el.mousepos.x = e.pageX;
420 el.mousepos.y = e.pageY;
424 function overleft(lens) {
425 return el.mousepos.x - (lens.w) / 2 < smallimage.pos.l;
428 function overright(lens) {
429 return el.mousepos.x + (lens.w) / 2 > smallimage.pos.r;
433 function overtop(lens) {
434 return el.mousepos.y - (lens.h) / 2 < smallimage.pos.t;
437 function overbottom(lens) {
438 return el.mousepos.y + (lens.h) / 2 > smallimage.pos.b;
441 lensleft = el.mousepos.x + smallimage.bleft - smallimage.pos.l - (this.node.w + 2) / 2;
442 lenstop = el.mousepos.y + smallimage.btop - smallimage.pos.t - (this.node.h + 2) / 2;
443 if (overleft(this.node)) {
444 lensleft = smallimage.bleft - 1;
445 } else if (overright(this.node)) {
446 lensleft = smallimage.w + smallimage.bleft - this.node.w - 1;
448 if (overtop(this.node)) {
449 lenstop = smallimage.btop - 1;
450 } else if (overbottom(this.node)) {
451 lenstop = smallimage.h + smallimage.btop - this.node.h - 1;
454 this.node.left = lensleft;
455 this.node.top = lenstop;
457 'left': lensleft + 'px',
458 'top': lenstop + 'px'
460 if (settings.zoomType == 'reverse') {
461 if ($.browser.msie && $.browser.version > 7) {
462 $(this.node).empty().append(this.image);
466 position: 'absolute',
468 left: -(this.node.left + 1 - smallimage.bleft) + 'px',
469 top: -(this.node.top + 1 - smallimage.btop) + 'px'
473 largeimage.setposition();
475 this.hide = function () {
481 this.show = function () {
483 if (settings.zoomType != 'innerzoom' && (settings.lens || settings.zoomType == 'drag')) {
487 if (settings.zoomType == 'reverse') {
489 'opacity': settings.imageOpacity
493 this.getoffset = function () {
495 o.left = $obj.node.left;
496 o.top = $obj.node.top;
501 /*========================================================,
503 |---------------------------------------------------------:
504 | Window area that contains the large image
505 `========================================================*/
509 this.node = $("<div class='zoomWindow'><div class='zoomWrapper'><div class='zoomWrapperTitle'></div><div class='zoomWrapperImage'></div></div></div>");
510 this.ieframe = $('<iframe class="zoomIframe" src="javascript:\'\';" marginwidth="0" marginheight="0" align="bottom" scrolling="no" frameborder="0" ></iframe>');
511 this.setposition = function () {
512 this.node.leftpos = 0;
513 this.node.toppos = 0;
514 if (settings.zoomType != 'innerzoom') {
516 switch (settings.position) {
518 this.node.leftpos = (smallimage.pos.l - smallimage.bleft - Math.abs(settings.xOffset) - settings.zoomWidth > 0) ? (0 - settings.zoomWidth - Math.abs(settings.xOffset)) : (smallimage.ow + Math.abs(settings.xOffset));
519 this.node.toppos = Math.abs(settings.yOffset);
522 this.node.leftpos = Math.abs(settings.xOffset);
523 this.node.toppos = (smallimage.pos.t - smallimage.btop - Math.abs(settings.yOffset) - settings.zoomHeight > 0) ? (0 - settings.zoomHeight - Math.abs(settings.yOffset)) : (smallimage.oh + Math.abs(settings.yOffset));
526 this.node.leftpos = Math.abs(settings.xOffset);
527 this.node.toppos = (smallimage.pos.t - smallimage.btop + smallimage.oh + Math.abs(settings.yOffset) + settings.zoomHeight < screen.height) ? (smallimage.oh + Math.abs(settings.yOffset)) : (0 - settings.zoomHeight - Math.abs(settings.yOffset));
530 this.node.leftpos = (smallimage.rightlimit + Math.abs(settings.xOffset) + settings.zoomWidth < screen.width) ? (smallimage.ow + Math.abs(settings.xOffset)) : (0 - settings.zoomWidth - Math.abs(settings.xOffset));
531 this.node.toppos = Math.abs(settings.yOffset);
536 'left': this.node.leftpos + 'px',
537 'top': this.node.toppos + 'px'
541 this.append = function () {
542 $('.zoomPad', el).append(this.node);
544 position: 'absolute',
548 if (settings.zoomType == 'innerzoom') {
552 var thickness = (smallimage.bleft == 0) ? 1 : smallimage.bleft;
553 $('.zoomWrapper', this.node).css({
554 borderWidth: thickness + 'px'
558 $('.zoomWrapper', this.node).css({
559 width: Math.round(settings.zoomWidth) + 'px' ,
560 borderWidth: thickness + 'px'
562 $('.zoomWrapperImage', this.node).css({
564 height: Math.round(settings.zoomHeight) + 'px'
567 $('.zoomWrapperTitle', this.node).css({
572 $('.zoomWrapperTitle', this.node).hide();
573 if (settings.title && zoomtitle.length > 0) {
574 $('.zoomWrapperTitle', this.node).html(zoomtitle).show();
578 this.hide = function () {
579 switch (settings.hideEffect) {
581 this.node.fadeOut(settings.fadeoutSpeed, function () {});
589 this.show = function () {
590 switch (settings.showEffect) {
593 this.node.fadeIn(settings.fadeinSpeed, function () {});
599 if (isIE6 && settings.zoomType != 'innerzoom') {
600 this.ieframe.width = this.node.width();
601 this.ieframe.height = this.node.height();
602 this.ieframe.left = this.node.leftpos;
603 this.ieframe.top = this.node.toppos;
606 position: "absolute",
607 left: this.ieframe.left,
608 top: this.ieframe.top,
610 width: this.ieframe.width + 'px',
611 height: this.ieframe.height + 'px'
613 $('.zoomPad', el).append(this.ieframe);
618 /*========================================================,
620 |---------------------------------------------------------:
621 | The large detailed image
622 `========================================================*/
624 function Largeimage() {
626 this.node = new Image();
627 this.loadimage = function (url) {
631 this.node.style.position = 'absolute';
632 this.node.style.border = '0px';
633 this.node.style.display = 'none';
634 this.node.style.left = '-5000px';
635 this.node.style.top = '0px';
636 document.body.appendChild(this.node);
637 this.node.src = url; // fires off async
639 this.fetchdata = function () {
640 var image = $(this.node);
642 this.node.style.display = 'block';
643 $obj.w = image.width();
644 $obj.h = image.height();
645 $obj.pos = image.offset();
646 $obj.pos.l = image.offset().left;
647 $obj.pos.t = image.offset().top;
648 $obj.pos.r = $obj.w + $obj.pos.l;
649 $obj.pos.b = $obj.h + $obj.pos.t;
650 scale.x = ($obj.w / smallimage.w);
651 scale.y = ($obj.h / smallimage.h);
653 document.body.removeChild(this.node);
654 $('.zoomWrapperImage', el).empty().append(this.node);
655 //setting lens dimensions;
656 lens.setdimensions();
658 this.node.onerror = function () {
659 alert('Problems while loading the big image.');
660 throw 'Problems while loading the big image.';
662 this.node.onload = function () {
666 el.largeimageloading = false;
667 el.largeimageloaded = true;
668 if (settings.zoomType == 'drag' || settings.alwaysOn) {
674 this.setposition = function () {
675 var left = -el.scale.x * (lens.getoffset().left - smallimage.bleft + 1);
676 var top = -el.scale.y * (lens.getoffset().top - smallimage.btop + 1);
684 $(el).data("jqzoom", obj);
686 //es. $.jqzoom.disable('#jqzoom1');
689 zoomType: 'standard',
690 //innerzoom/standard/reverse/drag
692 //zoomWindow default width
694 //zoomWindow default height
696 //zoomWindow x offset, can be negative(more on the left) or positive(more on the right)
698 //zoomWindow y offset, can be negative(more on the left) or positive(more on the right)
700 //zoomWindow default position
703 preloadText: 'Loading zoom',
714 fadeoutSpeed: '2000' //fast/slow/number
716 disable: function (el) {
717 var api = $(el).data('jqzoom');
721 enable: function (el) {
722 var api = $(el).data('jqzoom');
726 disableAll: function (el) {
727 jqzoompluging_disabled = true;
729 enableAll: function (el) {
730 jqzoompluging_disabled = false;