5 changed files with 1100 additions and 1 deletions
@ -0,0 +1,171 @@ |
|||||||
|
@charset "UTF-8"; |
||||||
|
|
||||||
|
/*! |
||||||
|
* Pikaday |
||||||
|
* Copyright © 2012 David Bushell | BSD & MIT license | http://dbushell.com/ |
||||||
|
*/ |
||||||
|
|
||||||
|
.pika-single { |
||||||
|
z-index: 9999; |
||||||
|
display: block; |
||||||
|
position: relative; |
||||||
|
width: 240px; |
||||||
|
padding: 8px; |
||||||
|
color: #333; |
||||||
|
background: #fff; |
||||||
|
border: 1px solid #ccc; |
||||||
|
border-bottom-color: #bbb; |
||||||
|
font-family: "Helvetica Neue", Helvetica, Arial, sans-serif; |
||||||
|
} |
||||||
|
|
||||||
|
.pika-single.is-hidden { |
||||||
|
display: none; |
||||||
|
} |
||||||
|
|
||||||
|
.pika-single.is-bound { |
||||||
|
position: absolute; |
||||||
|
box-shadow: 0 5px 15px -5px rgba(0,0,0,.5); |
||||||
|
} |
||||||
|
|
||||||
|
.pika-title { |
||||||
|
position: relative; |
||||||
|
text-align: center; |
||||||
|
} |
||||||
|
|
||||||
|
.pika-label { |
||||||
|
display: inline-block; |
||||||
|
*display: inline; |
||||||
|
position: relative; |
||||||
|
z-index: 9999; |
||||||
|
overflow: hidden; |
||||||
|
margin: 0; |
||||||
|
padding: 5px 3px; |
||||||
|
font-size: 14px; |
||||||
|
line-height: 20px; |
||||||
|
font-weight: bold; |
||||||
|
background-color: #fff; |
||||||
|
} |
||||||
|
.pika-title select { |
||||||
|
cursor: pointer; |
||||||
|
position: absolute; |
||||||
|
z-index: 9998; |
||||||
|
margin: 0; |
||||||
|
left: 0; |
||||||
|
top: 5px; |
||||||
|
filter: alpha(opacity=0); |
||||||
|
opacity: 0; |
||||||
|
} |
||||||
|
|
||||||
|
.pika-prev, |
||||||
|
.pika-next { |
||||||
|
display: block; |
||||||
|
cursor: pointer; |
||||||
|
position: relative; |
||||||
|
outline: none; |
||||||
|
border: 0; |
||||||
|
padding: 0; |
||||||
|
width: 20px; |
||||||
|
height: 30px; |
||||||
|
background-color: transparent; |
||||||
|
background-position: center center; |
||||||
|
background-repeat: no-repeat; |
||||||
|
background-size: 75% 75%; |
||||||
|
white-space: nowrap; |
||||||
|
text-indent: 100%; |
||||||
|
overflow: hidden; |
||||||
|
opacity: .5; |
||||||
|
*position: absolute; |
||||||
|
*top: 0; |
||||||
|
} |
||||||
|
|
||||||
|
.pika-prev:hover, |
||||||
|
.pika-next:hover { |
||||||
|
opacity: 1; |
||||||
|
} |
||||||
|
|
||||||
|
.pika-prev, |
||||||
|
.is-rtl .pika-next { |
||||||
|
float: left; |
||||||
|
background-image: url('data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABQAAAAeCAYAAAAsEj5rAAAAUklEQVR42u3VMQoAIBADQf8Pgj+OD9hG2CtONJB2ymQkKe0HbwAP0xucDiQWARITIDEBEnMgMQ8S8+AqBIl6kKgHiXqQqAeJepBo/z38J/U0uAHlaBkBl9I4GwAAAABJRU5ErkJggg=='); |
||||||
|
*left: 0; |
||||||
|
} |
||||||
|
|
||||||
|
.pika-next, |
||||||
|
.is-rtl .pika-prev { |
||||||
|
float: right; |
||||||
|
background-image: url('data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABQAAAAeCAYAAAAsEj5rAAAAU0lEQVR42u3VOwoAMAgE0dwfAnNjU26bYkBCFGwfiL9VVWoO+BJ4Gf3gtsEKKoFBNTCoCAYVwaAiGNQGMUHMkjGbgjk2mIONuXo0nC8XnCf1JXgArVIZAQh5TKYAAAAASUVORK5CYII='); |
||||||
|
*right: 0; |
||||||
|
} |
||||||
|
|
||||||
|
.pika-prev.is-disabled, |
||||||
|
.pika-next.is-disabled { |
||||||
|
cursor: default; |
||||||
|
opacity: .2; |
||||||
|
} |
||||||
|
|
||||||
|
.pika-select { |
||||||
|
display: inline-block; |
||||||
|
*display: inline; |
||||||
|
} |
||||||
|
|
||||||
|
.pika-table { |
||||||
|
width: 100%; |
||||||
|
border-collapse: collapse; |
||||||
|
border-spacing: 0; |
||||||
|
border: 0; |
||||||
|
} |
||||||
|
|
||||||
|
.pika-table th, |
||||||
|
.pika-table td { |
||||||
|
width: 14.285714285714286%; |
||||||
|
} |
||||||
|
|
||||||
|
.pika-table th { |
||||||
|
color: #999; |
||||||
|
font-size: 12px; |
||||||
|
line-height: 25px; |
||||||
|
font-weight: bold; |
||||||
|
text-align: center; |
||||||
|
} |
||||||
|
|
||||||
|
.pika-button { |
||||||
|
cursor: pointer; |
||||||
|
display: block; |
||||||
|
outline: none; |
||||||
|
border: 0; |
||||||
|
margin: 0; |
||||||
|
width: 100%; |
||||||
|
padding: 5px; |
||||||
|
color: #666; |
||||||
|
font-size: 12px; |
||||||
|
line-height: 15px; |
||||||
|
text-align: right; |
||||||
|
background: #f5f5f5; |
||||||
|
} |
||||||
|
|
||||||
|
.is-today .pika-button { |
||||||
|
color: #33aaff; |
||||||
|
font-weight: bold; |
||||||
|
} |
||||||
|
|
||||||
|
.is-selected .pika-button { |
||||||
|
color: #fff; |
||||||
|
font-weight: bold; |
||||||
|
background: #33aaff; |
||||||
|
box-shadow: inset 0 1px 3px #178fe5; |
||||||
|
border-radius: 3px; |
||||||
|
} |
||||||
|
|
||||||
|
.is-disabled .pika-button { |
||||||
|
pointer-events: none; |
||||||
|
cursor: default; |
||||||
|
color: #999; |
||||||
|
opacity: .3; |
||||||
|
} |
||||||
|
|
||||||
|
.pika-button:hover { |
||||||
|
color: #fff !important; |
||||||
|
background: #ff8000 !important; |
||||||
|
box-shadow: none !important; |
||||||
|
border-radius: 3px !important; |
||||||
|
} |
@ -0,0 +1,26 @@ |
|||||||
|
html { margin: 0; padding: 0; } |
||||||
|
body { font-size: 100%; margin: 0; padding: 1.75em; font-family: 'Helvetica Neue', Arial, sans-serif; } |
||||||
|
|
||||||
|
h1 { font-size: 1.75em; margin: 0 0 0.6em 0; } |
||||||
|
h2 { font-size: 1.25em; margin: 0 0 0.6em 0; } |
||||||
|
|
||||||
|
a { color: #2996cc; } |
||||||
|
a:hover { text-decoration: none; } |
||||||
|
|
||||||
|
p { line-height: 1.5em; } |
||||||
|
.small { color: #666; font-size: 0.875em; } |
||||||
|
.large { font-size: 1.25em; } |
||||||
|
|
||||||
|
|
||||||
|
label { |
||||||
|
font-weight: bold; |
||||||
|
} |
||||||
|
|
||||||
|
input[type="text"] { |
||||||
|
margin: 0.5em 0 3em 0; |
||||||
|
padding: 0.5em; |
||||||
|
} |
||||||
|
|
||||||
|
button { |
||||||
|
margin-bottom: 3em; |
||||||
|
} |
@ -0,0 +1,896 @@ |
|||||||
|
/*! |
||||||
|
* Pikaday |
||||||
|
* |
||||||
|
* Copyright © 2013 David Bushell | BSD & MIT license | https://github.com/dbushell/Pikaday
|
||||||
|
*/ |
||||||
|
|
||||||
|
(function (root, factory) |
||||||
|
{ |
||||||
|
'use strict'; |
||||||
|
|
||||||
|
if (typeof define === 'function' && define.amd) { |
||||||
|
// AMD. Register as an anonymous module.
|
||||||
|
define(function (req) |
||||||
|
{ |
||||||
|
// Load moment.js as an optional dependency
|
||||||
|
var id = 'moment'; |
||||||
|
var moment = req.defined && req.defined(id) ? req(id) : undefined; |
||||||
|
return factory(moment || root.moment); |
||||||
|
}); |
||||||
|
} else { |
||||||
|
// Browser global
|
||||||
|
root.Pikaday = factory(root.moment); |
||||||
|
} |
||||||
|
}(this, function (moment) |
||||||
|
{ |
||||||
|
'use strict'; |
||||||
|
|
||||||
|
/** |
||||||
|
* feature detection and helper functions |
||||||
|
*/ |
||||||
|
var hasMoment = typeof moment === 'function', |
||||||
|
|
||||||
|
hasEventListeners = !!window.addEventListener, |
||||||
|
|
||||||
|
document = window.document, |
||||||
|
|
||||||
|
sto = window.setTimeout, |
||||||
|
|
||||||
|
addEvent = function(el, e, callback, capture) |
||||||
|
{ |
||||||
|
if (hasEventListeners) { |
||||||
|
el.addEventListener(e, callback, !!capture); |
||||||
|
} else { |
||||||
|
el.attachEvent('on' + e, callback); |
||||||
|
} |
||||||
|
}, |
||||||
|
|
||||||
|
removeEvent = function(el, e, callback, capture) |
||||||
|
{ |
||||||
|
if (hasEventListeners) { |
||||||
|
el.removeEventListener(e, callback, !!capture); |
||||||
|
} else { |
||||||
|
el.detachEvent('on' + e, callback); |
||||||
|
} |
||||||
|
}, |
||||||
|
|
||||||
|
fireEvent = function(el, eventName, data) |
||||||
|
{ |
||||||
|
var ev; |
||||||
|
|
||||||
|
if (document.createEvent) { |
||||||
|
ev = document.createEvent('HTMLEvents'); |
||||||
|
ev.initEvent(eventName, true, false); |
||||||
|
ev = extend(ev, data); |
||||||
|
el.dispatchEvent(ev); |
||||||
|
} else if (document.createEventObject) { |
||||||
|
ev = document.createEventObject(); |
||||||
|
ev = extend(ev, data); |
||||||
|
el.fireEvent('on' + eventName, ev); |
||||||
|
} |
||||||
|
}, |
||||||
|
|
||||||
|
trim = function(str) |
||||||
|
{ |
||||||
|
return str.trim ? str.trim() : str.replace(/^\s+|\s+$/g,''); |
||||||
|
}, |
||||||
|
|
||||||
|
hasClass = function(el, cn) |
||||||
|
{ |
||||||
|
return (' ' + el.className + ' ').indexOf(' ' + cn + ' ') !== -1; |
||||||
|
}, |
||||||
|
|
||||||
|
addClass = function(el, cn) |
||||||
|
{ |
||||||
|
if (!hasClass(el, cn)) { |
||||||
|
el.className = (el.className === '') ? cn : el.className + ' ' + cn; |
||||||
|
} |
||||||
|
}, |
||||||
|
|
||||||
|
removeClass = function(el, cn) |
||||||
|
{ |
||||||
|
el.className = trim((' ' + el.className + ' ').replace(' ' + cn + ' ', ' ')); |
||||||
|
}, |
||||||
|
|
||||||
|
isArray = function(obj) |
||||||
|
{ |
||||||
|
return (/Array/).test(Object.prototype.toString.call(obj)); |
||||||
|
}, |
||||||
|
|
||||||
|
isDate = function(obj) |
||||||
|
{ |
||||||
|
return (/Date/).test(Object.prototype.toString.call(obj)) && !isNaN(obj.getTime()); |
||||||
|
}, |
||||||
|
|
||||||
|
isLeapYear = function(year) |
||||||
|
{ |
||||||
|
// solution by Matti Virkkunen: http://stackoverflow.com/a/4881951
|
||||||
|
return year % 4 === 0 && year % 100 !== 0 || year % 400 === 0; |
||||||
|
}, |
||||||
|
|
||||||
|
getDaysInMonth = function(year, month) |
||||||
|
{ |
||||||
|
return [31, isLeapYear(year) ? 29 : 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31][month]; |
||||||
|
}, |
||||||
|
|
||||||
|
setToStartOfDay = function(date) |
||||||
|
{ |
||||||
|
if (isDate(date)) date.setHours(0,0,0,0); |
||||||
|
}, |
||||||
|
|
||||||
|
compareDates = function(a,b) |
||||||
|
{ |
||||||
|
// weak date comparison (use setToStartOfDay(date) to ensure correct result)
|
||||||
|
return a.getTime() === b.getTime(); |
||||||
|
}, |
||||||
|
|
||||||
|
extend = function(to, from, overwrite) |
||||||
|
{ |
||||||
|
var prop, hasProp; |
||||||
|
for (prop in from) { |
||||||
|
hasProp = to[prop] !== undefined; |
||||||
|
if (hasProp && typeof from[prop] === 'object' && from[prop].nodeName === undefined) { |
||||||
|
if (isDate(from[prop])) { |
||||||
|
if (overwrite) { |
||||||
|
to[prop] = new Date(from[prop].getTime()); |
||||||
|
} |
||||||
|
} |
||||||
|
else if (isArray(from[prop])) { |
||||||
|
if (overwrite) { |
||||||
|
to[prop] = from[prop].slice(0); |
||||||
|
} |
||||||
|
} else { |
||||||
|
to[prop] = extend({}, from[prop], overwrite); |
||||||
|
} |
||||||
|
} else if (overwrite || !hasProp) { |
||||||
|
to[prop] = from[prop]; |
||||||
|
} |
||||||
|
} |
||||||
|
return to; |
||||||
|
}, |
||||||
|
|
||||||
|
|
||||||
|
/** |
||||||
|
* defaults and localisation |
||||||
|
*/ |
||||||
|
defaults = { |
||||||
|
|
||||||
|
// bind the picker to a form field
|
||||||
|
field: null, |
||||||
|
|
||||||
|
// automatically show/hide the picker on `field` focus (default `true` if `field` is set)
|
||||||
|
bound: undefined, |
||||||
|
|
||||||
|
// the default output format for `.toString()` and `field` value
|
||||||
|
format: 'YYYY-MM-DD', |
||||||
|
|
||||||
|
// the initial date to view when first opened
|
||||||
|
defaultDate: null, |
||||||
|
|
||||||
|
// make the `defaultDate` the initial selected value
|
||||||
|
setDefaultDate: false, |
||||||
|
|
||||||
|
// first day of week (0: Sunday, 1: Monday etc)
|
||||||
|
firstDay: 0, |
||||||
|
|
||||||
|
// the minimum/earliest date that can be selected
|
||||||
|
minDate: null, |
||||||
|
// the maximum/latest date that can be selected
|
||||||
|
maxDate: null, |
||||||
|
|
||||||
|
// number of years either side, or array of upper/lower range
|
||||||
|
yearRange: 10, |
||||||
|
|
||||||
|
// used internally (don't config outside)
|
||||||
|
minYear: 0, |
||||||
|
maxYear: 9999, |
||||||
|
minMonth: undefined, |
||||||
|
maxMonth: undefined, |
||||||
|
|
||||||
|
isRTL: false, |
||||||
|
|
||||||
|
// Additional text to append to the year in the calendar title
|
||||||
|
yearSuffix: '', |
||||||
|
|
||||||
|
// Render the month after year in the calendar title
|
||||||
|
showMonthAfterYear: false, |
||||||
|
|
||||||
|
// how many months are visible (not implemented yet)
|
||||||
|
numberOfMonths: 1, |
||||||
|
|
||||||
|
// internationalization
|
||||||
|
i18n: { |
||||||
|
previousMonth : 'Previous Month', |
||||||
|
nextMonth : 'Next Month', |
||||||
|
months : ['January','February','March','April','May','June','July','August','September','October','November','December'], |
||||||
|
weekdays : ['Sunday','Monday','Tuesday','Wednesday','Thursday','Friday','Saturday'], |
||||||
|
weekdaysShort : ['Sun','Mon','Tue','Wed','Thu','Fri','Sat'] |
||||||
|
}, |
||||||
|
|
||||||
|
// callback function
|
||||||
|
onSelect: null, |
||||||
|
onOpen: null, |
||||||
|
onClose: null, |
||||||
|
onDraw: null |
||||||
|
}, |
||||||
|
|
||||||
|
|
||||||
|
/** |
||||||
|
* templating functions to abstract HTML rendering |
||||||
|
*/ |
||||||
|
renderDayName = function(opts, day, abbr) |
||||||
|
{ |
||||||
|
day += opts.firstDay; |
||||||
|
while (day >= 7) { |
||||||
|
day -= 7; |
||||||
|
} |
||||||
|
return abbr ? opts.i18n.weekdaysShort[day] : opts.i18n.weekdays[day]; |
||||||
|
}, |
||||||
|
|
||||||
|
renderDay = function(i, isSelected, isToday, isDisabled, isEmpty) |
||||||
|
{ |
||||||
|
if (isEmpty) { |
||||||
|
return '<td class="is-empty"></td>'; |
||||||
|
} |
||||||
|
var arr = []; |
||||||
|
if (isDisabled) { |
||||||
|
arr.push('is-disabled'); |
||||||
|
} |
||||||
|
if (isToday) { |
||||||
|
arr.push('is-today'); |
||||||
|
} |
||||||
|
if (isSelected) { |
||||||
|
arr.push('is-selected'); |
||||||
|
} |
||||||
|
return '<td data-day="' + i + '" class="' + arr.join(' ') + '"><button class="pika-button" type="button">' + i + '</button>' + '</td>'; |
||||||
|
}, |
||||||
|
|
||||||
|
renderRow = function(days, isRTL) |
||||||
|
{ |
||||||
|
return '<tr>' + (isRTL ? days.reverse() : days).join('') + '</tr>'; |
||||||
|
}, |
||||||
|
|
||||||
|
renderBody = function(rows) |
||||||
|
{ |
||||||
|
return '<tbody>' + rows.join('') + '</tbody>'; |
||||||
|
}, |
||||||
|
|
||||||
|
renderHead = function(opts) |
||||||
|
{ |
||||||
|
var i, arr = []; |
||||||
|
for (i = 0; i < 7; i++) { |
||||||
|
arr.push('<th scope="col"><abbr title="' + renderDayName(opts, i) + '">' + renderDayName(opts, i, true) + '</abbr></th>'); |
||||||
|
} |
||||||
|
return '<thead>' + (opts.isRTL ? arr.reverse() : arr).join('') + '</thead>'; |
||||||
|
}, |
||||||
|
|
||||||
|
renderTitle = function(instance) |
||||||
|
{ |
||||||
|
var i, j, arr, |
||||||
|
opts = instance._o, |
||||||
|
month = instance._m, |
||||||
|
year = instance._y, |
||||||
|
isMinYear = year === opts.minYear, |
||||||
|
isMaxYear = year === opts.maxYear, |
||||||
|
html = '<div class="pika-title">', |
||||||
|
monthHtml, |
||||||
|
yearHtml, |
||||||
|
prev = true, |
||||||
|
next = true; |
||||||
|
|
||||||
|
for (arr = [], i = 0; i < 12; i++) { |
||||||
|
arr.push('<option value="' + i + '"' + |
||||||
|
(i === month ? ' selected': '') + |
||||||
|
((isMinYear && i < opts.minMonth) || (isMaxYear && i > opts.maxMonth) ? 'disabled' : '') + '>' + |
||||||
|
opts.i18n.months[i] + '</option>'); |
||||||
|
} |
||||||
|
monthHtml = '<div class="pika-label">' + opts.i18n.months[month] + '<select class="pika-select pika-select-month">' + arr.join('') + '</select></div>'; |
||||||
|
|
||||||
|
if (isArray(opts.yearRange)) { |
||||||
|
i = opts.yearRange[0]; |
||||||
|
j = opts.yearRange[1] + 1; |
||||||
|
} else { |
||||||
|
i = year - opts.yearRange; |
||||||
|
j = 1 + year + opts.yearRange; |
||||||
|
} |
||||||
|
|
||||||
|
for (arr = []; i < j && i <= opts.maxYear; i++) { |
||||||
|
if (i >= opts.minYear) { |
||||||
|
arr.push('<option value="' + i + '"' + (i === year ? ' selected': '') + '>' + (i) + '</option>'); |
||||||
|
} |
||||||
|
} |
||||||
|
yearHtml = '<div class="pika-label">' + year + opts.yearSuffix + '<select class="pika-select pika-select-year">' + arr.join('') + '</select></div>'; |
||||||
|
|
||||||
|
if (opts.showMonthAfterYear) { |
||||||
|
html += yearHtml + monthHtml; |
||||||
|
} else { |
||||||
|
html += monthHtml + yearHtml; |
||||||
|
} |
||||||
|
|
||||||
|
if (isMinYear && (month === 0 || opts.minMonth >= month)) { |
||||||
|
prev = false; |
||||||
|
} |
||||||
|
|
||||||
|
if (isMaxYear && (month === 11 || opts.maxMonth <= month)) { |
||||||
|
next = false; |
||||||
|
} |
||||||
|
|
||||||
|
html += '<button class="pika-prev' + (prev ? '' : ' is-disabled') + '" type="button">' + opts.i18n.previousMonth + '</button>'; |
||||||
|
html += '<button class="pika-next' + (next ? '' : ' is-disabled') + '" type="button">' + opts.i18n.nextMonth + '</button>'; |
||||||
|
|
||||||
|
return html += '</div>'; |
||||||
|
}, |
||||||
|
|
||||||
|
renderTable = function(opts, data) |
||||||
|
{ |
||||||
|
return '<table cellpadding="0" cellspacing="0" class="pika-table">' + renderHead(opts) + renderBody(data) + '</table>'; |
||||||
|
}, |
||||||
|
|
||||||
|
|
||||||
|
/** |
||||||
|
* Pikaday constructor |
||||||
|
*/ |
||||||
|
Pikaday = function(options) |
||||||
|
{ |
||||||
|
var self = this, |
||||||
|
opts = self.config(options); |
||||||
|
|
||||||
|
self._onMouseDown = function(e) |
||||||
|
{ |
||||||
|
if (!self._v) { |
||||||
|
return; |
||||||
|
} |
||||||
|
e = e || window.event; |
||||||
|
var target = e.target || e.srcElement; |
||||||
|
if (!target) { |
||||||
|
return; |
||||||
|
} |
||||||
|
|
||||||
|
if (!hasClass(target, 'is-disabled')) { |
||||||
|
if (hasClass(target, 'pika-button') && !hasClass(target, 'is-empty')) { |
||||||
|
self.setDate(new Date(self._y, self._m, parseInt(target.innerHTML, 10))); |
||||||
|
if (opts.bound) { |
||||||
|
sto(function() { |
||||||
|
self.hide(); |
||||||
|
}, 100); |
||||||
|
} |
||||||
|
return; |
||||||
|
} |
||||||
|
else if (hasClass(target, 'pika-prev')) { |
||||||
|
self.prevMonth(); |
||||||
|
} |
||||||
|
else if (hasClass(target, 'pika-next')) { |
||||||
|
self.nextMonth(); |
||||||
|
} |
||||||
|
} |
||||||
|
if (!hasClass(target, 'pika-select')) { |
||||||
|
if (e.preventDefault) { |
||||||
|
e.preventDefault(); |
||||||
|
} else { |
||||||
|
e.returnValue = false; |
||||||
|
return false; |
||||||
|
} |
||||||
|
} else { |
||||||
|
self._c = true; |
||||||
|
} |
||||||
|
}; |
||||||
|
|
||||||
|
self._onChange = function(e) |
||||||
|
{ |
||||||
|
e = e || window.event; |
||||||
|
var target = e.target || e.srcElement; |
||||||
|
if (!target) { |
||||||
|
return; |
||||||
|
} |
||||||
|
if (hasClass(target, 'pika-select-month')) { |
||||||
|
self.gotoMonth(target.value); |
||||||
|
} |
||||||
|
else if (hasClass(target, 'pika-select-year')) { |
||||||
|
self.gotoYear(target.value); |
||||||
|
} |
||||||
|
}; |
||||||
|
|
||||||
|
self._onInputChange = function(e) |
||||||
|
{ |
||||||
|
var date; |
||||||
|
|
||||||
|
if (e.firedBy === self) { |
||||||
|
return; |
||||||
|
} |
||||||
|
if (hasMoment) { |
||||||
|
date = moment(opts.field.value, opts.format); |
||||||
|
date = (date && date.isValid()) ? date.toDate() : null; |
||||||
|
} |
||||||
|
else { |
||||||
|
date = new Date(Date.parse(opts.field.value)); |
||||||
|
} |
||||||
|
self.setDate(isDate(date) ? date : null); |
||||||
|
if (!self._v) { |
||||||
|
self.show(); |
||||||
|
} |
||||||
|
}; |
||||||
|
|
||||||
|
self._onInputFocus = function() |
||||||
|
{ |
||||||
|
self.show(); |
||||||
|
}; |
||||||
|
|
||||||
|
self._onInputClick = function() |
||||||
|
{ |
||||||
|
self.show(); |
||||||
|
}; |
||||||
|
|
||||||
|
self._onInputBlur = function() |
||||||
|
{ |
||||||
|
if (!self._c) { |
||||||
|
self._b = sto(function() { |
||||||
|
self.hide(); |
||||||
|
}, 50); |
||||||
|
} |
||||||
|
self._c = false; |
||||||
|
}; |
||||||
|
|
||||||
|
self._onClick = function(e) |
||||||
|
{ |
||||||
|
e = e || window.event; |
||||||
|
var target = e.target || e.srcElement, |
||||||
|
pEl = target; |
||||||
|
if (!target) { |
||||||
|
return; |
||||||
|
} |
||||||
|
if (!hasEventListeners && hasClass(target, 'pika-select')) { |
||||||
|
if (!target.onchange) { |
||||||
|
target.setAttribute('onchange', 'return;'); |
||||||
|
addEvent(target, 'change', self._onChange); |
||||||
|
} |
||||||
|
} |
||||||
|
do { |
||||||
|
if (hasClass(pEl, 'pika-single')) { |
||||||
|
return; |
||||||
|
} |
||||||
|
} |
||||||
|
while ((pEl = pEl.parentNode)); |
||||||
|
if (self._v && target !== opts.trigger) { |
||||||
|
self.hide(); |
||||||
|
} |
||||||
|
}; |
||||||
|
|
||||||
|
self.el = document.createElement('div'); |
||||||
|
self.el.className = 'pika-single' + (opts.isRTL ? ' is-rtl' : ''); |
||||||
|
|
||||||
|
addEvent(self.el, 'mousedown', self._onMouseDown, true); |
||||||
|
addEvent(self.el, 'change', self._onChange); |
||||||
|
|
||||||
|
if (opts.field) { |
||||||
|
if (opts.bound) { |
||||||
|
document.body.appendChild(self.el); |
||||||
|
} else { |
||||||
|
opts.field.parentNode.insertBefore(self.el, opts.field.nextSibling); |
||||||
|
} |
||||||
|
addEvent(opts.field, 'change', self._onInputChange); |
||||||
|
|
||||||
|
if (!opts.defaultDate) { |
||||||
|
if (hasMoment && opts.field.value) { |
||||||
|
opts.defaultDate = moment(opts.field.value, opts.format).toDate(); |
||||||
|
} else { |
||||||
|
opts.defaultDate = new Date(Date.parse(opts.field.value)); |
||||||
|
} |
||||||
|
opts.setDefaultDate = true; |
||||||
|
} |
||||||
|
} |
||||||
|
|
||||||
|
var defDate = opts.defaultDate; |
||||||
|
|
||||||
|
if (isDate(defDate)) { |
||||||
|
if (opts.setDefaultDate) { |
||||||
|
self.setDate(defDate, true); |
||||||
|
} else { |
||||||
|
self.gotoDate(defDate); |
||||||
|
} |
||||||
|
} else { |
||||||
|
self.gotoDate(new Date()); |
||||||
|
} |
||||||
|
|
||||||
|
if (opts.bound) { |
||||||
|
this.hide(); |
||||||
|
self.el.className += ' is-bound'; |
||||||
|
addEvent(opts.trigger, 'click', self._onInputClick); |
||||||
|
addEvent(opts.trigger, 'focus', self._onInputFocus); |
||||||
|
addEvent(opts.trigger, 'blur', self._onInputBlur); |
||||||
|
} else { |
||||||
|
this.show(); |
||||||
|
} |
||||||
|
|
||||||
|
}; |
||||||
|
|
||||||
|
|
||||||
|
/** |
||||||
|
* public Pikaday API |
||||||
|
*/ |
||||||
|
Pikaday.prototype = { |
||||||
|
|
||||||
|
|
||||||
|
/** |
||||||
|
* configure functionality |
||||||
|
*/ |
||||||
|
config: function(options) |
||||||
|
{ |
||||||
|
if (!this._o) { |
||||||
|
this._o = extend({}, defaults, true); |
||||||
|
} |
||||||
|
|
||||||
|
var opts = extend(this._o, options, true); |
||||||
|
|
||||||
|
opts.isRTL = !!opts.isRTL; |
||||||
|
|
||||||
|
opts.field = (opts.field && opts.field.nodeName) ? opts.field : null; |
||||||
|
|
||||||
|
opts.bound = !!(opts.bound !== undefined ? opts.field && opts.bound : opts.field); |
||||||
|
|
||||||
|
opts.trigger = (opts.trigger && opts.trigger.nodeName) ? opts.trigger : opts.field; |
||||||
|
|
||||||
|
var nom = parseInt(opts.numberOfMonths, 10) || 1; |
||||||
|
opts.numberOfMonths = nom > 4 ? 4 : nom; |
||||||
|
|
||||||
|
if (!isDate(opts.minDate)) { |
||||||
|
opts.minDate = false; |
||||||
|
} |
||||||
|
if (!isDate(opts.maxDate)) { |
||||||
|
opts.maxDate = false; |
||||||
|
} |
||||||
|
if ((opts.minDate && opts.maxDate) && opts.maxDate < opts.minDate) { |
||||||
|
opts.maxDate = opts.minDate = false; |
||||||
|
} |
||||||
|
if (opts.minDate) { |
||||||
|
setToStartOfDay(opts.minDate); |
||||||
|
opts.minYear = opts.minDate.getFullYear(); |
||||||
|
opts.minMonth = opts.minDate.getMonth(); |
||||||
|
} |
||||||
|
if (opts.maxDate) { |
||||||
|
setToStartOfDay(opts.maxDate); |
||||||
|
opts.maxYear = opts.maxDate.getFullYear(); |
||||||
|
opts.maxMonth = opts.maxDate.getMonth(); |
||||||
|
} |
||||||
|
|
||||||
|
if (isArray(opts.yearRange)) { |
||||||
|
var fallback = new Date().getFullYear() - 10; |
||||||
|
opts.yearRange[0] = parseInt(opts.yearRange[0], 10) || fallback; |
||||||
|
opts.yearRange[1] = parseInt(opts.yearRange[1], 10) || fallback; |
||||||
|
} else { |
||||||
|
opts.yearRange = Math.abs(parseInt(opts.yearRange, 10)) || defaults.yearRange; |
||||||
|
if (opts.yearRange > 100) { |
||||||
|
opts.yearRange = 100; |
||||||
|
} |
||||||
|
} |
||||||
|
|
||||||
|
return opts; |
||||||
|
}, |
||||||
|
|
||||||
|
/** |
||||||
|
* return a formatted string of the current selection (using Moment.js if available) |
||||||
|
*/ |
||||||
|
toString: function(format) |
||||||
|
{ |
||||||
|
return !isDate(this._d) ? '' : hasMoment ? moment(this._d).format(format || this._o.format) : this._d.toDateString(); |
||||||
|
}, |
||||||
|
|
||||||
|
/** |
||||||
|
* return a Moment.js object of the current selection (if available) |
||||||
|
*/ |
||||||
|
getMoment: function() |
||||||
|
{ |
||||||
|
return hasMoment ? moment(this._d) : null; |
||||||
|
}, |
||||||
|
|
||||||
|
/** |
||||||
|
* set the current selection from a Moment.js object (if available) |
||||||
|
*/ |
||||||
|
setMoment: function(date) |
||||||
|
{ |
||||||
|
if (hasMoment && moment.isMoment(date)) { |
||||||
|
this.setDate(date.toDate()); |
||||||
|
} |
||||||
|
}, |
||||||
|
|
||||||
|
/** |
||||||
|
* return a Date object of the current selection |
||||||
|
*/ |
||||||
|
getDate: function() |
||||||
|
{ |
||||||
|
return isDate(this._d) ? new Date(this._d.getTime()) : null; |
||||||
|
}, |
||||||
|
|
||||||
|
/** |
||||||
|
* set the current selection |
||||||
|
*/ |
||||||
|
setDate: function(date, preventOnSelect) |
||||||
|
{ |
||||||
|
if (!date) { |
||||||
|
this._d = null; |
||||||
|
return this.draw(); |
||||||
|
} |
||||||
|
if (typeof date === 'string') { |
||||||
|
date = new Date(Date.parse(date)); |
||||||
|
} |
||||||
|
if (!isDate(date)) { |
||||||
|
return; |
||||||
|
} |
||||||
|
|
||||||
|
var min = this._o.minDate, |
||||||
|
max = this._o.maxDate; |
||||||
|
|
||||||
|
if (isDate(min) && date < min) { |
||||||
|
date = min; |
||||||
|
} else if (isDate(max) && date > max) { |
||||||
|
date = max; |
||||||
|
} |
||||||
|
|
||||||
|
this._d = new Date(date.getTime()); |
||||||
|
setToStartOfDay(this._d); |
||||||
|
this.gotoDate(this._d); |
||||||
|
|
||||||
|
if (this._o.field) { |
||||||
|
this._o.field.value = this.toString(); |
||||||
|
fireEvent(this._o.field, 'change', { firedBy: this }); |
||||||
|
} |
||||||
|
if (!preventOnSelect && typeof this._o.onSelect === 'function') { |
||||||
|
this._o.onSelect.call(this, this.getDate()); |
||||||
|
} |
||||||
|
}, |
||||||
|
|
||||||
|
/** |
||||||
|
* change view to a specific date |
||||||
|
*/ |
||||||
|
gotoDate: function(date) |
||||||
|
{ |
||||||
|
if (!isDate(date)) { |
||||||
|
return; |
||||||
|
} |
||||||
|
this._y = date.getFullYear(); |
||||||
|
this._m = date.getMonth(); |
||||||
|
this.draw(); |
||||||
|
}, |
||||||
|
|
||||||
|
gotoToday: function() |
||||||
|
{ |
||||||
|
this.gotoDate(new Date()); |
||||||
|
}, |
||||||
|
|
||||||
|
/** |
||||||
|
* change view to a specific month (zero-index, e.g. 0: January) |
||||||
|
*/ |
||||||
|
gotoMonth: function(month) |
||||||
|
{ |
||||||
|
if (!isNaN( (month = parseInt(month, 10)) )) { |
||||||
|
this._m = month < 0 ? 0 : month > 11 ? 11 : month; |
||||||
|
this.draw(); |
||||||
|
} |
||||||
|
}, |
||||||
|
|
||||||
|
nextMonth: function() |
||||||
|
{ |
||||||
|
if (++this._m > 11) { |
||||||
|
this._m = 0; |
||||||
|
this._y++; |
||||||
|
} |
||||||
|
this.draw(); |
||||||
|
}, |
||||||
|
|
||||||
|
prevMonth: function() |
||||||
|
{ |
||||||
|
if (--this._m < 0) { |
||||||
|
this._m = 11; |
||||||
|
this._y--; |
||||||
|
} |
||||||
|
this.draw(); |
||||||
|
}, |
||||||
|
|
||||||
|
/** |
||||||
|
* change view to a specific full year (e.g. "2012") |
||||||
|
*/ |
||||||
|
gotoYear: function(year) |
||||||
|
{ |
||||||
|
if (!isNaN(year)) { |
||||||
|
this._y = parseInt(year, 10); |
||||||
|
this.draw(); |
||||||
|
} |
||||||
|
}, |
||||||
|
|
||||||
|
/** |
||||||
|
* change the minDate |
||||||
|
*/ |
||||||
|
setMinDate: function(value) |
||||||
|
{ |
||||||
|
this._o.minDate = value; |
||||||
|
}, |
||||||
|
|
||||||
|
/** |
||||||
|
* change the maxDate |
||||||
|
*/ |
||||||
|
setMaxDate: function(value) |
||||||
|
{ |
||||||
|
this._o.maxDate = value; |
||||||
|
}, |
||||||
|
|
||||||
|
/** |
||||||
|
* refresh the HTML |
||||||
|
*/ |
||||||
|
draw: function(force) |
||||||
|
{ |
||||||
|
if (!this._v && !force) { |
||||||
|
return; |
||||||
|
} |
||||||
|
var opts = this._o, |
||||||
|
minYear = opts.minYear, |
||||||
|
maxYear = opts.maxYear, |
||||||
|
minMonth = opts.minMonth, |
||||||
|
maxMonth = opts.maxMonth; |
||||||
|
|
||||||
|
if (this._y <= minYear) { |
||||||
|
this._y = minYear; |
||||||
|
if (!isNaN(minMonth) && this._m < minMonth) { |
||||||
|
this._m = minMonth; |
||||||
|
} |
||||||
|
} |
||||||
|
if (this._y >= maxYear) { |
||||||
|
this._y = maxYear; |
||||||
|
if (!isNaN(maxMonth) && this._m > maxMonth) { |
||||||
|
this._m = maxMonth; |
||||||
|
} |
||||||
|
} |
||||||
|
|
||||||
|
this.el.innerHTML = renderTitle(this) + this.render(this._y, this._m); |
||||||
|
|
||||||
|
if (opts.bound) { |
||||||
|
this.adjustPosition(); |
||||||
|
if(opts.field.type !== 'hidden') { |
||||||
|
sto(function() { |
||||||
|
opts.trigger.focus(); |
||||||
|
}, 1); |
||||||
|
} |
||||||
|
} |
||||||
|
|
||||||
|
if (typeof this._o.onDraw === 'function') { |
||||||
|
var self = this; |
||||||
|
sto(function() { |
||||||
|
self._o.onDraw.call(self); |
||||||
|
}, 0); |
||||||
|
} |
||||||
|
}, |
||||||
|
|
||||||
|
adjustPosition: function() |
||||||
|
{ |
||||||
|
var field = this._o.trigger, pEl = field, |
||||||
|
width = this.el.offsetWidth, height = this.el.offsetHeight, |
||||||
|
viewportWidth = window.innerWidth || document.documentElement.clientWidth, |
||||||
|
viewportHeight = window.innerHeight || document.documentElement.clientHeight, |
||||||
|
scrollTop = window.pageYOffset || document.body.scrollTop || document.documentElement.scrollTop, |
||||||
|
left, top, clientRect; |
||||||
|
|
||||||
|
if (typeof field.getBoundingClientRect === 'function') { |
||||||
|
clientRect = field.getBoundingClientRect(); |
||||||
|
left = clientRect.left + window.pageXOffset; |
||||||
|
top = clientRect.bottom + window.pageYOffset; |
||||||
|
} else { |
||||||
|
left = pEl.offsetLeft; |
||||||
|
top = pEl.offsetTop + pEl.offsetHeight; |
||||||
|
while((pEl = pEl.offsetParent)) { |
||||||
|
left += pEl.offsetLeft; |
||||||
|
top += pEl.offsetTop; |
||||||
|
} |
||||||
|
} |
||||||
|
|
||||||
|
if (left + width > viewportWidth) { |
||||||
|
left = left - width + field.offsetWidth; |
||||||
|
} |
||||||
|
if (top + height > viewportHeight + scrollTop) { |
||||||
|
top = top - height - field.offsetHeight; |
||||||
|
} |
||||||
|
this.el.style.cssText = 'position:absolute;left:' + left + 'px;top:' + top + 'px;'; |
||||||
|
}, |
||||||
|
|
||||||
|
/** |
||||||
|
* render HTML for a particular month |
||||||
|
*/ |
||||||
|
render: function(year, month) |
||||||
|
{ |
||||||
|
var opts = this._o, |
||||||
|
now = new Date(), |
||||||
|
days = getDaysInMonth(year, month), |
||||||
|
before = new Date(year, month, 1).getDay(), |
||||||
|
data = [], |
||||||
|
row = []; |
||||||
|
setToStartOfDay(now); |
||||||
|
if (opts.firstDay > 0) { |
||||||
|
before -= opts.firstDay; |
||||||
|
if (before < 0) { |
||||||
|
before += 7; |
||||||
|
} |
||||||
|
} |
||||||
|
var cells = days + before, |
||||||
|
after = cells; |
||||||
|
while(after > 7) { |
||||||
|
after -= 7; |
||||||
|
} |
||||||
|
cells += 7 - after; |
||||||
|
for (var i = 0, r = 0; i < cells; i++) |
||||||
|
{ |
||||||
|
var day = new Date(year, month, 1 + (i - before)), |
||||||
|
isDisabled = (opts.minDate && day < opts.minDate) || (opts.maxDate && day > opts.maxDate), |
||||||
|
isSelected = isDate(this._d) ? compareDates(day, this._d) : false, |
||||||
|
isToday = compareDates(day, now), |
||||||
|
isEmpty = i < before || i >= (days + before); |
||||||
|
|
||||||
|
row.push(renderDay(1 + (i - before), isSelected, isToday, isDisabled, isEmpty)); |
||||||
|
|
||||||
|
if (++r === 7) { |
||||||
|
data.push(renderRow(row, opts.isRTL)); |
||||||
|
row = []; |
||||||
|
r = 0; |
||||||
|
} |
||||||
|
} |
||||||
|
return renderTable(opts, data); |
||||||
|
}, |
||||||
|
|
||||||
|
isVisible: function() |
||||||
|
{ |
||||||
|
return this._v; |
||||||
|
}, |
||||||
|
|
||||||
|
show: function() |
||||||
|
{ |
||||||
|
if (!this._v) { |
||||||
|
if (this._o.bound) { |
||||||
|
addEvent(document, 'click', this._onClick); |
||||||
|
} |
||||||
|
removeClass(this.el, 'is-hidden'); |
||||||
|
this._v = true; |
||||||
|
this.draw(); |
||||||
|
if (typeof this._o.onOpen === 'function') { |
||||||
|
this._o.onOpen.call(this); |
||||||
|
} |
||||||
|
} |
||||||
|
}, |
||||||
|
|
||||||
|
hide: function() |
||||||
|
{ |
||||||
|
var v = this._v; |
||||||
|
if (v !== false) { |
||||||
|
if (this._o.bound) { |
||||||
|
removeEvent(document, 'click', this._onClick); |
||||||
|
} |
||||||
|
this.el.style.cssText = ''; |
||||||
|
addClass(this.el, 'is-hidden'); |
||||||
|
this._v = false; |
||||||
|
if (v !== undefined && typeof this._o.onClose === 'function') { |
||||||
|
this._o.onClose.call(this); |
||||||
|
} |
||||||
|
} |
||||||
|
}, |
||||||
|
|
||||||
|
/** |
||||||
|
* GAME OVER |
||||||
|
*/ |
||||||
|
destroy: function() |
||||||
|
{ |
||||||
|
this.hide(); |
||||||
|
removeEvent(this.el, 'mousedown', this._onMouseDown, true); |
||||||
|
removeEvent(this.el, 'change', this._onChange); |
||||||
|
if (this._o.field) { |
||||||
|
removeEvent(this._o.field, 'change', this._onInputChange); |
||||||
|
if (this._o.bound) { |
||||||
|
removeEvent(this._o.trigger, 'click', this._onInputClick); |
||||||
|
removeEvent(this._o.trigger, 'focus', this._onInputFocus); |
||||||
|
removeEvent(this._o.trigger, 'blur', this._onInputBlur); |
||||||
|
} |
||||||
|
} |
||||||
|
if (this.el.parentNode) { |
||||||
|
this.el.parentNode.removeChild(this.el); |
||||||
|
} |
||||||
|
} |
||||||
|
|
||||||
|
}; |
||||||
|
|
||||||
|
return Pikaday; |
||||||
|
|
||||||
|
})); |
Loading…
Reference in new issue