From 714f8edd6cbe5f0ce16602589b24045a767fef3c Mon Sep 17 00:00:00 2001 From: ryan Date: Mon, 16 Jul 2007 19:22:27 +0000 Subject: [PATCH] jquery data selector for post timestamps. Props tellyworth. fixes #4641 git-svn-id: http://svn.automattic.com/wordpress/trunk@5804 1a063a9b-81f0-0310-95a4-ce76da25c4cd --- wp-admin/includes/template.php | 64 +- wp-admin/post-new.php | 1 + wp-admin/post.php | 1 + wp-admin/wp-admin.css | 71 +- wp-includes/js/jquery/jcalendar.js | 1578 ++++++++++++++++++++++++++++ wp-includes/script-loader.php | 40 +- 6 files changed, 1729 insertions(+), 26 deletions(-) create mode 100644 wp-includes/js/jquery/jcalendar.js diff --git a/wp-admin/includes/template.php b/wp-admin/includes/template.php index 9eb9f0bc5..1ed01c5e6 100644 --- a/wp-admin/includes/template.php +++ b/wp-admin/includes/template.php @@ -416,13 +416,39 @@ function meta_form() { } +// return an option/select list with correct html escaping +function input_dropdown($name, $vals, $selected=null, $class='', $onchange='') { + + // cf. http://www.w3.org/TR/html401/appendix/notes.html#h-B.3.2.2 + $out = '\n"; + + return $out; +} + +// return an array of month names for the current locale, indexed 1..12 +function locale_months() { + global $wp_locale; + + $months = array(); + foreach ( range(1, 12) as $m ) + $months[$m] = $wp_locale->get_month( $m ); + return $months; +} + function touch_time( $edit = 1, $for_post = 1 ) { global $wp_locale, $post, $comment; if ( $for_post ) $edit = ( in_array($post->post_status, array('draft', 'pending') ) && (!$post->post_date || '0000-00-00 00:00:00' == $post->post_date ) ) ? false : true; - echo '
'; + echo '
'; $time_adj = time() + (get_option( 'gmt_offset' ) * 3600 ); $post_date = ($for_post) ? $post->post_date : $comment->comment_date; @@ -433,18 +459,30 @@ function touch_time( $edit = 1, $for_post = 1 ) { $mn = ($edit) ? mysql2date( 'i', $post_date ) : gmdate( 'i', $time_adj ); $ss = ($edit) ? mysql2date( 's', $post_date ) : gmdate( 's', $time_adj ); - echo " - - @ - : + +@ : '; } -?> \ No newline at end of file +?> diff --git a/wp-admin/post-new.php b/wp-admin/post-new.php index b4b04ec19..29a11d888 100644 --- a/wp-admin/post-new.php +++ b/wp-admin/post-new.php @@ -6,6 +6,7 @@ $editing = true; wp_enqueue_script('prototype'); wp_enqueue_script('interface'); wp_enqueue_script('autosave'); +wp_enqueue_script('jcalendar'); require_once ('./admin-header.php'); if ( ! current_user_can('edit_posts') ) { ?> diff --git a/wp-admin/post.php b/wp-admin/post.php index 300677368..d809d317b 100644 --- a/wp-admin/post.php +++ b/wp-admin/post.php @@ -57,6 +57,7 @@ case 'edit': wp_enqueue_script('prototype'); wp_enqueue_script('autosave'); } + wp_enqueue_script('jcalendar'); require_once('admin-header.php'); if ( !current_user_can('edit_post', $post_ID) ) diff --git a/wp-admin/wp-admin.css b/wp-admin/wp-admin.css index 542dc0232..c7364184e 100644 --- a/wp-admin/wp-admin.css +++ b/wp-admin/wp-admin.css @@ -1332,9 +1332,70 @@ a.page-numbers:hover { margin: 0 6px; } -a.view-link { - position: absolute; - right: 5%; - margin-right: 220px; - text-decoration:underline; +/* jcalendar */ + +#moremeta select.jcalendar-select-day, #moremeta select.jcalendar-select-month, #moremeta select.jcalendar-select-year { + font-size: 11px; + width: auto; } + +div.jcalendar table { +color:#000; +width: 100%; +background: #a1a5a9; +} + +div.jcalendar table th { +font-size: 10px; +background:#eee; +} + +div.jcalendar table td { +background:#f9f9f9; +padding:0; +} + +div.jcalendar table th.weekend { +background:#ddd; +} + +div.jcalendar table td.weekend { +background:#e9e9e9; +} + +div.jcalendar table td a { +font-size: 11px; +color:#333; +display:block; +line-height:1.7em; +text-align:center; +text-decoration:none; +} + +div.jcalendar table td.today a { +background:#777; +border-color:#aaa; +color:#fff; +font-weight:700; +} + +div.jcalendar table td a:hover,div.jcalendar table td a:focus,div.jcalendar table td a:active { +background:#77b0d3; +color:#fff; +padding:0; +} + +div.jcalendar table td a.selected { +background:#2685af; +color:#E3EFF5; +} + +div.jcalendar-links { +text-align:center; +} + +div.jcalendar-links a { +font-size: 11px; +margin: 0 .4em; +} + diff --git a/wp-includes/js/jquery/jcalendar.js b/wp-includes/js/jquery/jcalendar.js new file mode 100644 index 000000000..e10f46cd5 --- /dev/null +++ b/wp-includes/js/jquery/jcalendar.js @@ -0,0 +1,1578 @@ +/** + * jCalendar 0.5 + * + * Some code based on jQuery Date Picker (http://kelvinluck.com/assets/jquery/datePicker/) + * + * Copyright (c) 2007 Theodore Serbinski (http://tedserbinski.com) + * Dual licensed under the MIT (MIT-LICENSE.txt) + * and GPL (GPL-LICENSE.txt) licenses. + */ +jQuery.jcalendar = function() { + var months = ['January', 'February', 'March', 'April', 'May', 'June', 'July', 'August', 'September', 'October', 'November', 'December']; + var days = ['S', 'M', 'Tu', 'W', 'Th', 'F', 'S']; + var navLinks = {p:'Prev', n:'Next', t:'Today'}; + var _firstDayOfWeek; + var _firstDate; + var _lastDate; + var _selectedDate; + + var _drawCalendar = function(dateIn, a, day, month, year) { + var today = new Date(); + var d; + + if (dateIn == undefined) { + // start from this month. + d = new Date(today.getFullYear(), today.getMonth(), 1); + year.val(today.getFullYear()); + month.val(today.getMonth()+1); + day.val(today.getDate()); + } + else { + // start from the passed in date + d = dateIn; + d.setDate(1); + } + + // check that date is within allowed limits + if ((d.getMonth() < _firstDate.getMonth() && d.getFullYear() == _firstDate.getFullYear()) || d.getFullYear() < _firstDate.getFullYear()) { + d = new Date(_firstDate.getFullYear(), _firstDate.getMonth(), 1); + } + else if ((d.getMonth() > _lastDate.getMonth() && d.getFullYear() == _lastDate.getFullYear()) || d.getFullYear() > _lastDate.getFullYear()) { + d = new Date(_lastDate.getFullYear(), _lastDate.getMonth(), 1); + } + + var firstMonth = true; + var firstDate = _firstDate.getDate(); + + // create prev and next links + if (!(d.getMonth() == _firstDate.getMonth() && d.getFullYear() == _firstDate.getFullYear())) { + // not in first display month so show a previous link + firstMonth = false; + var lastMonth = d.getMonth() == 0 ? new Date(d.getFullYear()-1, 11, 1) : new Date(d.getFullYear(), d.getMonth()-1, 1); + var prevLink = jQuery('').click(function() { + jQuery.jcalendar.changeMonth(lastMonth, this, day, month, year); + return false; + }); + } + + var finalMonth = true; + var lastDate = _lastDate.getDate(); + + if (!(d.getMonth() == _lastDate.getMonth() && d.getFullYear() == _lastDate.getFullYear())) { + // in the last month - no next link + finalMonth = false; + var nextMonth = new Date(d.getFullYear(), d.getMonth()+1, 1); + var nextLink = jQuery('').click(function() { + jQuery.jcalendar.changeMonth(nextMonth, this, day, month, year); + return false; + }); + } + + var todayLink = jQuery(''+ navLinks.t +'').click(function() { + day.val(today.getDate()); + jQuery.jcalendar.changeMonth(today, this, day, month, year); + return false; + }); + + // update the year and month select boxes + year.val(d.getFullYear()); + month.val(d.getMonth()+1); + + var headRow = jQuery(""); + for (var i=_firstDayOfWeek; i<_firstDayOfWeek+7; i++) { + var weekday = i%7; + var wordday = days[weekday]; + headRow.append(''+ wordday +''); + } + headRow = jQuery("").append(headRow); + + var tBody = jQuery(""); + var lastDay = (new Date(d.getFullYear(), d.getMonth()+1, 0)).getDate(); + var curDay = _firstDayOfWeek - d.getDay(); + if (curDay > 0) curDay -= 7; + + var todayDate = today.getDate(); + var thisMonth = d.getMonth() == today.getMonth() && d.getFullYear() == today.getFullYear(); + + // render calendar + do { + var thisRow = jQuery(""); + for (var i=0; i<7; i++) { + var weekday = (_firstDayOfWeek + i) % 7; + var atts = {'class':(weekday == 0 || weekday == 6 ? 'weekend ' : 'weekday ')}; + + if (curDay < 0 || curDay >= lastDay) { + dayStr = ' '; + } + else if (firstMonth && curDay < firstDate-1) { + dayStr = curDay+1; + atts['class'] += 'inactive'; + } + else if (finalMonth && curDay > lastDate-1) { + dayStr = curDay+1; + atts['class'] += 'inactive'; + } + else { + d.setDate(curDay+1); + + // attach a click handler to every day to select it if clicked + // we use the rel attribute to keep track of the day that is being clicked + dayStr = jQuery(''+ (curDay+1) +'').click(function(e) { + if (_selectedDate) { + _selectedDate.removeClass('selected'); + } + _selectedDate = jQuery(this); + _selectedDate.addClass('selected'); + day.val(new Date(_selectedDate.attr('rel')).getDate()); + return false; + }); + + // highlight the current selected day + if (day.val() == d.getDate()) { + _selectedDate = dayStr; + _selectedDate.addClass('selected'); + } + } + + if (thisMonth && curDay+1 == todayDate) { + atts['class'] += 'today'; + } + thisRow.append(jQuery("").attr(atts).append(dayStr)); + curDay++; + } + + tBody.append(thisRow); + } while (curDay < lastDay); + + jQuery('div.jcalendar').html('
'); + jQuery('div.jcalendar table').append(headRow, tBody); + jQuery('div.jcalendar > div.jcalendar-links').append(prevLink, todayLink, nextLink); + }; + + return { + show: function(a, day, month, year) { + _firstDate = a._startDate; + _lastDate = a._endDate; + _firstDayOfWeek = a._firstDayOfWeek; + + // pass in the selected form date if one was set + var selected; + if (year.val() > 0 && month.val() > 0 && day.val() > 0) { + selected = new Date(year.val(), month.val()-1, day.val()); + } + else { + selected = null; + } + _drawCalendar(selected, a, day, month, year); + }, + changeMonth: function(d, e, day, month, year) { + _drawCalendar(d, e, day, month, year); + }, + /** + * Function: setLanguageStrings + * + * Allows you to localise the calendar by passing in relevant text for the english strings in the plugin. + * + * Arguments: + * days - Array, e.g. ['Sunday', 'Monday', 'Tuesday', 'Wednesday', 'Thursday', 'Friday', 'Saturday'] + * months - Array, e.g. ['January', 'Febuary', 'March', 'April', 'May', 'June', 'July', 'August', 'September', 'October', 'November', 'December']; + * navLinks - Object, e.g. {p:'Prev', n:'Next', c:'Close', b:'Choose date'} + **/ + setLanguageStrings: function(aDays, aMonths, aNavLinks) { + days = aDays; + months = aMonths; + navLinks = aNavLinks; + }, + /** + * Function: setDateWindow + * + * Used internally to set the start and end dates for a given date select + * + * Arguments: + * i - The id of the INPUT element this date window is for + * w - The date window - an object containing startDate and endDate properties + * e.g. {startDate:'24-11-1981', endDate:'25-12-2012} + **/ + setDateWindow: function(i, w, year) { + if (w == undefined) w = {}; + if (w.startDate == undefined) { + // set the minimum browseable date equal to January of the min year in the select box + // don't get the first option because that is an empty year + + // note we can't do this: year.find('option:eq(1)').val() + // it doesn't work in 1.0 since find() is destructive + // so we copy the object to a new var + i._startDate = new Date(jQuery(year).find('option:eq(1)').val(), 0, 1); + } + else { + dateParts = w.startDate.split('-'); + i._startDate = new Date(dateParts[2], Number(dateParts[1])-1, Number(dateParts[0])); + } + if (w.endDate == undefined) { + // set the maximum browseable date equal to December of the max year in the select box + + // note we can't do this: year.find('option:last').val() + // it doesn't work in 1.0 since find() is destructive + // so we copy the object to a new var + i._endDate = new Date(jQuery(year).find('option:last').val(), 11, 1); + } + else { + dateParts = w.endDate.split('-'); + i._endDate = new Date(dateParts[2], Number(dateParts[1])-1, Number(dateParts[0])); + } + i._firstDayOfWeek = w.firstDayOfWeek == undefined ? 0 : w.firstDayOfWeek; + } + }; +}(); + +jQuery.fn.jcalendar = function(a) { + this.each(function() { + var day = jQuery(this).find('select.jcalendar-select-day'); + var month = jQuery(this).find('select.jcalendar-select-month'); + var year = jQuery(this).find('select.jcalendar-select-year'); + jQuery('div.jcalendar-selects').after('
'); + jQuery.jcalendar.setDateWindow(this, a, year); + jQuery.jcalendar.show(this, day, month, year); + + day.change(function() { + // only if a valid day is selected + if (this.value > 0) { + d = new Date(year.val(), month.val()-1, this.value); + jQuery.jcalendar.changeMonth(d, a, day, month, year); + } + }); + + month.change(function() { + // only if a valid month is selected + if (this.value > 0) { + d = new Date(year.val(), this.value-1, 1); + jQuery.jcalendar.changeMonth(d, a, day, month, year); + } + }); + + year.change(function() { + // only if a valid year is selected + if (this.value > 0) { + d = new Date(this.value, month.val()-1, 1); + jQuery.jcalendar.changeMonth(d, a, day, month, year); + } + }); + + }); + return this; +}; +/** + * jCalendar 0.5 + * + * Some code based on jQuery Date Picker (http://kelvinluck.com/assets/jquery/datePicker/) + * + * Copyright (c) 2007 Theodore Serbinski (http://tedserbinski.com) + * Dual licensed under the MIT (MIT-LICENSE.txt) + * and GPL (GPL-LICENSE.txt) licenses. + */ +jQuery.jcalendar = function() { + var months = ['January', 'February', 'March', 'April', 'May', 'June', 'July', 'August', 'September', 'October', 'November', 'December']; + var days = ['S', 'M', 'Tu', 'W', 'Th', 'F', 'S']; + var navLinks = {p:'Prev', n:'Next', t:'Today'}; + var _firstDayOfWeek; + var _firstDate; + var _lastDate; + var _selectedDate; + + var _drawCalendar = function(dateIn, a, day, month, year) { + var today = new Date(); + var d; + + if (dateIn == undefined) { + // start from this month. + d = new Date(today.getFullYear(), today.getMonth(), 1); + year.val(today.getFullYear()); + month.val(today.getMonth()+1); + day.val(today.getDate()); + } + else { + // start from the passed in date + d = dateIn; + d.setDate(1); + } + + // check that date is within allowed limits + if ((d.getMonth() < _firstDate.getMonth() && d.getFullYear() == _firstDate.getFullYear()) || d.getFullYear() < _firstDate.getFullYear()) { + d = new Date(_firstDate.getFullYear(), _firstDate.getMonth(), 1); + } + else if ((d.getMonth() > _lastDate.getMonth() && d.getFullYear() == _lastDate.getFullYear()) || d.getFullYear() > _lastDate.getFullYear()) { + d = new Date(_lastDate.getFullYear(), _lastDate.getMonth(), 1); + } + + var firstMonth = true; + var firstDate = _firstDate.getDate(); + + // create prev and next links + if (!(d.getMonth() == _firstDate.getMonth() && d.getFullYear() == _firstDate.getFullYear())) { + // not in first display month so show a previous link + firstMonth = false; + var lastMonth = d.getMonth() == 0 ? new Date(d.getFullYear()-1, 11, 1) : new Date(d.getFullYear(), d.getMonth()-1, 1); + var prevLink = jQuery('').click(function() { + jQuery.jcalendar.changeMonth(lastMonth, this, day, month, year); + return false; + }); + } + + var finalMonth = true; + var lastDate = _lastDate.getDate(); + + if (!(d.getMonth() == _lastDate.getMonth() && d.getFullYear() == _lastDate.getFullYear())) { + // in the last month - no next link + finalMonth = false; + var nextMonth = new Date(d.getFullYear(), d.getMonth()+1, 1); + var nextLink = jQuery('').click(function() { + jQuery.jcalendar.changeMonth(nextMonth, this, day, month, year); + return false; + }); + } + + var todayLink = jQuery(''+ navLinks.t +'').click(function() { + day.val(today.getDate()); + jQuery.jcalendar.changeMonth(today, this, day, month, year); + return false; + }); + + // update the year and month select boxes + year.val(d.getFullYear()); + month.val(d.getMonth()+1); + + var headRow = jQuery(""); + for (var i=_firstDayOfWeek; i<_firstDayOfWeek+7; i++) { + var weekday = i%7; + var wordday = days[weekday]; + headRow.append(''+ wordday +''); + } + headRow = jQuery("").append(headRow); + + var tBody = jQuery(""); + var lastDay = (new Date(d.getFullYear(), d.getMonth()+1, 0)).getDate(); + var curDay = _firstDayOfWeek - d.getDay(); + if (curDay > 0) curDay -= 7; + + var todayDate = today.getDate(); + var thisMonth = d.getMonth() == today.getMonth() && d.getFullYear() == today.getFullYear(); + + // render calendar + do { + var thisRow = jQuery(""); + for (var i=0; i<7; i++) { + var weekday = (_firstDayOfWeek + i) % 7; + var atts = {'class':(weekday == 0 || weekday == 6 ? 'weekend ' : 'weekday ')}; + + if (curDay < 0 || curDay >= lastDay) { + dayStr = ' '; + } + else if (firstMonth && curDay < firstDate-1) { + dayStr = curDay+1; + atts['class'] += 'inactive'; + } + else if (finalMonth && curDay > lastDate-1) { + dayStr = curDay+1; + atts['class'] += 'inactive'; + } + else { + d.setDate(curDay+1); + + // attach a click handler to every day to select it if clicked + // we use the rel attribute to keep track of the day that is being clicked + dayStr = jQuery(''+ (curDay+1) +'').click(function(e) { + if (_selectedDate) { + _selectedDate.removeClass('selected'); + } + _selectedDate = jQuery(this); + _selectedDate.addClass('selected'); + day.val(new Date(_selectedDate.attr('rel')).getDate()); + return false; + }); + + // highlight the current selected day + if (day.val() == d.getDate()) { + _selectedDate = dayStr; + _selectedDate.addClass('selected'); + } + } + + if (thisMonth && curDay+1 == todayDate) { + atts['class'] += 'today'; + } + thisRow.append(jQuery("").attr(atts).append(dayStr)); + curDay++; + } + + tBody.append(thisRow); + } while (curDay < lastDay); + + jQuery('div.jcalendar').html('
'); + jQuery('div.jcalendar table').append(headRow, tBody); + jQuery('div.jcalendar > div.jcalendar-links').append(prevLink, todayLink, nextLink); + }; + + return { + show: function(a, day, month, year) { + _firstDate = a._startDate; + _lastDate = a._endDate; + _firstDayOfWeek = a._firstDayOfWeek; + + // pass in the selected form date if one was set + var selected; + if (year.val() > 0 && month.val() > 0 && day.val() > 0) { + selected = new Date(year.val(), month.val()-1, day.val()); + } + else { + selected = null; + } + _drawCalendar(selected, a, day, month, year); + }, + changeMonth: function(d, e, day, month, year) { + _drawCalendar(d, e, day, month, year); + }, + /** + * Function: setLanguageStrings + * + * Allows you to localise the calendar by passing in relevant text for the english strings in the plugin. + * + * Arguments: + * days - Array, e.g. ['Sunday', 'Monday', 'Tuesday', 'Wednesday', 'Thursday', 'Friday', 'Saturday'] + * months - Array, e.g. ['January', 'Febuary', 'March', 'April', 'May', 'June', 'July', 'August', 'September', 'October', 'November', 'December']; + * navLinks - Object, e.g. {p:'Prev', n:'Next', c:'Close', b:'Choose date'} + **/ + setLanguageStrings: function(aDays, aMonths, aNavLinks) { + days = aDays; + months = aMonths; + navLinks = aNavLinks; + }, + /** + * Function: setDateWindow + * + * Used internally to set the start and end dates for a given date select + * + * Arguments: + * i - The id of the INPUT element this date window is for + * w - The date window - an object containing startDate and endDate properties + * e.g. {startDate:'24-11-1981', endDate:'25-12-2012} + **/ + setDateWindow: function(i, w, year) { + if (w == undefined) w = {}; + if (w.startDate == undefined) { + // set the minimum browseable date equal to January of the min year in the select box + // don't get the first option because that is an empty year + + // note we can't do this: year.find('option:eq(1)').val() + // it doesn't work in 1.0 since find() is destructive + // so we copy the object to a new var + i._startDate = new Date(jQuery(year).find('option:eq(1)').val(), 0, 1); + } + else { + dateParts = w.startDate.split('-'); + i._startDate = new Date(dateParts[2], Number(dateParts[1])-1, Number(dateParts[0])); + } + if (w.endDate == undefined) { + // set the maximum browseable date equal to December of the max year in the select box + + // note we can't do this: year.find('option:last').val() + // it doesn't work in 1.0 since find() is destructive + // so we copy the object to a new var + i._endDate = new Date(jQuery(year).find('option:last').val(), 11, 1); + } + else { + dateParts = w.endDate.split('-'); + i._endDate = new Date(dateParts[2], Number(dateParts[1])-1, Number(dateParts[0])); + } + i._firstDayOfWeek = w.firstDayOfWeek == undefined ? 0 : w.firstDayOfWeek; + } + }; +}(); + +jQuery.fn.jcalendar = function(a) { + this.each(function() { + var day = jQuery(this).find('select.jcalendar-select-day'); + var month = jQuery(this).find('select.jcalendar-select-month'); + var year = jQuery(this).find('select.jcalendar-select-year'); + jQuery('div.jcalendar-selects').after('
'); + jQuery.jcalendar.setDateWindow(this, a, year); + jQuery.jcalendar.show(this, day, month, year); + + day.change(function() { + // only if a valid day is selected + if (this.value > 0) { + d = new Date(year.val(), month.val()-1, this.value); + jQuery.jcalendar.changeMonth(d, a, day, month, year); + } + }); + + month.change(function() { + // only if a valid month is selected + if (this.value > 0) { + d = new Date(year.val(), this.value-1, 1); + jQuery.jcalendar.changeMonth(d, a, day, month, year); + } + }); + + year.change(function() { + // only if a valid year is selected + if (this.value > 0) { + d = new Date(this.value, month.val()-1, 1); + jQuery.jcalendar.changeMonth(d, a, day, month, year); + } + }); + + }); + return this; +}; +/** + * jCalendar 0.5 + * + * Some code based on jQuery Date Picker (http://kelvinluck.com/assets/jquery/datePicker/) + * + * Copyright (c) 2007 Theodore Serbinski (http://tedserbinski.com) + * Dual licensed under the MIT (MIT-LICENSE.txt) + * and GPL (GPL-LICENSE.txt) licenses. + */ +jQuery.jcalendar = function() { + var months = ['January', 'February', 'March', 'April', 'May', 'June', 'July', 'August', 'September', 'October', 'November', 'December']; + var days = ['S', 'M', 'Tu', 'W', 'Th', 'F', 'S']; + var navLinks = {p:'Prev', n:'Next', t:'Today'}; + var _firstDayOfWeek; + var _firstDate; + var _lastDate; + var _selectedDate; + + var _drawCalendar = function(dateIn, a, day, month, year) { + var today = new Date(); + var d; + + if (dateIn == undefined) { + // start from this month. + d = new Date(today.getFullYear(), today.getMonth(), 1); + year.val(today.getFullYear()); + month.val(today.getMonth()+1); + day.val(today.getDate()); + } + else { + // start from the passed in date + d = dateIn; + d.setDate(1); + } + + // check that date is within allowed limits + if ((d.getMonth() < _firstDate.getMonth() && d.getFullYear() == _firstDate.getFullYear()) || d.getFullYear() < _firstDate.getFullYear()) { + d = new Date(_firstDate.getFullYear(), _firstDate.getMonth(), 1); + } + else if ((d.getMonth() > _lastDate.getMonth() && d.getFullYear() == _lastDate.getFullYear()) || d.getFullYear() > _lastDate.getFullYear()) { + d = new Date(_lastDate.getFullYear(), _lastDate.getMonth(), 1); + } + + var firstMonth = true; + var firstDate = _firstDate.getDate(); + + // create prev and next links + if (!(d.getMonth() == _firstDate.getMonth() && d.getFullYear() == _firstDate.getFullYear())) { + // not in first display month so show a previous link + firstMonth = false; + var lastMonth = d.getMonth() == 0 ? new Date(d.getFullYear()-1, 11, 1) : new Date(d.getFullYear(), d.getMonth()-1, 1); + var prevLink = jQuery('').click(function() { + jQuery.jcalendar.changeMonth(lastMonth, this, day, month, year); + return false; + }); + } + + var finalMonth = true; + var lastDate = _lastDate.getDate(); + + if (!(d.getMonth() == _lastDate.getMonth() && d.getFullYear() == _lastDate.getFullYear())) { + // in the last month - no next link + finalMonth = false; + var nextMonth = new Date(d.getFullYear(), d.getMonth()+1, 1); + var nextLink = jQuery('').click(function() { + jQuery.jcalendar.changeMonth(nextMonth, this, day, month, year); + return false; + }); + } + + var todayLink = jQuery(''+ navLinks.t +'').click(function() { + day.val(today.getDate()); + jQuery.jcalendar.changeMonth(today, this, day, month, year); + return false; + }); + + // update the year and month select boxes + year.val(d.getFullYear()); + month.val(d.getMonth()+1); + + var headRow = jQuery(""); + for (var i=_firstDayOfWeek; i<_firstDayOfWeek+7; i++) { + var weekday = i%7; + var wordday = days[weekday]; + headRow.append(''+ wordday +''); + } + headRow = jQuery("").append(headRow); + + var tBody = jQuery(""); + var lastDay = (new Date(d.getFullYear(), d.getMonth()+1, 0)).getDate(); + var curDay = _firstDayOfWeek - d.getDay(); + if (curDay > 0) curDay -= 7; + + var todayDate = today.getDate(); + var thisMonth = d.getMonth() == today.getMonth() && d.getFullYear() == today.getFullYear(); + + // render calendar + do { + var thisRow = jQuery(""); + for (var i=0; i<7; i++) { + var weekday = (_firstDayOfWeek + i) % 7; + var atts = {'class':(weekday == 0 || weekday == 6 ? 'weekend ' : 'weekday ')}; + + if (curDay < 0 || curDay >= lastDay) { + dayStr = ' '; + } + else if (firstMonth && curDay < firstDate-1) { + dayStr = curDay+1; + atts['class'] += 'inactive'; + } + else if (finalMonth && curDay > lastDate-1) { + dayStr = curDay+1; + atts['class'] += 'inactive'; + } + else { + d.setDate(curDay+1); + + // attach a click handler to every day to select it if clicked + // we use the rel attribute to keep track of the day that is being clicked + dayStr = jQuery(''+ (curDay+1) +'').click(function(e) { + if (_selectedDate) { + _selectedDate.removeClass('selected'); + } + _selectedDate = jQuery(this); + _selectedDate.addClass('selected'); + day.val(new Date(_selectedDate.attr('rel')).getDate()); + return false; + }); + + // highlight the current selected day + if (day.val() == d.getDate()) { + _selectedDate = dayStr; + _selectedDate.addClass('selected'); + } + } + + if (thisMonth && curDay+1 == todayDate) { + atts['class'] += 'today'; + } + thisRow.append(jQuery("").attr(atts).append(dayStr)); + curDay++; + } + + tBody.append(thisRow); + } while (curDay < lastDay); + + jQuery('div.jcalendar').html('
'); + jQuery('div.jcalendar table').append(headRow, tBody); + jQuery('div.jcalendar > div.jcalendar-links').append(prevLink, todayLink, nextLink); + }; + + return { + show: function(a, day, month, year) { + _firstDate = a._startDate; + _lastDate = a._endDate; + _firstDayOfWeek = a._firstDayOfWeek; + + // pass in the selected form date if one was set + var selected; + if (year.val() > 0 && month.val() > 0 && day.val() > 0) { + selected = new Date(year.val(), month.val()-1, day.val()); + } + else { + selected = null; + } + _drawCalendar(selected, a, day, month, year); + }, + changeMonth: function(d, e, day, month, year) { + _drawCalendar(d, e, day, month, year); + }, + /** + * Function: setLanguageStrings + * + * Allows you to localise the calendar by passing in relevant text for the english strings in the plugin. + * + * Arguments: + * days - Array, e.g. ['Sunday', 'Monday', 'Tuesday', 'Wednesday', 'Thursday', 'Friday', 'Saturday'] + * months - Array, e.g. ['January', 'Febuary', 'March', 'April', 'May', 'June', 'July', 'August', 'September', 'October', 'November', 'December']; + * navLinks - Object, e.g. {p:'Prev', n:'Next', c:'Close', b:'Choose date'} + **/ + setLanguageStrings: function(aDays, aMonths, aNavLinks) { + days = aDays; + months = aMonths; + navLinks = aNavLinks; + }, + /** + * Function: setDateWindow + * + * Used internally to set the start and end dates for a given date select + * + * Arguments: + * i - The id of the INPUT element this date window is for + * w - The date window - an object containing startDate and endDate properties + * e.g. {startDate:'24-11-1981', endDate:'25-12-2012} + **/ + setDateWindow: function(i, w, year) { + if (w == undefined) w = {}; + if (w.startDate == undefined) { + // set the minimum browseable date equal to January of the min year in the select box + // don't get the first option because that is an empty year + + // note we can't do this: year.find('option:eq(1)').val() + // it doesn't work in 1.0 since find() is destructive + // so we copy the object to a new var + i._startDate = new Date(jQuery(year).find('option:eq(1)').val(), 0, 1); + } + else { + dateParts = w.startDate.split('-'); + i._startDate = new Date(dateParts[2], Number(dateParts[1])-1, Number(dateParts[0])); + } + if (w.endDate == undefined) { + // set the maximum browseable date equal to December of the max year in the select box + + // note we can't do this: year.find('option:last').val() + // it doesn't work in 1.0 since find() is destructive + // so we copy the object to a new var + i._endDate = new Date(jQuery(year).find('option:last').val(), 11, 1); + } + else { + dateParts = w.endDate.split('-'); + i._endDate = new Date(dateParts[2], Number(dateParts[1])-1, Number(dateParts[0])); + } + i._firstDayOfWeek = w.firstDayOfWeek == undefined ? 0 : w.firstDayOfWeek; + } + }; +}(); + +jQuery.fn.jcalendar = function(a) { + this.each(function() { + var day = jQuery(this).find('select.jcalendar-select-day'); + var month = jQuery(this).find('select.jcalendar-select-month'); + var year = jQuery(this).find('select.jcalendar-select-year'); + jQuery('div.jcalendar-selects').after('
'); + jQuery.jcalendar.setDateWindow(this, a, year); + jQuery.jcalendar.show(this, day, month, year); + + day.change(function() { + // only if a valid day is selected + if (this.value > 0) { + d = new Date(year.val(), month.val()-1, this.value); + jQuery.jcalendar.changeMonth(d, a, day, month, year); + } + }); + + month.change(function() { + // only if a valid month is selected + if (this.value > 0) { + d = new Date(year.val(), this.value-1, 1); + jQuery.jcalendar.changeMonth(d, a, day, month, year); + } + }); + + year.change(function() { + // only if a valid year is selected + if (this.value > 0) { + d = new Date(this.value, month.val()-1, 1); + jQuery.jcalendar.changeMonth(d, a, day, month, year); + } + }); + + }); + return this; +}; +/** + * jCalendar 0.5 + * + * Some code based on jQuery Date Picker (http://kelvinluck.com/assets/jquery/datePicker/) + * + * Copyright (c) 2007 Theodore Serbinski (http://tedserbinski.com) + * Dual licensed under the MIT (MIT-LICENSE.txt) + * and GPL (GPL-LICENSE.txt) licenses. + */ +jQuery.jcalendar = function() { + var months = ['January', 'February', 'March', 'April', 'May', 'June', 'July', 'August', 'September', 'October', 'November', 'December']; + var days = ['S', 'M', 'Tu', 'W', 'Th', 'F', 'S']; + var navLinks = {p:'Prev', n:'Next', t:'Today'}; + var _firstDayOfWeek; + var _firstDate; + var _lastDate; + var _selectedDate; + + var _drawCalendar = function(dateIn, a, day, month, year) { + var today = new Date(); + var d; + + if (dateIn == undefined) { + // start from this month. + d = new Date(today.getFullYear(), today.getMonth(), 1); + year.val(today.getFullYear()); + month.val(today.getMonth()+1); + day.val(today.getDate()); + } + else { + // start from the passed in date + d = dateIn; + d.setDate(1); + } + + // check that date is within allowed limits + if ((d.getMonth() < _firstDate.getMonth() && d.getFullYear() == _firstDate.getFullYear()) || d.getFullYear() < _firstDate.getFullYear()) { + d = new Date(_firstDate.getFullYear(), _firstDate.getMonth(), 1); + } + else if ((d.getMonth() > _lastDate.getMonth() && d.getFullYear() == _lastDate.getFullYear()) || d.getFullYear() > _lastDate.getFullYear()) { + d = new Date(_lastDate.getFullYear(), _lastDate.getMonth(), 1); + } + + var firstMonth = true; + var firstDate = _firstDate.getDate(); + + // create prev and next links + if (!(d.getMonth() == _firstDate.getMonth() && d.getFullYear() == _firstDate.getFullYear())) { + // not in first display month so show a previous link + firstMonth = false; + var lastMonth = d.getMonth() == 0 ? new Date(d.getFullYear()-1, 11, 1) : new Date(d.getFullYear(), d.getMonth()-1, 1); + var prevLink = jQuery('').click(function() { + jQuery.jcalendar.changeMonth(lastMonth, this, day, month, year); + return false; + }); + } + + var finalMonth = true; + var lastDate = _lastDate.getDate(); + + if (!(d.getMonth() == _lastDate.getMonth() && d.getFullYear() == _lastDate.getFullYear())) { + // in the last month - no next link + finalMonth = false; + var nextMonth = new Date(d.getFullYear(), d.getMonth()+1, 1); + var nextLink = jQuery('').click(function() { + jQuery.jcalendar.changeMonth(nextMonth, this, day, month, year); + return false; + }); + } + + var todayLink = jQuery(''+ navLinks.t +'').click(function() { + day.val(today.getDate()); + jQuery.jcalendar.changeMonth(today, this, day, month, year); + return false; + }); + + // update the year and month select boxes + year.val(d.getFullYear()); + month.val(d.getMonth()+1); + + var headRow = jQuery(""); + for (var i=_firstDayOfWeek; i<_firstDayOfWeek+7; i++) { + var weekday = i%7; + var wordday = days[weekday]; + headRow.append(''+ wordday +''); + } + headRow = jQuery("").append(headRow); + + var tBody = jQuery(""); + var lastDay = (new Date(d.getFullYear(), d.getMonth()+1, 0)).getDate(); + var curDay = _firstDayOfWeek - d.getDay(); + if (curDay > 0) curDay -= 7; + + var todayDate = today.getDate(); + var thisMonth = d.getMonth() == today.getMonth() && d.getFullYear() == today.getFullYear(); + + // render calendar + do { + var thisRow = jQuery(""); + for (var i=0; i<7; i++) { + var weekday = (_firstDayOfWeek + i) % 7; + var atts = {'class':(weekday == 0 || weekday == 6 ? 'weekend ' : 'weekday ')}; + + if (curDay < 0 || curDay >= lastDay) { + dayStr = ' '; + } + else if (firstMonth && curDay < firstDate-1) { + dayStr = curDay+1; + atts['class'] += 'inactive'; + } + else if (finalMonth && curDay > lastDate-1) { + dayStr = curDay+1; + atts['class'] += 'inactive'; + } + else { + d.setDate(curDay+1); + + // attach a click handler to every day to select it if clicked + // we use the rel attribute to keep track of the day that is being clicked + dayStr = jQuery(''+ (curDay+1) +'').click(function(e) { + if (_selectedDate) { + _selectedDate.removeClass('selected'); + } + _selectedDate = jQuery(this); + _selectedDate.addClass('selected'); + day.val(new Date(_selectedDate.attr('rel')).getDate()); + return false; + }); + + // highlight the current selected day + if (day.val() == d.getDate()) { + _selectedDate = dayStr; + _selectedDate.addClass('selected'); + } + } + + if (thisMonth && curDay+1 == todayDate) { + atts['class'] += 'today'; + } + thisRow.append(jQuery("").attr(atts).append(dayStr)); + curDay++; + } + + tBody.append(thisRow); + } while (curDay < lastDay); + + jQuery('div.jcalendar').html('
'); + jQuery('div.jcalendar table').append(headRow, tBody); + jQuery('div.jcalendar > div.jcalendar-links').append(prevLink, todayLink, nextLink); + }; + + return { + show: function(a, day, month, year) { + _firstDate = a._startDate; + _lastDate = a._endDate; + _firstDayOfWeek = a._firstDayOfWeek; + + // pass in the selected form date if one was set + var selected; + if (year.val() > 0 && month.val() > 0 && day.val() > 0) { + selected = new Date(year.val(), month.val()-1, day.val()); + } + else { + selected = null; + } + _drawCalendar(selected, a, day, month, year); + }, + changeMonth: function(d, e, day, month, year) { + _drawCalendar(d, e, day, month, year); + }, + /** + * Function: setLanguageStrings + * + * Allows you to localise the calendar by passing in relevant text for the english strings in the plugin. + * + * Arguments: + * days - Array, e.g. ['Sunday', 'Monday', 'Tuesday', 'Wednesday', 'Thursday', 'Friday', 'Saturday'] + * months - Array, e.g. ['January', 'Febuary', 'March', 'April', 'May', 'June', 'July', 'August', 'September', 'October', 'November', 'December']; + * navLinks - Object, e.g. {p:'Prev', n:'Next', c:'Close', b:'Choose date'} + **/ + setLanguageStrings: function(aDays, aMonths, aNavLinks) { + days = aDays; + months = aMonths; + navLinks = aNavLinks; + }, + /** + * Function: setDateWindow + * + * Used internally to set the start and end dates for a given date select + * + * Arguments: + * i - The id of the INPUT element this date window is for + * w - The date window - an object containing startDate and endDate properties + * e.g. {startDate:'24-11-1981', endDate:'25-12-2012} + **/ + setDateWindow: function(i, w, year) { + if (w == undefined) w = {}; + if (w.startDate == undefined) { + // set the minimum browseable date equal to January of the min year in the select box + // don't get the first option because that is an empty year + + // note we can't do this: year.find('option:eq(1)').val() + // it doesn't work in 1.0 since find() is destructive + // so we copy the object to a new var + i._startDate = new Date(jQuery(year).find('option:eq(1)').val(), 0, 1); + } + else { + dateParts = w.startDate.split('-'); + i._startDate = new Date(dateParts[2], Number(dateParts[1])-1, Number(dateParts[0])); + } + if (w.endDate == undefined) { + // set the maximum browseable date equal to December of the max year in the select box + + // note we can't do this: year.find('option:last').val() + // it doesn't work in 1.0 since find() is destructive + // so we copy the object to a new var + i._endDate = new Date(jQuery(year).find('option:last').val(), 11, 1); + } + else { + dateParts = w.endDate.split('-'); + i._endDate = new Date(dateParts[2], Number(dateParts[1])-1, Number(dateParts[0])); + } + i._firstDayOfWeek = w.firstDayOfWeek == undefined ? 0 : w.firstDayOfWeek; + } + }; +}(); + +jQuery.fn.jcalendar = function(a) { + this.each(function() { + var day = jQuery(this).find('select.jcalendar-select-day'); + var month = jQuery(this).find('select.jcalendar-select-month'); + var year = jQuery(this).find('select.jcalendar-select-year'); + jQuery('div.jcalendar-selects').after('
'); + jQuery.jcalendar.setDateWindow(this, a, year); + jQuery.jcalendar.show(this, day, month, year); + + day.change(function() { + // only if a valid day is selected + if (this.value > 0) { + d = new Date(year.val(), month.val()-1, this.value); + jQuery.jcalendar.changeMonth(d, a, day, month, year); + } + }); + + month.change(function() { + // only if a valid month is selected + if (this.value > 0) { + d = new Date(year.val(), this.value-1, 1); + jQuery.jcalendar.changeMonth(d, a, day, month, year); + } + }); + + year.change(function() { + // only if a valid year is selected + if (this.value > 0) { + d = new Date(this.value, month.val()-1, 1); + jQuery.jcalendar.changeMonth(d, a, day, month, year); + } + }); + + }); + return this; +}; +/** + * jCalendar 0.5 + * + * Some code based on jQuery Date Picker (http://kelvinluck.com/assets/jquery/datePicker/) + * + * Copyright (c) 2007 Theodore Serbinski (http://tedserbinski.com) + * Dual licensed under the MIT (MIT-LICENSE.txt) + * and GPL (GPL-LICENSE.txt) licenses. + */ +jQuery.jcalendar = function() { + var months = ['January', 'February', 'March', 'April', 'May', 'June', 'July', 'August', 'September', 'October', 'November', 'December']; + var days = ['S', 'M', 'Tu', 'W', 'Th', 'F', 'S']; + var navLinks = {p:'Prev', n:'Next', t:'Today'}; + var _firstDayOfWeek; + var _firstDate; + var _lastDate; + var _selectedDate; + + var _drawCalendar = function(dateIn, a, day, month, year) { + var today = new Date(); + var d; + + if (dateIn == undefined) { + // start from this month. + d = new Date(today.getFullYear(), today.getMonth(), 1); + year.val(today.getFullYear()); + month.val(today.getMonth()+1); + day.val(today.getDate()); + } + else { + // start from the passed in date + d = dateIn; + d.setDate(1); + } + + // check that date is within allowed limits + if ((d.getMonth() < _firstDate.getMonth() && d.getFullYear() == _firstDate.getFullYear()) || d.getFullYear() < _firstDate.getFullYear()) { + d = new Date(_firstDate.getFullYear(), _firstDate.getMonth(), 1); + } + else if ((d.getMonth() > _lastDate.getMonth() && d.getFullYear() == _lastDate.getFullYear()) || d.getFullYear() > _lastDate.getFullYear()) { + d = new Date(_lastDate.getFullYear(), _lastDate.getMonth(), 1); + } + + var firstMonth = true; + var firstDate = _firstDate.getDate(); + + // create prev and next links + if (!(d.getMonth() == _firstDate.getMonth() && d.getFullYear() == _firstDate.getFullYear())) { + // not in first display month so show a previous link + firstMonth = false; + var lastMonth = d.getMonth() == 0 ? new Date(d.getFullYear()-1, 11, 1) : new Date(d.getFullYear(), d.getMonth()-1, 1); + var prevLink = jQuery('').click(function() { + jQuery.jcalendar.changeMonth(lastMonth, this, day, month, year); + return false; + }); + } + + var finalMonth = true; + var lastDate = _lastDate.getDate(); + + if (!(d.getMonth() == _lastDate.getMonth() && d.getFullYear() == _lastDate.getFullYear())) { + // in the last month - no next link + finalMonth = false; + var nextMonth = new Date(d.getFullYear(), d.getMonth()+1, 1); + var nextLink = jQuery('').click(function() { + jQuery.jcalendar.changeMonth(nextMonth, this, day, month, year); + return false; + }); + } + + var todayLink = jQuery(''+ navLinks.t +'').click(function() { + day.val(today.getDate()); + jQuery.jcalendar.changeMonth(today, this, day, month, year); + return false; + }); + + // update the year and month select boxes + year.val(d.getFullYear()); + month.val(d.getMonth()+1); + + var headRow = jQuery(""); + for (var i=_firstDayOfWeek; i<_firstDayOfWeek+7; i++) { + var weekday = i%7; + var wordday = days[weekday]; + headRow.append(''+ wordday +''); + } + headRow = jQuery("").append(headRow); + + var tBody = jQuery(""); + var lastDay = (new Date(d.getFullYear(), d.getMonth()+1, 0)).getDate(); + var curDay = _firstDayOfWeek - d.getDay(); + if (curDay > 0) curDay -= 7; + + var todayDate = today.getDate(); + var thisMonth = d.getMonth() == today.getMonth() && d.getFullYear() == today.getFullYear(); + + // render calendar + do { + var thisRow = jQuery(""); + for (var i=0; i<7; i++) { + var weekday = (_firstDayOfWeek + i) % 7; + var atts = {'class':(weekday == 0 || weekday == 6 ? 'weekend ' : 'weekday ')}; + + if (curDay < 0 || curDay >= lastDay) { + dayStr = ' '; + } + else if (firstMonth && curDay < firstDate-1) { + dayStr = curDay+1; + atts['class'] += 'inactive'; + } + else if (finalMonth && curDay > lastDate-1) { + dayStr = curDay+1; + atts['class'] += 'inactive'; + } + else { + d.setDate(curDay+1); + + // attach a click handler to every day to select it if clicked + // we use the rel attribute to keep track of the day that is being clicked + dayStr = jQuery(''+ (curDay+1) +'').click(function(e) { + if (_selectedDate) { + _selectedDate.removeClass('selected'); + } + _selectedDate = jQuery(this); + _selectedDate.addClass('selected'); + day.val(new Date(_selectedDate.attr('rel')).getDate()); + return false; + }); + + // highlight the current selected day + if (day.val() == d.getDate()) { + _selectedDate = dayStr; + _selectedDate.addClass('selected'); + } + } + + if (thisMonth && curDay+1 == todayDate) { + atts['class'] += 'today'; + } + thisRow.append(jQuery("").attr(atts).append(dayStr)); + curDay++; + } + + tBody.append(thisRow); + } while (curDay < lastDay); + + jQuery('div.jcalendar').html('
'); + jQuery('div.jcalendar table').append(headRow, tBody); + jQuery('div.jcalendar > div.jcalendar-links').append(prevLink, todayLink, nextLink); + }; + + return { + show: function(a, day, month, year) { + _firstDate = a._startDate; + _lastDate = a._endDate; + _firstDayOfWeek = a._firstDayOfWeek; + + // pass in the selected form date if one was set + var selected; + if (year.val() > 0 && month.val() > 0 && day.val() > 0) { + selected = new Date(year.val(), month.val()-1, day.val()); + } + else { + selected = null; + } + _drawCalendar(selected, a, day, month, year); + }, + changeMonth: function(d, e, day, month, year) { + _drawCalendar(d, e, day, month, year); + }, + /** + * Function: setLanguageStrings + * + * Allows you to localise the calendar by passing in relevant text for the english strings in the plugin. + * + * Arguments: + * days - Array, e.g. ['Sunday', 'Monday', 'Tuesday', 'Wednesday', 'Thursday', 'Friday', 'Saturday'] + * months - Array, e.g. ['January', 'Febuary', 'March', 'April', 'May', 'June', 'July', 'August', 'September', 'October', 'November', 'December']; + * navLinks - Object, e.g. {p:'Prev', n:'Next', c:'Close', b:'Choose date'} + **/ + setLanguageStrings: function(aDays, aMonths, aNavLinks) { + days = aDays; + months = aMonths; + navLinks = aNavLinks; + }, + /** + * Function: setDateWindow + * + * Used internally to set the start and end dates for a given date select + * + * Arguments: + * i - The id of the INPUT element this date window is for + * w - The date window - an object containing startDate and endDate properties + * e.g. {startDate:'24-11-1981', endDate:'25-12-2012} + **/ + setDateWindow: function(i, w, year) { + if (w == undefined) w = {}; + if (w.startDate == undefined) { + // set the minimum browseable date equal to January of the min year in the select box + // don't get the first option because that is an empty year + + // note we can't do this: year.find('option:eq(1)').val() + // it doesn't work in 1.0 since find() is destructive + // so we copy the object to a new var + i._startDate = new Date(jQuery(year).find('option:eq(1)').val(), 0, 1); + } + else { + dateParts = w.startDate.split('-'); + i._startDate = new Date(dateParts[2], Number(dateParts[1])-1, Number(dateParts[0])); + } + if (w.endDate == undefined) { + // set the maximum browseable date equal to December of the max year in the select box + + // note we can't do this: year.find('option:last').val() + // it doesn't work in 1.0 since find() is destructive + // so we copy the object to a new var + i._endDate = new Date(jQuery(year).find('option:last').val(), 11, 1); + } + else { + dateParts = w.endDate.split('-'); + i._endDate = new Date(dateParts[2], Number(dateParts[1])-1, Number(dateParts[0])); + } + i._firstDayOfWeek = w.firstDayOfWeek == undefined ? 0 : w.firstDayOfWeek; + } + }; +}(); + +jQuery.fn.jcalendar = function(a) { + this.each(function() { + var day = jQuery(this).find('select.jcalendar-select-day'); + var month = jQuery(this).find('select.jcalendar-select-month'); + var year = jQuery(this).find('select.jcalendar-select-year'); + jQuery('div.jcalendar-selects').after('
'); + jQuery.jcalendar.setDateWindow(this, a, year); + jQuery.jcalendar.show(this, day, month, year); + + day.change(function() { + // only if a valid day is selected + if (this.value > 0) { + d = new Date(year.val(), month.val()-1, this.value); + jQuery.jcalendar.changeMonth(d, a, day, month, year); + } + }); + + month.change(function() { + // only if a valid month is selected + if (this.value > 0) { + d = new Date(year.val(), this.value-1, 1); + jQuery.jcalendar.changeMonth(d, a, day, month, year); + } + }); + + year.change(function() { + // only if a valid year is selected + if (this.value > 0) { + d = new Date(this.value, month.val()-1, 1); + jQuery.jcalendar.changeMonth(d, a, day, month, year); + } + }); + + }); + return this; +}; +/** + * jCalendar 0.5 + * + * Some code based on jQuery Date Picker (http://kelvinluck.com/assets/jquery/datePicker/) + * + * Copyright (c) 2007 Theodore Serbinski (http://tedserbinski.com) + * Dual licensed under the MIT (MIT-LICENSE.txt) + * and GPL (GPL-LICENSE.txt) licenses. + */ +jQuery.jcalendar = function() { + var months = ['January', 'February', 'March', 'April', 'May', 'June', 'July', 'August', 'September', 'October', 'November', 'December']; + var days = ['S', 'M', 'Tu', 'W', 'Th', 'F', 'S']; + var navLinks = {p:'Prev', n:'Next', t:'Today'}; + var _firstDayOfWeek; + var _firstDate; + var _lastDate; + var _selectedDate; + + var _drawCalendar = function(dateIn, a, day, month, year) { + var today = new Date(); + var d; + + if (dateIn == undefined) { + // start from this month. + d = new Date(today.getFullYear(), today.getMonth(), 1); + year.val(today.getFullYear()); + month.val(today.getMonth()+1); + day.val(today.getDate()); + } + else { + // start from the passed in date + d = dateIn; + d.setDate(1); + } + + // check that date is within allowed limits + if ((d.getMonth() < _firstDate.getMonth() && d.getFullYear() == _firstDate.getFullYear()) || d.getFullYear() < _firstDate.getFullYear()) { + d = new Date(_firstDate.getFullYear(), _firstDate.getMonth(), 1); + } + else if ((d.getMonth() > _lastDate.getMonth() && d.getFullYear() == _lastDate.getFullYear()) || d.getFullYear() > _lastDate.getFullYear()) { + d = new Date(_lastDate.getFullYear(), _lastDate.getMonth(), 1); + } + + var firstMonth = true; + var firstDate = _firstDate.getDate(); + + // create prev and next links + if (!(d.getMonth() == _firstDate.getMonth() && d.getFullYear() == _firstDate.getFullYear())) { + // not in first display month so show a previous link + firstMonth = false; + var lastMonth = d.getMonth() == 0 ? new Date(d.getFullYear()-1, 11, 1) : new Date(d.getFullYear(), d.getMonth()-1, 1); + var prevLink = jQuery('').click(function() { + jQuery.jcalendar.changeMonth(lastMonth, this, day, month, year); + return false; + }); + } + + var finalMonth = true; + var lastDate = _lastDate.getDate(); + + if (!(d.getMonth() == _lastDate.getMonth() && d.getFullYear() == _lastDate.getFullYear())) { + // in the last month - no next link + finalMonth = false; + var nextMonth = new Date(d.getFullYear(), d.getMonth()+1, 1); + var nextLink = jQuery('').click(function() { + jQuery.jcalendar.changeMonth(nextMonth, this, day, month, year); + return false; + }); + } + + var todayLink = jQuery(''+ navLinks.t +'').click(function() { + day.val(today.getDate()); + jQuery.jcalendar.changeMonth(today, this, day, month, year); + return false; + }); + + // update the year and month select boxes + year.val(d.getFullYear()); + month.val(d.getMonth()+1); + + var headRow = jQuery(""); + for (var i=_firstDayOfWeek; i<_firstDayOfWeek+7; i++) { + var weekday = i%7; + var wordday = days[weekday]; + headRow.append(''+ wordday +''); + } + headRow = jQuery("").append(headRow); + + var tBody = jQuery(""); + var lastDay = (new Date(d.getFullYear(), d.getMonth()+1, 0)).getDate(); + var curDay = _firstDayOfWeek - d.getDay(); + if (curDay > 0) curDay -= 7; + + var todayDate = today.getDate(); + var thisMonth = d.getMonth() == today.getMonth() && d.getFullYear() == today.getFullYear(); + + // render calendar + do { + var thisRow = jQuery(""); + for (var i=0; i<7; i++) { + var weekday = (_firstDayOfWeek + i) % 7; + var atts = {'class':(weekday == 0 || weekday == 6 ? 'weekend ' : 'weekday ')}; + + if (curDay < 0 || curDay >= lastDay) { + dayStr = ' '; + } + else if (firstMonth && curDay < firstDate-1) { + dayStr = curDay+1; + atts['class'] += 'inactive'; + } + else if (finalMonth && curDay > lastDate-1) { + dayStr = curDay+1; + atts['class'] += 'inactive'; + } + else { + d.setDate(curDay+1); + + // attach a click handler to every day to select it if clicked + // we use the rel attribute to keep track of the day that is being clicked + dayStr = jQuery(''+ (curDay+1) +'').click(function(e) { + if (_selectedDate) { + _selectedDate.removeClass('selected'); + } + _selectedDate = jQuery(this); + _selectedDate.addClass('selected'); + day.val(new Date(_selectedDate.attr('rel')).getDate()); + return false; + }); + + // highlight the current selected day + if (day.val() == d.getDate()) { + _selectedDate = dayStr; + _selectedDate.addClass('selected'); + } + } + + if (thisMonth && curDay+1 == todayDate) { + atts['class'] += 'today'; + } + thisRow.append(jQuery("").attr(atts).append(dayStr)); + curDay++; + } + + tBody.append(thisRow); + } while (curDay < lastDay); + + jQuery('div.jcalendar').html('
'); + jQuery('div.jcalendar table').append(headRow, tBody); + jQuery('div.jcalendar > div.jcalendar-links').append(prevLink, todayLink, nextLink); + }; + + return { + show: function(a, day, month, year) { + _firstDate = a._startDate; + _lastDate = a._endDate; + _firstDayOfWeek = a._firstDayOfWeek; + + // pass in the selected form date if one was set + var selected; + if (year.val() > 0 && month.val() > 0 && day.val() > 0) { + selected = new Date(year.val(), month.val()-1, day.val()); + } + else { + selected = null; + } + _drawCalendar(selected, a, day, month, year); + }, + changeMonth: function(d, e, day, month, year) { + _drawCalendar(d, e, day, month, year); + }, + /** + * Function: setLanguageStrings + * + * Allows you to localise the calendar by passing in relevant text for the english strings in the plugin. + * + * Arguments: + * days - Array, e.g. ['Sunday', 'Monday', 'Tuesday', 'Wednesday', 'Thursday', 'Friday', 'Saturday'] + * months - Array, e.g. ['January', 'Febuary', 'March', 'April', 'May', 'June', 'July', 'August', 'September', 'October', 'November', 'December']; + * navLinks - Object, e.g. {p:'Prev', n:'Next', c:'Close', b:'Choose date'} + **/ + setLanguageStrings: function(aDays, aMonths, aNavLinks) { + days = aDays; + months = aMonths; + navLinks = aNavLinks; + }, + /** + * Function: setDateWindow + * + * Used internally to set the start and end dates for a given date select + * + * Arguments: + * i - The id of the INPUT element this date window is for + * w - The date window - an object containing startDate and endDate properties + * e.g. {startDate:'24-11-1981', endDate:'25-12-2012} + **/ + setDateWindow: function(i, w, year) { + if (w == undefined) w = {}; + if (w.startDate == undefined) { + // set the minimum browseable date equal to January of the min year in the select box + // don't get the first option because that is an empty year + + // note we can't do this: year.find('option:eq(1)').val() + // it doesn't work in 1.0 since find() is destructive + // so we copy the object to a new var + i._startDate = new Date(jQuery(year).find('option:eq(1)').val(), 0, 1); + } + else { + dateParts = w.startDate.split('-'); + i._startDate = new Date(dateParts[2], Number(dateParts[1])-1, Number(dateParts[0])); + } + if (w.endDate == undefined) { + // set the maximum browseable date equal to December of the max year in the select box + + // note we can't do this: year.find('option:last').val() + // it doesn't work in 1.0 since find() is destructive + // so we copy the object to a new var + i._endDate = new Date(jQuery(year).find('option:last').val(), 11, 1); + } + else { + dateParts = w.endDate.split('-'); + i._endDate = new Date(dateParts[2], Number(dateParts[1])-1, Number(dateParts[0])); + } + i._firstDayOfWeek = w.firstDayOfWeek == undefined ? 0 : w.firstDayOfWeek; + } + }; +}(); + +jQuery.fn.jcalendar = function(a) { + this.each(function() { + var day = jQuery(this).find('select.jcalendar-select-day'); + var month = jQuery(this).find('select.jcalendar-select-month'); + var year = jQuery(this).find('select.jcalendar-select-year'); + jQuery('div.jcalendar-selects').after('
'); + jQuery.jcalendar.setDateWindow(this, a, year); + jQuery.jcalendar.show(this, day, month, year); + + day.change(function() { + // only if a valid day is selected + if (this.value > 0) { + d = new Date(year.val(), month.val()-1, this.value); + jQuery.jcalendar.changeMonth(d, a, day, month, year); + } + }); + + month.change(function() { + // only if a valid month is selected + if (this.value > 0) { + d = new Date(year.val(), this.value-1, 1); + jQuery.jcalendar.changeMonth(d, a, day, month, year); + } + }); + + year.change(function() { + // only if a valid year is selected + if (this.value > 0) { + d = new Date(this.value, month.val()-1, 1); + jQuery.jcalendar.changeMonth(d, a, day, month, year); + } + }); + + }); + return this; +}; diff --git a/wp-includes/script-loader.php b/wp-includes/script-loader.php index d059c5330..d34453fb0 100644 --- a/wp-includes/script-loader.php +++ b/wp-includes/script-loader.php @@ -74,6 +74,19 @@ class WP_Scripts { $this->add( 'jquery', '/wp-includes/js/jquery/jquery.js', false, '1.1.3.1'); $this->add( 'jquery-form', '/wp-includes/js/jquery/jquery.form.js', array('jquery'), '1.0.3'); $this->add( 'interface', '/wp-includes/js/jquery/interface.js', array('jquery'), '1.2'); + $this->add( 'jcalendar', '/wp-includes/js/jquery/jcalendar.js', array('jquery'), '0.5' ); + + // this would be much nicer if localize used json so it could handle arrays + global $wp_locale; + $this->localize( 'jcalendar', 'jcalendar_L10n', array( + 'days' => array_values($wp_locale->weekday_abbrev), + 'months' => array_values($wp_locale->month), + 'navLinks' => array( + 'p' => __('Prev'), + 'n' => __('Next'), + 't' => __('Today'), + ), + ) ); if ( is_admin() ) { global $pagenow; @@ -205,17 +218,28 @@ class WP_Scripts { echo "\n"; } + /** + * Poor man's json: recursively encode an associative array of strings or arrays as a javascript array definition + */ + function js_encode_array( $name, $vals, $level=0 ) { + $out = array(); + foreach ( $vals as $var => $val ) { + if ( is_array($val) ) + $out[] = $this->js_encode_array( $var, $val, $level+1 ); + else + $out[] = str_repeat("\t", $level+1) . "{$var}: \"" . js_escape( $val ) . '"'; + } + + return str_repeat("\t", $level) . "{$name} " . ($level ? ':' : '=') . " {\n" + . join( ",\n", $out ) + . "\n" . str_repeat("\t", $level) . "}"; + } + /** * Determines dependencies of scripts *