jQuery Datepicker Ajax Request to Highlight Days from MySQL

datepicker available days

datepicker available days

With a bit of fiddling you can retrieve a bunch of dates in a given timespan from the database (or elsewhere) and make your jQuery UI Datepicker a bit more practical and informative.

A method within the Datepicker plugin called beforeShowDay can do the following magic:

  1. disable a given day from selection
  2. add a CSS class to a given day
  3. add a tooltip to a given day

Whilst it is probably a bit easier to make the ajax request itself using the beforeShowDay method, that puts us in the uncomfortable position of making 30+ ajax requests, one for every day displayed. If we are showing 2 months or the page has more than one datepicker, thats 60+ requests!

The better option is to make a single request onload, and an additional request whenever the month or year is changed.

The purpose of my implementation is to highlight days which have no due items in my Studiotime time management web software. This allows me to select a due date without worrying about whether I have other items already due on that day. You can just as easily check for other parameters relevant to your application – you need only adjust the sql query.

Lets start with the freeDays array and the onload javascript on the datepicker input.

// declare freeDays global
var freeDays = [];

// perform initial json request for free days
fetchFreeDays();

$(document).ready(function()
{

    // fairly standard configuration, importantly containing beforeShowDay and onChangeMonthYear custom methods
    $("#datepicker").datepicker({
        changeMonth: true,
        changeYear: true,
        showOtherMonths: true,
        selectOtherMonths: true,
        dateFormat: 'DD, d MM, yy',
        altField: '#date_due',
        altFormat: 'yy-mm-dd',
        beforeShowDay: highlightDays,
        onChangeMonthYear: fetchFreeDays,
        firstDay: 1 // rows starts on Monday
    });
});

// query for free days in datepicker
function fetchFreeDays(year, month)
{
    var start_date = '';

    // if a month and year were supplied, build a start_date in yyyy-mm-dd format
    if (year != undefined && month != undefined) {
      start_date = year +'-';
      start_date += month +'-';
      start_date += '01';
    }

    $.getJSON("ajax.todos.php?start_date="+ start_date, function(data){
         $.each(data, function(index, value) {
            freeDays.push(value.freeDate); // add this date to the freeDays array
        });
    });
}

// runs for every day displayed in datepicker, adds class and tooltip if matched to days in freeDays array
function highlightDays(date)
{
    for (var i = 0; i < freeDays.length; i++) {
      if (new Date(freeDays[i]).toString() == date.toString()) {
         return [true, 'free-day', 'no to-do items due']; // [0] = true | false if this day is selectable, [1] = class to add, [2] = tooltip to display
      }
    }

    return [true, ''];
}

So now we have a working method of requesting a php page on every page load and again every time the month or year selectors are changed. Lets have a look at how the PHP and MySQL script looks:

// ajax.todos.php
$i = 0; // counter prevents infinite loop
$cutoff = '61'; // limit on timespan (in days)
$result = array();

// if date is provided, use it, otherwise default to today
$start_date = (!empty($start_date)) ? mysql_real_escape_string($start_date) : date('Y-m-d');
$check_date = $start_date;
$end_date = date('Y-m-d', strtotime("$start_date +$cutoff days")); // never retrieve more than 2 months

while ($check_date != $end_date)
{
    // check if any incomplete todos exist on this date
    if (mysql_result(mysql_query("SELECT COUNT(id) FROM " . DB_TODOS . " WHERE date_due = '$check_date'"), 0) == 0)
    {
        $result[] = array('freeDate' => $check_date);
    }

    // +1 day to the check date
    $check_date = date('Y-m-d', strtotime("$check_date +1 day"));

    // break from loop if its looking like an infinite loop
    $i++;
    if ($i > $cutoff) break;
}

header('Content-type: application/json');
echo json_encode($result);

The CSS rule is as follows:

/* override free days background in jquery ui datepicker */
.free-day {
  background: #2e9500;
}

.free-day a {
  opacity: 0.7;
}

Disclaimer: I am no jQuery ninja and produced this tutorial by combining various other resources that I have linked to below. If you have any suggestions or improvements let everybody benefit by contributing to the comments below!

Notes:

  • I’m not entirely happy with the way this CSS rule looks
  • There is most likely an issue with the ajax result failing to be retrieved before the datepicker pops up, which could be worked around by embedding datepicker into the ajax call

Resources:

Posted in jQuery | 15 Comments

Notes for Installing Symphony CMS on Ubuntu

Symphony CMS is relatively easy to install on a Ubuntu server.

Here are a couple of commands I issued on a clean Ubuntu install to get everthing I needed for Symphony CMS, including cloning the git archive.

Important notes:

  • I chose to make a symbolic link from /var/www to my user directory, to skip writing a new apache site-available file, however for production purposes I would suggest to write a new proper apache2 site configuration file
  • The default apache2 site-enabled file has “AllowOverride None” – this needs to be changed to “AllowOverride All” for mod_rewrite to work
  • The php5-xsl package is vital for XSLT to work!


sudo apt-get install git-core apache2 php5 mysql-server php5-mysql php5-xsl
## now that mysql is installed, create a database and database user and GRANT PRIVILEGES ##
sudo a2enmod rewrite
sudo vi /etc/apache2/sites-enabled/000-default (change AllowOverride None to AllowOverride All)
sudo /etc/init.d/apache2 restart
cd /home/steve
mkdir symphony-cms
cd symphony-cms
git clone git://github.com/symphonycms/symphony-2.git
cd symphony-2
git submodule update --init
git clone git://github.com/symphonycms/workspace.git
ln -s /home/steve/symphony-cms/symphony-2 /var/www/symphony
chmod -R 777 /home/steve/symphony-cms/symphony-2/workspace
chmod 777 /home/steve/symphony-cms/symphony-2
## run web configuration now at yourwebsite.com/install.php ##
chmod -R 755 workspace
rm install.php install.sql workspace/install.sql update.php

See the git documentation for further reading.

If you need any clarifications, ask away in the comments section.

Posted in Notes | Leave a comment

Moving backups between servers using WHM and cPanel

It is surprisingly easy to move an account (website) from one cPanel based server to another.

  1. First, open cPanel on the old server, and go to the backups tab.
  2. Next, select Generate/Download a Full Backup
  3. Select Remote FTP server from the dropdown menu. At this point, enter the FTP details of any account on the new server. Any standard account will do, however do not create an account for the site that is to be moved on the new server beforehand, as you will only have to delete it again to restore the backup.
  4. For the port option, usually 21 is the correct value.
  5. Leave the Remote Dir value blank unless you have specifically created a folder for the backup (its easy to find anyway).
  6. Once you press the Generate Backup button, cPanel will begin to create an archive of the entire site contents, including mail, mysql, logs, web files. Depending on the size of the site this might take a few minutes. (But god damn servers can transfer between each other quickly!).
  7. Once the email notification arrives that the backup has been transferred, login to the new server as root. If you don’t have root privileges you might wish to contact your hosting company and hopefully they can take over from here.
  8. The backup file will usually be located in /home/username/backup-mm.dd.yyyy_xx-xx-xx_oldusername.tar.gz
  9. From the command line, navigate to the backup location, and enter something along the lines of
    mv backup-12.18.2008_11-08-09_oldusername.tar.gz /home
  10. In WHM on the new server, select Restore a Full Backup/cpmove file. At this point it should detect the archive located in /home/. If not you must have put the archive in the wrong place.  Enter the old username and press Restore – thats it!

How much better is that than moving an account database by database, db user by db user, mail account by mail account!

Posted in Web Hosting | 4 Comments