docs: function formToData(formEl) {
      var app = this;
      var $formEl = $(formEl).eq(0);
      if ($formEl.length === 0) { return undefined; }
  
      // Form data
      var data = {};
  
      // Skip input types
      var skipTypes = ['submit', 'image', 'button', 'file'];
      var skipNames = [];
      $formEl.find('input, select, textarea').each(function (inputIndex, inputEl) {
        var $inputEl = $(inputEl);
        if ($inputEl.hasClass('ignore-store-data') || $inputEl.hasClass('no-store-data')) {
          return;
        }
        var name = $inputEl.attr('name');
        var type = $inputEl.attr('type');
        var tag = inputEl.nodeName.toLowerCase();
        if (skipTypes.indexOf(type) >= 0) { return; }
        if (skipNames.indexOf(name) >= 0 || !name) { return; }
        if (tag === 'select' && $inputEl.prop('multiple')) {
          skipNames.push(name);
          data[name] = [];
          $formEl.find(("select[name=\"" + name + "\"] option")).each(function (index, el) {
            if (el.selected) { data[name].push(el.value); }
          });
        } else {
          switch (type) {
            case 'checkbox':
              skipNames.push(name);
              data[name] = [];
              $formEl.find(("input[name=\"" + name + "\"]")).each(function (index, el) {
                if (el.checked) { data[name].push(el.value); }
              });
              break;
            case 'radio':
              skipNames.push(name);
              $formEl.find(("input[name=\"" + name + "\"]")).each(function (index, el) {
                if (el.checked) { data[name] = el.value; }
              });
              break;
            default:
              data[name] = $inputEl.val();
              break;
          }
        }
      });
      $formEl.trigger('form:todata', data);
      app.emit('formToData', $formEl[0], data);
  
      return data;
    }