首先,描述一下问题:
因为最近需要在进行中的 J2EE 项目中(已经快结束了,不然会考虑用 ROR的 ),需要支持 AJAX 的功能(Type Aheand suggest),所以在页面中引用了 prototype.js , 同时,项目本身早就用上 Struts Validator,并且启用client端的就 javascript 验证,在成功实现了Ajax 的 Type Ahead Suggest 后, 欣喜之后发现:client端的就 javascript 验证不起作用了,查了3个小时,最终发现:是上述两个框架冲突了。
接下来,详解:
以上一帖的“必填”验证为例:
function theForm_required ()
{
this.a0 = new Array("theField", "The Field is required.", new Function ("varName", " return this[varName];"));
this.a0 = new Array("theField", "The Field is required.", new Function ("varName", " return this[varName];"));
}
接下来,我提一下 Struts Validator 包中的javascript目录里的validateRequired.js 的function validateRequired(form) 函数,如下:
function validateRequired(form) {
var isValid = true;
var focusField = null;
var i = 0;
var fields = new Array();
var formName = form.getAttributeNode("name");
var isValid = true;
var focusField = null;
var i = 0;
var fields = new Array();
var formName = form.getAttributeNode("name");
oRequired = eval('new ' + formName.value + '_required()');
alert(oRequired);
for (x in oRequired) {
var field = form[oRequired[x][0]];
alert(x);
if ((field.type == 'hidden' ||
field.type == 'text' ||
field.type == 'textarea' ||
field.type == 'file' ||
field.type == 'checkbox' ||
field.type == 'select-one' ||
field.type == 'password') &&
field.disabled == false) {
alert(oRequired);
for (x in oRequired) {
var field = form[oRequired[x][0]];
alert(x);
if ((field.type == 'hidden' ||
field.type == 'text' ||
field.type == 'textarea' ||
field.type == 'file' ||
field.type == 'checkbox' ||
field.type == 'select-one' ||
field.type == 'password') &&
field.disabled == false) {
var value = '';
// get field's value
if (field.type == "select-one") {
var si = field.selectedIndex;
if (si >= 0) {
value = field.options[si].value;
}
} else if (field.type == 'checkbox') {
if (field.checked) {
value = field.value;
}
} else {
value = field.value;
}
// get field's value
if (field.type == "select-one") {
var si = field.selectedIndex;
if (si >= 0) {
value = field.options[si].value;
}
} else if (field.type == 'checkbox') {
if (field.checked) {
value = field.value;
}
} else {
value = field.value;
}
if (trim(value).length == 0) {
if (i == 0) {
focusField = field;
}
fields[i++] = oRequired[x][1];
isValid = false;
}
} else if (field.type == "select-multiple") {
var numOptions = field.options.length;
lastSelected=-1;
for(loop=numOptions-1;loop>=0;loop--) {
if(field.options[loop].selected) {
lastSelected = loop;
value = field.options[loop].value;
break;
}
}
if(lastSelected < 0 || trim(value).length == 0) {
if(i == 0) {
focusField = field;
}
fields[i++] = oRequired[x][1];
isValid=false;
}
} else if ((field.length > 0) && (field[0].type == 'radio' || field[0].type == 'checkbox')) {
isChecked=-1;
for (loop=0;loop < field.length;loop++) {
if (field[loop].checked) {
isChecked=loop;
break; // only one needs to be checked
}
}
if (isChecked < 0) {
if (i == 0) {
focusField = field[0];
}
fields[i++] = oRequired[x][1];
isValid=false;
}
}
}
if (fields.length > 0) {
focusField.focus();
alert(fields.join('\n'));
}
return isValid;
}
focusField = field;
}
fields[i++] = oRequired[x][1];
isValid = false;
}
} else if (field.type == "select-multiple") {
var numOptions = field.options.length;
lastSelected=-1;
for(loop=numOptions-1;loop>=0;loop--) {
if(field.options[loop].selected) {
lastSelected = loop;
value = field.options[loop].value;
break;
}
}
if(lastSelected < 0 || trim(value).length == 0) {
if(i == 0) {
focusField = field;
}
fields[i++] = oRequired[x][1];
isValid=false;
}
} else if ((field.length > 0) && (field[0].type == 'radio' || field[0].type == 'checkbox')) {
isChecked=-1;
for (loop=0;loop < field.length;loop++) {
if (field[loop].checked) {
isChecked=loop;
break; // only one needs to be checked
}
}
if (isChecked < 0) {
if (i == 0) {
focusField = field[0];
}
fields[i++] = oRequired[x][1];
isValid=false;
}
}
}
if (fields.length > 0) {
focusField.focus();
alert(fields.join('\n'));
}
return isValid;
}
请注意我在上面的代码中标示
红色的代码行,看到了吧,其实
'new ' + formName.value + '_required()' 就是
theForm_required()
函数名, 而
oRequired 就是利用javascript 强大的动态解析
功能得到的
theForm_required
对象,后面的代码我就不用多做解析了吧,就是循环此对象的每个内部的数组(每个数组就是配置文件内容的客户端表示,就此例来说分别是:字段名,出错提示,提示参数获取函数)。
本帖重点:
说了那么多,前面描述的问题还没用解决呢? 好,开始把,其实很简单(看似简单的问题最会搞死人! ^_^); 只要在 Struts Validator 包中的javascript目录里的的每一个 .js 文件里的函数内部加入以下标示为
红色的代码行即可!
function validateRequired(form) {
var isValid = true;
var focusField = null;
var i = 0;
var fields = new Array();
var formName = form.getAttributeNode("name");
var isValid = true;
var focusField = null;
var i = 0;
var fields = new Array();
var formName = form.getAttributeNode("name");
oRequired = eval('new ' + formName.value + '_required()');
alert(oRequired);
for (x in oRequired) {
var re = /^a\d+/;
if(! re.test(x) )
{
continue;
}
var field = form[oRequired[x][0]];
alert(x);
if ((field.type == 'hidden' ||
field.type == 'text' ||
field.type == 'textarea' ||
field.type == 'file' ||
field.type == 'checkbox' ||
field.type == 'select-one' ||
field.type == 'password') &&
field.disabled == false) {
alert(oRequired);
for (x in oRequired) {
var re = /^a\d+/;
if(! re.test(x) )
{
continue;
}
var field = form[oRequired[x][0]];
alert(x);
if ((field.type == 'hidden' ||
field.type == 'text' ||
field.type == 'textarea' ||
field.type == 'file' ||
field.type == 'checkbox' ||
field.type == 'select-one' ||
field.type == 'password') &&
field.disabled == false) {
var value = '';
// get field's value
if (field.type == "select-one") {
var si = field.selectedIndex;
if (si >= 0) {
value = field.options[si].value;
}
} else if (field.type == 'checkbox') {
if (field.checked) {
value = field.value;
}
} else {
value = field.value;
}
// get field's value
if (field.type == "select-one") {
var si = field.selectedIndex;
if (si >= 0) {
value = field.options[si].value;
}
} else if (field.type == 'checkbox') {
if (field.checked) {
value = field.value;
}
} else {
value = field.value;
}
if (trim(value).length == 0) {
if (i == 0) {
focusField = field;
}
fields[i++] = oRequired[x][1];
isValid = false;
}
} else if (field.type == "select-multiple") {
var numOptions = field.options.length;
lastSelected=-1;
for(loop=numOptions-1;loop>=0;loop--) {
if(field.options[loop].selected) {
lastSelected = loop;
value = field.options[loop].value;
break;
}
}
if(lastSelected < 0 || trim(value).length == 0) {
if(i == 0) {
focusField = field;
}
fields[i++] = oRequired[x][1];
isValid=false;
}
} else if ((field.length > 0) && (field[0].type == 'radio' || field[0].type == 'checkbox')) {
isChecked=-1;
for (loop=0;loop < field.length;loop++) {
if (field[loop].checked) {
isChecked=loop;
break; // only one needs to be checked
}
}
if (isChecked < 0) {
if (i == 0) {
focusField = field[0];
}
fields[i++] = oRequired[x][1];
isValid=false;
}
}
}
if (fields.length > 0) {
focusField.focus();
alert(fields.join('\n'));
}
return isValid;
}
focusField = field;
}
fields[i++] = oRequired[x][1];
isValid = false;
}
} else if (field.type == "select-multiple") {
var numOptions = field.options.length;
lastSelected=-1;
for(loop=numOptions-1;loop>=0;loop--) {
if(field.options[loop].selected) {
lastSelected = loop;
value = field.options[loop].value;
break;
}
}
if(lastSelected < 0 || trim(value).length == 0) {
if(i == 0) {
focusField = field;
}
fields[i++] = oRequired[x][1];
isValid=false;
}
} else if ((field.length > 0) && (field[0].type == 'radio' || field[0].type == 'checkbox')) {
isChecked=-1;
for (loop=0;loop < field.length;loop++) {
if (field[loop].checked) {
isChecked=loop;
break; // only one needs to be checked
}
}
if (isChecked < 0) {
if (i == 0) {
focusField = field[0];
}
fields[i++] = oRequired[x][1];
isValid=false;
}
}
}
if (fields.length > 0) {
focusField.focus();
alert(fields.join('\n'));
}
return isValid;
}
总结:
由于 prototype.js 对 Object() 类作了扩展,因此上面的 eval() 语句动态生成的对象除了
this.a0 还有
其他的字段, 而 Struts Validator 所需要的是配置文件内容的客户端表示的 a[XXXX] 字段而已。
注意!要在 Struts Validator 包中的javascript目录里的的每一个 .js 文件里的函数内部都加入以上标示为
红色的代码行,并重新打包成.jar。
后语:
本帖提到的Ajax支持的后端也是本人在Struts Action 基础上实现的,后端没有用其他的Ajax框架,前端还用到了 Rico 框架!