javascript表单域与json数据间的交互

  包括对象中有集合属性、对象中引用其他对象属性:

  

复制代码 代码如下:

  /**

  **json对象数据设置到表单域中

  */

  function jsonObjectToForm(form, jsonObject){

  for(i = 0, max = form.elements.length; i < max; i++) {

  e = form.elements[i];

  eName = e.name;

  if(eName.indexOf('.') > 0){

  dotIndex = eName.indexOf('.');

  parentName = eName.substring(0, dotIndex);

  childName = eName.substring(dotIndex+1);

  //迭代判断eName,组装成json数据结构

  eValue = iterValueFromJsonObject(jsonObject, parentName, childName);

  }else{

  eValue = jsonObject[eName];

  }

  if(eValue && eValue != "undefined" && eValue != "null"){

  switch(e.type){

  case 'checkbox':

  case 'radio':

  if(e.value == eValue){

  e.checked = true;

  }

  break;

  case 'hidden':

  case 'password':

  case 'textarea':

  case 'text':

  e.value = eValue;

  break;

  case 'select-one':

  case 'select-multiple':

  for(j = 0; j < e.options.length; j++){

  op = e.options[j];

  //alert("eName : " + eName + "; op value : " + op.value + "; eValue : " + eValue);

  if(op.value == eValue){

  op.selected = true;

  }

  }

  break;

  case 'button':

  case 'file':

  case 'image':

  case 'reset':

  case 'submit':

  default:

  }

  }

  }

  }

  /**

  * json数组读写有两种方式

  * 1: a.bs[0].id

  * 2: a["bs"][0]["id"]

  * 把表单转换成json数据格式

  */

  function formToJsonObject(form){

  var jsonObject = {};

  for(i = 0, max = form.elements.length; i < max; i++) {

  e = form.elements[i];

  em = new Array();

  if(e.type == 'select-multiple'){

  for(j = 0; j < e.options.length; j++){

  op = e.options[j];

  if(op.selected){

  em[em.length] = op.value;

  }

  }

  }

  switch(e.type){

  case 'checkbox':

  case 'radio':

  if (!e.checked) { break; }

  case 'hidden':

  case 'password':

  case 'select-one':

  case 'select-multiple':

  case 'textarea':

  case 'text':

  eName = e.name;

  if(e.type == 'select-multiple'){

  eValue = em;

  }else{

  eValue = e.value.replace(new RegExp('(["\\\\])', 'g'), '\\$1');

  }

  //判断是否是对象类型数据

  if(eName.indexOf('.') > 0){

  dotIndex = eName.indexOf('.');

  parentName = eName.substring(0, dotIndex);

  childName = eName.substring(dotIndex+1);

  //迭代判断eName,组装成json数据结构

  iterJsonObject(jsonObject, parentName, childName, eValue);

  }else{

  jsonObject[eName] = eValue;

  }

  break;

  case 'button':

  case 'file':

  case 'image':

  case 'reset':

  case 'submit':

  default:

  }

  }

  return jsonObject;

  }

  /**

  * 把表单元素迭代转换成json数据

  */

  function iterJsonObject(jsonObject, parentName, childName, eValue){

  //pArrayIndex用于判断元素是否是数组标示

  pArrayIndex = parentName.indexOf('[');

  //判断是否集合数据,不是则只是对象属性

  if(pArrayIndex < 0){

  var child = jsonObject[parentName];

  if(!child){

  jsonObject[parentName] = {};

  }

  dotIndex = childName.indexOf('.');

  if(dotIndex > 0){

  iterJsonObject(jsonObject[parentName], childName.substring(0, dotIndex), childName.substring(dotIndex+1), eValue);

  }else{

  jsonObject[parentName][childName] = eValue;

  }

  }else{

  pArray = jsonObject[parentName.substring(0, pArrayIndex)];

  //若不存在js数组,则初始化一个数组类型

  if(!pArray){

  jsonObject[parentName.substring(0, pArrayIndex)] = new Array();

  }

  //取得集合下标,并判断对应下标是否存在js对象

  arrayIndex = parentName.substring(pArrayIndex+1, parentName.length-1);

  var c = jsonObject[parentName.substring(0, pArrayIndex)][arrayIndex];

  if(!c){

  jsonObject[parentName.substring(0, pArrayIndex)][arrayIndex] = {};

  }

  dotIndex = childName.indexOf('.');

  if(dotIndex > 0){

  iterJsonObject(jsonObject[parentName.substring(0, pArrayIndex)][arrayIndex], childName.substring(0, dotIndex), childName.substring(dotIndex+1), eValue);

  }else{

  jsonObject[parentName.substring(0, pArrayIndex)][arrayIndex][childName] = eValue;

  }

  }

  }

  /**

  * 迭代json数据对象设置到表单域中

  */

  function iterValueFromJsonObject(jsonObject, parentName, childName){

  //pArrayIndex用于判断元素是否是数组标示

  pArrayIndex = parentName.indexOf('[');

  //判断是否集合数据,不是则只是对象属性

  if(pArrayIndex < 0){

  dotIndex = childName.indexOf('.');

  if(dotIndex > 0){

  return iterValueFromJsonObject(jsonObject[parentName], childName.substring(0, dotIndex), childName.substring(dotIndex+1));

  }else{

  return jsonObject[parentName][childName]

  }

  }else{

  pArray = jsonObject[parentName.substring(0, pArrayIndex)];

  //取得集合下标,并判断对应下标是否存在js对象

  arrayIndex = parentName.substring(pArrayIndex+1, parentName.length-1);

  var c = jsonObject[parentName.substring(0, pArrayIndex)][arrayIndex];

  dotIndex = childName.indexOf('.');

  if(dotIndex > 0){

  return iterValueFromJsonObject(jsonObject[parentName.substring(0, pArrayIndex)][arrayIndex], childName.substring(0, dotIndex), childName.substring(dotIndex+1));

  }else{

  return jsonObject[parentName.substring(0, pArrayIndex)][arrayIndex][childName]

  }

  }

  }

  挑一些 小毛病:

  不用 var 声明函数级变量是个坏习惯

  if(eValue && eValue != "undefined" && eValue != "null") 这句判断欠妥

  json 中包含数组的情况考虑不周

  form中有多个name相同元素的情况考虑不周

  多选select情况考虑不周

  checkbox radiobox 考虑不周

  disabled 和 readonly 的情况 考虑不周

  元素没有name时的策略是什么? 没有name就不处理 还是没有name取id?? 最后给个参数选择

  总结:

  lz写的函数 目前还不适合在实际中使用

  哈哈,终于看到有人和我有相同的想法了,(以前没有发现).

  不过,其实这个想法可以延伸的,而且我已经延伸了.那就是:

  既然是要得到JSON的数据,那一定和form有关么?非要从form中获取么?

  当然不是.因此我写了一个基于jQuery的扩展

  

