(  
 function($){


	$.fn.wiggle = function(method, options) {
		options = $.extend({
			wiggleDegrees: ['1','1','1','0','-1','-2','-1','0'],
			delay: 60,
			limit: null,
			randomStart: true,
			onWiggle: function(object) {},
			onWiggleStart: function(object) {},
			onWiggleStop: function(object) {}
		}, options);

		var methods = {
			wiggle: function(object, step){
				if(step === undefined) {
					step = options.randomStart ? Math.floor(Math.random()*options.wiggleDegrees.length) : 0;
				}

				if(!$(object).hasClass('wiggling')) {
					$(object).addClass('wiggling');
				}

				var degree = options.wiggleDegrees[step];
				$(object).css({
					'-webkit-transform': 'rotate('+degree+'deg)',
					'-moz-transform': 'rotate('+degree+'deg)',
					'-o-transform': 'rotate('+degree+'deg)',
					'-sand-transform': 'rotate('+degree+'deg)',
					'transform': 'rotate('+degree+'deg)'
				});

				if(step == (options.wiggleDegrees.length - 1)) {
					step = 0;
					if($(object).data('wiggles') === undefined) {
						$(object).data('wiggles', 1);
					} else {
						$(object).data('wiggles', $(object).data('wiggles') + 1);
					}
					options.onWiggle(object);
				}


				object.timeout = setTimeout(function(){
					methods.wiggle(object, step+1);
				}, options.delay);
			
			}
		};

		this.each(function() {
			if((method == 'start' || method === undefined) && !this.timeout) {
				methods.wiggle(this);
				options.onWiggleStart(this);
			} else if (method == 'stop') {
				methods.stop(this);
			}
		});

		return this;
	}
})(jQuery);
