jQuery.fn.vibrate = function( options ) {
	var settings = {
		times:      2,
		horizontal: 20,
		vertical:   0,
		speed:      50,
		easing:     "linear"
	};

	jQuery.extend(settings, options);

	this.each(function( intI ) {
		var e = $(this);

		var coord = e.offset();
		jQuery.extend(coord, {
			width: e.width(),
			height: e.height()
		});

		var o = {
			top:    coord.top,
			left:   coord.left,
			width:  coord.width,
			height: coord.height
		};
		var p = {
			left: parseInt(o.left) + settings.horizontal + "px",
			top:  parseInt(o.top) + settings.vertical + "px"
		};
		var n = {
			left: parseInt(o.left) - settings.horizontal + "px",
			top:  parseInt(o.top) - settings.vertical + "px"
		};

		var i = settings.times * 2;

		e.css(o);
		e.css({
			position: "absolute"
		});

		var f = function( times, cb ) {
			e.animate((times % 2) ? p : n, settings.speed, settings.easing, function() {
				if (--times) {
					f(times, cb);
					return;
				}

				cb();
			});
		};

		f(i, function() {
			e.animate(o, settings.speed, settings.easing);
		});
	});
};
$(document).ready(function() {
	$("form.ajax").each(function() {
		var f = $(this);

		// animate this box
		var d = f.parents("div.animate");

		// username field
		var u = $("input.username", f);

		// password field
		var p = $("input.password", f);

		// challenge field
		var c = $("input.challenge", f);

		// error field
		var ef = $("p.error", f);

		var submitForm = function( username, password ) {
			d.block();

			// hide previous error
			ef.css({
				display: "none"
			});

			$.ajax({
				type:     "POST",
				url:      "/ajax/login/",
				dataType: "json",
				data: {
					username: username,
					password: password
				},
				error: function( e, error ) {
					// unblock ui
					d.unblock()

					ef.html(_(error));
					ef.fadeIn("slow");

					d.vibrate();
					p.val("").focus();
				},
				success: function( data ) {
					if (data.successful) {
						window.location = data.destination;
						return;
					}

					// unblock ui
					d.unblock()

					ef.html(data.error);
					ef.fadeIn("slow");

					d.vibrate();
					p.val("").focus();

					if (data.challenge) c.val(data.challenge);
				}
			});

			return false;
		};

		if (f.is(".serverside")) {
			//
			// server side crypting means crypt() authentication,
			// so we have to send the username and password in
			// cleartext
			//
			f.bind("submit", function() {
				return submitForm(u.val(), p.val());
			});

			return;
		}

		//
		// challenge-response authentication
		//
		$.getScript("/files/js/md5.js", function() {
			//
			// set to challengeresponse 
			$("input.challengeresponse").val(1);

			f.bind("submit", function() {
				// calculate password hash
				var s = new String();
				var password = hex_md5(s.concat(p.val(), c.val()));

				// remove password
				p.val("");

				return submitForm(u.val(), password);
			});
		});
	});
});

