'Is it possible to save form data to a data file on the local computer and then reload that text file back into a form to select those same items?

I have a rather extensive form that I use to create a 3-4 page report. There are times when, for one reason or another, I can't complete and submit the form to generate the report. Is it possible to somehow save the values from the form fields to a file on the local device and then, at a later date, reload that data back into the form so that all the same values are checked/selected/loaded? I'm assuming I would need some type of Javascript button that loops through and reads if items are checked or not, but I'm unsure of how to save and load that information. A short example of the form might be:

<form method="POST" action="processnote.php">

    <legend>
        <h1>Academic Background</h1>
    </legend>
    <b>Highest Education Level</b>
    <ul class="checkbox">
        <li><input type="checkbox" name="education[]" id="education0" value="no formal education"><label for="education0">No Formal Education</label></li>
        <li><input type="checkbox" name="education[]" id="education1" value="some high school"><label for="education1">Some High School</label></li>
        <li><input type="checkbox" name="education[]" id="education2" value="high school/GED"><label for="education2">High School</label></li>
        <li><input type="checkbox" name="education[]" id="education3" value="some college"><label for="education3">Some College</label></li>
        <li><input type="checkbox" name="education[]" id="education4" value="trade school"><label for="education4">Trade School</label></li>
        <li><input type="checkbox" name="education[]" id="education5" value="an associate degree"><label for="education5">Associate's Degree</label></li>
        <li><input type="checkbox" name="education[]" id="education6" value="a bachelor degree"><label for="education6">Bachelor's Degree</label></li>
        <li><input type="checkbox" name="education[]" id="education7" value="a master degree"><label for="education7">Master's Degree</label></li>
        <li><input type="checkbox" name="education[]" id="education8" value="a doctoral degree"><label for="education8">Doctoral Degree</label></li>
        <li><label for="education9">Other:</label><input type="text" name="education[]" id="education9" value=""></li>
    </ul>

    <p>
        <input type="submit" class="btn btn-default btn-lg" name="submit" value="Submit">
        <input type="reset" class="btn btn-default btn-lg" value="Reset">
    </p>
</form>

So, if "High School" and "Some College" were selected and in the text field "certificate program" was typed, how could I save those values to a file and then reload those values back into a clear copy of the form? Is it possible? (I know almost anything is possible...but you know...reasonably possible for a novice)



Solution 1:[1]

Quite complicated task, tested mostly in IE 11 ? Had some problems with FF during development, but now it seems to be working also in FF & Chrome, but not much tested there.

var myForm = document.forms[0],
  formData;
myForm.countries.selectedIndex = -1;
formData = getFormData(myForm[0]);

