Sabre Spark

DateTypeahead

Listen to an input element and format it as the user types.

Option name Type Description
module helper/date-typeahead.js
Example
new DateTypeahead(el);

DateTypeahead

function
 DateTypeahead() 

DateTypeahead constructor

Option name Type Description
el Element

Optional

params Object

Optional

function DateTypeahead(el, params) {

  // If only one arg passed, assume it was a parameters
  // object since the user MUST provide those but the element
  // is optional. Doing it this way to keep the arity the same
  // as other components.
  if (arguments.length < 2) {
    params = el || {};
    el = this._createDefaultElement();
  }

  this._setParams(this.defaults, true);
  this._setParams(params);
  this._bindEventListenerCallbacks();
  this._createTypeahead(el, params);
}

DateTypeahead.prototype = {

_setParams

property
 _setParams 

Include common functionality.

_setParams: Base.setParams,
remove: Base.remove,

_whitelistedParams

property
 _whitelistedParams 

Whitelisted parameters which can be set on construction.

Option name Type Description
_whitelistedParams: ['type', 'onChange', 'onFocus', 'onBlur', 'onBackspace', 'onEnd'],

defaults

property
 defaults 

Default values for internal properties we will be setting.
These are set on each construction so we don't leak properties
into the prototype chain.

Option name Type Description
defaults: {
  type: null,
  typeahead: null,
  onChange: null,
  onFocus: null,
  onBlur: null,
  onBackspace: null,
  onEnd: null,
  _onTypeaheadChangeBound: null,
  _onTypeaheadFocusBound: null,
  _onTypeaheadBlurBound: null,
  _onTypeaheadBackspaceBound: null,
  _onTypeaheadEndBound: null
},

getValue

method
 getValue() 

Get the value.

Option name Type Description
asInt Boolean

Get the value as a parsed integer.

return Mixed
getValue: function(asInt) {
  return this.typeahead.getValue(asInt);
},

setValue

method
 setValue() 

Set the value.

Option name Type Description
val Mixed
setValue: function(val) {
  return this.typeahead.setValue(val);
},

run

method
 run() 

Run the typeahead calculations.

run: function() {
  return this.typeahead.run();
},

pause

method
 pause() 

Pause the typeahead events.

pause: function() {
  return this.typeahead.pause();
},

resume

method
 resume() 

Reseume typeahead events.

resume: function() {
  return this.typeahead.resume();
},

_createDefaultElement

method
 _createDefaultElement() 

Create the default input element.

Option name Type Description
return Element
_createDefaultElement: function() {
  var el = document.createElement('span');
  el.className = 'spark-input';
  return el;
},

_createTypeahead

method
 _createTypeahead() 

Create a typeahead with the given format.

Option name Type Description
el Object
params Object
_createTypeahead: function(el, params) {

  params = params || {};

  if (!params.placeholder) {
    throw new Error('You must provide a placeholder value for a DateTypeahead.');
  }

  if (params.length !== undefined) {
    params.format = this._lengthToFormat(params.length);
  }

  if (!params.format) {
    throw new Error('You must provide a format value for a DateTypeahead.');
  }

  this.typeahead = new Typeahead(el, {
    placeholder: params.placeholder,
    format: params.format,
    matchPlaceholderSize: true,
    onChange: this._onTypeaheadChangeBound,
    onFocus: this._onTypeaheadFocusBound,
    onBlur: this._onTypeaheadBlurBound,
    onBackspace: this._onTypeaheadBackspaceBound,
    onEnd: this._onTypeaheadEndBound
  });

  // Ensure we have an ARIA label
  var input = el.querySelector('input');
  if (input && !input.getAttribute('aria-label')) {
    input.setAttribute('aria-label', this.type);
  }
},

_bindEventListenerCallbacks

method
 _bindEventListenerCallbacks() 

Create bound versions of event listener callbacks and store them.
Otherwise we can't unbind from these events later because the
function signatures won't match.

_bindEventListenerCallbacks: function() {
  this._onTypeaheadChangeBound = this._onTypeaheadChange.bind(this);
  this._onTypeaheadFocusBound = this._onTypeaheadFocus.bind(this);
  this._onTypeaheadBlurBound = this._onTypeaheadBlur.bind(this);
  this._onTypeaheadBackspaceBound = this._onTypeaheadBackspace.bind(this);
  this._onTypeaheadEndBound = this._onTypeaheadEnd.bind(this);
},

_lengthToFormat

method
 _lengthToFormat() 

Take a length and return a format string with that many digits.

Option name Type Description
length Number
return String
_lengthToFormat: function(length) {

  var i = 0;
  var ret = '';

  for (; i < length; i++) {
    ret += '\\d';
  }

  return ret;
},

_checkValidity

method
 _checkValidity() 

Check to see if an input value is valid.

Option name Type Description
val Mixed
allowEmpty Boolean

All the value to be empty instead of 0.

_checkValidity: function(val, allowEmpty) {

  val = parseInt(val, 10);

  var origVal = val;
  var isNumber = !isNaN(val);

  // If we were passed an empty string or something, don't try to validate.
  // Treat zeros as a non-entry for days and months.
  if (isNumber) {

    if (this.type === 'day') {
      val = val ? Math.min(Math.max(val, 1), 31) : (allowEmpty ? '' : 0);
    } else if (this.type === 'month') {
      val = val ? Math.min(Math.max(val, 1), 12) : (allowEmpty ? '' : 0);
    } else {
      val = val === 0 ? (allowEmpty ? '' : 0) : Math.max(val, 0);
    }
  }

  // Need to make sure we aren't looping forever on these updates.
  if (isNumber && val !== origVal) {
    this.typeahead.setValue(val + '');
    return false;
  }

  return true;
},

_onTypeaheadChange

method
 _onTypeaheadChange() 

When the typeahead changes, make sure the value is valid. This
is very basic validation. More complex validation like the number
of days in a specific month should be handled by the callback.
And run our callback.

Option name Type Description
val String

The value of the input

oldVal String

The previous value

_onTypeaheadChange: function(val) {
  if (this._checkValidity(val)) {
    (this.onChange || noop)(val, this);
  }
},

_onTypeaheadFocus

method
 _onTypeaheadFocus() 

When the typeahead gains focus, let anyone who is interested know.

Option name Type Description
val String
_onTypeaheadFocus: function(val) {
  (this.onFocus || noop)(val, this);
},

_onTypeaheadBlur

method
 _onTypeaheadBlur() 

When the typeahead loses focus, let anyone who is interested know.

Option name Type Description
val String
_onTypeaheadBlur: function(val) {
  this._checkValidity(val, true);
  (this.onBlur || noop)(val, this);
},

_onTypeaheadBackspace

method
 _onTypeaheadBackspace() 

When the typeahead fires a backspace event because it's empty and
the user is hitting backspace, let anyone who is interested know.

Option name Type Description
val String
_onTypeaheadBackspace: function(val) {
  (this.onBackspace || noop)(val, this);
},

_onTypeaheadEnd

method
 _onTypeaheadEnd() 

When the typeahead is full and at its end, let anyone who is interested know.

Option name Type Description
typeahead Object
character String

Optional The character to pass to the next input.

_onTypeaheadEnd: function(typeahead, character) {
  (this.onEnd || noop)(this, character);
}
  };

  Base.exportjQuery(DateTypeahead, 'DateTypeahead');

  return DateTypeahead;
}));