Login Register

Ugly attempt to DateTime widget

Hi to all!
After a little bit of research I've come up with an attempt to a date+time widget. Here is the template:

<table cellspacing="0" cellpadding="0"
       class="dijit dijitReset dijitInlineTable"
       style="display: -moz-inline-stack; border: none"
       waiRole="presentation"
       id="widget_dt_${id}"
       tabindex="0"
       dojoAttachPoint="containerNode">

    <tr class="dijitReset">
      <td class="required_${required}">
        <input type="hidden"
               name="${name}"
               dojoAttachPoint="textbox,textNode"
               style="display: none">

         
      </td>
      <td class="required_${required}"
          dojoAttachPoint="focusNode"
          class="dijitReset dijitInputField">

        <input type="text"
               dojoType="dijit.form.DateTextBox"
               dojoAttachPoint="dateNode"
               id="${id}_datePart"
               required="${required}"
               style="width: 10em;">


      <td class="required_${required}"
          class="dijitReset dijitInputField">

        <input type="text"
               dojoType="dijit.form.TimeTextBox"
               dojoAttachPoint="timeNode"
               id="${id}_timePart"
               required="${required}"
               style="width: 8em;">


      </td>
    </tr>
</table>

and here is the .js part (DateTime.js):

dojo.provide("dojoc.widget.DateTime");
dojo.require("dijit.form._FormWidget");
dojo.require("dijit.form.TimeTextBox");
dojo.require("dijit.form.DateTextBox");
dojo.require("dojo.date");
dojo.require("dojo.date.locale");
dojo.require("dojo.date.stamp");
dojo.require("dojo.parser");
dojo.declare("dojoc.widget.DateTime", [ dijit.form._FormWidget,  dijit.form.TimeTextBox ], {
  id: 'dt',
      name: 'dt',
      required: true,
      constraints: {},
      value: dojo.date.locale.format(new Date(),
                                     { timePattern:"HH:mm", datePattern:"yyyy/MM/dd"}),
      templatePath: dojo.moduleUrl("dojoc.widget","DateTime/DateTime.html"),
      templateString: "",
      src: "",
      disabled: false,
      widgetsInTemplate: true,
     
      startup: function() {
      this.setValue(this.value);
    },
      postCreate: function() {
      this.connect(this.dateNode, "onChange", "_onChange");
      this.connect(this.timeNode, "onChange", "_onChange");
      this.setDisabled();
    },
      setDisabled: function() {
      this.dateNode.setDisabled(this.disabled);
      this.timeNode.setDisabled(this.disabled);
    },
      setDisplayedValue: function(value) {

      var myDate=dojo.date.locale.parse(value);
      this.dateNode.setValue(myDate);
      this.timeNode.setValue(myDate);
    },
      getDisplayedValue: function() {

      var dateVal=this.dateNode.textbox.value;
      var timeVal=this.timeNode.textbox.value;
      return dateVal+" "+timeVal;
    },
      getValue: function() {
      var dateVal=dojo.date.stamp.toISOString(this.dateNode.getValue(),
                                              { selector: "date", timePattern: "yyyy-MM-dd" });
      // var dateVal=this.dateNode.textbox.value;
      var timeVal=this.timeNode.textbox.value;
      return dateVal+"T"+timeVal;
    },
      setValue: function(val, options) {
      var myDate=new Date(val);
      this.dateNode.setValue(myDate);
      this.timeNode.setValue(myDate);
    },
      toString: function(val, options) {
      if(val) {
        var dateVal=dojo.date.locale.format(val, {selector:'date', datePattern: 'yyyy-MM-dd'});
        var timeVal=dojo.date.locale.format(val, {selector:'time', timePattern: 'HH:mm:ss'});
        return dateVal+"T"+timeVal;
      } else {
        return this.getValue();
      }
    },
      updateValue: function() {
      this.textNode.value=this.getValue();
      this.validate(false);
    },
      _open: function() {
      return true;
    },
      _close: function() {
      return true;
    },
      _onBlur: function (e) {
      return true;
    },
      _onChange: function(e) {
      this.updateValue();
      this.onChange();
    },
      validator: function(value,constraints){
      var date=dojo.date.stamp.fromISOString(value);
      var minDate=dojo.date.stamp.fromISOString(constraints.min);
      var maxDate=dojo.date.stamp.fromISOString(constraints.max);

      if(typeof constraints.min != "undefined") {
        var minDate=dojo.date.stamp.fromISOString(constraints.min);
        var isMajor=(date >= minDate);
      } else {
        var isMajor=true;
      }
      if(typeof constraints.max != "undefined") {
        var maxDate=dojo.date.stamp.fromISOString(constraints.max);
        var isMinor=(date <= maxDate);
      } else {
        var isMinor=true;
      }

      if(isMinor && isMajor) {
        return true;
      } else {
        return false;
      }
    },
      validate: function(isFocused) {
      var isValid = this.isValid(isFocused);
      var isEmpty = this._isEmpty(this.textbox.value);
      var state = (isValid || isEmpty) ? "" : "Error";
      this.timeNode.state = state;
      this.dateNode.state = state;
      this.state = state;

      this.timeNode._setStateClass();
      this.dateNode._setStateClass();
      this._setStateClass();

      dijit.setWaiState(this.timeNode.focusNode, "invalid", (isValid? "false" : "true"));
      dijit.setWaiState(this.dateNode.focusNode, "invalid", (isValid? "false" : "true"));
    },
      isValid: function(isFocused) {
      return this.validator(this.textNode.value, this.constraints);
    }
  }
  );

It is ugly, I've not tested it with IE and it has a seriouse cosmetic bug, since the containing table get focus when you tab on all fields of a form, instead of being ignored, but it should be a start.

Any suggestions?

Akel

If you still need this...

Thanks to some feedback I got from Wombat in regards to a similar problem I had with my Date Range widget I think I've found your issue.

If you extend dijit._Templated rather than dijit.form.TimeTextBox you will resolve the issue of the container node.

dojo.declare("dojoc.widget.DateTime", [ dijit.form._FormWidget,  dijit._Templated ], {

You'll be missing the _isEmpty function that was inherited from ValidationTextBox via TimeTextBox but you can reference it explicitly

var isEmpty = dijit.form.ValidationTextBox.prototype._isEmpty(this.textbox.value);

Or just drop it into your class so you don't have to deal with the possibility of them changing the function since it's private.