CSS:
View Code
@charset "utf-8"; /* CSS Document */ .datepicker { border-collapse: collapse; border: 2px solid #999; position: absolute; } .datepicker tr.controls th { height: 22px; font-size: 11px; } .datepicker select { font-size: 11px; } .datepicker tr.days th { height: 18px; } .datepicker tfoot td { height: 18px; text-align: center; text-transform: capitalize; } .datepicker th, .datepicker tfoot td { background: #eee; font: 10px/18px Verdana, Arial, Helvetica, sans-serif; } .datepicker th span, .datepicker tfoot td span { font-weight: bold; } .datepicker tbody td { 24px; height: 24px; border: 1px solid #ccc; font: 11px/22px Arial, Helvetica, sans-serif; text-align: center; background: #fff; } .datepicker tbody td.date { cursor: pointer; } .datepicker tbody td.date.over { background-color: #99ffff; } .datepicker tbody td.date.chosen { font-weight: bold; background-color: #ccffcc; }
JQUERY:
View Code
/** the script only works on "input [type=text]" **/ // don't declare anything out here in the global namespace (function ($) { // create private scope (inside you can use $ instead of jQuery) // functions and vars declared here are effectively 'singletons'. there will be only a single // instance of them. so this is a good place to declare any immutable items or stateless // functions. for example: var today = new Date(); // used in defaults var months = '一月,二月,三月,四月,五月,六月,七月,八月,九月,十月,十一月,十二月'.split(','); var monthlengths = '31,28,31,30,31,30,31,31,30,31,30,31'.split(','); var dateRegEx = /^\d{1,2}\/\d{1,2}\/\d{2}|\d{4}$/; var yearRegEx = /^\d{4,4}$/; // next, declare the plugin function $.fn.simpleDatepicker = function (options) { // functions and vars declared here are created each time your plugn function is invoked // you could probably refactor your 'build', 'load_month', etc, functions to be passed // the DOM element from below var opts = jQuery.extend({}, jQuery.fn.simpleDatepicker.defaults, options); // replaces a date string with a date object in opts.startdate and opts.enddate, if one exists // populates two new properties with a ready-to-use year: opts.startyear and opts.endyear setupYearRange(); /** extracts and setup a valid year range from the opts object **/ function setupYearRange() { var startyear, endyear; if (opts.startdate.constructor == Date) { startyear = opts.startdate.getFullYear(); } else if (opts.startdate) { if (yearRegEx.test(opts.startdate)) { startyear = opts.startdate; } else if (dateRegEx.test(opts.startdate)) { opts.startdate = new Date(opts.startdate); startyear = opts.startdate.getFullYear(); } else { startyear = today.getFullYear(); } } else { startyear = today.getFullYear(); } opts.startyear = startyear; if (opts.enddate.constructor == Date) { endyear = opts.enddate.getFullYear(); } else if (opts.enddate) { if (yearRegEx.test(opts.enddate)) { endyear = opts.enddate; } else if (dateRegEx.test(opts.enddate)) { opts.enddate = new Date(opts.enddate); endyear = opts.enddate.getFullYear(); } else { endyear = today.getFullYear(); } } else { endyear = today.getFullYear(); } opts.endyear = endyear; } /** HTML factory for the actual datepicker table element **/ // has to read the year range so it can setup the correct years in our HTML <select> function newDatepickerHTML() { var years = []; // process year range into an array for (var i = 0; i <= opts.endyear - opts.startyear; i++) years[i] = opts.startyear + i; // build the table structure var table = jQuery('<table class="datepicker" cellpadding="0" cellspacing="0"></table>'); table.append('<thead></thead>'); table.append('<tfoot></tfoot>'); table.append('<tbody></tbody>'); // month select field var monthselect = '<select name="month">'; for (var i in months) monthselect += '<option value="' + i + '">' + months[i] + '</option>'; monthselect += '</select>'; // year select field var yearselect = '<select name="year">'; for (var i in years) yearselect += '<option>' + years[i] + '</option>'; yearselect += '</select>'; jQuery("thead", table).append('<tr class="controls"><th colspan="7"><span class="prevMonth">«</span> ' + monthselect + yearselect + ' <span class="nextMonth">»</span></th></tr>'); jQuery("thead", table).append('<tr class="days"><th>S</th><th>M</th><th>T</th><th>W</th><th>T</th><th>F</th><th>S</th></tr>'); jQuery("tfoot", table).append('<tr><td colspan="2"><span class="today">今天</span></td><td colspan="3"> </td><td colspan="2"><span class="close">关闭</span></td></tr>'); for (var i = 0; i < 6; i++) jQuery("tbody", table).append('<tr><td></td><td></td><td></td><td></td><td></td><td></td><td></td></tr>'); return table; } /** get the real position of the input (well, anything really) **/ //http://www.quirksmode.org/js/findpos.html function findPosition(obj) { var curleft = curtop = 0; if (obj.offsetParent) { do { curleft += obj.offsetLeft; curtop += obj.offsetTop; } while (obj = obj.offsetParent); return [curleft, curtop]; } else { return false; } } /** load the initial date and handle all date-navigation **/ // initial calendar load (e is null) // prevMonth & nextMonth buttons // onchange for the select fields function loadMonth(e, el, datepicker, chosendate) { // reference our years for the nextMonth and prevMonth buttons var mo = jQuery("select[name=month]", datepicker).get(0).selectedIndex; var yr = jQuery("select[name=year]", datepicker).get(0).selectedIndex; var yrs = jQuery("select[name=year] option", datepicker).get().length; // first try to process buttons that may change the month we're on if (e && jQuery(e.target).hasClass('prevMonth')) { if (0 == mo && yr) { yr -= 1; mo = 11; jQuery("select[name=month]", datepicker).get(0).selectedIndex = 11; jQuery("select[name=year]", datepicker).get(0).selectedIndex = yr; } else { mo -= 1; jQuery("select[name=month]", datepicker).get(0).selectedIndex = mo; } } else if (e && jQuery(e.target).hasClass('nextMonth')) { if (11 == mo && yr + 1 < yrs) { yr += 1; mo = 0; jQuery("select[name=month]", datepicker).get(0).selectedIndex = 0; jQuery("select[name=year]", datepicker).get(0).selectedIndex = yr; } else { mo += 1; jQuery("select[name=month]", datepicker).get(0).selectedIndex = mo; } } // maybe hide buttons if (0 == mo && !yr) jQuery("span.prevMonth", datepicker).hide(); else jQuery("span.prevMonth", datepicker).show(); if (yr + 1 == yrs && 11 == mo) jQuery("span.nextMonth", datepicker).hide(); else jQuery("span.nextMonth", datepicker).show(); // clear the old cells var cells = jQuery("tbody td", datepicker).unbind().empty().removeClass('date'); // figure out what month and year to load var m = jQuery("select[name=month]", datepicker).val(); var y = jQuery("select[name=year]", datepicker).val(); var d = new Date(y, m, 1); var startindex = d.getDay(); var numdays = monthlengths[m]; // http://en.wikipedia.org/wiki/Leap_year if (1 == m && ((y % 4 == 0 && y % 100 != 0) || y % 400 == 0)) numdays = 29; // test for end dates (instead of just a year range) if (opts.startdate.constructor == Date) { var startMonth = opts.startdate.getMonth(); var startDate = opts.startdate.getDate(); } if (opts.enddate.constructor == Date) { var endMonth = opts.enddate.getMonth(); var endDate = opts.enddate.getDate(); } // walk through the index and populate each cell, binding events too for (var i = 0; i < numdays; i++) { var cell = jQuery(cells.get(i + startindex)).removeClass('chosen'); // test that the date falls within a range, if we have a range if ( (yr || ((!startDate && !startMonth) || ((i + 1 >= startDate && mo == startMonth) || mo > startMonth))) && (yr + 1 < yrs || ((!endDate && !endMonth) || ((i + 1 <= endDate && mo == endMonth) || mo < endMonth)))) { cell .text(i + 1) .addClass('date') .hover( function () { jQuery(this).addClass('over'); }, function () { jQuery(this).removeClass('over'); }) .click(function () { var chosenDateObj = new Date(jQuery("select[name=year]", datepicker).val(), jQuery("select[name=month]", datepicker).val(), jQuery(this).text()); closeIt(el, datepicker, chosenDateObj); }); // highlight the previous chosen date if (i + 1 == chosendate.getDate() && m == chosendate.getMonth() && y == chosendate.getFullYear()) cell.addClass('chosen'); } } } /** closes the datepicker **/ // sets the currently matched input element's value to the date, if one is available // remove the table element from the DOM // indicate that there is no datepicker for the currently matched input element function closeIt(el, datepicker, dateObj) { if (dateObj && dateObj.constructor == Date) el.val(jQuery.fn.simpleDatepicker.formatOutput(dateObj)); datepicker.remove(); datepicker = null; jQuery.data(el.get(0), "simpleDatepicker", { hasDatepicker: false }); } // iterate the matched nodeset return this.each(function () { // functions and vars declared here are created for each matched element. so if // your functions need to manage or access per-node state you can defined them // here and use $this to get at the DOM element if (jQuery(this).is('input') && 'text' == jQuery(this).attr('type')) { var datepicker; jQuery.data(jQuery(this).get(0), "simpleDatepicker", { hasDatepicker: false }); // open a datepicker on the click event jQuery(this).click(function (ev) { var $this = jQuery(ev.target); if (false == jQuery.data($this.get(0), "simpleDatepicker").hasDatepicker) { // store data telling us there is already a datepicker jQuery.data($this.get(0), "simpleDatepicker", { hasDatepicker: true }); // validate the form's initial content for a date var initialDate = $this.val(); if (initialDate && dateRegEx.test(initialDate)) { var chosendate = new Date(initialDate); } else if (opts.chosendate.constructor == Date) { var chosendate = opts.chosendate; } else if (opts.chosendate) { var chosendate = new Date(opts.chosendate); } else { var chosendate = today; } // insert the datepicker in the DOM datepicker = newDatepickerHTML(); jQuery("body").prepend(datepicker); // position the datepicker var elPos = findPosition($this.get(0)); var x = (parseInt(opts.x) ? parseInt(opts.x) : 0) + elPos[0]; var y = (parseInt(opts.y) ? parseInt(opts.y) : 0) + elPos[1]; jQuery(datepicker).css({ position: 'absolute', left: x, top: y }); // bind events to the table controls jQuery("span", datepicker).css("cursor", "pointer"); jQuery("select", datepicker).bind('change', function () { loadMonth(null, $this, datepicker, chosendate); }); jQuery("span.prevMonth", datepicker).click(function (e) { loadMonth(e, $this, datepicker, chosendate); }); jQuery("span.nextMonth", datepicker).click(function (e) { loadMonth(e, $this, datepicker, chosendate); }); jQuery("span.today", datepicker).click(function () { closeIt($this, datepicker, new Date()); }); jQuery("span.close", datepicker).click(function () { closeIt($this, datepicker); }); // set the initial values for the month and year select fields // and load the first month jQuery("select[name=month]", datepicker).get(0).selectedIndex = chosendate.getMonth(); jQuery("select[name=year]", datepicker).get(0).selectedIndex = Math.max(0, chosendate.getFullYear() - opts.startyear); loadMonth(null, $this, datepicker, chosendate); } }); } }); }; // finally, I like to expose default plugin options as public so they can be manipulated. one // way to do this is to add a property to the already-public plugin fn jQuery.fn.simpleDatepicker.formatOutput = function (dateObj) { return (dateObj.getMonth() + 1) + "/" + dateObj.getDate() + "/" + dateObj.getFullYear(); }; jQuery.fn.simpleDatepicker.defaults = { // date string matching /^\d{1,2}\/\d{1,2}\/\d{2}|\d{4}$/ chosendate: today, // date string matching /^\d{1,2}\/\d{1,2}\/\d{2}|\d{4}$/ // or four digit year startdate: today.getFullYear(), enddate: today.getFullYear() + 1, // offset from the top left corner of the input element x: 18, // must be in px y: 18 // must be in px }; })(jQuery);
JS调用:
View Code
<script type="text/javascript"> jQuery(document).ready(function () { $('input.one').simpleDatepicker(); // $('input.two').simpleDatepicker({ startdate: 2008, enddate: 2012 }); // $('input.three').simpleDatepicker({ chosendate: '9/9/2010', startdate: '6/10/2008', enddate: '7/20/2011' }); // $('input.four').simpleDatepicker({ x: 45, y: 3 }); }); </script>
页面text格式:
View Code
<input class="one" type="text" name="date" value="" />