Initial Release of the calendar plugin

This commit is contained in:
Tobias Hößl 2012-06-03 18:19:28 +00:00
parent 45cc9885fc
commit 7115197a33
561 changed files with 189494 additions and 0 deletions

56
dav/timepicker/README.md Normal file
View file

@ -0,0 +1,56 @@
timePicker
==========
A time picker control for textfields built using jQuery. Inspired by Google Calendar.
Examples
--------
Default:
$("#time1").timePicker();
02.00 AM - 03.30 PM, 15 minutes steps:
$("#time2").timePicker({
startTime: "02.00", // Using string. Can take string or Date object.
endTime: new Date(0, 0, 0, 15, 30, 0), // Using Date object here.
show24Hours: false,
separator: '.',
step: 15});
An example how the two helper functions can be used to achieve
advanced functionality.
- Linking: When changing the first input the second input is updated and the
duration is kept.
- Validation: If the second input has a time earlier than the firs input,
an error class is added.
The example:
// Use default settings
$("#time3, #time4").timePicker();
// Store time used by duration.
var oldTime = $.timePicker("#time3").getTime();
// Keep the duration between the two inputs.
$("#time3").change(function() {
if ($("#time4").val()) { // Only update when second input has a value.
// Calculate duration.
var duration = ($.timePicker("#time4").getTime() - oldTime);
var time = $.timePicker("#time3").getTime();
// Calculate and update the time in the second input.
$.timePicker("#time4").setTime(new Date(new Date(time.getTime() + duration)));
oldTime = time;
}
});
// Validate.
$("#time4").change(function() {
if($.timePicker("#time3").getTime() > $.timePicker(this).getTime()) {
$(this).addClass("error");
}
else {
$(this).removeClass("error");
}
});

137
dav/timepicker/index.htm Normal file
View file

