最近运营部的同事给我们提出一个需求--想实现一个自动保存表单内容的功能,因为我们网站的表单页比较多,而且每页面要填的内容也比较多,像那些发布产品,发布需求页面要填 的字段比较多,有时候他们电脑突然出问题了,或者不小心把浏览器关了或者...,总之是一些乱七八糟的因素导致页面没有填完就被强行关闭了,那以前辛辛苦苦填的东西就都没有了,所以就有了这个需求。如是就有了下面这段代码:
JS:
(function(){
var events = {};
var autoSave = function(opts){
return new autoSave.prototype.init(opts)
};
autoSave.prototype = {
constructor:autoSave,
init:function(opts){
var set = extend({
time:10,
form:'formID',
url:'',
changeCallback:function(){}
},opts || {});
var _this = this;
var form = document.getElementById(set.form),timer = null;
var names = getFormElement(form);
events[set.form] = {};
ajax({
url:SBI_ROOT+'/html!tempSave.action',
data:'html='+set.form,
onsuccess:function(data){
var data = eval('('+ this.responseText +')');
if(data.param){
var value = eval('('+data.param.value+')');
var callbacks = eval('('+data.param.callback+')');
setAllValue(names,value,set.changeCallback,callbacks||{});
}
}
});
timer = setInterval(function(){
var v = getAllValue(names,events[set.form]);
if(v.empty) return;
ajax({
url:SBI_ROOT+'/html!tempSave.action',
type:'post',
data:'html='+set.form+'¶m.value='+JSONToString(v)+'¶m.callback='+JSONToString(events[set.form]) ,
onsuccess:function(){
//alert(this.responseText);
}
});
},set.time * 1000 );
addEvent(form,'submit',function(e){_this.clear(set.form);e.preventDefault();});
},
clear:function(form,callback){
ajax({
url:SBI_ROOT+'/html!tempDel.action',
data:'html='+form,
callback:function(){
callback && callback();
}
});
}
};
autoSave.prototype.init.prototype = autoSave.prototype;
window.autoSave = autoSave;
function extend(source,target){
for(var pro in target) source[pro] = target[pro];
return source;
};
function getAllValue(names,events){
var V = {empty:true},i=0,len=names.length,v;
for(;i<len;i++){
v = getItemValue(names[i],events);
if(v.value == '' || v.value.length == 0) continue;
V[v.name] = encodeURIComponent(v.value);
V.empty = false;
};
return V;
};
function getItemValue(name,events){
var els = document.getElementsByName(name),el=els[0],name;
switch(el.type){
case 'checkbox' :
case 'radio' :
return getCheckboxOrRadioValue(els,events);
case 'select' :
return getSelectValue(el,events);
default :
if(el.value != ''){
name = el.name.replace(/^[-\.]|[-\.]&/,'').replace(/[-.]+/g,'_');
events[el.name] = 'sbi_'+name;
}
return {'name':el.name,'value':el.value};
};
};
function getCheckboxOrRadioValue(els,events){
var i=0,len=els.length,re = [],name;
for(;i<len;i++){
if(els[i].checked){
re.push(els[i].value);
name = els[i].name.replace(/^[-\.]|[-\.]&/,'').replace(/[-.]+/g,'_');
events[el.name+i] = 'sbi_'+name+i;
};
};
return {'name':els[0].name,'value':re};
};
function getSelectValue(el,events){
var i=0,options = el.options;len=options.length,option,re=[],name;
for(;i<len;i++){
option = options[i];
if(option.selected){
var v = '';
if(option.hasAttribute){
v = option.hasAttribute('value') ? option.value : option.text;
}else{
v = option.attributes['value'].specified ? option.value : option.text;
};
};
re.push(v);
};
name = el.name.replace(/^[-\.]|[-\.]&/,'').replace(/[-.]+/g,'_');
events[el.name] = 'sbi_'+name;
return {'name':item.name,'value':re};
};
function setAllValue(names,v,callback,events){
var i=0,len=names.length,name;
for(;i<len;i++){
name = names[i];
if(!v[name]) continue;
setItemValue(name,v[name],callback,events);
};
};
function setItemValue(name,v,callback,events){
var els = document.getElementsByName(name),el=els[0],fn;
switch(el.type){
case 'checkbox' :
case 'radio' :
return setgetCheckboxOrRadioState(els,v,callback,events);
case 'select' :
return setSelectState(el,v,callback,events);
default :
if(v != ''){
el.value = v;
callback && callback.call(el);
fn = events[el.name];
(typeof window[fn] == 'function') && window[fn].call(el);
};
};
};
function setgetCheckboxOrRadioState(els,v,callback,events){
var i=0,len=els.length,el,fn;
for(;i<len;i++){
el = els[i];
if(hasValue(el.value,v) != -1){
el.checked = true;
callback && callback.call(el);
fn = events[el.name+i];
(typeof fn == 'function') && fn.call(el);
}
};
};
function setSelectState(el,arr,callback,events){
var i=0,options = el.options;len=options.length,option,v,fn;
for(;i<len;i++){
option = options[i];
if(option.hasAttribute){
v = option.hasAttribute('value') ? option.value : option.text;
}else{
v = option.attributes['value'].specified ? option.value : option.text;
};
if(hasValue(arr,v) != -1){
option.selected = true;
callback && callback.call(option);
fn = events[el.name];
(typeof fn == 'function') && fn.call(option);
}
};
};
function hasValue(arr,v){
for(var i=0,len=arr.length;i<len;i++){
if(arr[i] === v) return i;
};
return -1;
};
function getFormElement(form){
var els = form.elements,i=0,len=els.length,r={},re=[],el;
for(;i<len;i++){
el = els[i];
if(el.type == 'button' || el.type == 'submit' || el.type == 'file') continue;
r[el.name] = [el.name];
};
for(var n in r) re.push(r[n]);
return re;
};
function addEvent(el,type,fn){
if(el.addEventListener){
el.addEventListener(type,fn,false);
}else if(el.attachEvent){
el.attachEvent('on'+type,fn);
}else{
el['on'+type] = fn;
}
};
function createXhr(){
if(typeof XMLHttpRequest != 'undefined'){
return new XMLHttpRequest();
}else{
var xhr = null;
try{
xhr = new ActiveXObject('MSXML2.XmlHttp.6.0');
return xhr;
}catch(e){
try{
xhr = new ActiveXObject('MSXML2.XmlHttp.3.0');
return xhr;
}catch(e){
throw Error('cannot create XMLHttp object!');
};
};
};
};
function ajax(opts){
var set = extend({
url:'',
data:'',
type:'GET',
onsuccess:function(){}
},opts||{});
var xhr = createXhr();
if((set.type).toUpperCase() == 'GET'){
if(set.data){
set.url += (set.url.indexOf('?') >= 0 ? '&' : '?') + set.data;
set.data = null;
};
if(set.noCache){
set.url+=(set.url.indexOf('?') >= 0 ? '&' : '?')+'t='+(+new Date());
};
};
xhr.onreadystatechange = function(){
if(xhr.readyState == 4){
if(xhr.status >= 200 && xhr.status < 300){
set.onsuccess.call(xhr);
};
};
};
xhr.open(set.type,set.url);
if((set.type).toUpperCase() == 'POST'){
xhr.setRequestHeader('Content-Type','application/x-www-form-urlencoded');
}
xhr.send(set.data);
};
function JSONToString(obj){
if(typeof JSON.stringify !== 'undefined'){
return JSON.stringify(obj);
}else{
(function(o){
var r = [];
if(typeof o =="string") return "\""+o.replace(/([\'\"\\])/g,"\\$1").replace(/(\n)/g,"\\n").replace(/(\r)/g,"\\r").replace(/(\t)/g,"\\t")+"\"";
if(typeof o =="undefined") return "undefined";
if(typeof o == "object"){
if(o===null) return "null";
else if(!o.push){
for(var i in o)
r.push("\""+i+"\""+":"+arguments.callee(o[i]));
r="{"+r.join()+"}"
}else{
for(var i =0;i<o.length;i++)
r.push(arguments.callee(o[i]));
r="["+r.join()+"]"
};
return r;
};
return o.toString();
})(obj);
};
};
})();
说明:这段JS的功能是每隔一段时间就会把已经填值的表单元素的值保存起来提交到后台,然后在正常提交表单后,会再次发送一个请求通知后台把先前提交的数据删除。如果没有提交表单,那么下次打开的时候,就会把上次已填入的值自动填进表单元素,并且会调用一个以‘sbi’+元素name( 如果name中有-和.会被替换成_,而且会去掉以-或.开头和结尾)为名称的函数,用来执行先前在上面绑定过的事件,比如需要验证,或者需要把图片显示出来,又或者需要根据选中的值来控制层的显示与隐藏。可以手动清除保存在后台的值,比如 var a = autoSave({...});a.clear(formID,callback)