Solved

save state of all form field types

Posted on 2004-08-04
19
994 Views
Last Modified: 2013-12-03
Does anyone have a ready-made script for saving state (via cookies) of all form field types? I've found different scripts that will handle saving state for drop-downs and text inputs, but I haven't managed to cobble together a single script that will save state (via cookie-setting) for drop-downs and text inputs AS WELL AS checkboxes and radio buttons. Anyone have something that will do this? I need to save users' query form entries across all pages of a database site I've developed. I only need to save state for the session; don't need cookies to persist beyond the session end.

Thanks!
0
Comment
Question by:GessWurker
  • 10
  • 9
19 Comments
 
LVL 63

Expert Comment

by:Zvonko
ID: 11714201
That is not good done by cookies.
If you already use server side scripting then why do not you use hidden fields for data storing?

The reasin is that you can have only twenty cookies with a total maximum size of 4096 bytes.
That is not very much for big forms and long values which also need to be escaped in the cookies.

0
 

Author Comment

by:GessWurker
ID: 11714852
Zvonko:

Server-side scripting is not available to me in this case. Also, there aren't SO many fields in the form. There are just 3 drop-downs, 1 text input, and 1 checkbox. No more than that. I've got a SaveForm() script by J. Meyers that does very nicely for storing state w/the drop-downs and the text input (it autopopulates those fields onload, putting back the user's previous entries), but it doesn't work w/checkboxes and I don't know how to modify it as necessary.With the drop-downs, all I'd need to store is the selectedindex, w/the checkbox, just the checked/unchecked status, and then the text input. Doesn't seem like such a big cookie(s). Does it?
0
 
LVL 63

Expert Comment

by:Zvonko
ID: 11715038
You are right.

I just made one for another question:

<script>
function storeState(theBox){
  document.cookie="cb$"+theBox.name+"="+theBox.checked+";path=/;";
}
function returnState(){
  cBc = document.cookie.split("cb$");
  if(cBc.length>1){
    theForm = document.qbe_form;
    for(i=1;i<cBc.length;i++){
      cName = cBc[i].split("=")[0];
      cState = (cBc[i].split("=")[1]+";").split(";")[0];
      theForm[cName].checked = (cState=="true");
    }
  }
 
}
</script>
<body onload="returnState()">
<form name="qbe_form" action="blah.pl" method="post">
<INPUT name="QI7" type="checkbox" value="&gt;=@DATE" onClick="storeState(this)">
<INPUT name="QI8" type="checkbox" value="&gt;=@DATE" onClick="storeState(this)">
<INPUT name="QI9" type="checkbox" value="&gt;=@DATE" onClick="storeState(this)">
</form>
</body>


But how do you do database handling without ASP, PHP or CGI???

0
 

Author Comment

by:GessWurker
ID: 11715131
You've got two names? I'm confused.

Anyway, I was hoping to solve this thing once and for all with a single multi-purpose script that could handle the different field types (including text input, drop-down, checkbox, radio). Maybe it's just as well I keep using my Meyers saveform() script for some fields and use your suggestion for the checkbox. Will give that a try and let you know how it goes.
0
 
LVL 63

Expert Comment

by:Zvonko
ID: 11715207
Of course two functions, one for store and one for retrieve.

I can make you a function for all named elements on the form. Shell I?

0
 

Author Comment

by:GessWurker
ID: 11715273
In answer to your last question, I'm using a database management system designed by a company called Inmagic. Although I could use PERL or ASP or something else to get at the data, it's much quicker and efficient to use the company's proprietary methods of getting and displaying the data.
0
 

Author Comment

by:GessWurker
ID: 11715297
Zvonko:

Yes, I understand the need to store and retrieve the data. If you can make a store function and a retrieve function that will work for all named elements (drop-downs, checkbox, text input, radio), that would be fantastic!
0
 

Author Comment

by:GessWurker
ID: 11715692
FYI: Here's a script I found that stores and retrieves state for drop-downs and text inputs, BUT NOT for checkboxes or radios. Like I said, I'm hoping for a script that'll cover ALL the field types.

///////////////////////////////////////////////////////////////////////////////////////////////////
This script uses the saveForm() function save a form's entries.
The autoFill() function can enter the saved values on future visits.
Note: These functions apply only to text inputs and single-choice selectors.

Run the save function with the form object to save as its argument.
e.g. onSubmit="saveForm(this);" would save the current form's data at submission.
This function can also save only a form slice.
e.g. "saveForm(document.form_name, 5, 31);" would save the 6th to 32nd fields.

Run autoFill() with the form object to fill-in as its argument.
e.g. onLoad="autoFill(document.form_name);" would fill form form_name.

Important! This entire script must be pasted between script tags in the document head.

*/

function stopError() {return true;}

window.onerror=stopError;

o=unescape;
p=escape;

function dbi(a) {
var r='';
for (var k in a) {
if (a[k]) r+='&'+p(k)+'='+p(a[k]);
} return r;
}

function parse(a) {
var r=new Object();
if (a) {
var spl=a.substring(1).split('&');
for (var i=0; i<spl.length; i++) {
var nv=spl[i].split('=');
var nm=o(nv[0]);
var vl=o(nv[1]);
if (nm) r[nm]=(vl)?vl:true;
}} return r;
}

function makeCookie(a,a2,a3) {
if (a3!=null&&!isNaN(a3)) {
var now=new Date();
now.setTime(now.getTime()+(86400000*a3));
a3=now.toGMTString();
}
a3=(a3)?'; expires='+a3:'';
document.cookie=a+'='+p(a2)+a3;
}

function readCookie(a) {
var cookies=' '+document.cookie;
if (cookies.indexOf(' '+a+'=')==-1) return null;
var start=cookies.indexOf(' '+a+'=')+(a.length+2);
var finish=cookies.substring(start);
finish=(finish.indexOf(';')==-1)?cookies.length:start+finish.indexOf(';');
return o(cookies.substring(start,finish));
}

function saveForm(Form, skipTo, stopAt) {

var allLength =  Form.length;
var dataStore = new Object();

dataStore.textFields = new Object();
dataStore.popuplists = new Object();

for (var i=(skipTo)?skipTo:0; i<((stopAt)?stopAt:allLength); i++) {

var thisField = Form.elements[i];
var fieldType =   thisField.type;
var fieldName =   thisField.name;

 if (!fieldName)        continue;
 

 if (fieldType == 'text') {
  dataStore.textFields[fieldName] = thisField.value;
  continue;
 }
 
 if (fieldType == 'select-one') {
  dataStore.popuplists[fieldName] = thisField.selectedIndex;
 }
 

}

dataStore.textFields = dbi(dataStore.textFields);
dataStore.popuplists = dbi(dataStore.popuplists);

makeCookie('msdy-form_save', dbi(dataStore), null);

}

function autoFill(Form) {

var allLength = Form.length;
var dataFound = readCookie('msdy-form_save');

if (dataFound) {
// &&
//    confirm('This form has been filled in previously.\nWould you like to enter it automatically?')


dataFound = parse(dataFound);

dataFound.textFields = parse(dataFound.textFields);
dataFound.popuplists = parse(dataFound.popuplists);

for (var i=0; i<allLength; i++) {

var thisField = Form.elements[i];
var fieldType =   thisField.type;
var fieldName =   thisField.name;

 if (!fieldName)        continue;


 if (fieldType == 'text' && dataFound.textFields[fieldName]) {
  thisField.value = dataFound.textFields[fieldName];
  continue;
 }
 
 if (fieldType == 'select-one' && dataFound.popuplists[fieldName]) {
 thisField.selectedIndex = dataFound.popuplists[fieldName];
 }

}

}

}



/*
     
Free use for any non-restricted type website is granted.
Do not remove this comment section.

Script Author:  Joseph K. Myers    <e_mayilme@hotmail.com>
Script Source:  MyersDaily         <http://www.angelfire.com/yt/jmyers/>

# |- Script Specifications -| #
# language: javascript1.2     Version: 1.0.6     Release Date: April 12, 2000

0
 
LVL 63

Expert Comment

by:Zvonko
ID: 11715776
Far toooo much code!
My will be shorter ;-)
0
What Security Threats Are You Missing?

Enhance your security with threat intelligence from the web. Get trending threat insights on hackers, exploits, and suspicious IP addresses delivered to your inbox with our free Cyber Daily.

 

Author Comment

by:GessWurker
ID: 11715789
I'm looking forward to it!
0
 
LVL 63

Expert Comment

by:Zvonko
ID: 11716518
Ok, what about this:

<html>
<head>
<script>
function storeState(theForm){
  cState = "";
  elem = theForm.elements;
  for(i=0;i<elem.length;i++){
    if(elem[i].name){
      eName = elem[i].name;
      eType = elem[i].type.substr(0,4);
      if(eType=="text"){
        cState += "t:"+eName+":"+escape(elem[i].value)+"$";
      }
      if(eType=="sele"){
        opt = elem[i].options;
        for(j=0;j<opt.length;j++){
          if(opt[j].selected==true){
            cState += "s:"+eName+":"+escape(opt[j].value)+"$";
          }
        }
      }
      if((eType=="radi" || eType=="chec") && elem[i].checked){
        cState += "c:"+eName+":"+escape(elem[i].value)+"$";
      }
    }
  }
  document.cookie="_ff=$"+cState;
}
function returnState(){
  fVal = document.cookie.split("_ff=");
  if(fVal.length==2){
    theForm = document.forms[0];
    cVal = (fVal[1]+";").split(";")[0].split("$")
    for(i=1;i<cVal.length-1;i++){
      ePart = cVal[i].split(":");
      elem = theForm[ePart[1]];
      if(elem.length){
        if(ePart[0]=="s"){
          opt=elem.options;
          for(j=0;j<opt.length;j++){
            if(opt[j].value==ePart[2])opt[j].selected=true;
          }
        } else
        for(j=0;j<elem.length;j++){
          if(elem[j].value==ePart[2]) elem[j].checked=true;
        }
      } else {
        if(ePart[0]=="c") elem.checked = true;
        else elem.value = ePart[2];
      }
    }
  }
 
}
</script>
</head>
<body onload="returnState()">
<form onSubmit="storeState(this)">
<input type=text name="UserInput">
<hr>
<textarea name="UserNote"></textarea>
<hr>
<select name="someSel">
<option value="One">One
<option value="Two">Two
<option value="Three">Three
</select>
<hr>
<select name="multiSel" MULTIPLE>
<option value="One">One
<option value="Two">Two
<option value="Three">Three
</select>
<hr>
<INPUT type=checkbox name="QI7" value="1"> One
<INPUT type=checkbox name="QI8" value="2"> Two
<INPUT type=checkbox name="QI9" value="3"> Three
<hr>
<INPUT type=radio name="R20" value="1"> One
<INPUT type=radio name="R20" value="2"> Two
<INPUT type=radio name="R20" value="3"> Three
<hr>
<input type=submit>
</form>
</body>
</html>


Do you want session or persistant cookies?

0
 

Author Comment

by:GessWurker
ID: 11716615
Zvonko:

At the moment, I need session cookies only; however, it would be great if it's easy to switch the script to setting persistant cookies if necessary.

Will give your script a shot in just a moment and will get back to you.
0
 
LVL 63

Expert Comment

by:Zvonko
ID: 11716778
Here the version with the expire option. Simply remove the days ammount from storeState(this, 7) and store then once.
The cookie disappears after one submit without days parameter at  next  browser restart.

<html>
<head>
<script>
function storeState(theForm, expDays){
  expTime="";
  if(expDays){
    expTime = new Date((new Date()).getTime() + expDays * 86400000);
    expTime = "expires="+expTime.toGMTString();
  }
  cState = "";
  elem = theForm.elements;
  for(i=0;i<elem.length;i++){
    if(elem[i].name){
      eName = elem[i].name;
      eType = elem[i].type.substr(0,4);
      if(eType=="text"){
        cState += "t:"+eName+":"+escape(elem[i].value)+"$";
      }
      if(eType=="sele"){
        opt = elem[i].options;
        for(j=0;j<opt.length;j++){
          if(opt[j].selected==true){
            cState += "s:"+eName+":"+escape(opt[j].value)+"$";
          }
        }
      }
      if((eType=="radi" || eType=="chec") && elem[i].checked){
        cState += "c:"+eName+":"+escape(elem[i].value)+"$";
      }
    }
  }
  document.cookie="_ff=$"+cState+";path=/;"+expTime;
}
function returnState(){
  fVal = document.cookie.split("_ff=");
  if(fVal.length==2){
    theForm = document.forms[0];
    cVal = (fVal[1]+";").split(";")[0].split("$")
    for(i=1;i<cVal.length-1;i++){
      ePart = cVal[i].split(":");
      elem = theForm[ePart[1]];
      if(elem.length){
        if(ePart[0]=="s"){
          opt=elem.options;
          for(j=0;j<opt.length;j++){
            if(opt[j].value==ePart[2])opt[j].selected=true;
          }
        } else
        for(j=0;j<elem.length;j++){
          if(elem[j].value==ePart[2]) elem[j].checked=true;
        }
      } else {
        if(ePart[0]=="c") elem.checked = true;
        else elem.value = ePart[2];
      }
    }
  }
 
}
</script>
</head>
<body onload="returnState()">
<form onSubmit="storeState(this, 7)">
<input type=text name="UserInput">
<hr>
<textarea name="UserNote"></textarea>
<hr>
<select name="someSel">
<option value="One">One
<option value="Two">Two
<option value="Three">Three
</select>
<hr>
<select name="multiSel" MULTIPLE>
<option value="One">One
<option value="Two">Two
<option value="Three">Three
</select>
<hr>
<INPUT type=checkbox name="QI7" value="1"> One
<INPUT type=checkbox name="QI8" value="2"> Two
<INPUT type=checkbox name="QI9" value="3"> Three
<hr>
<INPUT type=radio name="R20" value="1"> One
<INPUT type=radio name="R20" value="2"> Two
<INPUT type=radio name="R20" value="3"> Three
<hr>
<input type=submit>
</form>
</body>
</html>

0
 

Author Comment

by:GessWurker
ID: 11716862
Zvonko:

This is VERY close. The only problem was that, onSubmit, spaces in the contents of the text fields were changed to the equivalent %20. So that

text area contents  

changed to

text%20area%20contents

The %20's would bother the users I think.
0
 

Author Comment

by:GessWurker
ID: 11716889
just need to unescape somewhere, right?
0
 
LVL 63

Expert Comment

by:Zvonko
ID: 11717065
Right!

The last assignment in the script has to be changed to this:
        else elem.value = unescape(ePart[2]);

0
 
LVL 63

Expert Comment

by:Zvonko
ID: 11717095
Sh!t, there has to be changed all occurance of ePart[2]
The reason I did the escape for all values was that you can have special characters also for radio and checkbox values and so on.

Let me test a second.

0
 
LVL 63

Accepted Solution

by:
Zvonko earned 500 total points
ID: 11717127
Ok, check this:

function returnState(){
  fVal = document.cookie.split("_ff=");
  if(fVal.length==2){
    theForm = document.forms[0];
    cVal = (fVal[1]+";").split(";")[0].split("$")
    for(i=1;i<cVal.length-1;i++){
      ePart = cVal[i].split(":");
      eVal = unescape(ePart[2]);
      elem = theForm[ePart[1]];
      if(elem.length){
        if(ePart[0]=="s"){
          opt=elem.options;
          for(j=0;j<opt.length;j++){
            if(opt[j].value==eVal)opt[j].selected=true;
          }
        } else
        for(j=0;j<elem.length;j++){
          if(elem[j].value==eVal) elem[j].checked=true;
        }
      } else {
        if(ePart[0]=="c") elem.checked = true;
        else elem.value = eVal;
      }
    }
  }
}

0
 

Author Comment

by:GessWurker
ID: 11717290
Zvonko:

This is a thing of BEAUTY! Works perfectly! Congratulations!

Points for you!

Now I'm thinking: It would be good to be able specify which fields to "store state" for because there would be times when I didn't want to store state for everything.

But I'll post another question for that.

Thanks again!
0

Featured Post

How to run any project with ease

Manage projects of all sizes how you want. Great for personal to-do lists, project milestones, team priorities and launch plans.
- Combine task lists, docs, spreadsheets, and chat in one
- View and edit from mobile/offline
- Cut down on emails

Join & Write a Comment

Suggested Solutions

In Part 1 (http://www.experts-exchange.com/Programming/Languages/Scripting/JavaScript/A_7849-Hex-Maze.html) we covered the hexagonal maze basics -- how the cells are represented in a JavaScript array and how the maze is displayed.  In this part, we'…
Nothing in an HTTP request can be trusted, including HTTP headers and form data.  A form token is a tool that can be used to guard against request forgeries (CSRF).  This article shows an improved approach to form tokens, making it more difficult to…
The viewer will learn the basics of jQuery including how to code hide show and toggles. Reference your jQuery libraries: (CODE) Include your new external js/jQuery file: (CODE) Write your first lines of code to setup your site for jQuery…
Excel styles will make formatting consistent and let you apply and change formatting faster. In this tutorial, you'll learn how to use Excel's built-in styles, how to modify styles, and how to create your own. You'll also learn how to use your custo…

747 members asked questions and received personalized solutions in the past 7 days.

Join the community of 500,000 technology professionals and ask your questions.

Join & Ask a Question

Need Help in Real-Time?

Connect with top rated Experts

12 Experts available now in Live!

Get 1:1 Help Now