JQuery

Disabling certain days in jquery UI datepicker

I wrote a site for my local pub and it involved a restaurant booking section. The user could select a date and a time (plus name, phone number and number of people)

The kitchen was closed on Mondays, so I needed to stop any bookings for Mondays. I had two options I could see,

  1. Server side, using PHP to check the date and refuse the request
  2. Client side, using JavaScript to block the request

I decided client side was best for the end user, otherwise they have to go back and pick a new date, etc.

I was using jquery UI’s datepicker and its very simple to just block Mondays:

$('.datebox').datepicker({
    "dateFormat"    : "DD dd/MM/yy",
    "beforeShowDay" : function(date) {
        var day_of_week = date.getDay();
        return [(day_of_week != 1), ''];
        }
    });

The day_of_week numbers start at 0 for Sunday, to 6 for Saturday. SIMPLES

Passing variable as key in jQuery ajax

I wanted to pass a simple key/value string to an Ajax request, but you cannot simply use the variable as the key in the data:

var $fieldname  = 'company_name';
var $value      = 'Tate-Davies Inc.';
var $promise = $.ajax({
    'url'       : '/some/action',
    'dataType'  : 'json',
    'data'      : {
                  $fieldname : $value
                  }
    )};

The above just will not work, and the $_GET will contain:

'fieldname'    => 'Tate-Davies Inc.'

What I actually want is:

'company_name' => 'Tate-Davies Inc.'

So, in order to fix this:

var $data      = JSON.parse('{"' + $fieldname + '":"' + $value + '"}');

And pass that instead:

var $promise = $.ajax({
    'url'       : '/some/action',
    'dataType'  : 'json',
    'data'      : $data 
    )};

Change jQuery autosuggest to 2 column dropdown

I often have the problem that the autosuggest isn’t flexible enough, and I need to show contact name AND client name in the drop down

Here is a way you can ‘hack’ the default set up:

$.ui.autocomplete.prototype._renderItem = function(ul, item) {
    var new_string = "<div style='width:450px;'>
                      <div style='width:200px; float:left;'>" + 
                      item.contactname + 
                      "&nbsp;</div>
                      <div>" + item.companyname + "</div></div>";

        return $("<li></li>")
            .data("item.autocomplete", item )
            .append("<a>" + new_string + "</a>")
            .appendTo(ul);
 };

Now, obviously the function that returns the data for the autosuggest needs to have these new fields in it (companyname, etc), a bit like this:

foreach ($data as $row) {
    $array[] = array(
        "value"       => $row['contactname'],
        "companyname" => $row['companyname'],
        "contactname" => $row['contactname'],
        "contactID"   => $row['contactID']
        );
}
echo json_encode($array);

EASY

jQuery tablesorter custom date sort

