请您先登录,才能继续操作

论坛首页 Web前端技术论坛

表单域与json数据间的交互

浏览 19767 次
精华帖 (0) :: 良好帖 (0) :: 新手帖 (0) :: 隐藏帖 (0)
作者 正文
   发表时间:2008-10-09  

找了几个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]
		}
	}
}

 

 

欢迎大家讨论,最近在研究jsp页面纯净,只与js有关,但这将导致rich client

 

so bad  不知道有什么好的建议没 

   发表时间:2008-10-09  
不用 var 声明函数级变量是个坏习惯
0 请登录后投票
   发表时间:2008-10-09  
fins 写道

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

   对,要改正
0 请登录后投票
   发表时间:2008-10-09  
挑一些 小毛病:

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

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

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

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

多选select情况考虑不周

checkbox radiobox 考虑不周


disabled 和 readonly 的情况 考虑不周

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


总结:
lz写的函数 目前还不适合在实际中使用
0 请登录后投票
   发表时间:2008-10-09  
fins 写道

挑一些 小毛病: 不用 var 声明函数级变量是个坏习惯 if(eValue &amp;&amp; eValue != "undefined" &amp;&amp; eValue != "null") 这句判断欠妥 json 中包含数组的情况考虑不周 form中有多个name相同元素的情况考虑不周 多选select情况考虑不周 checkbox radiobox 考虑不周 disabled 和 readonly 的情况 考虑不周 元素没有name时的策略是什么? 没有name就不处理 还是没有name取id?? 最后给个参数选择 总结: lz写的函数 目前还不适合在实际中使用



因为在后台的话,是把json格式数据转换成对象,所以若多个name相同的话,那就要求是:name[0]、name[1]。。。这样来构造数组形式。

多选select情况考虑不周
---指的是select-multiple吗?
checkbox radiobox 考虑不周
---请指出?
disabled 和 readonly 的情况 考虑不周
---请指出?

谢谢指点。。。
0 请登录后投票
   发表时间:2008-10-10  

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

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

既然是要得到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属性.调用类似这样的语法:

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

其次:我对name='/'的element做了特殊处理,比如:

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

 得到的结果是:

{foo:{user:"youname"}}

至于提交那是另外一件事情了.

 

另外就是:

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

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

   如果不符合你的习惯,可以按照你上面的代码修改一下了.

2.支持"."操作符

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

将获得

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

 

0 请登录后投票
   发表时间:2008-10-10  
多选select情况考虑不周
---指的是select-multiple吗? 
答: 是的

引用
因为在后台的话,是把json格式数据转换成对象,所以若多个name相同的话,那就要求是:name[0]、name[1]。。。这样来构造数组形式。


你可能没理解我的意思 要么就是我没理解你. 用示例来说明吧
有这样一个json
{ 
 name : '张一' ,
 sister : [
   '张二', '张三','张四'
 ]
}


有这样一个form
<form>
姓名:<input type='text' name='name' />
姐妹们:
<input type='text' name='sister' />
<input type='text' name='sister' />
<input type='text' name='sister' />
</form>


问:
用你的函数 怎么把 这个json 添到这个form 里?
反过来又怎么从form里取数据出来 拼装成示例中那种格式的json?


引用

checkbox radiobox 考虑不周
---请指出?
disabled 和 readonly 的情况 考虑不周
---请指出?

这几个你自己思考一下吧(1 考虑不周 2 有bug)
建议你找一些现有的例子 看看人家是怎么处理的.





0 请登录后投票
   发表时间:2008-10-10  
谢谢您的提醒  
0 请登录后投票
   发表时间:2008-10-10  
不知道您有没有在后台转换json数据格式为java对象呢?
对于select-multiple的数据类型(int、String)
封装成json时,有什么好的办法只把int的整成[1, 2, 3],String的整成['1', '2', '3']
因为在java中,可能有一类型int[],但传['1', '2', '3']时,真正转换会报错的。

不知道我这样说明白没?     谢谢
1 请登录后投票
   发表时间:2008-10-10  
你用什么工具做的转换啊?

json和java转换的东西我做过很多
你这个问题 建议在转换前就处理好

是int 型 还是string 型你必须要明确的告诉 转换器

目前我的做法是   json --->java 时 , 按字符串从sjon中取值
在向 java对象中赋值时 判断对象的类型 然后做响应的转换.

btw: select-multiple的数据在客户端时 都是字符串型
最后到后台是什么类型取决于你的需求.
1 请登录后投票
论坛首页 Web前端技术版

跳转论坛:
Global site tag (gtag.js) - Google Analytics