复制代码 代码如下:

  /*

  * jQuery Ajax By Name Plugin

  *

  * licensed under the MIT licenses:

  * http://www.opensource.org/licenses/mit-license.php

  *

  * Author achun (achun.shx at gmail.com)

  * Create Date: 2008-6-21

  * Last Date: 2008-6-21

  * Revision:2.8.6.21

  */

  (function($) {

  /**

  * 获取鼠标点击的元素坐标

  */

  $.fn.clickPos = function(e){

  var pos ={x:0,y:0};

  if (e.offsetX != undefined) {

  pos.x = e.offsetX;

  pos.y = e.offsetY;

  } else if (typeof $.fn.offset == 'function') {

  var offset = this.offset();

  pos.x = e.pageX - offset.left;

  pos.y = e.pageY - offset.top;

  } else {

  pos.x = e.pageX - this[0].offsetLeft;

  pos.y = e.pageY - this[0].offsetTop;

  }

  return pos;

  }

  /**

  * ajaxName() 根据标签name属性来提交数据,替代form提交方式

  * options:{//与ajax的options是一样的结构

  * data:{}//要附加提交的数据

  * }

  * successful:如果元素有有效值,defualt:true

  */

  $.fn.ajaxName = function(options,successful) {

  if(options==undefined) options={};

  options.data = options.data || {};

  successful = successful == undefined ? true:successful;

  var data = {};

  var name= options.name || '';

  this.each(function() {

  var el=this,o=$(this),n = o.attr('name'),hasval = o.attr('value')!=undefined;

  if (!n) return;

  var t = el.type, tag = el.tagName.toLowerCase();

  if (n=='/'){

  if (name=='') name = hasval?o.attr('value'):o.text();

  return;

  }

  if (successful && (el.disabled || t == 'reset' || t == 'button' ||

  (t == 'checkbox' || t == 'radio') && !el.checked ||

  (t == 'submit' || t == 'image') ||

  tag == 'select' && el.selectedIndex == -1))

  return;

  var v= hasval? o.attr('value') :o.hasClass('ValueByText')?o.text():o.html();

  if (v == undefined) return;

  if (n.indexOf('.')>0){

  n=n.split('.');

  var len=n.length - 1;

  var b=data;

  $.each(n,function(i){

  if (i!=len){

  if(b[this] == undefined) b[this]={};

  b=b[this];

  }else

  b[this]=v;

  });

  }else if (n.indexOf('[]')>0){

  n=n.slice(0,n.length-2);

  if(data[n] == undefined) data[n]=[];

  data[n].push(v);

  }else{

  data[n]=v;

  }

  });

  var dat={};

  if (name){

  dat[name]=data;

  data=dat[name];

  }else

  dat=data;

  for (var o in options.data){

  data[o]=options.data[o];

  };

  options.data=dat;

  return options.data;

  };

  })(jQuery);

  其中的clickPos扩展是为了取得图片点击提交点击坐标使用的扩展.

  使用方法:

  首先要调用这个使用,肯定需要element有name属性.调用类似这样的语法:

  Js代码

  var jsondat=$('#id [@name]').ajaxname()

  var jsondat=$('#id [@name]').ajaxname()其次:我对name='/'的element做了特殊处理,比如:

  Html代码

  <div name='/' value='foo'><span name='user'>youname</span></div>

  <div name='/' value='foo'><span name='user'>youname</span></div> 得到的结果是:

  Js代码

  {foo:{user:"youname"}}

  {foo:{user:"youname"}}至于提交那是另外一件事情了.

  另外就是:

  1.我的这个获取数组下标是自动增加下标的,写法类似这个

  Html代码

  <li name='a[]'>a0</li><li name='a[]'>a1</li><li name='a[]'>a2</li>

  <li name='a[]'>a0</li><li name='a[]'>a1</li><li name='a[]'>a2</li> 如果不符合你的习惯,可以按照你上面的代码修改一下了.

  2.支持"."操作符

  Html代码

  <li name='a.a'>a</li><li name='a.b'>b</li><li name='a.c'>c</li>

  <li name='a.a'>a</li><li name='a.b'>b</li><li name='a.c'>c</li>将获得

  Js代码

  {a:{a:'a',b:'b',c:'c'}}