ocadotechnology/hexagonjs

Modal: hx.modal.input should behave the same as prompt()

Opened this issue · 0 comments

Context

The prompt() function in JS shows a popup with confirm/cancel buttons, focuses the input box and also allows the user to press escape/enter to cancel/confirm the prompt.

The hx.modal.input should have the same behaviour.

Workaround

Coffeescript

makeButtons = (container, buttons, modal, callback) ->
  buttons.forEach (d) ->
    container.append('button')
      .attr('type', 'button')
      .class(d.classes)
      .add(hx.detached('i').class(d.icon))
      .add(hx.detached('span').text(' ' + d.text))
      .on 'click', 'hx.modal', ->
        callback?(d.value)
        modal.hide()
  return

modalInput = (title, message, callback, options) ->
  options = hx.merge.defined {
    value: ''
  }, options

  setup = (element) ->
    buttons = [
      {text: 'Cancel', icon: 'hx-icon hx-icon-close', value: false, classes: 'hx-btn hx-negative', key: 'Escape' }
      {text: 'Confirm', icon: 'hx-icon hx-icon-check', value: true, classes: 'hx-btn hx-positive', key: 'Enter' }
    ]
    container = hx.select(element)
    message = container.append('span').class('hx-modal-message').text(message)
    input = container.append('input').class('hx-modal-input').text(this.options.value)

    response = (res) ->
      if res then callback(input.value()) else callback(res)

    buttonContainer = container.append('div').class('hx-modal-buttons')
    makeButtons buttonContainer, buttons, this, response

    hx.select(window).on 'keydown', 'hx.modal', (event) ->
      switch event.key
        when 'Enter', 'Escape'
          response(buttons.find(({key}) -> key is event.key).value)
          modal.hide()

  modal = new hx.Modal title, setup, {
    closeWithShadeEnabled: options.closeWithShadeEnabled,
    closeButtonEnabled: options.closeButtonEnabled
  }
  modal.on 'showend', 'hx.modal', () ->
    modal.contentContainer.select('input').node().focus()

  modal.on 'close', 'hx.modal', (d) ->
    if d.cause isnt 'api' then callback()

  modal.on 'hide', 'hx.modal', () ->
    hx.select(window).off('keydown', 'hx.modal')

  modal.show()

Javascript

var makeButtons, modalInput;

makeButtons = function(container, buttons, modal, callback) {
  buttons.forEach(function(d) {
    return container.append('button').attr('type', 'button').class(d.classes).add(hx.detached('i').class(d.icon)).add(hx.detached('span').text(' ' + d.text)).on('click', 'hx.modal', function() {
      if (typeof callback === "function") {
        callback(d.value);
      }
      return modal.hide();
    });
  });
};

modalInput = function(title, message, callback, options) {
  var modal, setup;
  options = hx.merge.defined({
    value: ''
  }, options);
  setup = function(element) {
    var buttonContainer, buttons, container, input, response;
    buttons = [
      {
        text: 'Cancel',
        icon: 'hx-icon hx-icon-close',
        value: false,
        classes: 'hx-btn hx-negative',
        key: 'Escape'
      },
      {
        text: 'Confirm',
        icon: 'hx-icon hx-icon-check',
        value: true,
        classes: 'hx-btn hx-positive',
        key: 'Enter'
      }
    ];
    container = hx.select(element);
    message = container.append('span').class('hx-modal-message').text(message);
    input = container.append('input').class('hx-modal-input').text(this.options.value);
    response = function(res) {
      if (res) {
        return callback(input.value());
      } else {
        return callback(res);
      }
    };
    buttonContainer = container.append('div').class('hx-modal-buttons');
    makeButtons(buttonContainer, buttons, this, response);
    return hx.select(window).on('keydown', 'hx.modal', function(event) {
      switch (event.key) {
        case 'Enter':
        case 'Escape':
          response(buttons.find(function({key}) {
            return key === event.key;
          }).value);
          return modal.hide();
      }
    });
  };
  modal = new hx.Modal(title, setup, {
    closeWithShadeEnabled: options.closeWithShadeEnabled,
    closeButtonEnabled: options.closeButtonEnabled
  });
  modal.on('showend', 'hx.modal', function() {
    return modal.contentContainer.select('input').node().focus();
  });
  modal.on('close', 'hx.modal', function(d) {
    if (d.cause !== 'api') {
      return callback();
    }
  });
  modal.on('hide', 'hx.modal', function() {
    return hx.select(window).off('keydown', 'hx.modal');
  });
  return modal.show();
};

Your Environment

  • Hexagon Version: 1.17.1