@ -0,0 +1,137 @@
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
<html xmlns="http://www.w3.org/1999/xhtml" lang="en">
<head>
<title>jQuery timePicker</title>
<style type="text/css" media="all">@import "timePicker.css";</style>
<style type="text/css">
div {
margin-top:3em;
}
input {
margin:0;
padding:0;
}
body {
background: #eee;
}
pre {
background:#fff;
border:1px solid #ddd;
padding:4px;
}
.error {
border:1px solid red;
}
</style>
<script type="text/javascript" src="http://ajax.googleapis.com/ajax/libs/jquery/1.4.2/jquery.js"></script>
<script type="text/javascript" src="jquery.timePicker.js"></script>
<script type="text/javascript">
jQuery(function() {
// Default.
$("#time1").timePicker();
// 02.00 AM - 03.30 PM, 15 minutes steps.
$("#time2").timePicker({
startTime: "02.00", // Using string. Can take string or Date object.
endTime: new Date(0, 0, 0, 15, 30, 0), // Using Date object.
show24Hours: false,
separator:'.',
step: 15});
// An example how the two helper functions can be used to achieve
// advanced functionality.
// - Linking: When changing the first input the second input is updated and the
// duration is kept.
// - Validation: If the second input has a time earlier than the firs input,
// an error class is added.
// Use default settings
$("#time3, #time4").timePicker();
// Store time used by duration.
var oldTime = $.timePicker("#time3").getTime();
// Keep the duration between the two inputs.
$("#time3").change(function() {
if ($("#time4").val()) { // Only update when second input has a value.
// Calculate duration.
var duration = ($.timePicker("#time4").getTime() - oldTime);
var time = $.timePicker("#time3").getTime();
// Calculate and update the time in the second input.
$.timePicker("#time4").setTime(new Date(new Date(time.getTime() + duration)));
oldTime = time;
}
});
// Validate.
$("#time4").change(function() {
if($.timePicker("#time3").getTime() > $.timePicker(this).getTime()) {
$(this).addClass("error");
}
else {
$(this).removeClass("error");
}
});
});
</script>
<script type="text/javascript">
// Analytics.
var _gaq=_gaq||[];_gaq.push(["_setAccount","UA-123444-3"]),_gaq.push(["_trackPageview"]),function(){var a=document.createElement("script");a.type="text/javascript",a.async=!0,a.src=("https:"==document.location.protocol?"https://ssl":"http://www")+".google-analytics.com/ga.js";var b=document.getElementsByTagName("script")[0];b.parentNode.insertBefore(a,b)}()
</script>
</head>
<body>
<h1>jQuery timePicker</h1>
<p>A time picker for jQuery inspired by Google Calendar</p>
<p>Get the latest code on Github (the files used on this page might not be the latest): <a href="http://github.com/perifer/timePicker">http://github.com/perifer/timePicker</a>
<div><input type="text" id="time1" size="10" /></div>
<pre><code>// Default.
$("#time1").timePicker();</code></pre>
<div><input type="text" id="time2" size="10" value="12.00 PM"/></div>
<pre><code>// 02.00 AM - 03.30 PM, 15 minutes steps.
$("#time2").timePicker({
startTime: "02.00", // Using string. Can take string or Date object.
endTime: new Date(0, 0, 0, 15, 30, 0), // Using Date object here.
show24Hours: false,
separator: '.',
step: 15});</code></pre>
<div><input type="text" id="time3" size="10" value="08:00" /> <input type="text" id="time4" size="10" value="09:00" /></div>
<pre><code>// An example how the two helper functions can be used to achieve
// advanced functionality.
// - Linking: When changing the first input the second input is updated and the
// duration is kept.
// - Validation: If the second input has a time earlier than the firs input,
// an error class is added.
// Use default settings
$("#time3, #time4").timePicker();
// Store time used by duration.
var oldTime = $.timePicker("#time3").getTime();
// Keep the duration between the two inputs.
$("#time3").change(function() {
if ($("#time4").val()) { // Only update when second input has a value.
// Calculate duration.
var duration = ($.timePicker("#time4").getTime() - oldTime);
var time = $.timePicker("#time3").getTime();
// Calculate and update the time in the second input.
$.timePicker("#time4").setTime(new Date(new Date(time.getTime() + duration)));
oldTime = time;
}
});
// Validate.
$("#time4").change(function() {
if($.timePicker("#time3").getTime() > $.timePicker(this).getTime()) {
$(this).addClass("error");
}
else {
$(this).removeClass("error");
}
});</code></pre>
</body>
</html>

View file

