date.js 4.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159
  1. (function ($) {
  2. Drupal.behaviors.dateSelect = {};
  3. Drupal.behaviors.dateSelect.attach = function (context, settings) {
  4. var $widget = $('.form-type-date-select').parents('fieldset').once('date');
  5. var i;
  6. for (i = 0; i < $widget.length; i++) {
  7. new Drupal.date.EndDateHandler($widget[i]);
  8. }
  9. };
  10. Drupal.date = Drupal.date || {};
  11. /**
  12. * Constructor for the EndDateHandler object.
  13. *
  14. * The EndDateHandler is responsible for synchronizing a date select widget's
  15. * end date with its start date. This behavior lasts until the user
  16. * interacts with the end date widget.
  17. *
  18. * @param widget
  19. * The fieldset DOM element containing the from and to dates.
  20. */
  21. Drupal.date.EndDateHandler = function (widget) {
  22. this.$widget = $(widget);
  23. this.$start = this.$widget.find('.form-type-date-select[class$=value]');
  24. this.$end = this.$widget.find('.form-type-date-select[class$=value2]');
  25. if (this.$end.length === 0) {
  26. return;
  27. }
  28. this.initializeSelects();
  29. // Only act on date fields where the end date is completely blank or already
  30. // the same as the start date. Otherwise, we do not want to override whatever
  31. // the default value was.
  32. if (this.endDateIsBlank() || this.endDateIsSame()) {
  33. this.bindClickHandlers();
  34. // Start out with identical start and end dates.
  35. this.syncEndDate();
  36. }
  37. };
  38. /**
  39. * Store all the select dropdowns in an array on the object, for later use.
  40. */
  41. Drupal.date.EndDateHandler.prototype.initializeSelects = function () {
  42. var $starts = this.$start.find('select');
  43. var $end, $start, endId, i, id;
  44. this.selects = {};
  45. for (i = 0; i < $starts.length; i++) {
  46. $start = $($starts[i]);
  47. id = $start.attr('id');
  48. endId = id.replace('-value-', '-value2-');
  49. $end = $('#' + endId);
  50. this.selects[id] = {
  51. 'id': id,
  52. 'start': $start,
  53. 'end': $end
  54. };
  55. }
  56. };
  57. /**
  58. * Returns true if all dropdowns in the end date widget are blank.
  59. */
  60. Drupal.date.EndDateHandler.prototype.endDateIsBlank = function () {
  61. var id;
  62. for (id in this.selects) {
  63. if (this.selects.hasOwnProperty(id)) {
  64. if (this.selects[id].end.val() !== '') {
  65. return false;
  66. }
  67. }
  68. }
  69. return true;
  70. };
  71. /**
  72. * Returns true if the end date widget has the same value as the start date.
  73. */
  74. Drupal.date.EndDateHandler.prototype.endDateIsSame = function () {
  75. var id;
  76. for (id in this.selects) {
  77. if (this.selects.hasOwnProperty(id)) {
  78. if (this.selects[id].end.val() != this.selects[id].start.val()) {
  79. return false;
  80. }
  81. }
  82. }
  83. return true;
  84. };
  85. /**
  86. * Add a click handler to each of the start date's select dropdowns.
  87. */
  88. Drupal.date.EndDateHandler.prototype.bindClickHandlers = function () {
  89. var id;
  90. for (id in this.selects) {
  91. if (this.selects.hasOwnProperty(id)) {
  92. this.selects[id].start.bind('click.endDateHandler', this.startClickHandler.bind(this));
  93. this.selects[id].end.bind('focus', this.endFocusHandler.bind(this));
  94. }
  95. }
  96. };
  97. /**
  98. * Click event handler for each of the start date's select dropdowns.
  99. */
  100. Drupal.date.EndDateHandler.prototype.startClickHandler = function (event) {
  101. this.syncEndDate();
  102. };
  103. /**
  104. * Focus event handler for each of the end date's select dropdowns.
  105. */
  106. Drupal.date.EndDateHandler.prototype.endFocusHandler = function (event) {
  107. var id;
  108. for (id in this.selects) {
  109. if (this.selects.hasOwnProperty(id)) {
  110. this.selects[id].start.unbind('click.endDateHandler');
  111. }
  112. }
  113. $(event.target).unbind('focus', this.endFocusHandler);
  114. };
  115. Drupal.date.EndDateHandler.prototype.syncEndDate = function () {
  116. var id;
  117. for (id in this.selects) {
  118. if (this.selects.hasOwnProperty(id)) {
  119. this.selects[id].end.val(this.selects[id].start.val());
  120. }
  121. }
  122. };
  123. }(jQuery));
  124. /**
  125. * Function.prototype.bind polyfill for older browsers.
  126. * https://developer.mozilla.org/en/JavaScript/Reference/Global_Objects/Function/bind
  127. */
  128. if (!Function.prototype.bind) {
  129. Function.prototype.bind = function (oThis) {
  130. if (typeof this !== "function") // closest thing possible to the ECMAScript 5 internal IsCallable function
  131. throw new TypeError("Function.prototype.bind - what is trying to be fBound is not callable");
  132. var aArgs = Array.prototype.slice.call(arguments, 1),
  133. fToBind = this,
  134. fNOP = function () {},
  135. fBound = function () {
  136. return fToBind.apply(this instanceof fNOP ? this : oThis || window, aArgs.concat(Array.prototype.slice.call(arguments)));
  137. };
  138. fNOP.prototype = this.prototype;
  139. fBound.prototype = new fNOP();
  140. return fBound;
  141. };
  142. }