完成一个中心部件对象,也就是能够增加恭弘=叶 恭弘子节点的对象,终究这个中心件部件装载在根form对象上.这个中心件的长处是能够依据现实营业需求举行分组.本例中划分了三种营业,分别是名字分组,地点分组和测试分组.本例中还设想了remove依据id删除元素的要领,如许会越发天真.由于援用范例是公用的,纵然前面增加了,背面再删除,末了获得的照样删除后的结果.如许能够不必漫天寻觅代码,也不必非要在增加之前解释某段代码,这就是援用范例的长处.战略形式和组合形式之间是没有任何耦合的,我们完全能够在动态装载完form表单后,再依据详细字段绑定战略,至于依据现实需要拆开某些字段的战略,那就是战略形式本身的事了.
<!DOCTYPE html>
<html>
<head lang="en">
<meta charset="UTF-8">
<title>组合+战略形式</title>
</head>
<body>
</body>
</html>
<script type="text/javascript">
//战略类
var strategies = {
isNonEmpty: function(value, errorMsg) {
if(value === '') {
return errorMsg;
}
},
minLength: function(value, length, errorMsg) {
if(value.length < length) {
return errorMsg;
}
},
isMobile: function(value, errorMsg) {
if(!/1[3|5|8][0-9]{9}$/.test(value)) {
return errorMsg;
}
}
};
var Validator = function() {
this.cache = [];
}
Validator.prototype.add = function(dom, rules) {
var self = this;
for(var i=0; i<rules.length; i++) {
(function(rule) {
var arr = rule.strategy.split(':');
var errorMsg = rule.errorMsg;
//将函数都压入数组
self.cache.push(function() {
//拿出战略字串备用
var strategy = arr.shift();
//将dom值放在数组头一个
arr.unshift(dom.value);
//报错信息放在数组末了一个
arr.push(errorMsg);
return strategies[strategy].apply(dom, arr);
})
})(rules[i]);
}
};
Validator.prototype.start = function() {
for(var i=0; i<this.cache.length; i++) {
var msg = this.cache[i]();
if(msg) {
return msg;
}
}
}
//继续要领
function extend(newobj, obj) {
var F = function() {};
F.prototype = obj.prototype;
newobj.prototype = new F();
newobj.prototype.constructor = newobj;
}
//恭弘=叶 恭弘子对象
var Field = function(id) {
this.id = id;
this.divElement;
}
Field.prototype.save = function() {
sessionStorage.setItem(this.id, this.getValue());
console.log(sessionStorage.getItem(this.id));
}
//终究挪用子对象的divElement,这个this指向必需是子对象。
//用call函数能够修改this指向。
//以供下面部件对象CompositeFieldSet中运用。
Field.prototype.getDivElement = function() {
//这里还要注重divElement必需有个id,在部件对象的容器中作为key值运用。
return this.divElement;
}
//子类继续运用
Field.prototype.getValue = function() {
throw new Error('you should override this method');
}
var InputField = function(label, id, type) {
Field.call(this, id);
this.input = document.createElement('input');
//战略考证类运用name寻觅dom
this.input.name = id;
this.input.type = type;
this.label = document.createElement('label');
var labelTextNode = document.createTextNode(label);
this.label.appendChild(labelTextNode);
this.divElement = document.createElement('div');
this.divElement.id = id;
this.divElement.className = 'input-field';
this.divElement.appendChild(this.label);
this.divElement.appendChild(this.input);
}
extend(InputField, Field);
InputField.prototype.getValue = function() {
return this.input.value;
};
var SelectField = function(label, id, arr) {
Field.call(this, id);
this.select = document.createElement('select');
for(var i=0; i<arr.length; i++) {
var option = document.createElement('option');
option.text = arr[i].text;
option.value = arr[i].value;
this.select.options[i] = option;
}
this.label = document.createElement('label');
var labelTextNode = document.createTextNode(label);
this.label.appendChild(labelTextNode);
this.divElement = document.createElement('div');
this.divElement.id = id;
this.divElement.className = 'select-field';
this.divElement.appendChild(this.label);
this.divElement.appendChild(this.select);
}
extend(SelectField, Field);
SelectField.prototype.getValue = function() {
return this.select.options[this.select.selectedIndex].value;
}
//部件对象:能够依据营业分组表单元素
var CompositeFormSet = function(id, legendText) {
//注重这里不是数组了。
this.components = {};
//legend和fieldset元素在表单元素分组很经常使用
//一个fieldset包括很多legend
this.id = id;
this.element = document.createElement('fieldset');
this.element.id = id;
//dom分组
if(legendText) {
this.legend = document.createElement('legend');
this.legend.appendChild(document.createTextNode(legendText));
this.element.appendChild(this.legend);
}
}
CompositeFormSet.prototype.add = function(child) {
//容器内的元素依据id分组。
//每一个child是一个恭弘=叶 恭弘子对象。
this.components[child.getDivElement().id] = child;
this.element.appendChild(child.getDivElement());
}
//猎取这个部件对象,以供下面CompositeForm对象中运用。
CompositeFormSet.prototype.getElement = function() {
return this.element;
}
CompositeFormSet.prototype.save = function() {
console.log(this.components);
for(var id in this.components) {
//假如容器没有这个元素,直接跳过。
if(!this.components.hasOwnProperty(id)) {
continue;
}
this.components[id].save();
}
}
//拆开某个恭弘=叶 恭弘子对象
//如许就不必去寻觅增加元素的处所解释代码。
CompositeFormSet.prototype.remove = function() {
var child;
for(var key in this.components) {
if(this.components[key]['id'] === id) {
child = this.components[key];
delete this.components[child.getDivElement().id];
this.element.removeChild(child.getDivElement());
break;
}
}
}
var CompositeForm = function(id) {
this.formComponents = [];
this.formElement = document.createElement('form');
this.formElement.id = id;
this.formElement.onsubmit = function() {
return false;
}
}
CompositeForm.prototype.add = function(child) {
this.formComponents.push(child);
//增加部件元素
//每一个child是一个部件对象。
this.formElement.appendChild(child.getElement());
}
CompositeForm.prototype.save = function() {
for(var i=0; i<this.formComponents.length; i++) {
this.formComponents[i].save();
}
}
//拆掉某个元素
CompositeForm.prototype.remove = function(id) {
var child;
for(var i=0; i<this.formComponents.length; i++) {
if(this.formComponents[i].id === id) {
child = this.formComponents[i];
this.formComponents.splice(i, 1);
this.formElement.removeChild(child.getElement);
break;
}
}
}
//猎取终究form对象,以供追加到body下。
CompositeForm.prototype.getFinalElement = function() {
var submitButton = document.createElement('input');
submitButton.id = 'sub';
submitButton.type = 'submit';
this.formElement.appendChild(submitButton);
return this.formElement;
}
//最先组合
var form = new CompositeForm('comtact-form');
//造部件:名字分组
var nameFieldSet = new CompositeFormSet('name-fieldset', 'nameArea');
nameFieldSet.add(new InputField('first-name', 'firstName', 'text'));
nameFieldSet.add(new InputField('last-name', 'lastName', 'text'));
//造部件:地点分组
var addressFieldSet = new CompositeFormSet('address-fieldset', 'addressArea');
addressFieldSet.add(new SelectField('国度', 'country', [{text:'美国', value:'us'}, {text:'日本', value:'jp'}]));
addressFieldSet.add(new InputField('地点', 'detail', 'text'));
addressFieldSet.add(new InputField('手机号', 'phone', 'text'));
//造部件:测试分组
var testFieldSet = new CompositeFormSet('test-fieldset', 'testArea');
testFieldSet.add(new InputField('测试', 'test', 'text'));
form.add(nameFieldSet);
form.add(addressFieldSet);
form.add(testFieldSet);
//倏忽有一天,司理让你去掉测试分组,
//而且去掉地点分组中的国度元素。
//然则我并不想去找add的代码到底在那里
//因而能够从掌握台中直接找到id的相干信息,用remove删除就好
addressFieldSet.remove('country');
form.remove('test-fieldset');
var formNode = form.getFinalElement();
document.body.appendChild(formNode);
var todoFunc = function() {
var validator = new Validator();
validator.add(formNode.firstName, [
{strategy: 'isNonEmpty', errorMsg: 'firstName不能为空'},
{strategy: 'minLength:5', errorMsg: 'firstName长度不能少于5位'}
]);
validator.add(formNode.lastName, [
{strategy: 'isNonEmpty', errorMsg: 'lastName不能为空'},
{strategy: 'minLength:3', errorMsg: 'lastName长度不能少于3位'}
]);
validator.add(formNode.detail, [
{strategy: 'isNonEmpty', errorMsg: '地点不能为空'},
{strategy: 'minLength:10', errorMsg: '地点长度不能少于10位'}
]);
validator.add(formNode.phone, [
{strategy: 'isNonEmpty', errorMsg: '手机号不能为空'},
{strategy: 'isMobile', errorMsg: '手机号码花样不正确'}
]);
var errorMsg = validator.start();
return errorMsg;
}
document.getElementById('sub').onclick = function() {
form.save();
var errorMsg = todoFunc();
if(errorMsg) {
alert(errorMsg);
}
return false;
}
</script>