/* jshint -W071, -W074 */
/* global jQuery:false */

/* Disabled options are:
 * W071: This function has too many statements
 * W074: This function's cyclomatic complexity is too high
 */

/*
 *	jQuery ezPlus 1.1.21
 *	Demo's and documentation:
 *	http://igorlino.github.io/elevatezoom-plus/
 *
 *	licensed under MIT license.
 *	http://en.wikipedia.org/wiki/MIT_License
 *
 */

if (typeof Object.create !== 'function') {
    Object.create = function (obj) {
        function F() {
        }

        F.prototype = obj;
        return new F();
    };
}

(function ($, window, document, undefined) {
    var EZP = {
        init: function (options, elem) {
            var self = this;
            var $galleries;

            self.elem = elem;
            self.$elem = $(elem);

            self.options = $.extend({}, $.fn.ezPlus.options, self.responsiveConfig(options || {}));

            self.imageSrc = self.$elem.data(self.options.attrImageZoomSrc) ? self.$elem.data(self.options.attrImageZoomSrc) : self.$elem.attr('src');

            if (!self.options.enabled) {
                return;
            }

            //TINT OVERRIDE SETTINGS
            if (self.options.tint) {
                self.options.lensColour = 'transparent'; //colour of the lens background
                self.options.lensOpacity = '1'; //opacity of the lens
            }
            //INNER OVERRIDE SETTINGS
            if (self.options.zoomType === 'inner') {
                self.options.showLens = false;
            }

            // LENS OVERRIDE SETTINGS
            if (self.options.zoomType === 'lens') {
                self.options.zoomWindowWidth = 0;
            }

            //UUID WHEN MISSING IDENTIFIER
            if (self.options.zoomId === -1) {
                self.options.zoomId = generateUUID();
            }

            //Remove alt on hover

            self.$elem.parent().removeAttr('title').removeAttr('alt');

            self.zoomImage = self.imageSrc;

            self.refresh(1);

            //Create the image swap from the gallery
            $galleries = $(self.options.gallery ? ('#' + self.options.gallery) : self.options.gallerySelector);
            $galleries.on('click.zoom', self.options.galleryItem, function (e) {

                //Set a class on the currently active gallery image
                if (self.options.galleryActiveClass) {
                    $(self.options.galleryItem, $galleries).removeClass(self.options.galleryActiveClass);
                    $(this).addClass(self.options.galleryActiveClass);
                }
                //stop any link on the a tag from working
                if (this.tagName === 'A') {
                    e.preventDefault();
                }

                //call the swap image function
                if ($(this).data(self.options.attrImageZoomSrc)) {
                    self.zoomImagePre = $(this).data(self.options.attrImageZoomSrc);
                }
                else {
                    self.zoomImagePre = $(this).data('image');
                }
                self.swaptheimage($(this).data('image'), self.zoomImagePre);
                if (this.tagName === 'A') {
                    return false;
                }
            });

            function generateUUID() {
                var d = new Date().getTime();
                var uuid = 'xxxxxxxx-xxxx-4xxx-yxxx-xxxxxxxxxxxx'.replace(/[xy]/g, function (c) {
                    var r = (d + Math.random() * 16) % 16 | 0;
                    d = Math.floor(d / 16);
                    return (c == 'x' ? r : (r & 0x3 | 0x8)).toString(16);
                });
                return uuid;
            }
        },
        refresh: function (length) {
            var self = this;

            setTimeout(function () {
                self.fetch(self.imageSrc, self.$elem, self.options.minZoomLevel);

            }, length || self.options.refresh);
        },
        fetch: function (imgsrc, element, minZoom) {
            //get the image
            var self = this;
            var newImg = new Image();
            newImg.onload = function () {
                //set the large image dimensions - used to calculte ratio's
                if (newImg.width / element.width() <= minZoom) {
                    self.largeWidth = element.width() * minZoom;
                } else {
                    self.largeWidth = newImg.width;
                }
                if (newImg.height / element.height() <= minZoom) {
                    self.largeHeight = element.height() * minZoom;
                } else {
                    self.largeHeight = newImg.height;
                }
                //once image is loaded start the calls
                self.startZoom();
                self.currentImage = self.imageSrc;
                //let caller know image has been loaded
                self.options.onZoomedImageLoaded(self.$elem);
            };
            self.setImageSource(newImg, imgsrc); // this must be done AFTER setting onload

            return;
        },
        setImageSource: function (image, src) {
            //sets an image's source.
            image.src = src;
        },
        startZoom: function () {
            var self = this;
            //get dimensions of the non zoomed image
            self.nzWidth = self.$elem.width();
            self.nzHeight = self.$elem.height();

            //activated elements
            self.isWindowActive = false;
            self.isLensActive = false;
            self.isTintActive = false;
            self.overWindow = false;

            //CrossFade Wrapper
            if (self.options.imageCrossfade) {
                self.zoomWrap = self.$elem.wrap('<div style="height:' + self.nzHeight + 'px;width:' + self.nzWidth + 'px;" class="zoomWrapper" />');
                self.$elem.css('position', 'absolute');
            }

            self.zoomLock = 1;
            self.scrollingLock = false;
            self.changeBgSize = false;
            self.currentZoomLevel = self.options.zoomLevel;

            //get offset of the non zoomed image
            self.updateOffset(self);
            //calculate the width ratio of the large/small image
            self.widthRatio = (self.largeWidth / self.currentZoomLevel) / self.nzWidth;
            self.heightRatio = (self.largeHeight / self.currentZoomLevel) / self.nzHeight;

            function getWindowZoomStyle() {
                return 'display: none;' +
                    'position: absolute;' +
                    'float: left;' +
                    'height: ' + String(self.options.zoomWindowHeight) + 'px;' +
                    'width: ' + String(self.options.zoomWindowWidth) + 'px;' +
                    'text-align: center;' +
                    'border: ' + String(self.options.borderSize) + 'px solid ' + self.options.borderColour + ';' +
                    'background-size: ' + self.largeWidth / self.currentZoomLevel + 'px ' + self.largeHeight / self.currentZoomLevel + 'px;' +
                    'background-position: 0px 0px;' +
                    'background-repeat: no-repeat;' +
                    'background-color: ' + String(self.options.zoomWindowBgColour) + ';' +
                    'overflow: hidden;' +
                    'z-index: 100;';
            }

            //if window zoom
            if (self.options.zoomType === 'window') {
                self.zoomWindowStyle = getWindowZoomStyle();
            }

            function getInnerZoomStyle() {
                //has a border been put on the image? Lets cater for this
                var borderWidth = self.$elem.css('border-left-width');

                return 'display: none;' +
                    'position: absolute;' +
                    'float: left;' +
                    'height: ' + String(self.nzHeight) + 'px;' +
                    'width: ' + String(self.nzWidth) + 'px;' +
                    'margin-top: ' + String(borderWidth) + ';' +
                    'margin-left: ' + String(borderWidth) + ';' +
                    'border: ' + String(self.options.borderSize) + 'px solid ' + self.options.borderColour + ';' +
                    'background-position: 0px 0px;' +
                    'background-repeat: no-repeat;' +
                    'cursor:' + (self.options.cursor) + ';' +
                    'overflow: hidden;' +
                    'zindex: ' + self.options.zIndex + ";";
            }

            //if inner  zoom
            if (self.options.zoomType === 'inner') {
                self.zoomWindowStyle = getInnerZoomStyle();
            }

            function getWindowLensStyle() {
                // adjust images less than the window height

                if (self.nzHeight < self.options.zoomWindowHeight / self.heightRatio) {
                    self.lensHeight = self.nzHeight;
                }
                else {
                    self.lensHeight = String(self.options.zoomWindowHeight / self.heightRatio);
                }
                if (self.largeWidth < self.options.zoomWindowWidth) {
                    self.lensWidth = self.nzWidth;
                }
                else {
                    self.lensWidth = String(self.options.zoomWindowWidth / self.widthRatio);
                }

                return 'display: none;' +
                    'position: absolute;' +
                    'float: right;' +
                    'height: ' + self.lensHeight + 'px;' +
                    'width: ' + self.lensWidth + 'px;' +
                    'border: ' + (self.options.lensBorderSize) + 'px' + ' solid ' + (self.options.lensBorderColour) + ';' +
                    'background-position: 0px 0px;' +
                    'background-repeat: no-repeat;' +
                    'background-color: ' + (self.options.lensColour) + ';' +
                    'opacity: ' + (self.options.lensOpacity) + ';' +
                    'filter: alpha(opacity = ' + (self.options.lensOpacity * 100) + ');' +
                    'zoom: 1;' +
                    'cursor:' + (self.options.cursor) + ';' +
                    'z-index: 999;' +
                    'overflow: hidden;';
            }

            //lens style for window zoom
            if (self.options.zoomType === 'window') {
                self.lensStyle = getWindowLensStyle();
            }

            //tint style
            self.tintStyle =
                'display: block;' +
                'position: absolute;' +
                'height: ' + self.nzHeight + 'px;' +
                'width: ' + self.nzWidth + 'px;' +
                'background-color: ' + self.options.tintColour + ';' +
                'filter: alpha(opacity=0);' +
                'opacity: 0;';

            //lens style for lens zoom with optional round for modern browsers
            self.lensRound = '';

            if (self.options.zoomType === 'lens') {
                self.lensStyle =
                    'display: none;' +
                    'position: absolute;' +
                    'float: left;' +
                    'height:' + String(self.options.lensSize) + 'px;' +
                    'width:' + String(self.options.lensSize) + 'px;' +
                    'border: ' + String(self.options.borderSize) + 'px solid ' + self.options.borderColour + ';' +
                    'background-position: 0px 0px;' +
                    'background-repeat: no-repeat;' +
                    'background-color: ' + self.options.lensColour + ";" +
                    'cursor:' + (self.options.cursor) + ';';
            }

            //does not round in all browsers
            if (self.options.lensShape === 'round') {
                self.lensRound =
                    'border-radius: ' + String(self.options.lensSize / 2 + self.options.borderSize) + 'px;';
            }

            //create the div's                                                + ""
            //self.zoomContainer = $('<div/>').addClass('zoomContainer').css({"position":"relative", "height":self.nzHeight, "width":self.nzWidth});

            self.zoomContainer =
                $('<div class="zoomContainer" ' +
                'uuid="' + self.options.zoomId + '"' +
                'style="' +
                'position: absolute;' +
                'top: ' + self.nzOffset.top + 'px;' +
                'left: ' + self.nzOffset.left + 'px;' +
                'height: ' + self.nzHeight + 'px;' + '' +
                'width: ' + self.nzWidth + 'px;' +
                'z-index: ' + self.options.zIndex + '"></div>');
            if (self.$elem.attr('id')) {
                self.zoomContainer.attr('id', self.$elem.attr('id') + '-zoomContainer');
            }
            $(self.options.zoomContainerAppendTo).append(self.zoomContainer);

            //this will add overflow hidden and contrain the lens on lens mode
            if (self.options.containLensZoom && self.options.zoomType === 'lens') {
                self.zoomContainer.css('overflow', 'hidden');
            }
            if (self.options.zoomType !== 'inner') {
                self.zoomLens = $('<div class="zoomLens" style="' + self.lensStyle + self.lensRound + '">&nbsp;</div>')
                    .appendTo(self.zoomContainer)
                    .click(function () {
                        self.$elem.trigger('click');
                    });

                if (self.options.tint) {
                    self.tintContainer = $('<div/>').addClass('tintContainer');
                    self.zoomTint = $('<div class="zoomTint" style="' + self.tintStyle + '"></div>');

                    self.zoomLens.wrap(self.tintContainer);

                    self.zoomTintcss = self.zoomLens.after(self.zoomTint);

                    //if tint enabled - set an image to show over the tint

                    self.zoomTintImage = $('<img style="' +
                    'position: absolute;' +
                    'top: 0px;' +
                    'left: 0px;' +
                    'height: ' + self.nzHeight + 'px;" ' +
                    'width: ' + self.nzWidth + 'px; ' +
                    'max-width: none; ' +
                    'src="' + self.$elem.attr('src') + '">')
                        .appendTo(self.zoomLens)
                        .click(function () {
                            self.$elem.trigger('click');
                        });
                }
            }

            //create zoom window
            var targetZoomContainer = isNaN(self.options.zoomWindowPosition) ? 'body' : self.zoomContainer;
            self.zoomWindow = $('<div style="' +
            'z-index: 999;' +
            'top: ' + (self.windowOffsetTop) + 'px;' +
            'left: ' + (self.windowOffsetLeft) + 'px;' +
            self.zoomWindowStyle + '" class="zoomWindow">&nbsp;</div>')
                .appendTo(targetZoomContainer).click(function () {
                    self.$elem.trigger('click');
                });
            self.zoomWindowContainer = $('<div/>').addClass('zoomWindowContainer').css('width', self.options.zoomWindowWidth);
            self.zoomWindow.wrap(self.zoomWindowContainer);

            //  self.captionStyle = "text-align: left;background-color: black;'+
            // 'color: white;font-weight: bold;padding: 10px;font-family: sans-serif;font-size: 11px";
            // self.zoomCaption = $('<div class="ezplus-caption" '+
            // 'style="'+self.captionStyle+'display: block; width: 280px;">INSERT ALT TAG</div>').appendTo(self.zoomWindow.parent());

            if (self.options.zoomType === 'lens') {
                self.zoomLens.css('background-image', 'url("' + self.imageSrc + '")');
            }
            if (self.options.zoomType === 'window') {
                self.zoomWindow.css('background-image', 'url("' + self.imageSrc + '")');
            }
            if (self.options.zoomType === 'inner') {
                self.zoomWindow.css('background-image', 'url("' + self.imageSrc + '")');
            }

            /*-------------------END THE ZOOM WINDOW AND LENS----------------------------------*/
            if (self.options.touchEnabled) {
                //touch events
                self.$elem.bind('touchmove.ezpspace', function (e) {
                    e.preventDefault();
                    var touch = e.originalEvent.touches[0] || e.originalEvent.changedTouches[0];
                    self.setPosition(touch);
                });
                self.zoomContainer.bind('touchmove.ezpspace', function (e) {
                    self.setElements('show');
                    e.preventDefault();
                    var touch = e.originalEvent.touches[0] || e.originalEvent.changedTouches[0];
                    self.setPosition(touch);

                });
                self.zoomContainer.bind('touchend.ezpspace', function (e) {
                    self.showHideWindow('hide');
                    if (self.options.showLens) {
                        self.showHideLens('hide');
                    }
                    if (self.options.tint && self.options.zoomType !== 'inner') {
                        self.showHideTint('hide');
                    }
                });

                self.$elem.bind('touchend.ezpspace', function (e) {
                    self.showHideWindow('hide');
                    if (self.options.showLens) {
                        self.showHideLens('hide');
                    }
                    if (self.options.tint && self.options.zoomType !== 'inner') {
                        self.showHideTint('hide');
                    }
                });
                if (self.options.showLens) {
                    self.zoomLens.bind('touchmove.ezpspace', function (e) {

                        e.preventDefault();
                        var touch = e.originalEvent.touches[0] || e.originalEvent.changedTouches[0];
                        self.setPosition(touch);
                    });

                    self.zoomLens.bind('touchend.ezpspace', function (e) {
                        self.showHideWindow('hide');
                        if (self.options.showLens) {
                            self.showHideLens('hide');
                        }
                        if (self.options.tint && self.options.zoomType !== 'inner') {
                            self.showHideTint('hide');
                        }
                    });
                }
            }
            //Needed to work in IE
            self.$elem.bind('mousemove.ezpspace', function (e) {
                if (self.overWindow === false) {
                    self.setElements('show');
                }
                //make sure on orientation change the setposition is not fired
                if (self.lastX !== e.clientX || self.lastY !== e.clientY) {
                    self.setPosition(e);
                    self.currentLoc = e;
                }
                self.lastX = e.clientX;
                self.lastY = e.clientY;

            });

            self.zoomContainer.bind('click.ezpspace touchstart.ezpspace', self.options.onImageClick);

            self.zoomContainer.bind('mousemove.ezpspace', function (e) {
                if (self.overWindow === false) {
                    self.setElements('show');
                }
                mouseMoveZoomHandler(e);
            });

            function mouseMoveZoomHandler(e) {
                //self.overWindow = true;
                //make sure on orientation change the setposition is not fired
                if (self.lastX !== e.clientX || self.lastY !== e.clientY) {
                    self.setPosition(e);
                    self.currentLoc = e;
                }
                self.lastX = e.clientX;
                self.lastY = e.clientY;
            }

            var elementToTrack = null;
            if (self.options.zoomType !== 'inner') {
                elementToTrack = self.zoomLens;
            }
            if (self.options.tint && self.options.zoomType !== 'inner') {
                elementToTrack = self.zoomTint;
            }
            if (self.options.zoomType === 'inner') {
                elementToTrack = self.zoomWindow;
            }

            //register the mouse tracking
            if (elementToTrack) {
                elementToTrack.bind('mousemove.ezpspace', mouseMoveZoomHandler);
            }

            //  lensFadeOut: 500,  zoomTintFadeIn
            self.zoomContainer.add(self.$elem).mouseenter(function () {
                if (self.overWindow === false) {
                    self.setElements('show');
                }
            }).mouseleave(function () {
                if (!self.scrollLock) {
                    self.setElements('hide');
                    self.options.onDestroy(self.$elem);
                }
            });
            //end ove image

            if (self.options.zoomType !== 'inner') {
                self.zoomWindow.mouseenter(function () {
                    self.overWindow = true;
                    self.setElements('hide');
                }).mouseleave(function () {
                    self.overWindow = false;
                });
            }
            //end ove image

            // var delta = parseInt(e.originalEvent.wheelDelta || -e.originalEvent.detail);

            //      $(this).empty();
            //    return false;

            //fix for initial zoom setting
            //if (self.options.zoomLevel !== 1) {
            //    	self.changeZoomLevel(self.currentZoomLevel);
            //}
            //set the min zoomlevel
            if (self.options.minZoomLevel) {
                self.minZoomLevel = self.options.minZoomLevel;
            }
            else {
                self.minZoomLevel = self.options.scrollZoomIncrement * 2;
            }

            if (self.options.scrollZoom) {
                //see compatibility of mouse events at https://developer.mozilla.org/en-US/docs/Web/Events/mousewheel
                self.zoomContainer.add(self.$elem).bind('wheel DOMMouseScroll MozMousePixelScroll', function (e) {
                    // in IE there is issue with firing of mouseleave - So check whether still scrolling
                    // and on mouseleave check if scrolllock
                    self.scrollLock = true;
                    clearTimeout($.data(this, 'timer'));
                    $.data(this, 'timer', setTimeout(function () {
                        self.scrollLock = false;
                        //do something
                    }, 250));

                    var theEvent = e.originalEvent.deltaY || e.originalEvent.detail * -1;

                    //this.scrollTop += ( delta < 0 ? 1 : -1 ) * 30;
                    //   e.preventDefault();

                    e.stopImmediatePropagation();
                    e.stopPropagation();
                    e.preventDefault();

                    if (theEvent == 0) {
                        // fixes last event inversion bug
                        return false;
                    }

                    if (theEvent / 120 > 0) {
                        var nextZoomLevel = parseFloat(self.currentZoomLevel) - self.options.scrollZoomIncrement;
                        //scrolling up
                        if (nextZoomLevel >= parseFloat(self.minZoomLevel)) {
                            self.changeZoomLevel(nextZoomLevel);
                        }
                    }
                    else {
                        //scrolling down

                        //Check if it has to maintain original zoom window aspect ratio or not
                        if ((!self.fullheight && !self.fullwidth) || !self.options.mantainZoomAspectRatio) {
                            var nextZoomLevel = parseFloat(self.currentZoomLevel) + self.options.scrollZoomIncrement;

                            if (self.options.maxZoomLevel) {
                                if (nextZoomLevel <= self.options.maxZoomLevel) {
                                    self.changeZoomLevel(nextZoomLevel);
                                }
                            }
                            else {
                                //andy
                                self.changeZoomLevel(nextZoomLevel);
                            }
                        }
                    }
                    return false;
                });
            }
        },
        destroy: function () {
            var self = this;
            self.$elem.unbind('ezpspace');
            $(self.zoomContainer).remove();
            if (self.options.loadingIcon && !!self.spinner && !!self.spinner.length) {
                self.spinner.remove();
                delete self.spinner;
            }
        },
        getIdentifier: function () {
            var self = this;
            return self.options.zoomId;
        },
        setElements: function (type) {
            var self = this;
            if (!self.options.zoomEnabled) {
                return false;
            }
            if (type === 'show') {
                if (self.isWindowSet) {
                    if (self.options.zoomType === 'inner') {
                        self.showHideWindow('show');
                    }
                    if (self.options.zoomType === 'window') {
                        self.showHideWindow('show');
                    }
                    if (self.options.showLens) {
                        self.showHideLens('show');
                    }
                    if (self.options.tint && self.options.zoomType !== 'inner') {
                        self.showHideTint('show');
                    }
                }
            }

            if (type === 'hide') {
                if (self.options.zoomType === 'window') {
                    self.showHideWindow('hide');
                }
                if (!self.options.tint) {
                    self.showHideWindow('hide');
                }
                if (self.options.showLens) {
                    self.showHideLens('hide');
                }
                if (self.options.tint) {
                    self.showHideTint('hide');
                }
            }
        },
        setPosition: function (e) {

            var self = this;

            if (!self.options.zoomEnabled) {
                return false;
            }

            //recaclc offset each time in case the image moves
            //this can be caused by other on page elements
            self.nzHeight = self.$elem.height();
            self.nzWidth = self.$elem.width();
            self.updateOffset(self);

            if (self.options.tint && self.options.zoomType !== 'inner') {
                self.zoomTint.css({
                    top: 0,
                    left: 0
                });
            }
            //set responsive
            //will checking if the image needs changing before running this code work faster?
            if (self.options.responsive && !self.options.scrollZoom) {
                if (self.options.showLens) {
                    var lensHeight, lensWidth;
                    if (self.nzHeight < self.options.zoomWindowWidth / self.widthRatio) {
                        self.lensHeight = self.nzHeight;
                    }
                    else {
                        self.lensHeight = String((self.options.zoomWindowHeight / self.heightRatio));
                    }
                    if (self.largeWidth < self.options.zoomWindowWidth) {
                        self.lensWidth = self.nzWidth;
                    }
                    else {
                        self.lensWidth = (self.options.zoomWindowWidth / self.widthRatio);
                    }
                    self.widthRatio = self.largeWidth / self.nzWidth;
                    self.heightRatio = self.largeHeight / self.nzHeight;
                    if (self.options.zoomType !== 'lens') {
                        //possibly dont need to keep recalcalculating
                        //if the lens is heigher than the image, then set lens size to image size
                        if (self.nzHeight < self.options.zoomWindowWidth / self.widthRatio) {
                            self.lensHeight = self.nzHeight;

                        }
                        else {
                            self.lensHeight = String((self.options.zoomWindowHeight / self.heightRatio));
                        }

                        if (self.nzWidth < self.options.zoomWindowHeight / self.heightRatio) {
                            self.lensWidth = self.nzWidth;
                        }
                        else {
                            self.lensWidth = String((self.options.zoomWindowWidth / self.widthRatio));
                        }

                        self.zoomLens.css({
                            'width': self.lensWidth,
                            'height': self.lensHeight
                        });

                        if (self.options.tint) {
                            self.zoomTintImage.css({
                                'width': self.nzWidth,
                                'height': self.nzHeight
                            });
                        }

                    }
                    if (self.options.zoomType === 'lens') {
                        self.zoomLens.css({
                            width: String(self.options.lensSize) + 'px',
                            height: String(self.options.lensSize) + 'px'
                        });
                    }
                    //end responsive image change
                }
            }

            //container fix
            self.zoomContainer.css({
                top: self.nzOffset.top,
                left: self.nzOffset.left,
                width: self.nzWidth,  // new code
                height: self.nzHeight // new code
            });
            self.mouseLeft = parseInt(e.pageX - self.nzOffset.left);
            self.mouseTop = parseInt(e.pageY - self.nzOffset.top);
            //calculate the Location of the Lens

            //calculate the bound regions - but only if zoom window
            if (self.options.zoomType === 'window') {
                var zoomLensHeight = self.zoomLens.height() / 2;
                var zoomLensWidth = self.zoomLens.width() / 2;
                self.Etoppos = (self.mouseTop < 0 + zoomLensHeight);
                self.Eboppos = (self.mouseTop > self.nzHeight - zoomLensHeight - (self.options.lensBorderSize * 2));
                self.Eloppos = (self.mouseLeft < 0 + zoomLensWidth);
                self.Eroppos = (self.mouseLeft > (self.nzWidth - zoomLensWidth - (self.options.lensBorderSize * 2)));
            }
            //calculate the bound regions - but only for inner zoom
            if (self.options.zoomType === 'inner') {
                self.Etoppos = (self.mouseTop < ((self.nzHeight / 2) / self.heightRatio));
                self.Eboppos = (self.mouseTop > (self.nzHeight - ((self.nzHeight / 2) / self.heightRatio)));
                self.Eloppos = (self.mouseLeft < 0 + (((self.nzWidth / 2) / self.widthRatio)));
                self.Eroppos = (self.mouseLeft > (self.nzWidth - (self.nzWidth / 2) / self.widthRatio - (self.options.lensBorderSize * 2)));
            }

            // if the mouse position of the slider is one of the outerbounds, then hide  window and lens
            if (self.mouseLeft < 0 || self.mouseTop < 0 || self.mouseLeft > self.nzWidth || self.mouseTop > self.nzHeight) {
                self.setElements('hide');
                return;
            }
            //else continue with operations
            else {
                //lens options
                if (self.options.showLens) {
                    //		self.showHideLens('show');
                    //set background position of lens
                    self.lensLeftPos = String(Math.floor(self.mouseLeft - self.zoomLens.width() / 2));
                    self.lensTopPos = String(Math.floor(self.mouseTop - self.zoomLens.height() / 2));
                }
                //adjust the background position if the mouse is in one of the outer regions

                //Top region
                if (self.Etoppos) {
                    self.lensTopPos = 0;
                }
                //Left Region
                if (self.Eloppos) {
                    self.windowLeftPos = 0;
                    self.lensLeftPos = 0;
                    self.tintpos = 0;
                }
                //Set bottom and right region for window mode
                if (self.options.zoomType === 'window') {
                    if (self.Eboppos) {
                        self.lensTopPos = Math.max((self.nzHeight) - self.zoomLens.height() - (self.options.lensBorderSize * 2), 0);
                    }
                    if (self.Eroppos) {
                        self.lensLeftPos = (self.nzWidth - (self.zoomLens.width()) - (self.options.lensBorderSize * 2));
                    }
                }
                //Set bottom and right region for inner mode
                if (self.options.zoomType === 'inner') {
                    if (self.Eboppos) {
                        self.lensTopPos = Math.max(((self.nzHeight) - (self.options.lensBorderSize * 2)), 0);
                    }
                    if (self.Eroppos) {
                        self.lensLeftPos = (self.nzWidth - (self.nzWidth) - (self.options.lensBorderSize * 2));
                    }
                }
                //if lens zoom
                if (self.options.zoomType === 'lens') {

                    self.windowLeftPos = String(((e.pageX - self.nzOffset.left) * self.widthRatio - self.zoomLens.width() / 2) * (-1));
                    self.windowTopPos = String(((e.pageY - self.nzOffset.top) * self.heightRatio - self.zoomLens.height() / 2) * (-1));
                    self.zoomLens.css('background-position', self.windowLeftPos + 'px ' + self.windowTopPos + 'px');

                    if (self.changeBgSize) {
                        if (self.nzHeight > self.nzWidth) {
                            if (self.options.zoomType === 'lens') {
                                self.zoomLens.css('background-size',
                                    self.largeWidth / self.newvalueheight + 'px ' +
                                    self.largeHeight / self.newvalueheight + 'px');
                            }

                            self.zoomWindow.css('background-size',
                                self.largeWidth / self.newvalueheight + 'px ' +
                                self.largeHeight / self.newvalueheight + 'px');
                        }
                        else {
                            if (self.options.zoomType === 'lens') {
                                self.zoomLens.css('background-size',
                                    self.largeWidth / self.newvaluewidth + 'px ' +
                                    self.largeHeight / self.newvaluewidth + 'px');
                            }
                            self.zoomWindow.css('background-size',
                                self.largeWidth / self.newvaluewidth + 'px ' +
                                self.largeHeight / self.newvaluewidth + 'px');
                        }
                        self.changeBgSize = false;
                    }

                    self.setWindowPosition(e);
                }
                //if tint zoom
                if (self.options.tint && self.options.zoomType !== 'inner') {
                    self.setTintPosition(e);
                }
                //set the css background position
                if (self.options.zoomType === 'window') {
                    self.setWindowPosition(e);
                }
                if (self.options.zoomType === 'inner') {
                    self.setWindowPosition(e);
                }
                if (self.options.showLens) {
                    if (self.fullwidth && self.options.zoomType !== 'lens') {
                        self.lensLeftPos = 0;
                    }
                    self.zoomLens.css({
                        left: self.lensLeftPos + 'px',
                        top: self.lensTopPos + 'px'
                    });
                }

            } //end else
        },
        showHideZoomContainer: function (change) {
            var self = this;
            if (change === 'show') {
                if (self.zoomContainer) {
                    self.zoomContainer.show();
                }
            }
            if (change === 'hide') {
                if (self.zoomContainer) {
                    self.zoomContainer.hide();
                }
            }
        },
        showHideWindow: function (change) {
            var self = this;
            if (change === 'show') {
                if (!self.isWindowActive && self.zoomWindow) {
                    self.options.onShow(self);
                    if (self.options.zoomWindowFadeIn) {
                        self.zoomWindow.stop(true, true, false).fadeIn(self.options.zoomWindowFadeIn);
                    }
                    else {
                        self.zoomWindow.show();
                    }
                    self.isWindowActive = true;
                }
            }
            if (change === 'hide') {
                if (self.isWindowActive) {
                    if (self.options.zoomWindowFadeOut) {
                        self.zoomWindow.stop(true, true).fadeOut(self.options.zoomWindowFadeOut, function () {
                            if (self.loop) {
                                //stop moving the zoom window when zoom window is faded out
                                clearInterval(self.loop);
                                self.loop = false;
                            }
                        });
                    }
                    else {
                        self.zoomWindow.hide();
                    }
                    self.isWindowActive = false;
                }
            }
        },
        showHideLens: function (change) {
            var self = this;
            if (change === 'show') {
                if (!self.isLensActive) {
                    if (self.zoomLens) {
                        if (self.options.lensFadeIn) {
                            self.zoomLens.stop(true, true, false).fadeIn(self.options.lensFadeIn);
                        }
                        else {
                            self.zoomLens.show();
                        }
                    }
                    self.isLensActive = true;
                }
            }
            if (change === 'hide') {
                if (self.isLensActive) {
                    if (self.zoomLens) {
                        if (self.options.lensFadeOut) {
                            self.zoomLens.stop(true, true).fadeOut(self.options.lensFadeOut);
                        }
                        else {
                            self.zoomLens.hide();
                        }
                    }
                    self.isLensActive = false;
                }
            }
        },
        showHideTint: function (change) {
            var self = this;
            if (change === 'show') {
                if (!self.isTintActive && self.zoomTint) {

                    if (self.options.zoomTintFadeIn) {
                        self.zoomTint.css('opacity', self.options.tintOpacity).animate().stop(true, true).fadeIn('slow');
                    }
                    else {
                        self.zoomTint.css('opacity', self.options.tintOpacity).animate();
                        self.zoomTint.show();
                    }
                    self.isTintActive = true;
                }
            }
            if (change === 'hide') {
                if (self.isTintActive) {

                    if (self.options.zoomTintFadeOut) {
                        self.zoomTint.stop(true, true).fadeOut(self.options.zoomTintFadeOut);
                    }
                    else {
                        self.zoomTint.hide();
                    }
                    self.isTintActive = false;
                }
            }
        },

        setLensPosition: function (e) {
        },

        setWindowPosition: function (e) {
            //return obj.slice( 0, count );
            var self = this;

            if (!isNaN(self.options.zoomWindowPosition)) {

                switch (self.options.zoomWindowPosition) {
                    case 1: //done
                        self.windowOffsetTop = (self.options.zoomWindowOffsetY);//DONE - 1
                        self.windowOffsetLeft = (+self.nzWidth); //DONE 1, 2, 3, 4, 16
                        break;
                    case 2:
                        if (self.options.zoomWindowHeight > self.nzHeight) { //positive margin

                            self.windowOffsetTop = ((self.options.zoomWindowHeight / 2) - (self.nzHeight / 2)) * (-1);
                            self.windowOffsetLeft = (self.nzWidth); //DONE 1, 2, 3, 4, 16
                        }
                        else { //negative margin
                            $.noop();
                        }
                        break;
                    case 3: //done
                        self.windowOffsetTop = (self.nzHeight - self.zoomWindow.height() - (self.options.borderSize * 2)); //DONE 3,9
                        self.windowOffsetLeft = (self.nzWidth); //DONE 1, 2, 3, 4, 16
                        break;
                    case 4: //done
                        self.windowOffsetTop = (self.nzHeight); //DONE - 4,5,6,7,8
                        self.windowOffsetLeft = (self.nzWidth); //DONE 1, 2, 3, 4, 16
                        break;
                    case 5: //done
                        self.windowOffsetTop = (self.nzHeight); //DONE - 4,5,6,7,8
                        self.windowOffsetLeft = (self.nzWidth - self.zoomWindow.width() - (self.options.borderSize * 2)); //DONE - 5,15
                        break;
                    case 6:
                        if (self.options.zoomWindowHeight > self.nzHeight) { //positive margin
                            self.windowOffsetTop = (self.nzHeight);  //DONE - 4,5,6,7,8

                            self.windowOffsetLeft = ((self.options.zoomWindowWidth / 2) - (self.nzWidth / 2) + (self.options.borderSize * 2)) * (-1);
                        }
                        else { //negative margin
                            $.noop();
                        }

                        break;
                    case 7: //done
                        self.windowOffsetTop = (self.nzHeight);  //DONE - 4,5,6,7,8
                        self.windowOffsetLeft = 0; //DONE 7, 13
                        break;
                    case 8: //done
                        self.windowOffsetTop = (self.nzHeight); //DONE - 4,5,6,7,8
                        self.windowOffsetLeft = (self.zoomWindow.width() + (self.options.borderSize * 2)) * (-1);  //DONE 8,9,10,11,12
                        break;
                    case 9:  //done
                        self.windowOffsetTop = (self.nzHeight - self.zoomWindow.height() - (self.options.borderSize * 2)); //DONE 3,9
                        self.windowOffsetLeft = (self.zoomWindow.width() + (self.options.borderSize * 2)) * (-1);  //DONE 8,9,10,11,12
                        break;
                    case 10:
                        if (self.options.zoomWindowHeight > self.nzHeight) { //positive margin

                            self.windowOffsetTop = ((self.options.zoomWindowHeight / 2) - (self.nzHeight / 2)) * (-1);
                            self.windowOffsetLeft = (self.zoomWindow.width() + (self.options.borderSize * 2)) * (-1);  //DONE 8,9,10,11,12
                        }
                        else { //negative margin
                            $.noop();
                        }
                        break;
                    case 11:
                        self.windowOffsetTop = (self.options.zoomWindowOffsetY);
                        self.windowOffsetLeft = (self.zoomWindow.width() + (self.options.borderSize * 2)) * (-1);  //DONE 8,9,10,11,12
                        break;
                    case 12: //done
                        self.windowOffsetTop = (self.zoomWindow.height() + (self.options.borderSize * 2)) * (-1); //DONE 12,13,14,15,16
                        self.windowOffsetLeft = (self.zoomWindow.width() + (self.options.borderSize * 2)) * (-1);  //DONE 8,9,10,11,12
                        break;
                    case 13: //done
                        self.windowOffsetTop = (self.zoomWindow.height() + (self.options.borderSize * 2)) * (-1); //DONE 12,13,14,15,16
                        self.windowOffsetLeft = (0); //DONE 7, 13
                        break;
                    case 14:
                        if (self.options.zoomWindowHeight > self.nzHeight) { //positive margin
                            self.windowOffsetTop = (self.zoomWindow.height() + (self.options.borderSize * 2)) * (-1); //DONE 12,13,14,15,16

                            self.windowOffsetLeft = ((self.options.zoomWindowWidth / 2) - (self.nzWidth / 2) + (self.options.borderSize * 2)) * (-1);
                        }
                        else { //negative margin
                            $.noop();
                        }
                        break;
                    case 15://done
                        self.windowOffsetTop = (self.zoomWindow.height() + (self.options.borderSize * 2)) * (-1); //DONE 12,13,14,15,16
                        self.windowOffsetLeft = (self.nzWidth - self.zoomWindow.width() - (self.options.borderSize * 2)); //DONE - 5,15
                        break;
                    case 16:  //done
                        self.windowOffsetTop = (self.zoomWindow.height() + (self.options.borderSize * 2)) * (-1); //DONE 12,13,14,15,16
                        self.windowOffsetLeft = (self.nzWidth); //DONE 1, 2, 3, 4, 16
                        break;
                    default: //done
                        self.windowOffsetTop = (self.options.zoomWindowOffsetY);//DONE - 1
                        self.windowOffsetLeft = (self.nzWidth); //DONE 1, 2, 3, 4, 16
                }
            } //end isNAN
            else {
                // For BC purposes, treat passed element as ID if element not found
                self.externalContainer = $(self.options.zoomWindowPosition);
                if (!self.externalContainer.length) {
                    self.externalContainer = $('#' + self.options.zoomWindowPosition);
                }

                self.externalContainerWidth = self.externalContainer.width();
                self.externalContainerHeight = self.externalContainer.height();
                self.externalContainerOffset = self.externalContainer.offset();

                self.windowOffsetTop = self.externalContainerOffset.top;//DONE - 1
                self.windowOffsetLeft = self.externalContainerOffset.left; //DONE 1, 2, 3, 4, 16

            }
            self.isWindowSet = true;
            self.windowOffsetTop = self.windowOffsetTop + self.options.zoomWindowOffsetY;
            self.windowOffsetLeft = self.windowOffsetLeft + self.options.zoomWindowOffsetX;

            self.zoomWindow.css({
                top: self.windowOffsetTop,
                left: self.windowOffsetLeft
            });

            if (self.options.zoomType === 'inner') {
                self.zoomWindow.css({
                    top: 0,
                    left: 0
                });

            }

            self.windowLeftPos = String(((e.pageX - self.nzOffset.left) * self.widthRatio - self.zoomWindow.width() / 2) * (-1));
            self.windowTopPos = String(((e.pageY - self.nzOffset.top) * self.heightRatio - self.zoomWindow.height() / 2) * (-1));
            if (self.Etoppos) {
                self.windowTopPos = 0;
            }
            if (self.Eloppos) {
                self.windowLeftPos = 0;
            }
            if (self.Eboppos) {
                self.windowTopPos = (self.largeHeight / self.currentZoomLevel - self.zoomWindow.height()) * (-1);
            }
            if (self.Eroppos) {
                self.windowLeftPos = ((self.largeWidth / self.currentZoomLevel - self.zoomWindow.width()) * (-1));
            }

            //stops micro movements
            if (self.fullheight) {
                self.windowTopPos = 0;
            }
            if (self.fullwidth) {
                self.windowLeftPos = 0;
            }

            //set the css background position
            if (self.options.zoomType === 'window' || self.options.zoomType === 'inner') {

                if (self.zoomLock === 1) {
                    //overrides for images not zoomable
                    if (self.widthRatio <= 1) {
                        self.windowLeftPos = 0;
                    }
                    if (self.heightRatio <= 1) {
                        self.windowTopPos = 0;
                    }
                }
                // adjust images less than the window height

                if (self.options.zoomType === 'window') {
                    if (self.largeHeight < self.options.zoomWindowHeight) {
                        self.windowTopPos = 0;
                    }
                    if (self.largeWidth < self.options.zoomWindowWidth) {
                        self.windowLeftPos = 0;
                    }
                }
                //set the zoomwindow background position
                if (self.options.easing) {

                    //     if(self.changeZoom){
                    //           clearInterval(self.loop);
                    //           self.changeZoom = false;
                    //           self.loop = false;

                    //            }
                    //set the pos to 0 if not set
                    if (!self.xp) {
                        self.xp = 0;
                    }
                    if (!self.yp) {
                        self.yp = 0;
                    }
                    var interval = 16;
                    if (Number.isInteger(parseInt(self.options.easing))) {
                        interval = parseInt(self.options.easing);
                    }
                    //if loop not already started, then run it
                    if (!self.loop) {
                        self.loop = setInterval(function () {
                            //using zeno's paradox

                            self.xp += (self.windowLeftPos - self.xp) / self.options.easingAmount;
                            self.yp += (self.windowTopPos - self.yp) / self.options.easingAmount;
                            if (self.scrollingLock) {

                                clearInterval(self.loop);
                                self.xp = self.windowLeftPos;
                                self.yp = self.windowTopPos;

                                self.xp = ((e.pageX - self.nzOffset.left) * self.widthRatio - self.zoomWindow.width() / 2) * (-1);
                                self.yp = (((e.pageY - self.nzOffset.top) * self.heightRatio - self.zoomWindow.height() / 2) * (-1));

                                if (self.changeBgSize) {
                                    if (self.nzHeight > self.nzWidth) {
                                        if (self.options.zoomType === 'lens') {
                                            self.zoomLens.css('background-size',
                                                self.largeWidth / self.newvalueheight + 'px ' +
                                                self.largeHeight / self.newvalueheight + 'px');
                                        }
                                        self.zoomWindow.css('background-size',
                                            self.largeWidth / self.newvalueheight + 'px ' +
                                            self.largeHeight / self.newvalueheight + 'px');
                                    }
                                    else {
                                        if (self.options.zoomType !== 'lens') {
                                            self.zoomLens.css('background-size',
                                                self.largeWidth / self.newvaluewidth + 'px ' +
                                                self.largeHeight / self.newvalueheight + 'px');
                                        }
                                        self.zoomWindow.css('background-size',
                                            self.largeWidth / self.newvaluewidth + 'px ' +
                                            self.largeHeight / self.newvaluewidth + 'px');
                                    }

                                    /*
                                     if(!self.bgxp){self.bgxp = self.largeWidth/self.newvalue;}
                                     if(!self.bgyp){self.bgyp = self.largeHeight/self.newvalue ;}
                                     if (!self.bgloop){
                                     self.bgloop = setInterval(function(){

                                     self.bgxp += (self.largeWidth/self.newvalue  - self.bgxp) / self.options.easingAmount;
                                     self.bgyp += (self.largeHeight/self.newvalue  - self.bgyp) / self.options.easingAmount;

                                     self.zoomWindow.css('background-size', self.bgxp + 'px ' + self.bgyp + 'px' );


                                     }, 16);

                                     }
                                     */
                                    self.changeBgSize = false;
                                }

                                self.zoomWindow.css('background-position', self.windowLeftPos + 'px ' + self.windowTopPos + 'px');
                                self.scrollingLock = false;
                                self.loop = false;

                            }
                            else if (Math.round(Math.abs(self.xp - self.windowLeftPos) + Math.abs(self.yp - self.windowTopPos)) < 1) {
                                //stops micro movements
                                clearInterval(self.loop);
                                self.zoomWindow.css('background-position', self.windowLeftPos + 'px ' + self.windowTopPos + 'px');
                                self.loop = false;
                            }
                            else {
                                if (self.changeBgSize) {
                                    if (self.nzHeight > self.nzWidth) {
                                        if (self.options.zoomType === 'lens') {
                                            self.zoomLens.css('background-size',
                                                self.largeWidth / self.newvalueheight + 'px ' +
                                                self.largeHeight / self.newvalueheight + 'px');
                                        }
                                        self.zoomWindow.css('background-size',
                                            self.largeWidth / self.newvalueheight + 'px ' +
                                            self.largeHeight / self.newvalueheight + 'px');
                                    }
                                    else {
                                        if (self.options.zoomType !== 'lens') {
                                            self.zoomLens.css('background-size',
                                                self.largeWidth / self.newvaluewidth + 'px ' +
                                                self.largeHeight / self.newvaluewidth + 'px');
                                        }
                                        self.zoomWindow.css('background-size',
                                            self.largeWidth / self.newvaluewidth + 'px ' +
                                            self.largeHeight / self.newvaluewidth + 'px');
                                    }
                                    self.changeBgSize = false;
                                }

                                self.zoomWindow.css('background-position', self.xp + 'px ' + self.yp + 'px');
                            }
                        }, interval);
                    }
                }
                else {
                    if (self.changeBgSize) {
                        if (self.nzHeight > self.nzWidth) {
                            if (self.options.zoomType === 'lens') {
                                self.zoomLens.css('background-size',
                                    self.largeWidth / self.newvalueheight + 'px ' +
                                    self.largeHeight / self.newvalueheight + 'px');
                            }

                            self.zoomWindow.css('background-size',
                                self.largeWidth / self.newvalueheight + 'px ' +
                                self.largeHeight / self.newvalueheight + 'px');
                        }
                        else {
                            if (self.options.zoomType === 'lens') {
                                self.zoomLens.css('background-size',
                                    self.largeWidth / self.newvaluewidth + 'px ' +
                                    self.largeHeight / self.newvaluewidth + 'px');
                            }
                            if ((self.largeHeight / self.newvaluewidth) < self.options.zoomWindowHeight) {

                                self.zoomWindow.css('background-size',
                                    self.largeWidth / self.newvaluewidth + 'px ' +
                                    self.largeHeight / self.newvaluewidth + 'px');
                            }
                            else {

                                self.zoomWindow.css('background-size',
                                    self.largeWidth / self.newvalueheight + 'px ' +
                                    self.largeHeight / self.newvalueheight + 'px');
                            }

                        }
                        self.changeBgSize = false;
                    }

                    self.zoomWindow.css('background-position',
                        self.windowLeftPos + 'px ' +
                        self.windowTopPos + 'px');
                }
            }
        },

        setTintPosition: function (e) {
            var self = this;
            var zoomLensWidth = self.zoomLens.width();
            var zoomLensHeight = self.zoomLens.height();
            self.updateOffset(self);
            self.tintpos = String(((e.pageX - self.nzOffset.left) - (zoomLensWidth / 2)) * (-1));
            self.tintposy = String(((e.pageY - self.nzOffset.top) - zoomLensHeight / 2) * (-1));
            if (self.Etoppos) {
                self.tintposy = 0;
            }
            if (self.Eloppos) {
                self.tintpos = 0;
            }
            if (self.Eboppos) {
                self.tintposy = (self.nzHeight - zoomLensHeight - (self.options.lensBorderSize * 2)) * (-1);
            }
            if (self.Eroppos) {
                self.tintpos = ((self.nzWidth - zoomLensWidth - (self.options.lensBorderSize * 2)) * (-1));
            }
            if (self.options.tint) {
                //stops micro movements
                if (self.fullheight) {
                    self.tintposy = 0;

                }
                if (self.fullwidth) {
                    self.tintpos = 0;

                }
                self.zoomTintImage.css({
                    'left': self.tintpos + 'px',
                    'top': self.tintposy + 'px'
                });
            }
        },

        swaptheimage: function (smallimage, largeimage) {
            var self = this;
            var newImg = new Image();

            if (self.options.loadingIcon && !self.spinner) {
                var styleAttr = 'background: url(\'' + self.options.loadingIcon + '\') no-repeat center;' +
                    'height:' + self.nzHeight + 'px;' +
                    'width:' + self.nzWidth + 'px;' +
                    'z-index: 2000;' +
                    'position: absolute; ' +
                    'background-position: center center;';
                if (self.options.zoomType === 'inner') {
                    styleAttr += 'top: 0px;';
                }
                self.spinner = $('<div class="ezp-spinner" style="' + styleAttr + '"></div>');
                self.$elem.after(self.spinner);
            } else if (self.spinner) {
                self.spinner.show();
            }

            self.options.onImageSwap(self.$elem);

            newImg.onload = function () {
                self.largeWidth = newImg.width;
                self.largeHeight = newImg.height;
                self.zoomImage = largeimage;
                self.zoomWindow.css('background-size', self.largeWidth + 'px ' + self.largeHeight + 'px');

                self.swapAction(smallimage, largeimage);
                return;
            };
            self.setImageSource(newImg, largeimage);  // this must be done AFTER setting onload
        },

        swapAction: function (smallimage, largeimage) {
            var self = this;
            var elemWidth = self.$elem.width();
            var elemHeight = self.$elem.height();
            var newImg2 = new Image();
            newImg2.onload = function () {
                //re-calculate values
                self.nzHeight = newImg2.height;
                self.nzWidth = newImg2.width;
                self.options.onImageSwapComplete(self.$elem);

                self.doneCallback();
                return;
            };
            self.setImageSource(newImg2, smallimage);

            //reset the zoomlevel to that initially set in options
            self.currentZoomLevel = self.options.zoomLevel;
            self.options.maxZoomLevel = false;

            //swaps the main image
            //self.$elem.attr('src',smallimage);
            //swaps the zoom image
            if (self.options.zoomType === 'lens') {
                self.zoomLens.css('background-image', 'url("' + largeimage + '")');
            }
            if (self.options.zoomType === 'window') {
                self.zoomWindow.css('background-image', 'url("' + largeimage + '")');
            }
            if (self.options.zoomType === 'inner') {
                self.zoomWindow.css('background-image', 'url("' + largeimage + '")');
            }

            self.currentImage = largeimage;

            if (self.options.imageCrossfade) {
                var oldImg = self.$elem;
                var newImg = oldImg.clone();
                self.$elem.attr('src', smallimage);
                self.$elem.after(newImg);
                newImg.stop(true).fadeOut(self.options.imageCrossfade, function () {
                    $(this).remove();
                });

                // if(self.options.zoomType === 'inner'){
                //remove any attributes on the cloned image so we can resize later
                self.$elem.width('auto').removeAttr('width');
                self.$elem.height('auto').removeAttr('height');
                //   }

                oldImg.fadeIn(self.options.imageCrossfade);

                if (self.options.tint && self.options.zoomType !== 'inner') {

                    var oldImgTint = self.zoomTintImage;
                    var newImgTint = oldImgTint.clone();
                    self.zoomTintImage.attr('src', largeimage);
                    self.zoomTintImage.after(newImgTint);
                    newImgTint.stop(true).fadeOut(self.options.imageCrossfade, function () {
                        $(this).remove();
                    });

                    oldImgTint.fadeIn(self.options.imageCrossfade);

                    //self.zoomTintImage.attr('width',elem.data('image'));

                    //resize the tint window
                    self.zoomTint.css({
                        height: elemHeight,
                        width: elemWidth
                    });
                }

                self.zoomContainer.css({
                    'height': elemHeight,
                    'width': elemWidth
                });

                if (self.options.zoomType === 'inner') {
                    if (!self.options.constrainType) {
                        self.zoomWrap.parent().css({
                            'height': elemHeight,
                            'width': elemWidth
                        });

                        self.zoomWindow.css({
                            'height': elemHeight,
                            'width': elemWidth
                        });
                    }
                }

                if (self.options.imageCrossfade) {
                    self.zoomWrap.css({
                        'height': elemHeight,
                        'width': elemWidth
                    });
                }
            }
            else {
                self.$elem.attr('src', smallimage);
                if (self.options.tint) {
                    self.zoomTintImage.attr('src', largeimage);
                    //self.zoomTintImage.attr('width',elem.data('image'));
                    self.zoomTintImage.attr('height', elemHeight);
                    //self.zoomTintImage.attr('src') = elem.data('image');
                    self.zoomTintImage.css('height', elemHeight);
                    self.zoomTint.css('height', elemHeight);

                }
                self.zoomContainer.css({
                    'height': elemHeight,
                    'width': elemWidth
                });

                if (self.options.imageCrossfade) {
                    self.zoomWrap.css({
                        'height': elemHeight,
                        'width': elemWidth
                    });
                }
            }
            if (self.options.constrainType) {

                //This will contrain the image proportions
                if (self.options.constrainType === 'height') {

                    var autoWDimension = {
                        'height': self.options.constrainSize,
                        'width': 'auto'
                    };
                    self.zoomContainer.css(autoWDimension);

                    if (self.options.imageCrossfade) {
                        self.zoomWrap.css(autoWDimension);
                        self.constwidth = self.zoomWrap.width();
                    }
                    else {
                        self.$elem.css(autoWDimension);
                        self.constwidth = elemWidth;
                    }

                    var constWDim = {
                        'height': self.options.constrainSize,
                        'width': self.constwidth
                    };
                    if (self.options.zoomType === 'inner') {

                        self.zoomWrap.parent().css(constWDim);
                        self.zoomWindow.css(constWDim);
                    }
                    if (self.options.tint) {
                        self.tintContainer.css(constWDim);
                        self.zoomTint.css(constWDim);
                        self.zoomTintImage.css(constWDim);
                    }

                }
                if (self.options.constrainType === 'width') {
                    var autoHDimension = {
                        'height': 'auto',
                        'width': self.options.constrainSize
                    };
                    self.zoomContainer.css(autoHDimension);

                    if (self.options.imageCrossfade) {
                        self.zoomWrap.css(autoHDimension);
                        self.constheight = self.zoomWrap.height();
                    }
                    else {
                        self.$elem.css(autoHDimension);
                        self.constheight = elemHeight;
                    }

                    var constHDim = {
                        'height': self.constheight,
                        'width': self.options.constrainSize
                    };
                    if (self.options.zoomType === 'inner') {
                        self.zoomWrap.parent().css(constHDim);
                        self.zoomWindow.css(constHDim);
                    }
                    if (self.options.tint) {
                        self.tintContainer.css(constHDim);
                        self.zoomTint.css(constHDim);
                        self.zoomTintImage.css(constHDim);
                    }
                }
            }
        },

        doneCallback: function () {
            var self = this;
            if (self.options.loadingIcon && !!self.spinner && !!self.spinner.length) {
                self.spinner.hide();
            }

            self.updateOffset(self);
            self.nzWidth = self.$elem.width();
            self.nzHeight = self.$elem.height();

            // reset the zoomlevel back to default
            self.currentZoomLevel = self.options.zoomLevel;

            //ratio of the large to small image
            self.widthRatio = self.largeWidth / self.nzWidth;
            self.heightRatio = self.largeHeight / self.nzHeight;

            //NEED TO ADD THE LENS SIZE FOR ROUND
            // adjust images less than the window height
            if (self.options.zoomType === 'window') {

                if (self.nzHeight < self.options.zoomWindowHeight / self.heightRatio) {
                    self.lensHeight = self.nzHeight;

                }
                else {
                    self.lensHeight = String((self.options.zoomWindowHeight / self.heightRatio));
                }

                if (self.nzWidth < self.options.zoomWindowWidth) {
                    self.lensWidth = self.nzWidth;
                }
                else {
                    self.lensWidth = (self.options.zoomWindowWidth / self.widthRatio);
                }

                if (self.zoomLens) {
                    self.zoomLens.css({
                        'width': self.lensWidth,
                        'height': self.lensHeight
                    });
                }
            }
        },

        getCurrentImage: function () {
            var self = this;
            return self.zoomImage;
        },

        getGalleryList: function () {
            var self = this;
            //loop through the gallery options and set them in list for fancybox
            self.gallerylist = [];
            if (self.options.gallery) {
                $('#' + self.options.gallery + ' a').each(function () {

                    var imgSrc = '';
                    if ($(this).data(self.options.attrImageZoomSrc)) {
                        imgSrc = $(this).data(self.options.attrImageZoomSrc);
                    }
                    else if ($(this).data('image')) {
                        imgSrc = $(this).data('image');
                    }
                    //put the current image at the start
                    if (imgSrc === self.zoomImage) {
                        self.gallerylist.unshift({
                            href: '' + imgSrc + '',
                            title: $(this).find('img').attr('title')
                        });
                    }
                    else {
                        self.gallerylist.push({
                            href: '' + imgSrc + '',
                            title: $(this).find('img').attr('title')
                        });
                    }
                });
            }
            //if no gallery - return current image
            else {
                self.gallerylist.push({
                    href: '' + self.zoomImage + '',
                    title: $(this).find('img').attr('title')
                });
            }
            return self.gallerylist;
        },

        changeZoomLevel: function (value) {
            var self = this;

            //flag a zoom, so can adjust the easing during setPosition
            self.scrollingLock = true;

            //round to two decimal places
            self.newvalue = parseFloat(value).toFixed(2);
            var newvalue = self.newvalue;

            //maxwidth & Maxheight of the image
            var maxheightnewvalue = self.largeHeight / ((self.options.zoomWindowHeight / self.nzHeight) * self.nzHeight);
            var maxwidthtnewvalue = self.largeWidth / ((self.options.zoomWindowWidth / self.nzWidth) * self.nzWidth);

            //calculate new heightratio
            if (self.options.zoomType !== 'inner') {
                if (maxheightnewvalue <= newvalue) {
                    self.heightRatio = (self.largeHeight / maxheightnewvalue) / self.nzHeight;
                    self.newvalueheight = maxheightnewvalue;
                    self.fullheight = true;
                }
                else {
                    self.heightRatio = (self.largeHeight / newvalue) / self.nzHeight;
                    self.newvalueheight = newvalue;
                    self.fullheight = false;
                }

                // calculate new width ratio

                if (maxwidthtnewvalue <= newvalue) {
                    self.widthRatio = (self.largeWidth / maxwidthtnewvalue) / self.nzWidth;
                    self.newvaluewidth = maxwidthtnewvalue;
                    self.fullwidth = true;
                }
                else {
                    self.widthRatio = (self.largeWidth / newvalue) / self.nzWidth;
                    self.newvaluewidth = newvalue;
                    self.fullwidth = false;
                }
                if (self.options.zoomType === 'lens') {
                    if (maxheightnewvalue <= newvalue) {
                        self.fullwidth = true;
                        self.newvaluewidth = maxheightnewvalue;
                    } else {
                        self.widthRatio = (self.largeWidth / newvalue) / self.nzWidth;
                        self.newvaluewidth = newvalue;

                        self.fullwidth = false;
                    }
                }
            }

            if (self.options.zoomType === 'inner') {
                maxheightnewvalue = parseFloat(self.largeHeight / self.nzHeight).toFixed(2);
                maxwidthtnewvalue = parseFloat(self.largeWidth / self.nzWidth).toFixed(2);
                if (newvalue > maxheightnewvalue) {
                    newvalue = maxheightnewvalue;
                }
                if (newvalue > maxwidthtnewvalue) {
                    newvalue = maxwidthtnewvalue;
                }

                if (maxheightnewvalue <= newvalue) {
                    self.heightRatio = (self.largeHeight / newvalue) / self.nzHeight;
                    if (newvalue > maxheightnewvalue) {
                        self.newvalueheight = maxheightnewvalue;
                    } else {
                        self.newvalueheight = newvalue;
                    }
                    self.fullheight = true;
                }
                else {
                    self.heightRatio = (self.largeHeight / newvalue) / self.nzHeight;

                    if (newvalue > maxheightnewvalue) {

                        self.newvalueheight = maxheightnewvalue;
                    } else {
                        self.newvalueheight = newvalue;
                    }
                    self.fullheight = false;
                }

                if (maxwidthtnewvalue <= newvalue) {

                    self.widthRatio = (self.largeWidth / newvalue) / self.nzWidth;
                    if (newvalue > maxwidthtnewvalue) {

                        self.newvaluewidth = maxwidthtnewvalue;
                    } else {
                        self.newvaluewidth = newvalue;
                    }

                    self.fullwidth = true;
                }
                else {
                    self.widthRatio = (self.largeWidth / newvalue) / self.nzWidth;
                    self.newvaluewidth = newvalue;
                    self.fullwidth = false;
                }
            } //end inner
            var scrcontinue = false;

            if (self.options.zoomType === 'inner') {
                if (self.nzWidth >= self.nzHeight) {
                    if (self.newvaluewidth <= maxwidthtnewvalue) {
                        scrcontinue = true;
                    }
                    else {
                        scrcontinue = false;
                        self.fullheight = true;
                        self.fullwidth = true;
                    }
                }
                if (self.nzHeight > self.nzWidth) {
                    if (self.newvaluewidth <= maxwidthtnewvalue) {
                        scrcontinue = true;
                    }
                    else {
                        scrcontinue = false;
                        self.fullheight = true;
                        self.fullwidth = true;
                    }
                }
            }

            if (self.options.zoomType !== 'inner') {
                scrcontinue = true;
            }

            if (scrcontinue) {
                self.zoomLock = 0;
                self.changeZoom = true;

                //if lens height is less than image height
                if (((self.options.zoomWindowHeight) / self.heightRatio) <= self.nzHeight) {
                    self.currentZoomLevel = self.newvalueheight;
                    if (self.options.zoomType !== 'lens' && self.options.zoomType !== 'inner') {
                        self.changeBgSize = true;
                        self.zoomLens.css('height', String(self.options.zoomWindowHeight / self.heightRatio) + 'px');
                    }
                    if (self.options.zoomType === 'lens' || self.options.zoomType === 'inner') {
                        self.changeBgSize = true;
                    }
                }

                if ((self.options.zoomWindowWidth / self.widthRatio) <= self.nzWidth) {
                    if (self.options.zoomType !== 'inner') {
                        if (self.newvaluewidth > self.newvalueheight) {
                            self.currentZoomLevel = self.newvaluewidth;
                        }
                    }

                    if (self.options.zoomType !== 'lens' && self.options.zoomType !== 'inner') {
                        self.changeBgSize = true;

                        self.zoomLens.css('width', String(self.options.zoomWindowWidth / self.widthRatio) + 'px');
                    }
                    if (self.options.zoomType === 'lens' || self.options.zoomType === 'inner') {
                        self.changeBgSize = true;
                    }

                }
                if (self.options.zoomType === 'inner') {
                    self.changeBgSize = true;

                    if (self.nzWidth > self.nzHeight) {
                        self.currentZoomLevel = self.newvaluewidth;
                    }
                    else if (self.nzHeight >= self.nzWidth) {
                        self.currentZoomLevel = self.newvaluewidth;
                    }
                }
            }      //under

            //sets the boundry change, called in setWindowPos
            self.setPosition(self.currentLoc);
            //
        },

        closeAll: function () {
            var self = this;
            if (self.zoomWindow) {
                self.zoomWindow.hide();
            }
            if (self.zoomLens) {
                self.zoomLens.hide();
            }
            if (self.zoomTint) {
                self.zoomTint.hide();
            }
        },
        updateOffset: function (self) {
            if (self.options.zoomContainerAppendTo != 'body') {
                self.nzOffset = self.$elem.offset();
                appendedPosition = $(self.options.zoomContainerAppendTo).offset();
                self.nzOffset.top = self.$elem.offset().top - appendedPosition.top;
                self.nzOffset.left = self.$elem.offset().left - appendedPosition.left;

            } else {
                self.nzOffset = self.$elem.offset();
            }
        },

        changeState: function (value) {
            var self = this;
            if (value === 'enable') {
                self.options.zoomEnabled = true;
            }
            if (value === 'disable') {
                self.options.zoomEnabled = false;
            }
        },

        responsiveConfig: function (options) {
            if (options.respond && options.respond.length > 0) {
                return $.extend({}, options, this.configByScreenWidth(options));
            }
            return options;
        },

        configByScreenWidth: function (options) {
            var screenWidth = $(window).width();

            var config = $.grep(options.respond, function (item) {
                var range = item.range.split('-');
                return (screenWidth >= range[0]) && (screenWidth <= range[1]);
            });

            if (config.length > 0) {
                return config[0];
            } else {
                return options;
            }
        }
    };

    $.fn.ezPlus = function (options) {
        return this.each(function () {
            var elevate = Object.create(EZP);

            elevate.init(options, this);

            $.data(this, 'ezPlus', elevate);

        });
    };

    $.fn.ezPlus.options = {
        attrImageZoomSrc: 'zoom-image', // attribute to plugin use for zoom
        borderColour: '#888',
        borderSize: 4,
        constrainSize: false,  //in pixels the dimensions you want to constrain on
        constrainType: false,  //width or height
        containLensZoom: false,
        cursor: 'inherit', // user should set to what they want the cursor as, if they have set a click function
        debug: false,
        easing: false,
        easingAmount: 12,
        enabled: true,

        gallery: false,
        galleryActiveClass: 'zoomGalleryActive',
        gallerySelector: false,
        galleryItem: 'a',

        imageCrossfade: false,

        lensBorderColour: '#000',
        lensBorderSize: 1,
        lensColour: 'white', //colour of the lens background
        lensFadeIn: false,
        lensFadeOut: false,
        lensOpacity: 0.4, //opacity of the lens
        lensShape: 'square', //can be 'round'
        lensSize: 200,
        lenszoom: false,

        loadingIcon: false, //http://www.example.com/spinner.gif

        // This change will allow to decide if you want to decrease
        // zoom of one of the dimensions once the other reached it's top value,
        // or keep the aspect ratio, default behaviour still being as always,
        // allow to continue zooming out, so it keeps retrocompatibility.
        mantainZoomAspectRatio: false,
        maxZoomLevel: false,
        minZoomLevel: 1.01,

        onComplete: $.noop,
        onDestroy: $.noop,
        onImageClick: $.noop,
        onImageSwap: $.noop,
        onImageSwapComplete: $.noop,
        onShow: $.noop,
        onZoomedImageLoaded: $.noop,

        preloading: 1, //by default, load all the images, if 0, then only load images after activated (PLACEHOLDER FOR NEXT VERSION)
        respond: [],
        responsive: true,
        scrollZoom: false, //allow zoom on mousewheel, true to activate
        scrollZoomIncrement: 0.1,  //steps of the scrollzoom
        showLens: true,
        tint: false, //enable the tinting
        tintColour: '#333', //default tint color, can be anything, red, #ccc, rgb(0,0,0)
        tintOpacity: 0.4, //opacity of the tint
        touchEnabled: true,

        zoomActivation: 'hover', // Can also be click (PLACEHOLDER FOR NEXT VERSION)
        zoomContainerAppendTo: 'body', //zoom container parent selector
        zoomId: -1, // identifier for the zoom container
        zoomLevel: 1, //default zoom level of image
        zoomTintFadeIn: false,
        zoomTintFadeOut: false,
        zoomType: 'window', //window is default,  also 'lens' available -
        zoomWindowAlwaysShow: false,
        zoomWindowBgColour: '#fff',
        zoomWindowFadeIn: false,
        zoomWindowFadeOut: false,
        zoomWindowHeight: 400,
        zoomWindowOffsetX: 0,
        zoomWindowOffsetY: 0,
        zoomWindowPosition: 1, //Possible values: 1-16, but we can also position with a selector string.
        zoomWindowWidth: 400,
        zoomEnabled: true, //false disables zoomwindow from showing
        zIndex: 999
    };

})(jQuery, window, document);
