Mar '19

I spent some time messing about with Bootstrap popovers, and other similar tools but was finding that they tended to be overly complicated to use and skin, and also mostly wouldn’t allow form elements to be inside them. I found myself with a task where I was very tight on space and needed to add several textareas to my form. A popover was the obvious choice, but many relied on convoluted attributes on the trigger element or involved javascript handlers. Even more importantly most tend to destroy the popover when it is closed, which is clearly no use I want a form element in there.

After a bit of playing around I came up with this script myself:


.popover-container {
    position: relative;

.popover-content {
    z-index: 10000;
    border: 1px solid #555555;
    padding: 8px;
    margin-top: 10px;
    width: 300px;
    position: absolute;
    left: -1000000px;

.popover-content.open {
    left: -150px;

.popover-content.open:after {
    content: '';
    display: block;
    position: absolute;
    top: -6px;
    left: 150px;
    width: 10px;
    height: 10px;
    background: #FFFFFF;
    border-right:1px solid #555555;
    border-top:1px solid #555555;


$().ready(function() {

    $('.popover-container').on('click', 'button', function() {
        var parent = $(this).parents('.popover-container');
        var content = parent.find('.popover-content');

        if(content.hasClass('open')) {
        else {
            //Clear down any others first
            $('.popover-content.open').each(function() {


            var offset = 150 - (parent.width() / 2) - 2;

            content.css('left', '-' + offset + 'px');

    //Close on blur
    $('.popover-container').on('blur', '.popover-content', function() {

    //Close on escape key
    $(document).keyup(function(e) {
        if (e.keyCode === 27) {
            $('.popover-content.open').each(function() {

function closePopover(element) {
    element.css('left', '');

Example HTML:

<div class="popover-container">

    <button type="button" class="btn btn-xs btn-default">
        Show Popover

    <div class="popover-content">
        <div class="form-group">
            <p>This is my popover</p>
            <textarea name="my-textarea"></textarea>

Note that the CSS and JS above are based around the popover being 300px wide. You can change this to whatever you like, but bear in mind that the centering (the 150px offsets) needs to be adjusted in a corresponding way.

Nov '18

Ok many of you may already know this one, but it’s a relatively new one to me, and since non-HTML5 browsers are now mostly gone the way of the dinosaur, I’m much more comfortable relying on its elements for my core functionality. If you are still on IE9 or below then you deserve all you get!

This is as simple as I can make an AJAX form submission handler, that will also deal with files. It uses the HTML5 FormData object to serialise all the form data, including files, and allow us to pass it with the AJAX POST request.

$('.my-form').on('submit', function(e) {

    var form_data = new FormData($(this)[0]);

        type: 'POST',
        url: $(this).attr('action'),
        data: form_data,
        dataType: 'json',
        cache: false,
        contentType: false,
        processData: false,
        success: function(response) {
            // Wahey!
        error: function() {
            // Oh dear

    return false;

The ‘cache’, ‘contentType’ and ‘processData’ flags ARE necessary to make this work properly. The ‘dataType’ is optional, but if your server doesn’t send back JSON in response to an AJAX request as standard then you need to have a word with yourself!

Also notice that the FormData object needs the DOM version of the form, not the jQuery object, hence the need for “$(this)[0]” in the constructor.

Job. Done.

Mar '18

So this one had me puzzled for rather a while. We all know about the bootstrap event ‘shown.bs.modal’ that fires when a modal has been loaded. However, when the modal content is loaded via AJAX, I’ve found that can still be triggered a little bit in advance of contained elements loading in the DOM.

To give a concrete example, I encountered this when trying to activate datatables on a table that I was embedding in a modal. My script was set up as follows:

$('.modal').on('shown.bs.modal', function (e) {
        //Datatable options

This tended to work about 50% of the time, and after a lot of thought I realised that the times it didn’t run were due to the table element not being loaded into the DOM before the DataTable call is made. Even though the Bootstrap event had been fired, the DOM was yet to catch up.

Now there are various ways around this, most obviously by using ‘setTimeout’ to add a short delay before triggering subsequent logic, although this technique has always struck me as rather imprecise and risky. Fortunately, jQuery provides the ‘ready’ function which gives us all we need to make this logic work perfectly:

$('.modal').on('shown.bs.modal', function (e) {
    $('.table-class').ready(function() {
            //Datatable options

All we are doing here is adding a subsequent observer to the element so that we can be sure the DOM is aware of it before we try to run any further logic. Simple as that!

Oct '17

Cloning simple markup is usually a fairly trivial task in jQuery, using the .clone() function, however it becomes a major headache when there are form elements involved. jQuery’s clone function effectively works based on the raw HTML of the page and as such any changes that have since taken place within the DOM are ignored. This doesn’t sound like such a big deal until you realise that includes changes to all form input elements; the clone will have these all reset to their initial values.

I’ve written a little function to get round this issue, which simply ‘fixes’ the current values fo all input fields (except files) in the markup, allowing them to be cloned correctly:

function fixValues(element) {
    element.find('input[type=text]').each(function() {
        $(this).attr('value', $(this).val());

    element.find('input[type=checkbox], input[type=radio]').each(function() {
        $(this).attr('checked', $(this).is(':checked') ? 'checked' : '');

    element.find('select option:selected').each(function() {
        $(this).attr('selected', 'selected');

    element.find('textarea').each(function() {

Just trigger this function on the element you want to clone, immediately before calling the jQuery clone function (or, if you’re feeling really enthusiastic, you could even extend the clone function itself) and your values should all be copied over as expected.

May '17

Like me, you may find the jQuery $.getJSON function really useful for quick GET-based AJAX calls, and lament the lack of a corresponding POST function. Well here it is:

$.postJSON = function(url, data, func) { $.post(url, data, func, 'json'); }

You’re welcome!

Nov '16

Easy one this, just copy and paste code if you’re using Bootstrap.
Whenever a tab is changed, this code will take its ID from the trigger and put into the window location hash (AKA address anchor or, if you’re really posh, the fragment identifier).

//Remember tab state
$('ul.nav-tabs > li > a').on('shown.bs.tab', function(e) {
    if($(e.target).attr('href')) {
        var id = $(e.target).attr('href').substr(1);
        window.location.hash = id;

The second section of code ensures that whenever the page is reloaded, or the page is linked to using a valid tab ID, the identified tab will be selected automatically.

//Switch tab state
if (window.location.hash) {
    $("a[href='" + window.location.hash + "']").tab('show');


Aug '13

You won’t often find me posting an IE only chunk of code here but today I’m making an exception as I have found myself writing a site specifically for use in a call-centre where I know for a fact that everyone will be using IE so I can make a few custom nice-to-haves with that in mind.

IE, for all its faults, is the only browser that will let you implement a copy to clipboard function without the need for Flash plugins. There are lots of tutorials out there that show you ways to do this, but I ended up building a very quick jQuery function that I thought I’d share.

This assumes that you have a container with a class of ‘copy_text’ and a button, link or other clickable element with the class of ‘copy_to_clipboard’:

$('.copy_to_clipboard').click(function(e) {

    if (!document.all)
        return; // IE only

    var copy_text = $(this).siblings('.copy_text').html();
    var new_element = document.createElement('input');
    new_element.setAttribute('type', 'text');
    new_element.setAttribute('class', 'copy_text_dynamic');
    new_element.setAttribute('value', copy_text);

    r = new_element.createTextRange();

Now you’ll notice this has created an input element on the fly. This is because IE’s createTextRange call only works on input elements so we have to create one and fill it with the text that we want to copy to the clipboard.

The final part of this process is making sure that this newly created input element doesn’t show up on our page. You may have already noticed that you can’t hide an element (i.e. display: none) in IE if you want to do anything with it as it doesn’t bother putting hidden elements in the DOM. That being the case, as an alternative I prefer to fix the position of the element and send it way off the side of the screen like so:

.copy_text_dynamic {
    display: block;
    position: fixed;
    left: -10000px;
Jun '12

I have no problems using jQuery plugins that are rather old, if they are well written and efficient for my purpose. However jQuery hasn’t maintained complete backwards-compatibility throughout it’s life, notably when in version 1.5 the ‘handleError’ function was removed.
It is very simple to put in a patch for older plugins that still use this function – just extend jQuery and add the function back in yourself. If you don’t care about the error messages you can just add an empty function block but I prefer to use something like this to give me a better clue about the errors I might be dealing with:

	handleError: function( s, xhr, status, e ) {
		// If a local callback was specified, fire it
		if ( s.error )
			s.error( xhr, status, e );
		// If we have some XML response text (e.g. from an AJAX call) then log it in the console
		else if(xhr.responseText)
May '12

In my opinion one of the big glaring fails in CSS is the lack of ability to make an element expand to fill the remaining space within its parent container. So often, particularly in mobile design, in order to build as flexible a layout as possible I want to let one element be the size it needs to be and have another fill the remaining space. That’s what this jQuery plugin does.
This version works for filling the remaining height, but I’m sure you can see how easy it is to change it to work for widths.

(function($) {
	$.fn.dynamicElement = function() {
		options = jQuery.extend({
			spacing: 20
		}, options);

		this.each(function() {
			var sibling_height = 0;

			$(this).siblings().each(function() {
				sibling_height += $(this).outerHeight(true);

			var parent_height = $(this).parent().innerHeight();

			$(this).height(parent_height - sibling_height - options.spacing);

spacing – adds an extra gap. Do bear in mind though that the position of this gap will be dependent on how you have aligned your elements.

Calling the Function

$('.element').dynamicElement({ spacing: 50 });
Apr '12

In the process of learning mobile application design with jQuery Mobile I struggled greatly with making my layouts work with different screen sizes. There are a hundred and one articles online about screen sizes, resolutions etc but no clear consensus on an easy way to make your applications scale from phone to tablet. So I thought I’d build a plugin to do just that.
The idea behind this is simply that you design you application on a certain device with a certain screen width and make sure all your fonts are in the correct proportion. If you set a base font size and then use em sizes on all the rest then it’s simply a case of using a little logic on the current screen width to calculate what that base font size should be in order keep your scale correct.

(function($) {
	$.fn.dynamicText = function(options) {
		options = jQuery.extend({
			maxFontSize: 14,
			minFontSize: 6,
			baseFontSize: 10,
			baseScreenWidth: 800
		}, options);

		var element = $(this);


		$(window).resize(function() {

		function doTextResize() {
			var font_size = parseInt(options.baseFontSize * $(window).width() / options.baseScreenWidth);

			font_size = (font_size = options.minFontSize) ? font_size : options.minFontSize;
			element.css('font-size', font_size + 'pt');


  • maxfontSize – maximum size it will adjust your base font to
  • minFontSize – minimum size it will adjust your base font to
  • baseFontSize – the base font size you used for your development
  • baseScreenWidth – the screen width you used for your development

Calling the Function

$('body').dynamicText({ baseFontSize: 14 });
$('.container').dynamicText({ maxFontSize: 8, minFontSize: 16 });

You’ll notice that, although you will generally want to call this function on the entire body of your page, you by no means have to. It will set the base font of any specified element and as such scale all those below it.

The window resize listener is not strictly necessary for a static page but it will trigger when you change the orientation of your device which could be useful.