160 lines
4.5 KiB
JavaScript
160 lines
4.5 KiB
JavaScript
(function ($) {
|
|
|
|
|
|
Drupal.behaviors.dateSelect = {};
|
|
|
|
Drupal.behaviors.dateSelect.attach = function (context, settings) {
|
|
var $widget = $('.form-type-date-select').parents('fieldset').once('date');
|
|
var i;
|
|
for (i = 0; i < $widget.length; i++) {
|
|
new Drupal.date.EndDateHandler($widget[i]);
|
|
}
|
|
};
|
|
|
|
Drupal.date = Drupal.date || {};
|
|
|
|
/**
|
|
* Constructor for the EndDateHandler object.
|
|
*
|
|
* The EndDateHandler is responsible for synchronizing a date select widget's
|
|
* end date with its start date. This behavior lasts until the user
|
|
* interacts with the end date widget.
|
|
*
|
|
* @param widget
|
|
* The fieldset DOM element containing the from and to dates.
|
|
*/
|
|
Drupal.date.EndDateHandler = function (widget) {
|
|
this.$widget = $(widget);
|
|
this.$start = this.$widget.find('.form-type-date-select[class$=value]');
|
|
this.$end = this.$widget.find('.form-type-date-select[class$=value2]');
|
|
if (this.$end.length === 0) {
|
|
return;
|
|
}
|
|
this.initializeSelects();
|
|
// Only act on date fields where the end date is completely blank or already
|
|
// the same as the start date. Otherwise, we do not want to override whatever
|
|
// the default value was.
|
|
if (this.endDateIsBlank() || this.endDateIsSame()) {
|
|
this.bindClickHandlers();
|
|
// Start out with identical start and end dates.
|
|
this.syncEndDate();
|
|
}
|
|
};
|
|
|
|
/**
|
|
* Store all the select dropdowns in an array on the object, for later use.
|
|
*/
|
|
Drupal.date.EndDateHandler.prototype.initializeSelects = function () {
|
|
var $starts = this.$start.find('select');
|
|
var $end, $start, endId, i, id;
|
|
this.selects = {};
|
|
for (i = 0; i < $starts.length; i++) {
|
|
$start = $($starts[i]);
|
|
id = $start.attr('id');
|
|
endId = id.replace('-value-', '-value2-');
|
|
$end = $('#' + endId);
|
|
this.selects[id] = {
|
|
'id': id,
|
|
'start': $start,
|
|
'end': $end
|
|
};
|
|
}
|
|
};
|
|
|
|
/**
|
|
* Returns true if all dropdowns in the end date widget are blank.
|
|
*/
|
|
Drupal.date.EndDateHandler.prototype.endDateIsBlank = function () {
|
|
var id;
|
|
for (id in this.selects) {
|
|
if (this.selects.hasOwnProperty(id)) {
|
|
if (this.selects[id].end.val() !== '') {
|
|
return false;
|
|
}
|
|
}
|
|
}
|
|
return true;
|
|
};
|
|
|
|
/**
|
|
* Returns true if the end date widget has the same value as the start date.
|
|
*/
|
|
Drupal.date.EndDateHandler.prototype.endDateIsSame = function () {
|
|
var id;
|
|
for (id in this.selects) {
|
|
if (this.selects.hasOwnProperty(id)) {
|
|
if (this.selects[id].end.val() != this.selects[id].start.val()) {
|
|
return false;
|
|
}
|
|
}
|
|
}
|
|
return true;
|
|
};
|
|
|
|
/**
|
|
* Add a click handler to each of the start date's select dropdowns.
|
|
*/
|
|
Drupal.date.EndDateHandler.prototype.bindClickHandlers = function () {
|
|
var id;
|
|
for (id in this.selects) {
|
|
if (this.selects.hasOwnProperty(id)) {
|
|
this.selects[id].start.bind('click.endDateHandler', this.startClickHandler.bind(this));
|
|
this.selects[id].end.bind('focus', this.endFocusHandler.bind(this));
|
|
}
|
|
}
|
|
};
|
|
|
|
/**
|
|
* Click event handler for each of the start date's select dropdowns.
|
|
*/
|
|
Drupal.date.EndDateHandler.prototype.startClickHandler = function (event) {
|
|
this.syncEndDate();
|
|
};
|
|
|
|
/**
|
|
* Focus event handler for each of the end date's select dropdowns.
|
|
*/
|
|
Drupal.date.EndDateHandler.prototype.endFocusHandler = function (event) {
|
|
var id;
|
|
for (id in this.selects) {
|
|
if (this.selects.hasOwnProperty(id)) {
|
|
this.selects[id].start.unbind('click.endDateHandler');
|
|
}
|
|
}
|
|
$(event.target).unbind('focus', this.endFocusHandler);
|
|
};
|
|
|
|
Drupal.date.EndDateHandler.prototype.syncEndDate = function () {
|
|
var id;
|
|
for (id in this.selects) {
|
|
if (this.selects.hasOwnProperty(id)) {
|
|
this.selects[id].end.val(this.selects[id].start.val());
|
|
}
|
|
}
|
|
};
|
|
|
|
}(jQuery));
|
|
|
|
/**
|
|
* Function.prototype.bind polyfill for older browsers.
|
|
* https://developer.mozilla.org/en/JavaScript/Reference/Global_Objects/Function/bind
|
|
*/
|
|
if (!Function.prototype.bind) {
|
|
Function.prototype.bind = function (oThis) {
|
|
if (typeof this !== "function") // closest thing possible to the ECMAScript 5 internal IsCallable function
|
|
throw new TypeError("Function.prototype.bind - what is trying to be fBound is not callable");
|
|
|
|
var aArgs = Array.prototype.slice.call(arguments, 1),
|
|
fToBind = this,
|
|
fNOP = function () {},
|
|
fBound = function () {
|
|
return fToBind.apply(this instanceof fNOP ? this : oThis || window, aArgs.concat(Array.prototype.slice.call(arguments)));
|
|
};
|
|
|
|
fNOP.prototype = this.prototype;
|
|
fBound.prototype = new fNOP();
|
|
|
|
return fBound;
|
|
};
|
|
}
|