Beautifying York Lists with AJAX

How to use a little AJAX magic to hide the York lists service and give your site visitors a much slicker experience when they subscribe to your mailing list.

We’ve looked after our own mailing list for years. We had a nice database of users hosted on the website that was pretty flexible, easy for us to use and very easy to which to sign up.

But sending out mail is another matter entirely. We currently have around 700 addresses on our list, and it has become increasingly difficult to find a server that is prepared to send out that many messages. We had to resort to splitting mailouts, VPNing to York and dodging angry system administrators in order to get our mail out. And culling the dead emails from the list wasn’t much fun either.

So we’ve finally given up and got a York Lists account. In many ways it’s great: emailing the list is now as easy as, um, sending an email, and it deletes invalid addresses automatically.

A nice personality

But it’s a bit of an ugly thing. We used to have this signup form. The lists service gave us this one instead. It doesn’t match the rest of the site and provides far too much useless information on screen.

It would be nice to use the old signup form with our new lists account. And luckily we can.

Submitting to the lists service

First, create a form that submits to the lists service. I made this by copying the fields from the lists subscription form. Change the form action to point at your list. I’ve hidden a few of the fields as I don’t consider them important.

<form class="SubscribeForm" method="post" action="https://lists.york.ac.uk/mailman/subscribe/breakz-soc">
<h3>Sign me up!</h3>

<label for="name">Name</label>
<input class="SubscribeText" id="name" type="text" name="fullname" size="35" maxlength="255" />

<label for="email">Email</label>
<input class="SubscribeText" id="email" type="text" name="email" size="35" maxlength="255" />

<input type="hidden" name="pw" value="" />
<input type="hidden" name="pw-conf" value="" />
<input type="hidden" name="digest" value="0" />

<input class="SubscribeSubmit" type="submit" name="email-button" value="Subscribe" title="Click to submit details and join mailing list." />
</form>

The form should now work nicely, but unfortunately you’ll end up on the lists service site after submitting. It would look a lot more professional if we could stay on site throughout.

Keeping it on the site

And we can do this with a bit of AJAX. When someone submits the form, we send the data on to the lists service, get back its response and return a success (or failure) message. The AJAX itself is pretty simple, but unfortunately we’re not allowed to send data cross domain for security reasons.

Luckily we can get round this by using an AJAX proxy, which takes a local request and redirects it to an external domain. The one I used is the PHP AJAX proxy by Iacovos Constantinou.

We need to add a couple more elements to the form so we can give feedback to the user. I stuck these just after the submit button.

<img id="ajaxBusy" src="http://www.breakzdjs.com/images/progress.gif" alt="Busy..." />
<div id="ajaxResult"></div>

Apart from that, the form is identical. (So it still works for those without JavaScript.)

Driving the form with JavaScript

I used jQuery because I think it’s great. Along with other JavaScript libraries, it has a nice, high level interface to the AJAX functionality.

The code below intercepts the form submit function and posts the form data on to the AJAX proxy. Once we get a return value from the AJAX proxy (the ‘thanks for subscribing’ HTML page from the lists server), we process it to see what the list server said. The server success or error message is between the </h1> tag and the <hr> (sic.) tag, so we use a regexp to cull the rest.

The list server returns a verbose (and largely uninteresting) message if the subscription succeeds, starting with “Your subscription request has been received, and will soon be acted upon.” We search for that and, if it’s there, show a rather terser and to-the-point message for the user. If not, tell the user there’s a problem and print the server response. The code also throws up a link to the lists server subscribe page, just in case something funny is going on at this end.

jQuery(document).ready(function()
{
	var ajaxProxy = "http://www.breakzdjs.com/ajax-proxy.php";
	var listUrl = "https://lists.york.ac.uk/mailman/subscribe/breakz-soc";
	var signupUrl = "https://lists.york.ac.uk/mailman/listinfo/breakz-soc";

	jQuery("form.SubscribeForm").submit(function()
	{
		jQuery("#ajaxBusy").show();

		jQuery.post(ajaxProxy,
		{
			csurl: escape(listUrl),
			fullname: jQuery("#name").val(),
			email: jQuery("#email").val(),
			pw: "",
			digest: "0"
		},
		function(data)
		{
			jQuery("#ajaxBusy").hide();

			// Remove HTML guff.  Interesting bit is between </h1> and <hr>.
			data = data.replace(/(^(.|\n)*<\/h1>|<hr>(.|\n)*$)/gi, "");

			// Failed
			if (data.search("Your subscription request has been received, and will soon be acted upon.") == -1)
			{
				jQuery("#ajaxResult").html("<h3>Ooh dear.  Something went wrong.</h3><p>" + data + "</p><p>Keeps going wrong?  <a href=\"" + signupUrl + "\">Try signing up on the mailing list server&nbsp&raquo;</a></p>").fadeIn("fast");
			}
			else
			{
				jQuery("#ajaxResult").html("<h3>Thanks!</h3><p>You should get an email from the list service we use to confirm your subscription.  Just click the link in that and you&rsquo;re done.</p>").fadeIn("fast");
			}
		});

		return false;
	});
});

Ready to rumble

And that’s it. See it in action

Don’t forget to edit all of the files so they point to your lists URL.

Posted in Geek Stuff | 2 Comments

2 Responses

  1. Mike Houston says:

    Hey, thanks for that, that’s a pretty slick solution. I came to the same conclusion about the lists interface being ugly when I was webmaster for the G&S website a while back, but I did it server-side instead, generating a new email to the list server from the email address supplied by the user.

    It seems to have got lost in the transition to the new template for our site sadly, I’ve been meaning to ask the new webmaster where it’s gone… :)

  2. Andrew says:

    Thanks and I hope it’s useful. Having written the code, it seemed silly not to offer it to other lists users.

    Yes, it occurred to me after writing it that I could actually have done it all on the server instead of the AJAX proxy. (Don’t know why I didn’t think of that at the time actually.) Though the AJAX bit does of course make it twice as shiny… :)

    It would have been nice to intercept the confirmation screen as that’s a bit clunky too, but I couldn’t think of a way to do that.

    Hope you manage to get your code back on the G&S site.