Background:
After reading this thought provoking book I decided to write a small library as an exercise.
goog.require('goog.structs.Map');
var MyModule = {};
MyModule.FormHelper = {
/** @type {?Element} */
form: null,
/** @type {goog.structs.Map<string, string>} */
errors: {},
/** @param {!Element} element */
init: function(formElement) {
this.form = formElement;
},
/**
* @param {!Element} element
* @return {!Array<goog.structs.Map<string, Object>>}
*/
getElementAttributes: function(element) {
if (!element) return [];
return [].slice.call(element.attributes).map(function(attr) {
return {[attr.name]: attr.value};
});
},
/**
* @param {string} filterOn
* @return {!Array<!Element>}
*/
filterElements: function(filterOn) {
return [].slice.call(this.form.elements).filter(function(element) {
return element.hasAttribute(filterOn);
});
}
};
MyModule.Form = Object.create(MyModule.FormHelper);
MyModule.Form.validate = function() {
/** @type {!Array<!Element>} */
var elements = this.getRequiredElements();
elements.reduce(function(map, element) {
if (element.value == '') {
map[element.name] = 'Required field cannot be empty';
}
return map;
}, this.errors);
};
MyModule.Form.getRequiredElements = function() {
return this.filterElements('required');
};
MyModule.createForm = function(name) {
/** @type {!Element} */
var formElement = document.forms[name];
if (!formElement) {
throw new Error('Form not found.');
}
var form = Object.create(MyModule.Form);
form.init(formElement);
return form;
};
var contactForm;
var callback = function(e) {
e.preventDefault()
contactForm.validate();
console.log(contactForm.errors);
}
window.onload = function () {
contactForm = MyModule.createForm('ContactForm');
contactForm.form.addEventListener("submit", callback, false); //Modern browsers
}
I am using Google closure for type checking and advance code optimizations.
I want to check if I am following a good object oriented design and practices?
Update 1
;(function(global, doc, lib) {
var Form = {};
Form.create = function(name) {
var form = doc.forms[name];
if (!form) {
throw new Error('Form not found.');
}
this.formElement = form;
};
Form.elements = function() {
return this.formElement.elements;
};
Form.filter = function(attr) {
return [].slice.call(this.elements()).filter(function(element) {
return element.hasAttribute(attr);
});
};
Form.getAttributes = function(element) {
if (!element) return [];
return [].slice.call(element.attributes).map(function(attr) {
return {[attr.name]: attr.value};
});
};
Form.validate = function(formName) {
var elements = this.filter('required');
elements.reduce(function(error, element) {
if (element.value == '') {
error[element.name] = 'Required field cannot be empty';
}
return error;
}, this.errors);
};
lib.validate = function(formName) {
var form = Object.create(Form);
form.create(formName);
form.errors = [];
form.validate();
return form;
};
})(window, document, window.lib || (window.lib = {}));
window.onload = function() {
console.log(lib);
console.log(lib.validate('foo').errors);
};
{[attr.name]: attr.value }
is an ES6 object literal. \$\endgroup\$