@atlassian/aui
Version:
Atlassian User Interface Framework
427 lines (342 loc) • 19.7 kB
JavaScript
(function (global, factory) {
if (typeof define === "function" && define.amd) {
define(['module', 'exports', './jquery', './internal/log', './internal/browser', './internal/globalize', './inline-dialog', './key-code', './i18n', '../../js-vendor/jquery/jquery-ui/jquery.ui.datepicker'], factory);
} else if (typeof exports !== "undefined") {
factory(module, exports, require('./jquery'), require('./internal/log'), require('./internal/browser'), require('./internal/globalize'), require('./inline-dialog'), require('./key-code'), require('./i18n'), require('../../js-vendor/jquery/jquery-ui/jquery.ui.datepicker'));
} else {
var mod = {
exports: {}
};
factory(mod, mod.exports, global.jquery, global.log, global.browser, global.globalize, global.inlineDialog, global.keyCode, global.i18n, global.jqueryUi);
global.datePicker = mod.exports;
}
})(this, function (module, exports, _jquery, _log, _browser, _globalize, _inlineDialog, _keyCode, _i18n) {
'use strict';
Object.defineProperty(exports, "__esModule", {
value: true
});
var _jquery2 = _interopRequireDefault(_jquery);
var logger = _interopRequireWildcard(_log);
var _globalize2 = _interopRequireDefault(_globalize);
var _inlineDialog2 = _interopRequireDefault(_inlineDialog);
var _keyCode2 = _interopRequireDefault(_keyCode);
var _i18n2 = _interopRequireDefault(_i18n);
function _interopRequireWildcard(obj) {
if (obj && obj.__esModule) {
return obj;
} else {
var newObj = {};
if (obj != null) {
for (var key in obj) {
if (Object.prototype.hasOwnProperty.call(obj, key)) newObj[key] = obj[key];
}
}
newObj.default = obj;
return newObj;
}
}
function _interopRequireDefault(obj) {
return obj && obj.__esModule ? obj : {
default: obj
};
}
var datePickerCounter = 0;
function DatePicker(field, options) {
var datePicker;
var initPolyfill;
var $field;
var datePickerUUID;
var parentPopup;
datePicker = {};
datePickerUUID = datePickerCounter++;
// ---------------------------------------------------------------------
// fix up arguments ----------------------------------------------------
// ---------------------------------------------------------------------
$field = (0, _jquery2.default)(field);
$field.attr('data-aui-dp-uuid', datePickerUUID);
options = _jquery2.default.extend(undefined, DatePicker.prototype.defaultOptions, options);
// ---------------------------------------------------------------------
// expose arguments with getters ---------------------------------------
// ---------------------------------------------------------------------
datePicker.getField = function () {
return $field;
};
datePicker.getOptions = function () {
return options;
};
// ---------------------------------------------------------------------
// exposed methods -----------------------------------------------------
// ---------------------------------------------------------------------
initPolyfill = function initPolyfill() {
var calendar;
var handleDatePickerFocus;
var handleFieldBlur;
var handleFieldFocus;
var handleFieldUpdate;
var initCalendar;
var isSuppressingShow;
var isTrackingDatePickerFocus;
var popup;
var popupContents;
// -----------------------------------------------------------------
// expose methods for controlling the popup ------------------------
// -----------------------------------------------------------------
datePicker.hide = function () {
popup.hide();
};
datePicker.show = function () {
popup.show();
};
datePicker.setDate = function (value) {
if (typeof calendar !== 'undefined') {
calendar.datepicker('setDate', value);
}
};
datePicker.getDate = function () {
if (typeof calendar !== 'undefined') {
return calendar.datepicker('getDate');
}
};
// -----------------------------------------------------------------
// initialise the calendar -----------------------------------------
// -----------------------------------------------------------------
initCalendar = function initCalendar(i18nConfig) {
popupContents.off();
if (options.hint) {
var $hint = (0, _jquery2.default)('<div/>').addClass('aui-datepicker-hint');
$hint.append('<span/>').text(options.hint);
popupContents.append($hint);
}
calendar = (0, _jquery2.default)('<div/>');
calendar.attr('data-aui-dp-popup-uuid', datePickerUUID);
popupContents.append(calendar);
var config = {
'dateFormat': options.dateFormat,
'defaultDate': $field.val(),
'maxDate': $field.attr('max'),
'minDate': $field.attr('min'),
'nextText': '>',
'onSelect': function onSelect(dateText) {
$field.val(dateText);
$field.change();
datePicker.hide();
isSuppressingShow = true;
$field.focus();
options.onSelect && options.onSelect.call(this, dateText);
},
onChangeMonthYear: function onChangeMonthYear() {
// defer rehresh call until current stack has cleared (after month has rendered)
setTimeout(popup.refresh, 0);
},
'prevText': '<'
};
_jquery2.default.extend(config, i18nConfig);
if (options.firstDay > -1) {
config.firstDay = options.firstDay;
}
if (typeof $field.attr('step') !== 'undefined') {
logger.log('WARNING: The date picker polyfill currently does not support the step attribute!');
}
calendar.datepicker(config);
// bind additional field processing events
(0, _jquery2.default)('body').on('keydown', handleDatePickerFocus);
$field.on('focusout keydown', handleFieldBlur);
$field.on('propertychange keyup input paste', handleFieldUpdate);
};
// -----------------------------------------------------------------
// event handler wrappers ------------------------------------------
// -----------------------------------------------------------------
handleDatePickerFocus = function handleDatePickerFocus(event) {
var $eventTarget = (0, _jquery2.default)(event.target);
var isTargetInput = $eventTarget.closest(popupContents).length || $eventTarget.is($field);
var isTargetPopup = $eventTarget.closest('.ui-datepicker-header').length;
// Hide if we're clicking anywhere else but the input or popup OR if esc is pressed.
if (!isTargetInput && !isTargetPopup || event.keyCode === _keyCode2.default.ESCAPE) {
datePicker.hide();
return;
}
if ($eventTarget[0] !== $field[0]) {
event.preventDefault();
}
};
handleFieldBlur = function handleFieldBlur() {
// Trigger blur if event is keydown and esc OR is focusout.
if (!isTrackingDatePickerFocus) {
(0, _jquery2.default)('body').on('focus blur click mousedown', '*', handleDatePickerFocus);
isTrackingDatePickerFocus = true;
}
};
handleFieldFocus = function handleFieldFocus() {
if (!isSuppressingShow) {
datePicker.show();
} else {
isSuppressingShow = false;
}
};
handleFieldUpdate = function handleFieldUpdate() {
var val = (0, _jquery2.default)(this).val();
// IE10/11 fire the 'input' event when internally showing and hiding
// the placeholder of an input. This was cancelling the inital click
// event and preventing the selection of the first date. The val check here
// is a workaround to assure we have legitimate user input that should update
// the calendar
if (val) {
calendar.datepicker('setDate', $field.val());
calendar.datepicker('option', {
'maxDate': $field.attr('max'),
'minDate': $field.attr('min')
});
}
};
// -----------------------------------------------------------------
// undo (almost) everything ----------------------------------------
// -----------------------------------------------------------------
datePicker.destroyPolyfill = function () {
// goodbye, cruel world!
datePicker.hide();
$field.attr('placeholder', null);
$field.off('propertychange keyup input paste', handleFieldUpdate);
$field.off('focus click', handleFieldFocus);
$field.off('focusout keydown', handleFieldBlur);
(0, _jquery2.default)('body').off('keydown', handleFieldBlur);
if (DatePicker.prototype.browserSupportsDateField) {
$field[0].type = 'date';
}
if (typeof calendar !== 'undefined') {
calendar.datepicker('destroy');
}
// TODO: figure out a way to tear down the popup (if necessary)
delete datePicker.destroyPolyfill;
delete datePicker.show;
delete datePicker.hide;
};
// -----------------------------------------------------------------
// polyfill bootstrap ----------------------------------------------
// -----------------------------------------------------------------
isSuppressingShow = false; // used to stop the popover from showing when focus is restored to the field after a date has been selected
isTrackingDatePickerFocus = false; // used to prevent multiple bindings of handleDatePickerFocus within handleFieldBlur
if (!(options.languageCode in DatePicker.prototype.localisations)) {
options.languageCode = '';
}
var i18nConfig = DatePicker.prototype.localisations;
var containerClass = '';
var width = 240;
if (i18nConfig.size === 'large') {
width = 325;
containerClass = 'aui-datepicker-dialog-large';
}
var dialogOptions = {
'hideCallback': function hideCallback() {
(0, _jquery2.default)('body').off('focus blur click mousedown', '*', handleDatePickerFocus);
isTrackingDatePickerFocus = false;
if (parentPopup && parentPopup._datePickerPopup) {
delete parentPopup._datePickerPopup;
}
},
'hideDelay': null,
'noBind': true,
'persistent': true,
'closeOthers': false,
'width': width
};
if (options.position) {
dialogOptions.calculatePositions = function (popup, targetPosition) {
// create a jQuery object from the internal
var vanilla = (0, _jquery2.default)(popup[0]);
return options.position.call(this, vanilla, targetPosition);
};
}
popup = (0, _inlineDialog2.default)($field, undefined, function (contents, trigger, showPopup) {
if (typeof calendar === 'undefined') {
popupContents = contents;
initCalendar(i18nConfig);
}
parentPopup = (0, _jquery2.default)(trigger).closest('.aui-inline-dialog').get(0);
if (parentPopup) {
parentPopup._datePickerPopup = popup; // AUI-2696 - hackish coupling to control inline-dialog close behaviour.
}
showPopup();
}, dialogOptions);
popup.addClass('aui-datepicker-dialog');
popup.addClass(containerClass);
// bind what we need to start off with
$field.on('focus click', handleFieldFocus); // the click is for fucking opera... Y U NO FIRE FOCUS EVENTS PROPERLY???
// give users a hint that this is a date field; note that placeholder isn't technically a valid attribute
// according to the spec...
$field.attr('placeholder', options.dateFormat);
// override the browser's default date field implementation (if applicable)
// since IE doesn't support date input fields, we should be fine...
if (options.overrideBrowserDefault && DatePicker.prototype.browserSupportsDateField) {
$field[0].type = 'text';
//workaround for this issue in Edge: https://connect.microsoft.com/IE/feedback/details/1603512/changing-an-input-type-to-text-does-not-set-the-value
var value = $field[0].getAttribute('value'); //can't use jquery to get the attribute because it doesn't work in Edge
if (value) {
$field[0].value = value;
}
}
};
datePicker.reset = function () {
if (typeof datePicker.destroyPolyfill === 'function') {
datePicker.destroyPolyfill();
}
if (!DatePicker.prototype.browserSupportsDateField || options.overrideBrowserDefault) {
initPolyfill();
}
};
// ---------------------------------------------------------------------
// bootstrap -----------------------------------------------------------
// ---------------------------------------------------------------------
datePicker.reset();
return datePicker;
};
// -------------------------------------------------------------------------
// things that should be common --------------------------------------------
// -------------------------------------------------------------------------
DatePicker.prototype.browserSupportsDateField = (0, _browser.supportsDateField)();
DatePicker.prototype.defaultOptions = {
overrideBrowserDefault: false,
firstDay: -1,
languageCode: (0, _jquery2.default)('html').attr('lang') || 'en-AU',
dateFormat: _jquery2.default.datepicker.W3C // same as $.datepicker.ISO_8601
};
// adapted from the jQuery UI Datepicker widget (v1.8.16), with the following changes:
// - dayNamesShort -> dayNamesMin
// - unnecessary attributes omitted
/*
CODE to extract codes out:
var langCode, langs, out;
langs = jQuery.datepicker.regional;
out = {};
for (langCode in langs) {
if (langs.hasOwnProperty(langCode)) {
out[langCode] = {
'dayNames': langs[langCode].dayNames,
'dayNamesMin': langs[langCode].dayNamesShort, // this is deliberate
'firstDay': langs[langCode].firstDay,
'isRTL': langs[langCode].isRTL,
'monthNames': langs[langCode].monthNames,
'showMonthAfterYear': langs[langCode].showMonthAfterYear,
'yearSuffix': langs[langCode].yearSuffix
};
}
}
*/
DatePicker.prototype.localisations = {
"dayNames": [_i18n2.default.getText('ajs.datepicker.localisations.day-names.sunday'), _i18n2.default.getText('ajs.datepicker.localisations.day-names.monday'), _i18n2.default.getText('ajs.datepicker.localisations.day-names.tuesday'), _i18n2.default.getText('ajs.datepicker.localisations.day-names.wednesday'), _i18n2.default.getText('ajs.datepicker.localisations.day-names.thursday'), _i18n2.default.getText('ajs.datepicker.localisations.day-names.friday'), _i18n2.default.getText('ajs.datepicker.localisations.day-names.saturday')],
"dayNamesMin": [_i18n2.default.getText('ajs.datepicker.localisations.day-names-min.sunday'), _i18n2.default.getText('ajs.datepicker.localisations.day-names-min.monday'), _i18n2.default.getText('ajs.datepicker.localisations.day-names-min.tuesday'), _i18n2.default.getText('ajs.datepicker.localisations.day-names-min.wednesday'), _i18n2.default.getText('ajs.datepicker.localisations.day-names-min.thursday'), _i18n2.default.getText('ajs.datepicker.localisations.day-names-min.friday'), _i18n2.default.getText('ajs.datepicker.localisations.day-names-min.saturday')],
"firstDay": _i18n2.default.getText('ajs.datepicker.localisations.first-day'),
"isRTL": _i18n2.default.getText('ajs.datepicker.localisations.is-RTL') === "true" ? true : false,
"monthNames": [_i18n2.default.getText('ajs.datepicker.localisations.month-names.january'), _i18n2.default.getText('ajs.datepicker.localisations.month-names.february'), _i18n2.default.getText('ajs.datepicker.localisations.month-names.march'), _i18n2.default.getText('ajs.datepicker.localisations.month-names.april'), _i18n2.default.getText('ajs.datepicker.localisations.month-names.may'), _i18n2.default.getText('ajs.datepicker.localisations.month-names.june'), _i18n2.default.getText('ajs.datepicker.localisations.month-names.july'), _i18n2.default.getText('ajs.datepicker.localisations.month-names.august'), _i18n2.default.getText('ajs.datepicker.localisations.month-names.september'), _i18n2.default.getText('ajs.datepicker.localisations.month-names.october'), _i18n2.default.getText('ajs.datepicker.localisations.month-names.november'), _i18n2.default.getText('ajs.datepicker.localisations.month-names.december')],
"showMonthAfterYear": _i18n2.default.getText('ajs.datepicker.localisations.show-month-after-year') === "true" ? true : false,
"yearSuffix": _i18n2.default.getText('ajs.datepicker.localisations.year-suffix')
// -------------------------------------------------------------------------
// finally, integrate with jQuery for convenience --------------------------
// -------------------------------------------------------------------------
};_jquery2.default.fn.datePicker = function (options) {
return new DatePicker(this, options);
};
(0, _globalize2.default)('DatePicker', DatePicker);
exports.default = DatePicker;
module.exports = exports['default'];
});
//# sourceMappingURL=date-picker.js.map