@ -0,0 +1,277 @@
/*
* A time picker for jQuery
*
* Dual licensed under the MIT and GPL licenses.
* Copyright (c) 2009 Anders Fajerson
* @name timePicker
* @author Anders Fajerson (http://perifer.se)
* @example $("#mytime").timePicker();
* @example $("#mytime").timePicker({step:30, startTime:"15:00", endTime:"18:00"});
*
* Based on timePicker by Sam Collet (http://www.texotela.co.uk/code/jquery/timepicker/)
*
* Options:
* step: # of minutes to step the time by
* startTime: beginning of the range of acceptable times
* endTime: end of the range of acceptable times
* separator: separator string to use between hours and minutes (e.g. ':')
* show24Hours: use a 24-hour scheme
*/
(function($){
$.fn.timePicker = function(options) {
// Build main options before element iteration
var settings = $.extend({}, $.fn.timePicker.defaults, options);
return this.each(function() {
$.timePicker(this, settings);
});
};
$.timePicker = function (elm, settings) {
var e = $(elm)[0];
return e.timePicker || (e.timePicker = new jQuery._timePicker(e, settings));
};
$.timePicker.version = '0.3';
$._timePicker = function(elm, settings) {
var tpOver = false;
var keyDown = false;
var startTime = timeToDate(settings.startTime, settings);
var endTime = timeToDate(settings.endTime, settings);
var selectedClass = "selected";
var selectedSelector = "li." + selectedClass;
$(elm).attr('autocomplete', 'OFF'); // Disable browser autocomplete
var times = [];
var time = new Date(startTime); // Create a new date object.
while(time <= endTime) {
times[times.length] = formatTime(time, settings);
time = new Date(time.setMinutes(time.getMinutes() + settings.step));
}
var $tpDiv = $('<div class="time-picker'+ (settings.show24Hours ? '' : ' time-picker-12hours') +'"></div>');
var $tpList = $('<ul></ul>');
// Build the list.
for(var i = 0; i < times.length; i++) {
$tpList.append("<li>" + times[i] + "</li>");
}
$tpDiv.append($tpList);
// Append the timPicker to the body and position it.
$tpDiv.appendTo('body').hide();
// Store the mouse state, used by the blur event. Use mouseover instead of
// mousedown since Opera fires blur before mousedown.
$tpDiv.mouseover(function() {
tpOver = true;
}).mouseout(function() {
tpOver = false;
});
$("li", $tpList).mouseover(function() {
if (!keyDown) {
$(selectedSelector, $tpDiv).removeClass(selectedClass);
$(this).addClass(selectedClass);
}
}).mousedown(function() {
tpOver = true;
}).click(function() {
setTimeVal(elm, this, $tpDiv, settings);
tpOver = false;
});
var showPicker = function() {
if ($tpDiv.is(":visible")) {
return false;
}
$("li", $tpDiv).removeClass(selectedClass);
// Position
var elmOffset = $(elm).offset();
$tpDiv.css({'top':elmOffset.top + elm.offsetHeight, 'left':elmOffset.left});
// Show picker. This has to be done before scrollTop is set since that
// can't be done on hidden elements.
$tpDiv.show();
// Try to find a time in the list that matches the entered time.
var time = elm.value ? timeStringToDate(elm.value, settings) : startTime;
var startMin = startTime.getHours() * 60 + startTime.getMinutes();
var min = (time.getHours() * 60 + time.getMinutes()) - startMin;
var steps = Math.round(min / settings.step);
var roundTime = normaliseTime(new Date(0, 0, 0, 0, (steps * settings.step + startMin), 0));
roundTime = (startTime < roundTime && roundTime <= endTime) ? roundTime : startTime;
var $matchedTime = $("li:contains(" + formatTime(roundTime, settings) + ")", $tpDiv);
if ($matchedTime.length) {
$matchedTime.addClass(selectedClass);
// Scroll to matched time.
$tpDiv[0].scrollTop = $matchedTime[0].offsetTop;
}
return true;
};
// Attach to click as well as focus so timePicker can be shown again when
// clicking on the input when it already has focus.
$(elm).focus(showPicker).click(showPicker);
// Hide timepicker on blur
$(elm).blur(function() {
if (!tpOver) {
$tpDiv.hide();
}
});
// Keypress doesn't repeat on Safari for non-text keys.
// Keydown doesn't repeat on Firefox and Opera on Mac.
// Using kepress for Opera and Firefox and keydown for the rest seems to
// work with up/down/enter/esc.
var event = ($.browser.opera || $.browser.mozilla) ? 'keypress' : 'keydown';
$(elm)[event](function(e) {
var $selected;
keyDown = true;
var top = $tpDiv[0].scrollTop;
switch (e.keyCode) {
case 38: // Up arrow.
// Just show picker if it's hidden.
if (showPicker()) {
return false;
};
$selected = $(selectedSelector, $tpList);
var prev = $selected.prev().addClass(selectedClass)[0];
if (prev) {
$selected.removeClass(selectedClass);
// Scroll item into view.
if (prev.offsetTop < top) {
$tpDiv[0].scrollTop = top - prev.offsetHeight;
}
}
else {
// Loop to next item.
$selected.removeClass(selectedClass);
prev = $("li:last", $tpList).addClass(selectedClass)[0];
$tpDiv[0].scrollTop = prev.offsetTop - prev.offsetHeight;
}
return false;
break;
case 40: // Down arrow, similar in behaviour to up arrow.
if (showPicker()) {
return false;
};
$selected = $(selectedSelector, $tpList);
var next = $selected.next().addClass(selectedClass)[0];
if (next) {
$selected.removeClass(selectedClass);
if (next.offsetTop + next.offsetHeight > top + $tpDiv[0].offsetHeight) {
$tpDiv[0].scrollTop = top + next.offsetHeight;
}
}
else {
$selected.removeClass(selectedClass);
next = $("li:first", $tpList).addClass(selectedClass)[0];
$tpDiv[0].scrollTop = 0;
}
return false;
break;
case 13: // Enter
if ($tpDiv.is(":visible")) {
var sel = $(selectedSelector, $tpList)[0];
setTimeVal(elm, sel, $tpDiv, settings);
}
return false;
break;
case 27: // Esc
$tpDiv.hide();
return false;
break;
}
return true;
});
$(elm).keyup(function(e) {
keyDown = false;
});
// Helper function to get an inputs current time as Date object.
// Returns a Date object.
this.getTime = function() {
return timeStringToDate(elm.value, settings);
};
// Helper function to set a time input.
// Takes a Date object or string.
this.setTime = function(time) {
elm.value = formatTime(timeToDate(time, settings), settings);
// Trigger element's change events.
$(elm).change();
};
}; // End fn;
// Plugin defaults.
$.fn.timePicker.defaults = {
step:30,
startTime: new Date(0, 0, 0, 0, 0, 0),
endTime: new Date(0, 0, 0, 23, 30, 0),
separator: ':',
show24Hours: true
};
// Private functions.
function setTimeVal(elm, sel, $tpDiv, settings) {
// Update input field
elm.value = $(sel).text();
// Trigger element's change events.
$(elm).change();
// Keep focus for all but IE (which doesn't like it)
if (!$.browser.msie) {
elm.focus();
}
// Hide picker
$tpDiv.hide();
}
function formatTime(time, settings) {
var h = time.getHours();
var hours = settings.show24Hours ? h : (((h + 11) % 12) + 1);
var minutes = time.getMinutes();
return formatNumber(hours) + settings.separator + formatNumber(minutes) + (settings.show24Hours ? '' : ((h < 12) ? ' AM' : ' PM'));
}
function formatNumber(value) {
return (value < 10 ? '0' : '') + value;
}
function timeToDate(input, settings) {
return (typeof input == 'object') ? normaliseTime(input) : timeStringToDate(input, settings);
}
function timeStringToDate(input, settings) {
if (input) {
var array = input.split(settings.separator);
var hours = parseFloat(array[0]);
var minutes = parseFloat(array[1]);
// Convert AM/PM hour to 24-hour format.
if (!settings.show24Hours) {
if (hours === 12 && input.indexOf('AM') !== -1) {
hours = 0;
}
else if (hours !== 12 && input.indexOf('PM') !== -1) {
hours += 12;
}
}
var time = new Date(0, 0, 0, hours, minutes, 0);
return normaliseTime(time);
}
return null;
}
/* Normalise time object to a common date. */
function normaliseTime(time) {
time.setFullYear(2001);
time.setMonth(0);
time.setDate(0);
return time;
}
})(jQuery);

