123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658 |
- /*jslint eqeq: true, plusplus: true, undef: true, sloppy: true, vars: true, forin: true */
- (function ($) {
- var ms = $.mobiscroll,
- date = new Date(),
- defaults = {
- dateFormat: 'mm/dd/yy',
- dateOrder: 'mmddy',
- timeWheels: 'hhiiA',
- timeFormat: 'hh:ii A',
- startYear: date.getFullYear() - 100,
- endYear: date.getFullYear() + 1,
- monthNames: ['January', 'February', 'March', 'April', 'May', 'June', 'July', 'August', 'September', 'October', 'November', 'December'],
- monthNamesShort: ['Jan', 'Feb', 'Mar', 'Apr', 'May', 'Jun', 'Jul', 'Aug', 'Sep', 'Oct', 'Nov', 'Dec'],
- dayNames: ['Sunday', 'Monday', 'Tuesday', 'Wednesday', 'Thursday', 'Friday', 'Saturday'],
- dayNamesShort: ['Sun', 'Mon', 'Tue', 'Wed', 'Thu', 'Fri', 'Sat'],
- shortYearCutoff: '+10',
- monthText: 'Month',
- dayText: 'Day',
- yearText: 'Year',
- hourText: 'Hours',
- minuteText: 'Minutes',
- secText: 'Seconds',
- ampmText: ' ',
- nowText: 'Now',
- showNow: false,
- stepHour: 1,
- stepMinute: 1,
- stepSecond: 1,
- separator: ' '
- },
- preset = function (inst) {
- var that = $(this),
- html5def = {},
- format;
- // Force format for html5 date inputs (experimental)
- if (that.is('input')) {
- switch (that.attr('type')) {
- case 'date':
- format = 'yy-mm-dd';
- break;
- case 'datetime':
- format = 'yy-mm-ddTHH:ii:ssZ';
- break;
- case 'datetime-local':
- format = 'yy-mm-ddTHH:ii:ss';
- break;
- case 'month':
- format = 'yy-mm';
- html5def.dateOrder = 'mmyy';
- break;
- case 'time':
- format = 'HH:ii:ss';
- break;
- }
- // Check for min/max attributes
- var min = that.attr('min'),
- max = that.attr('max');
- if (min) {
- html5def.minDate = ms.parseDate(format, min);
- }
- if (max) {
- html5def.maxDate = ms.parseDate(format, max);
- }
- }
- // Set year-month-day order
- var s = $.extend({}, defaults, html5def, inst.settings),
- offset = 0,
- wheels = [],
- ord = [],
- o = {},
- i,
- k,
- f = { y: 'getFullYear', m: 'getMonth', d: 'getDate', h: getHour, i: getMinute, s: getSecond, a: getAmPm },
- p = s.preset,
- dord = s.dateOrder,
- tord = s.timeWheels,
- regen = dord.match(/D/),
- ampm = tord.match(/a/i),
- hampm = tord.match(/h/),
- hformat = p == 'datetime' ? s.dateFormat + s.separator + s.timeFormat : p == 'time' ? s.timeFormat : s.dateFormat,
- defd = new Date(),
- stepH = s.stepHour,
- stepM = s.stepMinute,
- stepS = s.stepSecond,
- mind = s.minDate || new Date(s.startYear, 0, 1),
- maxd = s.maxDate || new Date(s.endYear, 11, 31, 23, 59, 59);
-
- inst.settings = s;
- format = format || hformat;
-
- if (p.match(/date/i)) {
- // Determine the order of year, month, day wheels
- $.each(['y', 'm', 'd'], function (j, v) {
- i = dord.search(new RegExp(v, 'i'));
- if (i > -1) {
- ord.push({ o: i, v: v });
- }
- });
- ord.sort(function (a, b) { return a.o > b.o ? 1 : -1; });
- $.each(ord, function (i, v) {
- o[v.v] = i;
- });
- var w = {};
- for (k = 0; k < 3; k++) {
- if (k == o.y) {
- offset++;
- w[s.yearText] = {};
- var start = mind.getFullYear(),
- end = maxd.getFullYear();
- for (i = start; i <= end; i++) {
- w[s.yearText][i] = dord.match(/yy/i) ? i : (i + '').substr(2, 2);
- }
- } else if (k == o.m) {
- offset++;
- w[s.monthText] = {};
- for (i = 0; i < 12; i++) {
- var str = dord.replace(/[dy]/gi, '').replace(/mm/, i < 9 ? '0' + (i + 1) : i + 1).replace(/m/, (i + 1));
- w[s.monthText][i] = str.match(/MM/) ? str.replace(/MM/, '<span class="dw-mon">' + s.monthNames[i] + '</span>') : str.replace(/M/, '<span class="dw-mon">' + s.monthNamesShort[i] + '</span>');
- }
- } else if (k == o.d) {
- offset++;
- w[s.dayText] = {};
- for (i = 1; i < 32; i++) {
- w[s.dayText][i] = dord.match(/dd/i) && i < 10 ? '0' + i : i;
- }
- }
- }
- wheels.push(w);
- }
- if (p.match(/time/i)) {
- // Determine the order of hours, minutes, seconds wheels
- ord = [];
- $.each(['h', 'i', 's', 'a'], function (i, v) {
- i = tord.search(new RegExp(v, 'i'));
- if (i > -1) {
- ord.push({ o: i, v: v });
- }
- });
- ord.sort(function (a, b) {
- return a.o > b.o ? 1 : -1;
- });
- $.each(ord, function (i, v) {
- o[v.v] = offset + i;
- });
- w = {};
- for (k = offset; k < offset + 4; k++) {
- if (k == o.h) {
- offset++;
- w[s.hourText] = {};
- for (i = 0; i < (hampm ? 12 : 24); i += stepH) {
- w[s.hourText][i] = hampm && i == 0 ? 12 : tord.match(/hh/i) && i < 10 ? '0' + i : i;
- }
- } else if (k == o.i) {
- offset++;
- w[s.minuteText] = {};
- for (i = 0; i < 60; i += stepM) {
- w[s.minuteText][i] = tord.match(/ii/) && i < 10 ? '0' + i : i;
- }
- } else if (k == o.s) {
- offset++;
- w[s.secText] = {};
- for (i = 0; i < 60; i += stepS) {
- w[s.secText][i] = tord.match(/ss/) && i < 10 ? '0' + i : i;
- }
- } else if (k == o.a) {
- offset++;
- var upper = tord.match(/A/);
- w[s.ampmText] = { 0: upper ? 'AM' : 'am', 1: upper ? 'PM' : 'pm' };
- }
-
- }
- wheels.push(w);
- }
- function get(d, i, def) {
- if (o[i] !== undefined) {
- return +d[o[i]];
- }
- if (def !== undefined) {
- return def;
- }
- return defd[f[i]] ? defd[f[i]]() : f[i](defd);
- }
- function step(v, st) {
- return Math.floor(v / st) * st;
- }
- function getHour(d) {
- var hour = d.getHours();
- hour = hampm && hour >= 12 ? hour - 12 : hour;
- return step(hour, stepH);
- }
- function getMinute(d) {
- return step(d.getMinutes(), stepM);
- }
- function getSecond(d) {
- return step(d.getSeconds(), stepS);
- }
- function getAmPm(d) {
- return ampm && d.getHours() > 11 ? 1 : 0;
- }
- function getDate(d) {
- var hour = get(d, 'h', 0);
- return new Date(get(d, 'y'), get(d, 'm'), get(d, 'd', 1), get(d, 'a') ? hour + 12 : hour, get(d, 'i', 0), get(d, 's', 0));
- }
- inst.setDate = function (d, fill, time, temp) {
- var i;
- // Set wheels
- for (i in o) {
- this.temp[o[i]] = d[f[i]] ? d[f[i]]() : f[i](d);
- }
- this.setValue(true, fill, time, temp);
- };
- inst.getDate = function (d) {
- return getDate(d);
- };
- return {
- button3Text: s.showNow ? s.nowText : undefined,
- button3: s.showNow ? function () { inst.setDate(new Date(), false, 0.3, true); } : undefined,
- wheels: wheels,
- headerText: function (v) {
- return ms.formatDate(hformat, getDate(inst.temp), s);
- },
- /**
- * Builds a date object from the wheel selections and formats it to the given date/time format
- * @param {Array} d - An array containing the selected wheel values
- * @return {String} - The formatted date string
- */
- formatResult: function (d) {
- return ms.formatDate(format, getDate(d), s);
- },
- /**
- * Builds a date object from the input value and returns an array to set wheel values
- * @return {Array} - An array containing the wheel values to set
- */
- parseValue: function (val) {
- var d = new Date(),
- i,
- result = [];
- try {
- d = ms.parseDate(format, val, s);
- } catch (e) {
- }
- // Set wheels
- for (i in o) {
- result[o[i]] = d[f[i]] ? d[f[i]]() : f[i](d);
- }
- return result;
- },
- /**
- * Validates the selected date to be in the minDate / maxDate range and sets unselectable values to disabled
- * @param {Object} dw - jQuery object containing the generated html
- * @param {Integer} [i] - Index of the changed wheel, not set for initial validation
- */
- validate: function (dw, i) {
- var temp = inst.temp, //.slice(0),
- mins = { y: mind.getFullYear(), m: 0, d: 1, h: 0, i: 0, s: 0, a: 0 },
- maxs = { y: maxd.getFullYear(), m: 11, d: 31, h: step(hampm ? 11 : 23, stepH), i: step(59, stepM), s: step(59, stepS), a: 1 },
- minprop = true,
- maxprop = true;
- $.each(['y', 'm', 'd', 'a', 'h', 'i', 's'], function (x, i) {
- if (o[i] !== undefined) {
- var min = mins[i],
- max = maxs[i],
- maxdays = 31,
- val = get(temp, i),
- t = $('.dw-ul', dw).eq(o[i]),
- y,
- m;
- if (i == 'd') {
- y = get(temp, 'y');
- m = get(temp, 'm');
- maxdays = 32 - new Date(y, m, 32).getDate();
- max = maxdays;
- if (regen) {
- $('.dw-li', t).each(function () {
- var that = $(this),
- d = that.data('val'),
- w = new Date(y, m, d).getDay(),
- str = dord.replace(/[my]/gi, '').replace(/dd/, d < 10 ? '0' + d : d).replace(/d/, d);
- $('.dw-i', that).html(str.match(/DD/) ? str.replace(/DD/, '<span class="dw-day">' + s.dayNames[w] + '</span>') : str.replace(/D/, '<span class="dw-day">' + s.dayNamesShort[w] + '</span>'));
- });
- }
- }
- if (minprop && mind) {
- min = mind[f[i]] ? mind[f[i]]() : f[i](mind);
- }
- if (maxprop && maxd) {
- max = maxd[f[i]] ? maxd[f[i]]() : f[i](maxd);
- }
- if (i != 'y') {
- var i1 = $('.dw-li', t).index($('.dw-li[data-val="' + min + '"]', t)),
- i2 = $('.dw-li', t).index($('.dw-li[data-val="' + max + '"]', t));
- $('.dw-li', t).removeClass('dw-v').slice(i1, i2 + 1).addClass('dw-v');
- if (i == 'd') { // Hide days not in month
- $('.dw-li', t).removeClass('dw-h').slice(maxdays).addClass('dw-h');
- }
- }
- if (val < min) {
- val = min;
- }
- if (val > max) {
- val = max;
- }
- if (minprop) {
- minprop = val == min;
- }
- if (maxprop) {
- maxprop = val == max;
- }
- // Disable some days
- if (s.invalid && i == 'd') {
- var idx = [];
- // Disable exact dates
- if (s.invalid.dates) {
- $.each(s.invalid.dates, function (i, v) {
- if (v.getFullYear() == y && v.getMonth() == m) {
- idx.push(v.getDate() - 1);
- }
- });
- }
- // Disable days of week
- if (s.invalid.daysOfWeek) {
- var first = new Date(y, m, 1).getDay(),
- j;
- $.each(s.invalid.daysOfWeek, function (i, v) {
- for (j = v - first; j < maxdays; j += 7) {
- if (j >= 0) {
- idx.push(j);
- }
- }
- });
- }
- // Disable days of month
- if (s.invalid.daysOfMonth) {
- $.each(s.invalid.daysOfMonth, function (i, v) {
- v = (v + '').split('/');
- if (v[1]) {
- if (v[0] - 1 == m) {
- idx.push(v[1] - 1);
- }
- } else {
- idx.push(v[0] - 1);
- }
- });
- }
- $.each(idx, function (i, v) {
- $('.dw-li', t).eq(v).removeClass('dw-v');
- });
- }
- // Set modified value
- temp[o[i]] = val;
- }
- });
- },
- methods: {
- /**
- * Returns the currently selected date.
- * @param {Boolean} temp - If true, return the currently shown date on the picker, otherwise the last selected one
- * @return {Date}
- */
- getDate: function (temp) {
- var inst = $(this).mobiscroll('getInst');
- if (inst) {
- return inst.getDate(temp ? inst.temp : inst.values);
- }
- },
- /**
- * Sets the selected date
- * @param {Date} d - Date to select.
- * @param {Boolean} [fill] - Also set the value of the associated input element. Default is true.
- * @return {Object} - jQuery object to maintain chainability
- */
- setDate: function (d, fill, time, temp) {
- if (fill == undefined) {
- fill = false;
- }
- return this.each(function () {
- var inst = $(this).mobiscroll('getInst');
- if (inst) {
- inst.setDate(d, fill, time, temp);
- }
- });
- }
- }
- };
- };
- $.each(['date', 'time', 'datetime'], function (i, v) {
- ms.presets[v] = preset;
- ms.presetShort(v);
- });
- /**
- * Format a date into a string value with a specified format.
- * @param {String} format - Output format.
- * @param {Date} date - Date to format.
- * @param {Object} settings - Settings.
- * @return {String} - Returns the formatted date string.
- */
- ms.formatDate = function (format, date, settings) {
- if (!date) {
- return null;
- }
- var s = $.extend({}, defaults, settings),
- look = function (m) { // Check whether a format character is doubled
- var n = 0;
- while (i + 1 < format.length && format.charAt(i + 1) == m) {
- n++;
- i++;
- }
- return n;
- },
- f1 = function (m, val, len) { // Format a number, with leading zero if necessary
- var n = '' + val;
- if (look(m)) {
- while (n.length < len) {
- n = '0' + n;
- }
- }
- return n;
- },
- f2 = function (m, val, s, l) { // Format a name, short or long as requested
- return (look(m) ? l[val] : s[val]);
- },
- i,
- output = '',
- literal = false;
- for (i = 0; i < format.length; i++) {
- if (literal) {
- if (format.charAt(i) == "'" && !look("'")) {
- literal = false;
- } else {
- output += format.charAt(i);
- }
- } else {
- switch (format.charAt(i)) {
- case 'd':
- output += f1('d', date.getDate(), 2);
- break;
- case 'D':
- output += f2('D', date.getDay(), s.dayNamesShort, s.dayNames);
- break;
- case 'o':
- output += f1('o', (date.getTime() - new Date(date.getFullYear(), 0, 0).getTime()) / 86400000, 3);
- break;
- case 'm':
- output += f1('m', date.getMonth() + 1, 2);
- break;
- case 'M':
- output += f2('M', date.getMonth(), s.monthNamesShort, s.monthNames);
- break;
- case 'y':
- output += (look('y') ? date.getFullYear() : (date.getYear() % 100 < 10 ? '0' : '') + date.getYear() % 100);
- break;
- case 'h':
- var h = date.getHours();
- output += f1('h', (h > 12 ? (h - 12) : (h == 0 ? 12 : h)), 2);
- break;
- case 'H':
- output += f1('H', date.getHours(), 2);
- break;
- case 'i':
- output += f1('i', date.getMinutes(), 2);
- break;
- case 's':
- output += f1('s', date.getSeconds(), 2);
- break;
- case 'a':
- output += date.getHours() > 11 ? 'pm' : 'am';
- break;
- case 'A':
- output += date.getHours() > 11 ? 'PM' : 'AM';
- break;
- case "'":
- if (look("'")) {
- output += "'";
- } else {
- literal = true;
- }
- break;
- default:
- output += format.charAt(i);
- }
- }
- }
- return output;
- };
- /**
- * Extract a date from a string value with a specified format.
- * @param {String} format - Input format.
- * @param {String} value - String to parse.
- * @param {Object} settings - Settings.
- * @return {Date} - Returns the extracted date.
- */
- ms.parseDate = function (format, value, settings) {
- var def = new Date();
- if (!format || !value) {
- return def;
- }
- value = (typeof value == 'object' ? value.toString() : value + '');
- var s = $.extend({}, defaults, settings),
- shortYearCutoff = s.shortYearCutoff,
- year = def.getFullYear(),
- month = def.getMonth() + 1,
- day = def.getDate(),
- doy = -1,
- hours = def.getHours(),
- minutes = def.getMinutes(),
- seconds = 0, //def.getSeconds(),
- ampm = -1,
- literal = false, // Check whether a format character is doubled
- lookAhead = function (match) {
- var matches = (iFormat + 1 < format.length && format.charAt(iFormat + 1) == match);
- if (matches) {
- iFormat++;
- }
- return matches;
- },
- getNumber = function (match) { // Extract a number from the string value
- lookAhead(match);
- var size = (match == '@' ? 14 : (match == '!' ? 20 : (match == 'y' ? 4 : (match == 'o' ? 3 : 2)))),
- digits = new RegExp('^\\d{1,' + size + '}'),
- num = value.substr(iValue).match(digits);
- if (!num) {
- return 0;
- }
- //throw 'Missing number at position ' + iValue;
- iValue += num[0].length;
- return parseInt(num[0], 10);
- },
- getName = function (match, s, l) { // Extract a name from the string value and convert to an index
- var names = (lookAhead(match) ? l : s),
- i;
- for (i = 0; i < names.length; i++) {
- if (value.substr(iValue, names[i].length).toLowerCase() == names[i].toLowerCase()) {
- iValue += names[i].length;
- return i + 1;
- }
- }
- return 0;
- //throw 'Unknown name at position ' + iValue;
- },
- checkLiteral = function () {
- //if (value.charAt(iValue) != format.charAt(iFormat))
- //throw 'Unexpected literal at position ' + iValue;
- iValue++;
- },
- iValue = 0,
- iFormat;
- for (iFormat = 0; iFormat < format.length; iFormat++) {
- if (literal) {
- if (format.charAt(iFormat) == "'" && !lookAhead("'")) {
- literal = false;
- } else {
- checkLiteral();
- }
- } else {
- switch (format.charAt(iFormat)) {
- case 'd':
- day = getNumber('d');
- break;
- case 'D':
- getName('D', s.dayNamesShort, s.dayNames);
- break;
- case 'o':
- doy = getNumber('o');
- break;
- case 'm':
- month = getNumber('m');
- break;
- case 'M':
- month = getName('M', s.monthNamesShort, s.monthNames);
- break;
- case 'y':
- year = getNumber('y');
- break;
- case 'H':
- hours = getNumber('H');
- break;
- case 'h':
- hours = getNumber('h');
- break;
- case 'i':
- minutes = getNumber('i');
- break;
- case 's':
- seconds = getNumber('s');
- break;
- case 'a':
- ampm = getName('a', ['am', 'pm'], ['am', 'pm']) - 1;
- break;
- case 'A':
- ampm = getName('A', ['am', 'pm'], ['am', 'pm']) - 1;
- break;
- case "'":
- if (lookAhead("'")) {
- checkLiteral();
- } else {
- literal = true;
- }
- break;
- default:
- checkLiteral();
- }
- }
- }
- if (year < 100) {
- year += new Date().getFullYear() - new Date().getFullYear() % 100 +
- (year <= (typeof shortYearCutoff != 'string' ? shortYearCutoff : new Date().getFullYear() % 100 + parseInt(shortYearCutoff, 10)) ? 0 : -100);
- }
- if (doy > -1) {
- month = 1;
- day = doy;
- do {
- var dim = 32 - new Date(year, month - 1, 32).getDate();
- if (day <= dim) {
- break;
- }
- month++;
- day -= dim;
- } while (true);
- }
- hours = (ampm == -1) ? hours : ((ampm && hours < 12) ? (hours + 12) : (!ampm && hours == 12 ? 0 : hours));
- var date = new Date(year, month - 1, day, hours, minutes, seconds);
- if (date.getFullYear() != year || date.getMonth() + 1 != month || date.getDate() != day) {
- throw 'Invalid date';
- }
- return date;
- };
- })(jQuery);
|