I needed a custom sort column for jquery tablesorter (http://tablesorter.com/docs/) for dates in the format of 12-Aug-2013 as the default tried to sort it as a string

Was quite complicated to work out, but think its done:

$.tablesorter.addParser({
    'id' : 'customDates',
    'is' : function(string) {
         return false;
         },
    'format' : function(string) {
        if (string == "") {
            return '';
        }
        var thedate = string.split('-');
        var monthint = {};
        monthint['Jan'] = "01";
        monthint['Feb'] = "02";
        monthint['Mar'] = "03"; 
        monthint['Apr'] = "04";
        monthint['May'] = "05";
        monthint['Jun'] = "06";
        monthint['Jul'] = "07";
        monthint['Aug'] = "08";
        monthint['Sep'] = "09";
        monthint['Oct'] = "10";
        monthint['Nov'] = "11";
        monthint['Dec'] = "12";
        var date_day = parseInt(String(thedate[0]));
        if (date_day.length == 1) {
            date_day = '0' + date_day;
        }
        var date_month = monthint[thedate[1]];
        var date_year = thedate[2];
        return date_year + date_month + date_day;
    },
    'type' : 'numeric'
    });

And then apply it to the table

$('table').tablesorter({
    'debug' : 'true', 
    'headers' : {
        0 : {
            'sorter' : 'customDates'
            } 
        } 
    });

wkhtmltopdf repeat on subsequent pages

wkhtmltopdf has a bug as a result of a webkit bug. This means that the nice css styles for table printing don’t work in wkhtmltopdf.

Fortunately for us, wkhtmltopdf can handle JavaScript and that enables us to modify the DOM nicely prior to PDF creation.

Add the class ‘split_this_table’ to the table(s) you need to sort out over the page break, and then insert this code into the page in question:

$('.split_this_table').each(function(index, element) {

    //the height available is dependant on another item on the page
    var expanded_line = $('#another_element').size().height / 5;

    //manual calculation of the header size
    var per_page = 20 - expanded_line;

    //how many pages of rows have we got?
    var pages = Math.ceil($('tbody tr').length / per_page);

    //if we only have one page no more
    if (pages == 1) {
        return;
    }

    //get the table we're splutting
    var table_to_split = $(element);
    var current_page   = 1;

    //loop through each of our pages
    for (current_page = 1; current_page <= pages; current_page++) {

        //make a new copy of the table
        var cloned_table = table_to_split.clone();

        //remove rows on later pages
        $('tbody tr', table_to_split).each(function(loop, row_element) {

            //if we've reached our max
            if (loop >= per_page) {

                //get rid of the row
                $(row_element).remove();
            }
        });

        //loop through the other copy
        $('tbody tr', cloned_table).each(function(loop, row_element) {

            //if we are before our current page
            if (loop < per_page) {

                //remove that one
                $(row_element).remove();
            }
        });

        //insert the other table afdter the copy
        if (current_page < pages) {

            //insert the new table
            cloned_table.insertAfter(table_to_split);
        }

        //make a break
        cloned_table.css('page-break-before', 'always');

        //reset the table to the copy
        table_to_split = cloned_table;
    }
});

preventDefault not firing on onkeyup event

Simple one.

$(document).on('#element', 'keyup', function(event) {
    if (event.keyCode == 13) {
        event.preventDefault();
        //do some other stuff
    }
});

This doesn’t actually work as the Key Up event is too late down the event queue for preventDefault() to have any effect. Change your code to utilise the keydown or keypress event instead and you should be fine.

Ajax Loading GIF

So you want a little funky AJAX loader?

Add this to your JS main core file…:

$(document).ready(function() {
    //initiate an ajax start message
    $(document).ajaxStart(function() {
       //show the message
       $('#ajax_loading_indicator').show();
    });
    //when ajax is completed
    $(document).ajaxStop(function() {
       //hide the message
       $('#ajax_loading_indicator').hide();
    });
});

And create a nice little div somewhere:

<div id="ajax_loading_indicator">
    <img src="/public/images/ajax_loading.gif" alt="Loading" />
    PLEASE WAIT
</div>

I use the following CSS to style mine, so its unobtrusive but visible:

#ajax_loading_indicator {
    position: fixed;
    right: 2px;
    top: 2px;
    background-color: #efec9f;
    border: 1pt orange solid;
    padding: 5px 30px 5px 30px;
    display: none;
}

TIP: If you can’t be bothered to find an AJAX loading GIF, then there is a great little website that will create you one for free. Its, www.ajaxload.info

Easy!

You do need to have jQuery (version 1.0+) for this, in case you didn’t work that out… www.jquery.com

 

 

$.ajaxStart() not firing

If you use the above to show a nice loading message when an AJAX call is performed, you may have come across the problem that a JSONP request means the call is not called. This is due to the fact the ajaxStart() function is triggered by a internal XMLHttpRequest and the JSONP request uses a script tag instead (for XSS safety)

There is a way round this though. Use the $.ajaxSetup() function:

$(document).ready(function() {
    $.ajaxSetup({
        'beforeSend' : function() {
            $('pleasewaitelement').show();
        },
    'complete'   : function() {
            $('pleasewaitelement').hide();
        }
    });
});

This is a default for $.ajax() calls, and unless your AJAX call specifies a beforeSend or complete function, then the defaults above will show. If you did have to use a different beforeSend or complete callback, then just add in the relevant code for the hiding/showing.

Easy.

$.ajaxStart() not firing

If you use the above to show a nice loading message when an AJAX call is performed, you may have come across the problem that a JSONP request means the call is not called. This is due to the fact the ajaxStart() function is triggered by a internal XMLHttpRequest and the JSONP request uses a script tag instead (for XSS safety)

There is a way round this though. Use the $.ajaxSetup() function:

$(document).ready(function() {
    $.ajaxSetup({
        'beforeSend' : function() {
            $('pleasewaitelement').show();
        },
    'complete'   : function() {
            $('pleasewaitelement').hide();
        }
    });
});

This is a default for $.ajax() calls, and unless your AJAX call specifies a beforeSend or complete function, then the defaults above will show. If you did have to use a different beforeSend or complete callback, then just add in the relevant code for the hiding/showing.

Easy.