View file

@ -0,0 +1 @@
(function(a){function g(a){a.setFullYear(2001),a.setMonth(0),a.setDate(0);return a}function f(a,b){if(a){var c=a.split(b.separator),d=parseFloat(c[0]),e=parseFloat(c[1]);b.show24Hours||(d===12&&a.indexOf("AM")!==-1?d=0:d!==12&&a.indexOf("PM")!==-1&&(d+=12));var f=new Date(0,0,0,d,e,0);return g(f)}return null}function e(a,b){return typeof a=="object"?g(a):f(a,b)}function d(a){return(a<10?"0":"")+a}function c(a,b){var c=a.getHours(),e=b.show24Hours?c:(c+11)%12+1,f=a.getMinutes();return d(e)+b.separator+d(f)+(b.show24Hours?"":c<12?" AM":" PM")}function b(b,c,d,e){b.value=a(c).text(),a(b).change(),a.browser.msie||b.focus(),d.hide()}a.fn.timePicker=function(b){var c=a.extend({},a.fn.timePicker.defaults,b);return this.each(function(){a.timePicker(this,c)})},a.timePicker=function(b,c){var d=a(b)[0];return d.timePicker||(d.timePicker=new jQuery._timePicker(d,c))},a.timePicker.version="0.3",a._timePicker=function(d,h){var i=!1,j=!1,k=e(h.startTime,h),l=e(h.endTime,h),m="selected",n="li."+m;a(d).attr("autocomplete","OFF");var o=[],p=new Date(k);while(p<=l)o[o.length]=c(p,h),p=new Date(p.setMinutes(p.getMinutes()+h.step));var q=a('<div class="time-picker'+(h.show24Hours?"":" time-picker-12hours")+'"></div>'),r=a("<ul></ul>");for(var s=0;s<o.length;s++)r.append("<li>"+o[s]+"</li>");q.append(r),q.appendTo("body").hide(),q.mouseover(function(){i=!0}).mouseout(function(){i=!1}),a("li",r).mouseover(function(){j||(a(n,q).removeClass(m),a(this).addClass(m))}).mousedown(function(){i=!0}).click(function(){b(d,this,q,h),i=!1});var t=function(){if(q.is(":visible"))return!1;a("li",q).removeClass(m);var b=a(d).offset();q.css({top:b.top+d.offsetHeight,left:b.left}),q.show();var e=d.value?f(d.value,h):k,i=k.getHours()*60+k.getMinutes(),j=e.getHours()*60+e.getMinutes()-i,n=Math.round(j/h.step),o=g(new Date(0,0,0,0,n*h.step+i,0));o=k<o&&o<=l?o:k;var p=a("li:contains("+c(o,h)+")",q);p.length&&(p.addClass(m),q[0].scrollTop=p[0].offsetTop);return!0};a(d).focus(t).click(t),a(d).blur(function(){i||q.hide()});var u=a.browser.opera||a.browser.mozilla?"keypress":"keydown";a(d)[u](function(c){var e;j=!0;var f=q[0].scrollTop;switch(c.keyCode){case 38:if(t())return!1;e=a(n,r);var g=e.prev().addClass(m)[0];g?(e.removeClass(m),g.offsetTop<f&&(q[0].scrollTop=f-g.offsetHeight)):(e.removeClass(m),g=a("li:last",r).addClass(m)[0],q[0].scrollTop=g.offsetTop-g.offsetHeight);return!1;case 40:if(t())return!1;e=a(n,r);var i=e.next().addClass(m)[0];i?(e.removeClass(m),i.offsetTop+i.offsetHeight>f+q[0].offsetHeight&&(q[0].scrollTop=f+i.offsetHeight)):(e.removeClass(m),i=a("li:first",r).addClass(m)[0],q[0].scrollTop=0);return!1;case 13:if(q.is(":visible")){var k=a(n,r)[0];b(d,k,q,h)}return!1;case 27:q.hide();return!1}return!0}),a(d).keyup(function(a){j=!1}),this.getTime=function(){return f(d.value,h)},this.setTime=function(b){d.value=c(e(b,h),h),a(d).change()}},a.fn.timePicker.defaults={step:30,startTime:new Date(0,0,0,0,0,0),endTime:new Date(0,0,0,23,30,0),separator:":",show24Hours:!0}})(jQuery)

View file

@ -0,0 +1,29 @@
div.time-picker {
position: absolute;
height: 191px;
width:4em; /* needed for IE */
overflow: auto;
background: #fff;
border: 1px solid #aaa;
z-index: 99;
margin: 0;
}
div.time-picker-12hours {
width:6em; /* needed for IE */
}
div.time-picker ul {
list-style-type: none;
margin: 0;
padding: 0;
}
div.time-picker li {
cursor: pointer;
height: 10px;
font: 12px/1 Helvetica, Arial, sans-serif;
padding: 4px 3px;
}
div.time-picker li.selected {
background: #0063CE;
color: #fff;
}