CartoDB/cartodb20

View on GitHub
lib/assets/javascripts/cartodb/old_common/forms/date_field.js

Summary

Maintainability
C
1 day
Test Coverage

  /**
   *  Date field -> Place to choose and edit date field
   *  - It accepts a model with {attribute: 'colum', value: '2013-02-12T12:19:58+01:00'}
   *  - It will create a new model to split this value into {day, month, year and time}
   *  var date = new cdb.admin.DateField({ model: model })
   */

  cdb.admin.DateField = cdb.admin.StringField.extend({

    className: 'field date',

    timezone: "00:00",

    default_options: {
      template_name: 'old_common/views/forms/date_field',
      label:          false,
      readOnly:       false
    },

    events: {
      'change input.time': '_onChange',
      'keyup input.time':  '_onKeyUp'
    },

    initialize: function() {
      _.defaults(this.options, this.default_options);

      _.bindAll(this, '_onChange', '_onKeyUp', '_onChangeModel');

      this.template_base = this.options.template_base ? _.template(this.options.template_base) : cdb.templates.getTemplate(this.options.template_name);

      // Get date
      var date = this._splitDate((this.model.get('value')));

      this.timezone = this._getTimeZone(this.model.get('value'));

      // Generate a new date Model (later it will be removed and destroyed)
      this.date_model = new cdb.core.Model();

      // Begins as valid
      this.valid = true;

      // Bind changes
      this.date_model.bind('change', this._onChangeModel);

      // Date model data set
      this.date_model.set(date);

      // On clean
      this.bind('clean', this._reClean);
    },

    render: function() {
      this.$el.html(this.template_base(_.extend(this.model.toJSON(), this.options)));

      // Apply views
      this._initViews();

      // Check readOnly and unbind all events
      if (this.options.readOnly) {
        this.undelegateEvents();
      }

      return this;
    },

    _initViews: function() {

      // Days spinner
      var days = this.days = new cdb.forms.Spinner({
        el: this.$el.find('div.day'),
        model:    this.date_model,
        disabled: this.options.readOnly,
        property: 'day',
        min:      1,
        max:      31,
        inc:      1,
        width:    15,
        noSlider: true,
        pattern:  /^([12]?\d{0,1}|3[01]{0,2})$/
      });

      this.addView(this.days);
      this.$("div.day").append(days.render());

      // Year spinner
      var years = this.years = new cdb.forms.Spinner({
        el: this.$el.find('div.year'),
        model:    this.date_model,
        disabled: this.options.readOnly,
        property: 'year',
        min:      1900,
        max:      2100,
        width:    28,
        noSlider: true,
        pattern:  /^([0-9]{0,4})$/
      });
      this.addView(this.years);
      this.$("div.year").append(years.render());

      // Month selector
      var months = this.months = new cdb.forms.Combo({
        el: this.$el.find('div.month'),
        model:      this.date_model,
        disabled:   this.options.readOnly,
        property:   'month',
        width:      '140px',
        extra:      [['January',1], ['February',2], ['March',3], ['April',4], ['May',5], ['June',6], ['July',7], ['August',8], ['September',9], ['October',10], ['November',11], ['December',12]]
      });
      this.addView(this.months);
      this.$("div.month").append(months.render());

      // Time input
      this.$('input.time').val(this.date_model.get('time'));
    },

    /**
     *  Extracts the timezone from a date
     */
    _getTimeZone: function(date) {

      if (date) {
        var match = date.match(/\+(.*)$/);
        if (match && match.length == 2) return match[1];
      }

      return this.timezone;

    },

    /**
     *  Split the date string
     */
    _splitDate: function(str) {
      var date = {};

      // Get default date and time
      var today = new Date();

      var day   = today.getDate();
      var month = today.getMonth() + 1;
      var year  = today.getFullYear();

      var time = today.getHours() + ":" + today.getMinutes() + ":" + today.getSeconds();

      if (str == '') {
        date.day   = day;
        date.month = month;
        date.year  = year;
        date.time  = time;
      } else {
        try {
          var split_date_hour = str.split('T');

          if (split_date_hour.length > 1) {

            var split_date = split_date_hour[0].split('-');

            date.time  = split_date_hour[1].substr(0,8);
            date.day   = parseInt(split_date[2]);
            date.month = parseInt(split_date[1]);
            date.year  = parseInt(split_date[0]);

          } else {
            date.day   = day;
            date.month = month;
            date.year  = year;
            date.time  = time;
          }

        } catch (e) {
          date.day   = day;
          date.month = month;
          date.year  = year;
          date.time  = time;
        }
      }

      return date;

    },

    /**
     *  Get the date model and converts to date string
     */
    _toDate: function(date) {
      return date.year + "-" + date.month + "-" + date.day + "T" + date.time + "+" + this.timezone;
    },

    /**
     *  Check if the time is well formed or not
     */
    _checkTime: function(time) {
      var pattern = /^([01]{1}[0-9]|2[0-3]):[0-5][0-9]:[0-5][0-9]$/;
      if (pattern.test(time)) {
        return true
      } else {
        return false
      }
    },


    // Events
    _onChange: function(e) {
      var time = this.$('input.time').val();

      if (this._checkTime(time)) {
        this.date_model.set('time', time);
      }
    },

    _onChangeModel: function(m) {
      this.model.set('value', this._toDate(this.date_model.toJSON()));
    },


    _onKeyDown: function() {},


    _onKeyUp: function(e) {
      var time = $(e.target).val();

      if (this._checkTime(time)) {

        if (e.keyCode === 13) {
          e.preventDefault();
          this._triggerEvent('ENTER');
          return false;
        }

        this.valid = true;
        this.date_model.set('time', time);
        $(e.target).removeClass("error");
      } else {
        this.valid = false;
        $(e.target).addClass("error");
      }
    },

    _reClean: function() {
      this.date_model.unbind('change');
      this.date_model.destroy();
    }
  })