koss-lebedev/bootstrap-duration-picker

View on GitHub
src/bootstrap-duration-picker.js

Summary

Maintainability
D
1 day
Test Coverage
(function iife($) {

  $.DurationPicker = function DurationPicker(mainElement, options) {

    const defaults = {
      translations: {
        day: 'day',
        hour: 'hour',
        minute: 'minute',
        second: 'second',
        days: 'days',
        hours: 'hours',
        minutes: 'minutes',
        seconds: 'seconds',
      },
      showSeconds: false,
      showDays: true,
    };

    const plugin = this;

    plugin.settings = {};

    const mainInput = $(mainElement);

    plugin.init = function init() {
      plugin.settings = $.extend({}, defaults, options);

      const mainInputReplacer = $('<div>', {
        class: 'bdp-input',
        html: [
          buildDisplayBlock('days', !plugin.settings.showDays),
          buildDisplayBlock('hours', false, plugin.settings.showDays ? 23 : 99999),
          buildDisplayBlock('minutes', false, 59),
          buildDisplayBlock('seconds', !plugin.settings.showSeconds, 59),
        ],
      });

      mainInput.after(mainInputReplacer).hide();

      if (mainInput.val() === '') mainInput.val(0);
      setValue(mainInput.val(), true);
    };

    const inputs = [];
    const labels = [];
    const disabled = mainInput.hasClass('disabled') ||
      mainInput.attr('disabled') === 'disabled';

    let days = 0;
    let hours = 0;
    let minutes = 0;
    let seconds = 0;

    //
    // private methods
    //
    function translate(key) {
      return plugin.settings.translations[key];
    }

    function updateWordLabel(value, label) {
      const text = value === 1 ? label.substring(0, label.length - 1) : label;
      labels[label].text(translate(text));
    }

    function updateUI(isInitializing = false) {
      const total = seconds +
        minutes * 60 +
        hours * 60 * 60 +
        days * 24 * 60 * 60;
      mainInput.val(total);
      mainInput.change();

      updateWordLabel(days, 'days');
      updateWordLabel(hours, 'hours');
      updateWordLabel(minutes, 'minutes');
      updateWordLabel(seconds, 'seconds');

      inputs.days.val(days);
      inputs.hours.val(hours);
      inputs.minutes.val(minutes);
      inputs.seconds.val(seconds);

      if (typeof plugin.settings.onChanged === 'function') {
        plugin.settings.onChanged(mainInput.val(), isInitializing);
      }
    }

    function durationPickerChanged() {
      days = parseInt(inputs.days.val(), 10) || 0;
      hours = parseInt(inputs.hours.val(), 10) || 0;
      minutes = parseInt(inputs.minutes.val(), 10) || 0;
      seconds = parseInt(inputs.seconds.val(), 10) || 0;
      updateUI();
    }

    function buildDisplayBlock(id, hidden, max) {
      const input = $('<input>', {
        class: 'form-control input-sm',
        type: 'number',
        min: 0,
        value: 0,
        disabled,
      }).change(durationPickerChanged);

      if (max) {
        input.attr('max', max);
      }
      inputs[id] = input;

      const label = $('<div>', {
        id: `bdp-${id}-label`,
        text: translate(id),
      });
      labels[id] = label;

      return $('<div>', {
        class: `bdp-block ${hidden ? 'hidden' : ''}`,
        html: [input, label],
      });
    }

    function setValue(value, isInitializing) {
      mainInput.val(value);

      let total = parseInt(value, 10);
      seconds = total % 60;
      total = Math.floor(total / 60);
      minutes = total % 60;
      total = Math.floor(total / 60);

      if (plugin.settings.showDays) {
        hours = total % 24;
        days = Math.floor(total / 24);
      } else {
        hours = total;
        days = 0;
      }

      updateUI(isInitializing);
    }

    function getValue() { return mainInput.val(); }

    //
    // public methods
    //
    plugin.getValue = function() {
      return getValue();
    };

    plugin.setValue = function(value) {
      setValue(value, true);
    };

    plugin.destroy = function () {
      mainInput.next('.bdp-input').remove();
      mainInput.data('durationPicker', null).show();
    };

    plugin.init();
  };

  // eslint-disable-next-line no-param-reassign
  $.fn.durationPicker = function durationPicker(options) {
    return this.each(function() {
      if (undefined === $(this).data('durationPicker')) {
        const plugin = new $.DurationPicker(this, options);
        $(this).data('durationPicker', plugin);
      }
    });
  };

})(jQuery); // eslint-disable-line no-undef