text: /******************************************
   * Websanova.com
   *
   * Resources for web entrepreneurs
   *
   * @author          Websanova
   * @copyright       Copyright (c) 2012 Websanova.
   * @license         This wScratchPad jQuery plug-in is dual licensed under the MIT and GPL licenses.
   * @link            http://www.websanova.com
   * @github			http://github.com/websanova/wScratchPad
   * @version         Version 1.4.2
   *
   *
   ******************************************/
  
  (function($)
  {
  	$.fn.wScratchPad = function(option, settings)
  	{
  		if(typeof option === 'object')
  		{
  			settings = option;
  		}
  		else if(typeof option == 'string')
  		{
  			var values = [];
  
  			var elements = this.each(function()
  			{
  				var data = $(this).data('_wScratchPad');
  
  				if(data)
  				{
  					if(option === 'reset') { data.reset(); }
  					else if(option === 'clear') { data.clear(); }
  					else if(option === 'enabled') { data.enabled = settings === true; }
  					else if($.fn.wScratchPad.defaultSettings[option] !== undefined)
  					{
  						if(settings !== undefined) { data.settings[option] = settings; }
  						else { values.push(data.settings[option]); }
  					}
  				}
  			});
  
  			if(values.length === 1) { return values[0]; }
  			if(values.length > 0) { return values; }
  			else { return elements; }
  		}
  
  		settings = $.extend({}, $.fn.wScratchPad.defaultSettings, settings || {});
  
  		return this.each(function()
  		{
  			var elem = $(this);
  			var $settings = jQuery.extend(true, {}, settings);
  
  			//test for HTML5 canvas
  			var test = document.createElement('canvas');
  			if(!test.getContext)
  			{
  				elem.html("Browser does not support HTML5 canvas, please upgrade to a more modern browser.");
  				return false;
  			}
  
  			var sp = new ScratchPad($settings, elem);
  
  			elem.append(sp.generate());
  
  			//get number of pixels of canvas for percent calculations
  			sp.pixels = sp.canvas.width * sp.canvas.height;
  
  			elem.data('_wScratchPad', sp);
  
  			sp.init();
  		});
  	};
  
  	$.fn.wScratchPad.defaultSettings =
  	{
  		width		: 210,						// set width - best to match image width
  		height		: 100,						// set height - best to match image height
  		image		: null,		// set image path
  		image2		: null,						// set overlay image path - if set color is not used
  		color		: '#336699',				// set scratch color - if image2 is not set uses color
  		overlay		: 'none',					// set the type of overlay effect 'none', 'lighter' - only used with color
  		size		: 10,						// set size of scratcher
  		scratchDown	: null,						// scratchDown callback
  		scratchUp	: null,						// scratchUp callback
  		scratchMove	: null,						// scratcMove callback
  		cursor		: null						// Set path to custom cursor
  	};
  
  	function ScratchPad(settings, elem)
  	{
  		this.sp = null;
  		this.settings = settings;
  		this.$elem = elem;
  
  		this.enabled = true;
  		this.scratch = false;
  
  		this.canvas = null;
  		this.ctx = null;
  
  		return this;
  	}
  
  	ScratchPad.prototype =
  	{
  		generate: function()
  		{
  			var $this = this;
  
  			this.canvas = document.createElement('canvas');
  			this.ctx = this.canvas.getContext('2d');
  
  			this.sp =
  			$('<div></div>')
  			.css({position: 'relative'})
  			.append(
  				$(this.canvas)
  				.attr('width', this.settings.width + 'px')
  				.attr('height', this.settings.height + 'px')
  			)
  
  			$(this.canvas)
  			.mousedown(function(e)
  			{
  				if(!$this.enabled) return true;
  
  				e.preventDefault();
  				e.stopPropagation();
  
  				//reset canvas offset in case it has moved
  				$this.canvas_offset = $($this.canvas).offset();
  
  				$this.scratch = true;
  				$this.scratchFunc(e, $this, 'Down');
  			})
  			.mousemove(function(e)
  			{
  				e.preventDefault();
  				e.stopPropagation();
  
  				if($this.scratch) $this.scratchFunc(e, $this, 'Move');
  			})
  			.mouseup(function(e)
  			{
  				e.preventDefault();
  				e.stopPropagation();
  
  				//make sure we are in draw mode otherwise this will fire on any mouse up.
  				if($this.scratch)
  				{
  					$this.scratch = false;
  					$this.scratchFunc(e, $this, 'Up');
  				}
  			});
  
  			this.bindMobile(this.sp);
  
  			return this.sp;
  		},
  
  		bindMobile: function($el)
  		{
  			$el.bind('touchstart touchmove touchend touchcancel', function ()
  			{
  				var touches = event.changedTouches, first = touches[0], type = "";
  
  				switch (event.type)
  				{
  					case "touchstart": type = "mousedown"; break;
  					case "touchmove": type = "mousemove"; break;
  					case "touchend": type = "mouseup"; break;
  					default: return;
  				}
  
  				var simulatedEvent = document.createEvent("MouseEvent");
  
  				simulatedEvent.initMouseEvent(type, true, true, window, 1, first.screenX, first.screenY, first.clientX, first.clientY, false, false, false, false, 0/*left*/, null);
  				first.target.dispatchEvent(simulatedEvent);
  				event.preventDefault();
  			});
  		},
  
  		init: function()
  		{
  			this.sp.css('width', this.settings.width);
  			this.sp.css('height', this.settings.height);
  			this.sp.css('cursor', (this.settings.cursor ? 'url("' + this.settings.cursor + '"), default' : 'default'));
  
  			$(this.canvas).css({cursor: (this.settings.cursor ? 'url("' + this.settings.cursor + '"), default' : 'default')});
  
  			this.canvas.width = this.settings.width;
  			this.canvas.height = this.settings.height;
  
  			this.pixels = this.canvas.width * this.canvas.height;
  
  			if(this.settings.image2)
  			{
  				this.drawImage(this.settings.image2);
  			}
  			else
  			{
  				if(this.settings.overlay != 'none')
  				{
  					if(this.settings.image)
  					{
  						this.drawImage(this.settings.image);
  					}
  					this.ctx.globalCompositeOperation = this.settings.overlay;
  				}
  				else
  				{
  					this.setBgImage();
  				}
  
  				this.ctx.fillStyle = this.settings.color;
  				this.ctx.beginPath();
  				this.ctx.rect(0, 0, this.settings.width, this.settings.height)
  				this.ctx.fill();
  			}
  		},
  
  		reset: function()
  		{
  			this.ctx.globalCompositeOperation = 'source-over';
  			this.init();
  		},
  
  		clear: function()
  		{
  			this.ctx.clearRect(0, 0, this.settings.width, this.settings.height);
  		},
  
  		setBgImage: function()
  		{
  			if(this.settings.image)
  			{
  				this.sp.css({backgroundImage: 'url('+this.settings.image+')'});
  			}
  		},
  
  		drawImage: function(imagePath)
  		{
  			var $this = this;
  			var img = new Image();
    			img.src = imagePath;
    			$(img).load(function(){
    				$this.ctx.drawImage(img, 0, 0);
    				$this.setBgImage();
    			})
  		},
  
  		scratchFunc: function(e, $this, event)
  		{
  			e.pageX = Math.floor(e.pageX - $this.canvas_offset.left);
  			e.pageY = Math.floor(e.pageY - $this.canvas_offset.top);
  
  			$this['scratch' + event](e, $this);
  
  			if($this.settings['scratch' + event]) $this.settings['scratch' + event].apply($this, [e, $this.scratchPercentage($this)]);
  		},
  
  		scratchPercentage: function($this)
  		{
  			var hits = 0;
  			var imageData = $this.ctx.getImageData(0,0,$this.canvas.width,$this.canvas.height)
  
  			for(var i=0, ii=imageData.data.length; i<ii; i=i+4)
  			{
  				if(imageData.data[i] == 0 && imageData.data[i+1] == 0 && imageData.data[i+2] == 0 && imageData.data[i+3] == 0) hits++;
  			}
  
  			return (hits / $this.pixels) * 100;
  		},
  
  		scratchDown: function(e, $this)
  		{
  			$this.ctx.globalCompositeOperation = 'destination-out';
  			$this.ctx.lineJoin = "round";
  			$this.ctx.lineCap = "round";
  			$this.ctx.strokeStyle = $this.settings.color;
  			$this.ctx.lineWidth = $this.settings.size;
  
  			//draw single dot in case of a click without a move
  			$this.ctx.beginPath();
  			$this.ctx.arc(e.pageX, e.pageY, $this.settings.size/2, 0, Math.PI*2, true);
  			$this.ctx.closePath();
  			$this.ctx.fill();
  
  			//start the path for a drag
  			$this.ctx.beginPath();
  			$this.ctx.moveTo(e.pageX, e.pageY);
  
  			$(this.canvas).css('margin-right', $(this.canvas).css('margin-right') == "0px" ? "1px" : "0px");
  		},
  
  		scratchMove: function(e, $this)
  		{
  			$this.ctx.lineTo(e.pageX, e.pageY);
  			$this.ctx.stroke();
  
  			$(this.canvas).css('margin-right', $(this.canvas).css('margin-right') == "0px" ? "1px" : "0px");
  		},
  
  		scratchUp: function(e, $this)
  		{
  			$this.ctx.closePath();
  
  			$(this.canvas).css('margin-right', $(this.canvas).css('margin-right') == "0px" ? "1px" : "0px");
  		},
  	}
  })(jQuery);