/* * Zoomy 1.3.3 - jQuery plugin * http://redeyeops.com/plugins/zoomy * * Copyright (c) 2010 Jacob Lowe (http://redeyeoperations.com) * Dual licensed under the MIT (MIT-LICENSE.txt) * and GPL (GPL-LICENSE.txt) licenses. * * Built for jQuery library * http://jquery.com * * Addition fixes and modifications done by Larry Battle ( blarry@bateru.com ) * Code has been refactored and the logic has been corrected. * */ (function ($) { // global zoomys state, Indexed, 0 = no zoom, 1 = zoom; 'use strict'; var ZoomyS = { count : [], pos: null }; $.fn.zoomy = function (event, options) { //defaults && option list var defaults = { zoomSize: 200, round: true, glare: true, clickable: false, attr: 'href', border: '5px solid #999', zoomInit: null, //callback for when zoom initializes zoomStart: null, // callback for when zoom starts zoomStop: null // callback for when the zoom ends }, defaultEvent = 'click', change = { // Move Zoom Cursor move : function (ele, zoom, e) { var ratio = function (x, y) { var z = x / y; return z; }, id = zoom.attr('rel'), l = ele.offset(), theOffset = ZoomyS[id].zoom.border, zoomImgX = ZoomyS[id].zoom.x, zoomImgY = ZoomyS[id].zoom.y, tnImgX = ZoomyS[id].css.width, tnImgY = ZoomyS[id].css.height, zoomSize = options.zoomSize + (theOffset * 2), halfSize = zoomSize / 2, ratioX = ratio(tnImgX, zoomImgX), ratioY = ratio(tnImgY, zoomImgY), stop = halfSize - (halfSize * ratioX) - (theOffset * ratioX) + theOffset, stopPos = function (x) { var p = (x - zoomSize - theOffset) + stop; return p; }, rightStop = stopPos(tnImgX), bottomStop = stopPos(tnImgY), zoomY = zoomImgY - zoomSize, zoomX = zoomImgX - zoomSize, mousePos = function (x, y) { var p = x - y - halfSize; return p; }, zoomPos = function (x, y, z) { var p = ((x - y) / z) - halfSize + theOffset; return p; }, cdCreate = function (a, b, c, d) { var bgPos = '-' + a + 'px ' + '-' + b + 'px', o = { backgroundPosition: bgPos, left: c, top: d }; return o; }, posX = mousePos(e.pageX, l.left), posY = mousePos(e.pageY, l.top), leftX = zoomPos(e.pageX, l.left, ratioX), topY = zoomPos(e.pageY, l.top, ratioY), // Collision Detection Possiblities arrPosb = { // In the Center 0 : [leftX, topY, posX, posY], // On Left Side 1 : [0, topY, -stop, posY], // On the Top Left Corner 2 : [0, 0, -stop, -stop], //On the Bottom Left Corner 3 : [0, zoomY, -stop, bottomStop], // On the Top 4 : [leftX, 0, posX, -stop], //On the Top Right Corner 5 : [zoomX, 0, rightStop, -stop], //On the Right Side 6 : [zoomX, topY, rightStop, posY], //On the Bottom Right Corner 7 : [zoomX, zoomY, rightStop, bottomStop], //On the Bottom 8 : [leftX, zoomY, posX, bottomStop] }, // Test for collisions a = -stop <= posX, e2 = -stop > posX, b = -stop <= posY, f = -stop > posY, d = bottomStop > posY, g = bottomStop <= posY, c = rightStop > posX, j = rightStop <= posX, // Results cssArrIndex = (a && b && c && d) ? 0 : (e2) ? (b && d) ? 1 : (f) ? 2 : (g) ? 3 : null : (f) ? (c) ? 4 : 5 : (j) ? (d) ? 6 : 7 : (g) ? 8 : null, //Create CSS object to move Zoomy move = cdCreate(arrPosb[cssArrIndex][0], arrPosb[cssArrIndex][1], arrPosb[cssArrIndex][2], arrPosb[cssArrIndex][3], arrPosb[cssArrIndex][4], arrPosb[cssArrIndex][5]); //Uncomment to see Index number for collision type //console.log(cssArrIndex) // And Actual Call zoom.css(move || {}); }, // Change classes for original image effect classes : function (ele) { var i = ele.find('.zoomy').attr('rel'); if (ZoomyS[i].state === 0 || ZoomyS[i].state === null) { ele.removeClass('inactive'); } else { ele.addClass('inactive'); } }, // Enter zoom area start up Zoom again enter : function (ele, zoom) { var i = zoom.attr('rel'); ZoomyS[i].state = 1; zoom.css('visibility', 'visible'); change.classes(ele); }, // Leave zoom area leave : function (ele, zoom, x) { var i = zoom.attr('rel'); if (x !== null) { ZoomyS[i].state = null; } else { ZoomyS[i].state = 0; } zoom.css('visibility', 'hidden'); change.classes(ele); }, // Callback handler (startZoom && stopZoom) callback : function (type, zoom) { var callbackFunc = type, zoomId = zoom.attr('rel'); if (callbackFunc !== null && typeof callbackFunc === 'function') { callbackFunc($.extend({}, ZoomyS[zoomId], ZoomyS.pos)); } } }, // Styling Object, holds pretty much all styling except for some minor tweeks style = { round : function (x, y) { var cssObj = (!options.round) ? 0 : ( x === undefined) ? options.zoomSize + y / 2 + 'px' : options.zoomSize / 2 + 'px ' + options.zoomSize / 2 + 'px 0px 0px'; return cssObj; }, glare : function (zoom) { zoom.children('span').css({ height: options.zoomSize / 2, width: options.zoomSize - 10, margin: ($.browser.msie && parseInt($.browser.version, 10) === 9) ? 0 : '5px auto', 'border-radius': style.round(0) }); }, border: function (zoom) { var borderRaw = options.border.replace(/^\s*|\s*$/g,''), borderArr = borderRaw.split(' '), interger = parseFloat(borderArr[0]), size = (borderArr.length > 2 && interger * 1 === interger ) ? interger : 0; return [borderRaw, size]; }, params : function (ele, zoom) { var img = ele.children('img'), // TODO: Create function to filter out percents border = style.border(zoom), margin = { 'marginTop': img.css('margin-top'), 'marginRight': img.css('margin-right'), 'marginBottom': img.css('margin-bottom'), 'marginLeft': img.css('margin-left') }, floats = { 'float': img.css('float') }, //Zoomy needs these to work zoomMin = { 'display': 'block', height: img.height(), width: img.width(), 'position': 'relative' }, //A lil bit of geneology o.0 parentCenter = function () { //Checking for parent text-align center var textAlign = ele.parent('*:first').css('text-align'); if (textAlign === 'center') { margin.marginRight = 'auto'; margin.marginLeft = 'auto'; } }, id = zoom.attr('rel'), css = {}; if (floats['float'] === 'none') { parentCenter(); } $.extend(css, margin, floats, zoomMin); ZoomyS[id].css = css; if (!options.glare) { zoom.children('span').css({ height: options.zoomSize - 10, width: options.zoomSize - 10 }); } zoom.css({ height: options.zoomSize, width: options.zoomSize, 'border-radius': style.round(undefined, border[1]), border: border[0] }); img.css('margin', '0px'); img.one("load", function () { ele.css(ZoomyS[id].css); }).each(function () { if (this.complete || ($.browser.msie && parseInt($.browser.version, 10) === 6)) { $(this).trigger("load"); } }); } }, // Build Object, Elements are added to the DOM here build = { // Load Zoom Image image : function (image, zoom) { var id = zoom.attr('rel'); //Move the Zoomy out of the screen view while loading img zoom.show().css({top: '-999999px', left: '-999999px'}); if (zoom.find('img').attr('src') !== image) { zoom.find('img').attr('src', image).load(function () { var assets = (options.glare) ? '' : '', border = style.border(zoom); image = image.replace(/ /g, '%20'); ZoomyS[id].zoom = { 'x': zoom.find('img').width(), 'y': zoom.find('img').height(), 'border': border[1] }; zoom.append(assets) .css({ 'background-image': 'url(' + image + ')' }) .find('img') .remove(); style.glare(zoom); }).each(function () { if (this.complete || ($.browser.msie && parseInt($.browser.version, 10) === 6)) { $(this).trigger("load"); } }); } }, // Add zoom element to page zoom : function (ele, i) { //Adding Initial State ZoomyS[i] = { state: null, index : i }; ZoomyS.count.push(0); // Picking from the right attibute var image = (typeof (ele.attr(options.attr)) === 'string' && options.attr !== 'href') ? ele.attr(options.attr) : ele.attr('href'), zoom = null, initCallback = options.zoomInit, eventHandler = function () { var eventlist = [], //List of Actual Events zoomMove = function (e) { change.move(ele, zoom, e); //ZoomyS.pos = e; }, zoomStart = function () { change.enter(ele, zoom); ele.bind('mousemove', zoomMove); /* Start Zoom Callback */ change.callback(options.zoomStart, zoom); }, zoomStop = function (x) { change.leave(ele, zoom, x); ele.unbind('mousemove', zoomMove); /* Start Zoom Callback */ change.callback(options.zoomStop, zoom); }, events = { //List of Possible Events event: function (e) { ZoomyS.pos = e; if (!options.clickable) { e.preventDefault(); } if (ZoomyS[i].state === 0 || ZoomyS[i].state === null) { zoomStart(); //Fix on click show and positioning issues change.move(ele, zoom, e); } else if (ZoomyS[i].state === 1 && event !== 'mouseover' && event !== 'mouseenter') { zoomStop(0); } }, 'mouseover': function (e) { ZoomyS.pos = e; if (ZoomyS[i].state === 0) { zoomStart(); } }, 'mouseleave': function (e) { ZoomyS.pos = e; if (ZoomyS[i].state === 1) { zoomStop(null); } }, 'click': function () { return false; } }; // Making sure there is only one mouse over event & Click returns false when it suppose to if (event === 'mouseover') { eventlist[event] = events.event; } else { eventlist[event] = events.event; eventlist.mouseover = events.mouseover; } if (!options.clickable && event !== 'click') { eventlist.click = events.click; } eventlist.mouseleave = events.mouseleave; // Binding Events to element ele.bind(eventlist); }; eventHandler(); //Creating Zoomy Element ele.addClass('parent-zoom').append('
'); //Setting the Zoom Variable towards the right zoom object zoom = $('.zoom-obj-' + i); if (initCallback !== null && typeof initCallback === 'function') { initCallback(ele); } // Set basic parameters style.params(ele, zoom); // Load zoom image build.image(image, zoom); //Event Handler added 1.2 }, // Initialize element to add to page, check for initial image to be loaded init : function (ele, img) { img.one("load", function () { // Ready to build zoom build.zoom(ele, ZoomyS.count.length); }).each(function () { if (this.complete || ($.browser.msie && parseInt($.browser.version, 10) === 6)) { $(this).trigger("load"); } }); } }; //Fallback if there is no event but there are options if (typeof (event) === 'object' && options === undefined) { options = event; event = defaultEvent; } else if (event === undefined) { event = defaultEvent; } //overriding defaults with options options = $.extend(defaults, options); $(this).each(function () { var ele = $(this), img = ele.find('img'); // Start Building Zoom build.init(ele, img); }); }; }(jQuery));