text: import {Utils} from '@wiajs/core';
  
  // Form Data
  const FormData = {
    store(form, data) {
      const app = this;
      let formId = form;
  
      const $formEl = $(form);
      if ($formEl.length && $formEl.is('form') && $formEl.attr('id')) {
        formId = $formEl.attr('id');
      }
      // Store form data in app.formsData
      app.form.data[`form-${formId}`] = data;
  
      // Store form data in local storage also
      window.localStorage[`f7form-${formId}`] = JSON.stringify(data);
    },
    get(form) {
      const app = this;
      let formId = form;
  
      const $formEl = $(form);
      if ($formEl.length && $formEl.is('form') && $formEl.attr('id')) {
        formId = $formEl.attr('id');
      }
  
      if (window.localStorage[`f7form-${formId}`]) {
        return JSON.parse(window.localStorage[`f7form-${formId}`]);
      }
      if (app.form.data[`form-${formId}`]) {
        return app.form.data[`form-${formId}`];
      }
      return undefined;
    },
    remove(form) {
      const app = this;
      let formId = form;
  
      const $formEl = $(form);
      if ($formEl.length && $formEl.is('form') && $formEl.attr('id')) {
        formId = $formEl.attr('id');
      }
  
      // Delete form data from app.formsData
      if (app.form.data[`form-${formId}`]) {
        app.form.data[`form-${formId}`] = '';
        delete app.form.data[`form-${formId}`];
      }
  
      // Delete form data from local storage also
      if (window.localStorage[`f7form-${formId}`]) {
        window.localStorage[`f7form-${formId}`] = '';
        window.localStorage.removeItem(`f7form-${formId}`);
      }
    },
  };
  
  // Form Storage
  const FormStorage = {
    init(formEl) {
      const app = this;
      const $formEl = $(formEl);
      const formId = $formEl.attr('id');
      if (!formId) return;
      const initialData = app.form.getFormData(formId);
      if (initialData) {
        app.form.fillFromData($formEl, initialData);
      }
      function store() {
        const data = app.form.convertToData($formEl);
        if (!data) return;
        app.form.storeFormData(formId, data);
        $formEl.trigger('form:storedata', data);
        app.emit('formStoreData', $formEl[0], data);
      }
      $formEl.on('change submit', store);
    },
    destroy(formEl) {
      const $formEl = $(formEl);
      $formEl.off('change submit');
    },
  };
  
  // Form To/From Data
  function formToData(formEl) {
    const app = this;
    const $formEl = $(formEl).eq(0);
    if ($formEl.length === 0) return undefined;
  
    // Form data
    const data = {};
  
    // Skip input types
    const skipTypes = ['submit', 'image', 'button', 'file'];
    const skipNames = [];
    $formEl.find('input, select, textarea').each((inputIndex, inputEl) => {
      const $inputEl = $(inputEl);
      if ($inputEl.hasClass('ignore-store-data') || $inputEl.hasClass('no-store-data')) {
        return;
      }
      const name = $inputEl.attr('name');
      const type = $inputEl.attr('type');
      const 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((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((index, el) => {
              if (el.checked) data[name].push(el.value);
            });
            break;
          case 'radio':
            skipNames.push(name);
            $formEl.find(`input[name="${name}"]`).each((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;
  }
  function formFromData(formEl, formData) {
    const app = this;
    const $formEl = $(formEl).eq(0);
    if (!$formEl.length) return;
  
    let data = formData;
    const formId = $formEl.attr('id');
  
    if (!data && formId) {
      data = app.form.getFormData(formId);
    }
  
    if (!data) return;
  
    // Skip input types
    const skipTypes = ['submit', 'image', 'button', 'file'];
    const skipNames = [];
  
    $formEl.find('input, select, textarea').each((inputIndex, inputEl) => {
      const $inputEl = $(inputEl);
      if ($inputEl.hasClass('ignore-store-data') || $inputEl.hasClass('no-store-data')) {
        return;
      }
      const name = $inputEl.attr('name');
      const type = $inputEl.attr('type');
      const tag = inputEl.nodeName.toLowerCase();
      if (typeof data[name] === 'undefined' || data[name] === null) return;
      if (skipTypes.indexOf(type) >= 0) return;
      if (skipNames.indexOf(name) >= 0 || !name) return;
      if (tag === 'select' && $inputEl.prop('multiple')) {
        skipNames.push(name);
        $formEl.find(`select[name="${name}"] option`).each((index, el) => {
          const selectEl = el;
          if (data[name].indexOf(el.value) >= 0) selectEl.selected = true;
          else selectEl.selected = false;
        });
      } else {
        switch (type) {
          case 'checkbox':
            skipNames.push(name);
            $formEl.find(`input[name="${name}"]`).each((index, el) => {
              const checkboxEl = el;
              if (data[name].indexOf(el.value) >= 0) checkboxEl.checked = true;
              else checkboxEl.checked = false;
            });
            break;
          case 'radio':
            skipNames.push(name);
            $formEl.find(`input[name="${name}"]`).each((index, el) => {
              const radioEl = el;
              if (data[name] === el.value) radioEl.checked = true;
              else radioEl.checked = false;
            });
            break;
          default:
            $inputEl.val(data[name]);
            break;
        }
      }
      if (tag === 'select' || tag === 'input' || tag === 'textarea') {
        $inputEl.trigger('change', 'fromdata');
      }
    });
    $formEl.trigger('form:fromdata', data);
    app.emit('formFromData', $formEl[0], data);
  }
  
  function initAjaxForm() {
    const app = this;
  
    function onSubmitChange(e, fromData) {
      const $formEl = $(this);
      if (e.type === 'change' && !$formEl.hasClass('form-ajax-submit-onchange')) return;
      if (e.type === 'submit') e.preventDefault();
  
      if (e.type === 'change' && fromData === 'fromdata') return;
  
      const method = ($formEl.attr('method') || 'GET').toUpperCase();
      const contentType = $formEl.prop('enctype') || $formEl.attr('enctype');
  
      const url = $formEl.attr('action');
      if (!url) return;
  
      let data;
      if (method === 'POST') {
        if (contentType === 'application/x-www-form-urlencoded') {
          data = app.form.convertToData($formEl[0]);
        } else {
          data = new window.FormData($formEl[0]);
        }
      } else {
        data = Utils.serializeObject(app.form.convertToData($formEl[0]));
      }
  
      app.request({
        method,
        url,
        contentType,
        data,
        beforeSend(xhr) {
          $formEl.trigger('formajax:beforesend', { data, xhr });
          app.emit('formAjaxBeforeSend', $formEl[0], data, xhr);
        },
        error(xhr) {
          $formEl.trigger('formajax:error', { data, xhr });
          app.emit('formAjaxError', $formEl[0], data, xhr);
        },
        complete(xhr) {
          $formEl.trigger('formajax:complete', { data, xhr });
          app.emit('formAjaxComplete', $formEl[0], data, xhr);
        },
        success(response, status, xhr) {
          $formEl.trigger('formajax:success', { data, xhr });
          app.emit('formAjaxSuccess', $formEl[0], data, xhr);
        },
      });
    }
    $(document).on('submit change', 'form.form-ajax-submit, form.form-ajax-submit-onchange', onSubmitChange);
  }
  
  export default {
    name: 'form',
    create() {
      const app = this;
      Utils.extend(app, {
        form: {
          data: {},
          storeFormData: FormData.store.bind(app),
          getFormData: FormData.get.bind(app),
          removeFormData: FormData.remove.bind(app),
          convertToData: formToData.bind(app),
          fillFromData: formFromData.bind(app),
          storage: {
            init: FormStorage.init.bind(app),
            destroy: FormStorage.destroy.bind(app),
          },
        },
      });
    },
    on: {
      init() {
        const app = this;
        initAjaxForm.call(app);
      },
      tabBeforeRemove(tabEl) {
        const app = this;
        $(tabEl).find('.form-store-data').each((index, formEl) => {
          app.form.storage.destroy(formEl);
        });
      },
      tabMounted(tabEl) {
        const app = this;
        $(tabEl).find('.form-store-data').each((index, formEl) => {
          app.form.storage.init(formEl);
        });
      },
      pageBeforeRemove(page) {
        const app = this;
        page.$el.find('.form-store-data').each((index, formEl) => {
          app.form.storage.destroy(formEl);
        });
      },
      pageInit(page) {
        const app = this;
        page.$el.find('.form-store-data').each((index, formEl) => {
          app.form.storage.init(formEl);
        });
      },
    },
  };
  