/**
 * Zoomer tool
 *
 * Generates an image and zooms it
 */

(function($) {

	$.fn.zoomer = function(options) {

		options2 = $.extend({
			"overlayWidth": 75, 
			"overlayHeight": 75,
			"zoomedWidth": null,
			"zoomedHeight": null,
			"widthRatio": null,
			"heightRatio": null,
			"overlayClass": "zoomer"
		}, options);

		return this.each(function(index) {
			// they should all be images
			var $this = $(this);
			if (!$this.is('img')) {
				return;
			}
			
			var data = $this.data('zoomer');
			if (data) {
				$this.unbind('mousemove', data.onMouseMove);
				$this.unbind('mouseleave', data.onMouseLeave);

				data.o_div.unbind('mousemove', data.onZoomerMouseMove);
				data.o_div.unbind('mouseleave', data.onZoomerMouseLeave);
				data.o_div.remove();
				$this.data('zoomer', null);
			}
			if (options === 'remove') {
				return;
			}
			
			var o_div = $('<div />')
				.css('position', 'absolute')
				.css('display', 'none')
				.css('overflow', 'hidden')
				.addClass('zoomer')
				.addClass(options2.overlayClass);
			var z_img = $('<img />')
				.css('position', 'absolute');
			if (options2.zoomedWidth) {
				z_img.css('width', zoomedWidth);
			} else if (options2.widthRatio) {
				z_img.width((options2.widthRatio * $this.width()));
			}
			if (options2.zoomedHeight) {
				z_img.css('height', zoomedHeight);
			} else if (options2.heightRatio) {
				z_img.height((options2.heightRatio * $this.height()));
			}
			z_img.attr('src', $this.attr('src'));
			if (options2.overlayWidth) {
				o_div.width(options2.overlayWidth);
			}
			if (options2.overlayHeight) {
				o_div.height(options2.overlayHeight);
			}

			var onMouseMove = function(e) {
				var offset = $this.offset();
				var x = e.pageX - offset.left;
				var y = e.pageY - offset.top;
				var iw = $this.width(); // not inner, because it's an img
				var ih = $this.height();
				var xf = x/iw;
				var yf = y/ih;
				var ow = o_div.width();
				var oh = o_div.height();
				var zw = z_img.width();
				var zh = z_img.height();
				var o_bw = o_div.css('borderWidth');
				var o_bh = o_div.css('borderHeight');
				
				var o_left = offset.left + xf * (iw - ow);
				var o_top = offset.top + yf * (ih - oh);
				var z_left = offset.left + xf * (iw - zw) - o_left;
				var z_top = offset.top + yf * (ih - zh) - o_top;

				o_div.css('left', o_left+'px')
					.css('top', o_top+'px');
				z_img.css('left', z_left+'px')
					.css('top', z_top+'px');
				o_div.css('position', 'absolute');
				o_div.css('display', 'block');
			};

			var onMouseLeave = function(e) {
				var offset = $this.offset();
				if (e.pageX < offset.left
					|| e.pageY < offset.top 
					|| e.pageX > offset.left + $this.width()
					|| e.pageY > offset.top + $this.height()) {
					o_div.css('display', 'none');
				}
			};
			
			var onZoomerMouseMove = function(e) {
				var offset = $this.offset();
				if (e.pageX < offset.left
					|| e.pageY < offset.top 
					|| e.pageX > offset.left + $this.width()
					|| e.pageY > offset.top + $this.height()) {
					onMouseLeave(e);	
				} else {
					onMouseMove(e);
				}
			};
			var onZoomerMouseLeave = onZoomerMouseMove;

			//this.css('height', '200px');
			$this.mousemove(onMouseMove);
			$this.mouseleave(onMouseLeave);
			
			o_div.mousemove(onZoomerMouseMove);
			o_div.mouseleave(onZoomerMouseLeave);
			
			o_div.html(z_img);
			o_div.appendTo('body');
			
			$this.data('zoomer', {
				'onMouseMove': onMouseMove,
				'onMouseLeave': onMouseLeave,
				'onZoomerMouseMove': onZoomerMouseMove,
				'onZoomerMouseLeave': onZoomerMouseLeave,
				'o_div': o_div
			});
		});
		
	};
	
	$.fn.autogrow = function(options) {

        o = $.extend({
            maxWidth: 1000,
            minWidth: 0,
            comfortZone: 10,
			onResize: null
        }, options);

        this.filter('input:text').each(function(){

            var minWidth = o.minWidth || $(this).width(),
                val = '',
                input = $(this),
                testSubject = $('<tester/>').css({
                    position: 'absolute',
                    top: -9999,
                    left: -9999,
                    width: 'auto',
                    fontSize: input.css('fontSize'),
                    fontFamily: input.css('fontFamily'),
                    fontWeight: input.css('fontWeight'),
                    letterSpacing: input.css('letterSpacing'),
                    whiteSpace: 'nowrap'
                }),
                check = function() {

                    if (val === (val = input.val())) {return;}

                    // Enter new content into testSubject
                    var escaped = val.replace(/&/g, '&amp;').replace(/\s/g,'&nbsp;').replace(/</g, '&lt;').replace(/>/g, '&gt;');
                    testSubject.html(escaped);

                    // Calculate new width + whether to change
                    var testerWidth = testSubject.width(),
                        newWidth = (testerWidth + o.comfortZone) >= minWidth ? testerWidth + o.comfortZone : minWidth,
                        currentWidth = input.width(),
                        isValidWidthChange = (newWidth < currentWidth && newWidth >= minWidth)
                                             || (newWidth > minWidth && newWidth < o.maxWidth);

                    // Animate width
                    if (isValidWidthChange) {
                        input.width(newWidth);
						if (o.onResize) {
							o.onResize(newWidth);
						}
                    }

                };

            testSubject.insertAfter(input);

            $(this).bind('keyup keydown blur update', check);

        });

        return this;

    };
	
})(jQuery);

