[ Index ]

PHP Cross Reference of Phabricator

title

Body

[close]

/webroot/rsrc/js/core/ -> behavior-fancy-datepicker.js (source)

   1  /**
   2   * @provides javelin-behavior-fancy-datepicker
   3   * @requires javelin-behavior
   4   *           javelin-util
   5   *           javelin-dom
   6   *           javelin-stratcom
   7   *           javelin-vector
   8   */
   9  
  10  JX.behavior('fancy-datepicker', function() {
  11  
  12    var picker;
  13    var root;
  14  
  15    var value_y;
  16    var value_m;
  17    var value_d;
  18  
  19    var onopen = function(e) {
  20      e.kill();
  21  
  22      // If you click the calendar icon while the date picker is open, close it
  23      // without writing the change.
  24  
  25      if (picker) {
  26        if (root == e.getNode('phabricator-date-control')) {
  27          // If the user clicked the same control, just close it.
  28          onclose(e);
  29          return;
  30        } else {
  31          // If the user clicked a different control, close the old one but then
  32          // open the new one.
  33          onclose(e);
  34        }
  35      }
  36  
  37  
  38      root = e.getNode('phabricator-date-control');
  39  
  40      picker = JX.$N(
  41        'div',
  42        {className: 'fancy-datepicker', sigil: 'phabricator-datepicker'},
  43        JX.$N('div', {className: 'fancy-datepicker-core'}));
  44      document.body.appendChild(picker);
  45  
  46      var button = e.getNode('calendar-button');
  47      var p = JX.$V(button);
  48      var d = JX.Vector.getDim(picker);
  49  
  50      picker.style.left = (p.x - d.x - 2) + 'px';
  51      picker.style.top = (p.y) + 'px';
  52  
  53      JX.DOM.alterClass(root, 'picker-open', true);
  54  
  55      read_date();
  56      render();
  57    };
  58  
  59    var onclose = function(e) {
  60      if (!picker) {
  61        return;
  62      }
  63  
  64      JX.DOM.remove(picker);
  65      picker = null;
  66      JX.DOM.alterClass(root, 'picker-open', false);
  67      e.kill();
  68  
  69      root = null;
  70    };
  71  
  72    var ontoggle = function(e) {
  73      var box = e.getTarget();
  74      root = e.getNode('phabricator-date-control');
  75      JX.Stratcom.getData(root).disabled = !box.checked;
  76      redraw_inputs();
  77    };
  78  
  79    var get_inputs = function() {
  80      return {
  81        y: JX.DOM.find(root, 'select', 'year-input'),
  82        m: JX.DOM.find(root, 'select', 'month-input'),
  83        d: JX.DOM.find(root, 'select', 'day-input'),
  84        t: JX.DOM.find(root, 'input', 'time-input')
  85      };
  86    };
  87  
  88    var read_date = function() {
  89      var i = get_inputs();
  90      value_y = +i.y.value;
  91      value_m = +i.m.value;
  92      value_d = +i.d.value;
  93    };
  94  
  95    var write_date = function() {
  96      var i = get_inputs();
  97      i.y.value = value_y;
  98      i.m.value = value_m;
  99      i.d.value = value_d;
 100    };
 101  
 102    var render = function() {
 103      JX.DOM.setContent(
 104        picker.firstChild,
 105        [
 106          render_month(),
 107          render_day()
 108        ]);
 109    };
 110  
 111    var redraw_inputs = function() {
 112      var inputs = get_inputs();
 113      var disabled = JX.Stratcom.getData(root).disabled;
 114      for (var k in inputs) {
 115        if (disabled) {
 116          inputs[k].setAttribute('disabled', 'disabled');
 117        } else {
 118          inputs[k].removeAttribute('disabled');
 119        }
 120      }
 121  
 122      var box = JX.DOM.scry(root, 'input', 'calendar-enable');
 123      if (box.length) {
 124        box[0].checked = !disabled;
 125      }
 126    };
 127  
 128    // Render a cell for the date picker.
 129    var cell = function(label, value, selected, class_name) {
 130  
 131      class_name = class_name || '';
 132  
 133      if (selected) {
 134        class_name += ' datepicker-selected';
 135      }
 136      if (!value) {
 137        class_name += ' novalue';
 138      }
 139  
 140      return JX.$N('td', {meta: {value: value}, className: class_name}, label);
 141    };
 142  
 143  
 144    // Render the top bar which allows you to pick a month and year.
 145    var render_month = function() {
 146      var months = [
 147        'January',
 148        'February',
 149        'March',
 150        'April',
 151        'May',
 152        'June',
 153        'July',
 154        'August',
 155        'September',
 156        'October',
 157        'November',
 158        'December'];
 159  
 160      var buttons = [
 161        cell('\u25C0', 'm:-1', false, 'lrbutton'),
 162        cell(months[value_m - 1] + ' ' + value_y, null),
 163        cell('\u25B6', 'm:1', false, 'lrbutton')];
 164  
 165      return JX.$N(
 166        'table',
 167        {className: 'month-table'},
 168        JX.$N('tr', {}, buttons));
 169    };
 170  
 171  
 172    // Render the day-of-week and calendar views.
 173    var render_day = function() {
 174      var weeks = [];
 175  
 176      // First, render the weekday names.
 177      var weekdays = 'SMTWTFS';
 178      var weekday_names = [];
 179      var ii;
 180      for (ii = 0; ii < weekdays.length; ii++) {
 181        weekday_names.push(cell(weekdays.charAt(ii), null, false, 'day-name'));
 182      }
 183      weeks.push(JX.$N('tr', {}, weekday_names));
 184  
 185  
 186      // Render the calendar itself. NOTE: Javascript uses 0-based month indexes
 187      // while we use 1-based month indexes, so we have to adjust for that.
 188      var days = [];
 189      var start = new Date(value_y, value_m - 1, 1).getDay();
 190      while (start--) {
 191        days.push(cell('', null, false, 'day-placeholder'));
 192      }
 193  
 194      var today = new Date();
 195  
 196      for (ii = 1; ii <= 31; ii++) {
 197        var date = new Date(value_y, value_m - 1, ii);
 198        if (date.getMonth() != (value_m - 1)) {
 199          // We've spilled over into the next month, so stop rendering.
 200          break;
 201        }
 202  
 203        var is_today = (today.getYear() == date.getYear() &&
 204                        today.getMonth() == date.getMonth() &&
 205                        today.getDate() == date.getDate());
 206  
 207        var classes = [];
 208        classes.push('day');
 209        if (is_today) {
 210          classes.push('today');
 211        }
 212        if (date.getDay() === 0 || date.getDay() == 6) {
 213          classes.push('weekend');
 214        }
 215  
 216        days.push(cell(ii, 'd:'+ii, value_d == ii, classes.join(' ')));
 217      }
 218  
 219      // Slice the days into weeks.
 220      for (ii = 0; ii < days.length; ii += 7) {
 221        weeks.push(JX.$N('tr', {}, days.slice(ii, ii + 7)));
 222      }
 223  
 224      return JX.$N('table', {className: 'day-table'}, weeks);
 225    };
 226  
 227  
 228    JX.Stratcom.listen('click', 'calendar-button', onopen);
 229    JX.Stratcom.listen('change', 'calendar-enable', ontoggle);
 230  
 231    JX.Stratcom.listen(
 232      'click',
 233      ['phabricator-datepicker', 'tag:td'],
 234      function(e) {
 235        e.kill();
 236  
 237        var data = e.getNodeData('tag:td');
 238        if (!data.value) {
 239          return;
 240        }
 241  
 242        var p = data.value.split(':');
 243        switch (p[0]) {
 244          case 'm':
 245            // User clicked left or right month selection buttons.
 246            value_m = value_m + parseInt(p[1], 10);
 247            if (value_m > 12) {
 248              value_m -= 12;
 249              value_y++;
 250            } else if (value_m <= 0) {
 251              value_m += 12;
 252              value_y--;
 253            }
 254            break;
 255          case 'd':
 256            // User clicked a day.
 257            value_d = parseInt(p[1], 10);
 258            write_date();
 259  
 260            // Wait a moment to close the selector so they can see the effect
 261            // of their action.
 262            setTimeout(JX.bind(null, onclose, e), 150);
 263            break;
 264        }
 265  
 266        // Enable the control.
 267        JX.Stratcom.getData(root).disabled = false;
 268        redraw_inputs();
 269  
 270        render();
 271      });
 272  
 273  });


Generated: Sun Nov 30 09:20:46 2014 Cross-referenced by PHPXref 0.7.1