function saveForm(i) {
  var values = getFormData(i);

  // show JSON read
  document.getElementById("saving").innerText = JSON.stringify(values, null, 1)
    .replace(/\n "/g, '\n')
    .replace(/\n*[\{\}]\n*/g, '')
    .replace(/,\n/g, '\n')
    .replace(/([^"]+)":/g, '$1:');

  if (prompt('Clear data now ?', 'Yes will load them by file button') != null) setFormData(myForm, formData);

  return downloadObjectAsJson(values, "test");
}

function loadBack(t) {
  var f = t.files[0];

  var reader = new FileReader();
  // Closure to capture the file information.
  reader.onload = (function(theFile) {
    return function(e) {
      var json = JSON.parse(e.target.result);
      setFormData(myForm, json);
      return;
    }
  })(f);

  // Read in the image file as a data URL.
  reader.readAsText(f);
}

function setFormData(frm, values) {
  for (var v in values) {
    var el = frm[v],
      val = values[v];
    if (el.constructor == HTMLCollection) {
      // case "radio":
      //    values[el.name].checked = val;
      // break;
      for (var p = 0; p < el.length; p++) {
        el[p].checked = (el[p].value === val);
      }
    } else switch (el.type) {
      case "checkbox":
        el.checked = val;
        break;
      case 'select-one':
        if (val < 0) el.selectedIndex = val;
        else {
          for (var o = 0; o < el.options.length; o++) {
            if (el.options[o].value == val) el.selectedIndex = o;
          }
        }
        break;
      case 'select-multiple':
        for (var o = 0; o < el.options.length; o++) {
          el.options[o].selected = (val.indexOf(el.options[o].value) > -1);
        }
        break;
      default:
        el.value = val;
    }
  }
}

function getFormData(i) {
  var frm = i.form;
  var values = {};
  for (var a = 0; a < frm.length; a++) {
    var el = frm[a];
    switch (el.type) {
      case "checkbox":
        values[el.name] = el.checked;
        break;
      case "radio":
        if (el.checked) values[el.name] = el.value;
        else if (values[el.name] === undefined) values[el.name] = false;
        break;
      case 'select-one':
        values[el.name] = el.selectedIndex < 0 ? -1 : el.options[el.selectedIndex].value;
        break;
      case 'select-multiple':
        values[el.name] = [];
        for (var i = 0; i < el.options.length; i++) {
          if (el.options[i].selected) values[el.name].push(el.options[i].value);
        }
        break;
      case 'fieldset':
        break;
      case 'button':
        break;
      case 'submit':
        break;
      case 'reset':
        break;
      case 'file':
        break;
      case undefined:
        break;
      default:
        values[el.name] = el.value;
    }
  }
  return values;
}

function downloadObjectAsJson(exportObj, exportName) {
  if (navigator.msSaveBlob) { // IE10+
    var blob = new Blob([JSON.stringify(exportObj, null, 1)], {
      type: 'application/json'
    });
    return navigator.msSaveBlob(blob, exportName + ".json");
  }
  var dataStr = "data:application/json;charset=utf-8," + encodeURIComponent(JSON.stringify(exportObj, null, 1));
  var downloadAnchorNode = document.getElementsByName('_saveAnchor')[0];
  downloadAnchorNode.setAttribute("href", dataStr);
  downloadAnchorNode.setAttribute("download", exportName + ".json");
  downloadAnchorNode.click();
  downloadAnchorNode.remove();
}
<!-- form elements from https://www.fincher.org/tips/web/SimpleForm.shtml -->
<form>
   First Name: <input type="text" name="FirstName"/><br />
   <textarea name="comments"></textarea><br />
   Password:<input type="password" name="mypassword" value="start"/> „start“ as test value you can get from server<br />
   <input type="radio" name="title" value="mr" />Mr.<br />
   <input type="radio" name="title" value="ms" />Ms.<br />
   <input type="radio" name="title" value="decline"/>decline<br />
   <fieldset style="margin: 1em; text-align: center;">
      <legend>Select a Hero</legend>
      <input type="radio" name="hero"  value="Agamemnon" /> Agamemnon
      <input type="radio" name="hero"  value="Achilles" /> Achilles
      <input type="radio" name="hero"  value="Hector" /> Hector
      <div style="height: 1em;" />
   </fieldset>
   <input type="checkbox" name="mail" />Mail me more info<br />
   <input type="checkbox" name="e-mail" />E-Mail me more info<br />
      <select name="countries">
      <option>Argentina</option>
      <option>Albania</option>
      <option>Afganistain</option>
      <option>Aruba</option>
   </select>
   <select name="menuitems">
      <optgroup id="opt1" label="food">
         <option>Hamburgers</option>
         <option>Hotdogs</option>
      </optgroup>
      <optgroup id="opt2" label="drinks">
         <option>Coke</option>
         <option>Pepsi</option>
         <option>Water</option>
      </optgroup>
   </select>
   <select name="computerbrands" multiple="multiple">
      <option value="DELL">DELL</option>
      <option value="IBM">IBM</option>
      <option value="HP">HP</option>
      <option value="Compaq">Compaq</option>
      <option value="Sony">Sony</option>
   </select>
   <select name="countries2" size="4">
      <option value="0">Argentina</option>
      <option value="1">Albania</option>
      <option value="2">Afganistain</option>
      <option value="3">Aruba</option>
      <option value="4">Arabia</option>
   </select>
   <input type="hidden" name="computerType" value="hidden DELL" />
   <input type="submit" name="submitbutton" value="Submit" />
   <a name="_saveAnchor"><input type="button" value="Save content as JSON" onclick="saveForm(this)"></a>
   <input type="file" name="formFile" onchange="loadBack(this)"/>
</form>
<div id="saving"></div>

Made 2 new bookmarklets, only problem is to find proper form...

This 1 will save longest form to JSON

javascript:f=document.forms,longest=0;frm=0;for(i=0;i<f.length;i++)if(f[i].length>longest){longest=f[i].length;frm=f[i]}values={};for(a=0;a<longest;a++){el=frm[a];switch(el.type){case"checkbox":values[el.name]=el.checked;break;case"radio":if(el.checked)values[el.name]=el.value;else if(values[el.name]===undefined)values[el.name]=false;break;case'select-one':values[el.name]=el.selectedIndex<0?-1:el.options[el.selectedIndex].value;break;case'select-multiple':values[el.name]=[];for(i=0;i<el.options.length;i++){if(el.options[i].selected)values[el.name].push(el.options[i].value)}break;case'fieldset':break;case'button':break;case'submit':break;case'reset':break;case'file':break;case undefined:break;default:values[el.name] = el.value}}dataStr="data:application/json;charset=utf-8,"+encodeURIComponent(JSON.stringify(values));dwn=document.createElement('A');dwn.setAttribute("href",dataStr);dwn.setAttribute("download",location.href.split('/').pop()+".json");dwn.click();dwn.remove();undefined

Or formatted content

f = document.forms, longest = 0; frm = 0;
for (i = 0; i < f.length; i++)
    if (f[i].length > longest) { longest = f[i].length; frm = f[i] }
values = {};
for (a = 0; a < longest; a++) {
    el = frm[a];
    switch (el.type) {
        case "checkbox": values[el.name] = el.checked;
            break;
        case "radio":
            if (el.checked)
                values[el.name] = el.value;
            else if (values[el.name] === undefined)
                values[el.name] = false;
            break;
        case 'select-one': values[el.name] = el.selectedIndex < 0 ? -1 : el.options[el.selectedIndex].value; break;
        case 'select-multiple': values[el.name] = [];
            for (i = 0; i < el.options.length; i++) {
                if (el.options[i].selected)
                    values[el.name].push(el.options[i].value)
            }
            break;
        case 'fieldset': break;
        case 'button': break;
        case 'submit': break;
        case 'reset': break;
        case 'file': break;
        case undefined: break;
        default: values[el.name] = el.value
    }
} dataStr = "data:application/json;charset=utf-8," + encodeURIComponent(JSON.stringify(values));
dwn = document.createElement('A');
dwn.setAttribute("href", dataStr);
dwn.setAttribute("download", location.href.split('/').pop() + ".json");
dwn.click();
dwn.remove(); undefined

And this will read form from JSON

javascript:function setFormData(values){f=document.forms,longest=0;frm=0;for(i=0;i<f.length;i++)if(f[i].length>longest){longest=f[i].length;frm=f[i]}for(v in values){el=frm[v];val=values[v];if(el.constructor==HTMLCollection){for(p=0;p<el.length;p++){el[p].checked=(el[p].value===val)}}else switch(el.type){case"checkbox":el.checked=val;break;case'select-one':if(val<0)el.selectedIndex=val;else{for(o=0;o<el.options.length;o++){if(el.options[o].value==val)el.selectedIndex=o}}break;case'select-multiple':for(o=0;o<el.options.length;o++){el.options[o].selected=(val.indexOf(el.options[o].value)>-1)}break;default:el.value=val}}}f=document.createElement("input");f.type="file";f.onchange=(function(){reader=new FileReader();reader.onload=(function(theFile){return function(e){json = JSON.parse(e.target.result);setFormData(json);return;}})(event.srcElement.files[0]);reader.readAsText(event.srcElement.files[0]);});document.body.prepend(f);f.focus();

And this one:

function setFormData(values) {
    f = document.forms, longest = 0; frm = 0;
    for (i = 0; i < f.length; i++)
        if (f[i].length > longest) {
            longest = f[i].length; frm = f[i]
        }
    for (v in values) {
        el = frm[v]; val = values[v];
        if (el.constructor == HTMLCollection) {
            for (p = 0; p < el.length; p++) {
                el[p].checked = (el[p].value === val)
            }
        } else switch (el.type) {
            case "checkbox": el.checked = val;
                break;
            case 'select-one':
                if (val < 0) el.selectedIndex = val;
                else {
                    for (o = 0; o < el.options.length; o++) {
                        if (el.options[o].value == val) el.selectedIndex = o
                    }
                }
                break;
            case 'select-multiple':
                for (o = 0; o < el.options.length; o++) {
                    el.options[o].selected = (val.indexOf(el.options[o].value) > -1)
                }
                break;
            default: el.value = val
        }
    }
}
f = document.createElement("input");
f.type = "file";
f.onchange = (function () {
    reader = new FileReader();
    reader.onload = (function (theFile) {
        return function (e) {
            json = JSON.parse(e.target.result);
            setFormData(json);
            return;
        }
    })(event.srcElement.files[0]);
    reader.readAsText(event.srcElement.files[0]);
});
document.body.prepend(f);
f.focus();

Made another 2 bookmarklets, now using aria-label & className (hasOutput), etc.

javascript:f=document.forms,longest=0;frm=0;for(i=0;i<f.length;i++)if(f[i].length>longest){longest=f[i].length;frm=f[i]}values={};for(a=0;a<longest;a++){el=frm[a];switch(el.type){case "checkbox":values[el.name]=el.checked;break;case "radio":if(el.checked)values[el.name]=el.value;else if(values[el.name]===undefined){values[el.name]=false;continue}break;case "select-one":values[el.name]=el.selectedIndex<0?-1:el.options[el.selectedIndex].value;break;case "select-multiple":values[el.name]=[];for(i=0;i<el.options.length;i++){if(el.options[i].selected)values[el.name].push(el.options[i].value)}break;case "fieldset":case "button":case "submit":case "reset":case "file":case "hidden":case undefined:continue;default:values[el.name]=el.value}var old=values[el.name];delete values[el.name];if(!old)continue;var names=[],passed={};do{var el2=el;do{if(el2.className=="hasOutput"&&!passed[el2.innerText]){names.push(el2.innerText);passed[el2.innerText]=1}el2=el2.firstElementChild}while(el2)if(el.ariaLabel&&!passed[el.ariaLabel]){names.push(el.ariaLabel.trim());passed[el.ariaLabel]=1}}while(el=el.parentElement)if(names[0]=="M?na"&&old=="aed")continue;names.reverse();el=values;for(b=0;b<names.length-1;b++){if(!el[names[b]])el[names[b]]={};el=el[names[b]]}el[names[names.length-1]]=old}dataStr="data:application/json;charset=utf-8,"+encodeURIComponent(JSON.stringify(values));dwn=document.createElement("A");dwn.setAttribute("href",dataStr);dwn.setAttribute("download",location.href.split("/").pop()+".json");dwn.click();dwn.remove();undefined

f = document.forms, longest = 0; frm = 0;
for (i = 0; i < f.length; i++)
    if (f[i].length > longest) { longest = f[i].length; frm = f[i] }
values = {};
for (a = 0; a < longest; a++) {
    el = frm[a];
    switch (el.type) {
        case "checkbox": values[el.name] = el.checked;
            break;
        case "radio":
            if (el.checked)
                values[el.name] = el.value;
            else if (values[el.name] === undefined)
            {
                values[el.name] = false;
                continue;
            }
            break;
        case "select-one": values[el.name] = el.selectedIndex < 0 ? -1 : el.options[el.selectedIndex].value; break;
        case "select-multiple": values[el.name] = [];
            for (i = 0; i < el.options.length; i++) {
                if (el.options[i].selected)
                    values[el.name].push(el.options[i].value)
            }
            break;
        case "fieldset":
        case "button":
        case "submit":
        case "reset":
        case "file":
        case "hidden":
        case undefined:
            continue;
            break;
        default: values[el.name] = el.value
    }
    var old = values[el.name];
    delete values[el.name];
    if (!old) continue;
    var names = [], passed = {};
    do {
        var el2 = el;
        do {
            if (el2.className == "hasOutput" && !passed[el2.innerText])
            {
                names.push(el2.innerText);
                passed[el2.innerText] = 1;
            }
            el2 = el2.firstElementChild;
        } while (el2)
        if (el.ariaLabel && !passed[el.ariaLabel])
        {
            names.push(el.ariaLabel.trim());
            passed[el.ariaLabel] = 1;
        }
    } while (el = el.parentElement)
    if (names[0] == "M?na" && old == "aed") continue;
    names.reverse();
    el = values;
    for(b = 0; b < names.length - 1; b++)
    {
        if (!el[names[b]])
            el[names[b]] = {}
        el = el[names[b]];
    }
    el[names[names.length-1]] = old;
}
dataStr = "data:application/json;charset=utf-8," + encodeURIComponent(JSON.stringify(values));
dwn = document.createElement("A");
dwn.setAttribute("href", dataStr);
dwn.setAttribute("download", location.href.split("/").pop() + ".json");
dwn.click();
dwn.remove(); undefined

And back by

javascript:function setFormData(valuesBack){f=document.forms,longest=0;frm=0;for(i=0;i<f.length;i++)if(f[i].length>longest){longest=f[i].length;frm=f[i]}values={};for(a=0;a<longest;a++){el=frm[a];switch(el.type){case "checkbox":values[el.name]=el;break;case "radio":if(el.checked)values[el.name]=el;else if(values[el.name]===undefined){values[el.name]=el;continue}break;case "select-one":values[el.name]=el;break;case "select-multiple":values[el.name]=el;break;case "fieldset":case "button":case "submit":case "reset":case "file":case "hidden":case undefined:continue;break;default:values[el.name]=el}var names=[],passed={};var oldEl=values[el.name];do{var el2=el;do{if(el2.className=="hasOutput"&&!passed[el2.innerText]){names.push(el2.innerText);passed[el2.innerText]=1}el2=el2.firstElementChild}while(el2)if(el.ariaLabel&&!passed[el.ariaLabel]){names.push(el.ariaLabel.trim());passed[el.ariaLabel]=1}}while(el=el.parentElement)names.reverse();el=valuesBack;for(b=0;b<names.length&&el;b++){el=el[names[b]]}if(el===undefined)continue;val=el;el=oldEl;if(el.constructor==HTMLCollection){for(p=0;p<el.length;p++){el[p].checked=(el[p].value===val)}}else switch(el.type){case "checkbox":el.checked=val;break;case "select-one":if(val<0)el.selectedIndex=val;else{for(o=0;o<el.options.length;o++){if(el.options[o].value==val)el.selectedIndex=o}}break;case "select-multiple":for(o=0;o<el.options.length;o++){el.options[o].selected=(val.indexOf(el.options[o].value)>-1)}break;default:el.value=val}}}f=document.createElement("input");f.type="file";f.onchange=(function(){reader=new FileReader();reader.onload=(function(theFile){return function(e){json=JSON.parse(e.target.result);setFormData(json);return}})(event.srcElement.files[0]);reader.readAsText(event.srcElement.files[0])});document.body.prepend(f);f.focus();

function setFormData(valuesBack) {
    f = document.forms, longest = 0; frm = 0;
    for (i = 0; i < f.length; i++)
        if (f[i].length > longest) { longest = f[i].length; frm = f[i] }
    values = {};
    for (a = 0; a < longest; a++) {
        el = frm[a];
        switch (el.type) {
            case "checkbox": values[el.name] = el;
                break;
            case "radio":
                if (el.checked)
                    values[el.name] = el;
                else if (values[el.name] === undefined)
                {
                    values[el.name] = el;
                    continue;
                }
                break;
            case "select-one": values[el.name] = el; break;
            case "select-multiple": values[el.name] = el;
                break;
            case "fieldset":
            case "button":
            case "submit":
            case "reset":
            case "file":
            case "hidden":
            case undefined:
                continue;
                break;
            default: values[el.name] = el
        }
        var names = [], passed = {};
        var oldEl = values[el.name];
        do {
            var el2 = el;
            do {
                if (el2.className == "hasOutput" && !passed[el2.innerText])
                {
                    names.push(el2.innerText);
                    passed[el2.innerText] = 1;
                }
                el2 = el2.firstElementChild;
            } while (el2)
            if (el.ariaLabel && !passed[el.ariaLabel])
            {
                names.push(el.ariaLabel.trim());
                passed[el.ariaLabel] = 1;
            }
        } while (el = el.parentElement)
        names.reverse();
        el = valuesBack;
        for(b = 0; b < names.length && el; b++)
        {
            el = el[names[b]];
        }
        if (el === undefined) continue;
        val = el; el = oldEl;

        if(val === true) val = false;
        else val = val.split('').reverse().join('');

        if (el.constructor == HTMLCollection) {
            for (p = 0; p < el.length; p++) {
                el[p].checked = (el[p].value === val)
            }
        } else switch (el.type) {
            case "checkbox": el.checked = val;
                break;
            case "select-one":
                if (val < 0) el.selectedIndex = val;
                else {
                    for (o = 0; o < el.options.length; o++) {
                        if (el.options[o].value == val) el.selectedIndex = o
                    }
                }
                break;
            case "select-multiple":
                for (o = 0; o < el.options.length; o++) {
                    el.options[o].selected = (val.indexOf(el.options[o].value) > -1)
                }
                break;
            default: el.value = val
        }
        }
}
f = document.createElement("input");
f.type = "file";
f.onchange = (function () {
    reader = new FileReader();
    reader.onload = (function (theFile) {
        return function (e) {
            json = JSON.parse(e.target.result);
            setFormData(json);
            return;
        }
    })(event.srcElement.files[0]);
    reader.readAsText(event.srcElement.files[0]);
});
document.body.prepend(f);
f.focus();

Solution 2:[2]

There are multiple solutions to do what you're asking, the issue is data persistence. I would encourage a solution that saves the form submissions, and in-progress form submissions, to be saved to a DB or the cloud. We can talk about those if you're interested.

Generally, web browsers weren't made to create, save, and load data simply on the client. A server would be involved with the process. However, there is the option to use local storage on any modern browser. It's much more robust than using cookies. To get you started, take a look, at this example:

https://www.telerik.com/blogs/save-for-later-feature-in-forms-using-localstorage

It would also need an ID (like a date/time stamp) for each form submission, and a dialog box to pick which one to load, or create a new form submission.

Sources

This article follows the attribution requirements of Stack Overflow and is licensed under CC BY-SA 3.0.

Source: Stack Overflow

Solution Source
Solution 1
Solution 2 Tom C