I am starting to write a plugin that is aiming to validate a piece of mark up against requirements of schema.org.
I was hoping if I could get some more tips on how to improve the structure of my code. Is this how you would go about this if you were to do it?
$.fn.hasAttr = function(name) {
return this.attr(name) !== undefined;
};
$.fn.outerHTML = function(s) {
return $(this).clone().wrap('<div>').parent().html();
};
$.fn.getOpeningTag = function (s) {
return $(this).outerHTML().slice(0, $(this).outerHTML().indexOf(">") + 1)
}
$.fn.validateSchema = function(options) {
var defaults = {
// for a list of international postcode regex see: http://www.thalesjacobi.com/Regex_to_validate_postcodes
// The one used in the example is from the UK
localPostCodeFormat: new RegExp("^([Gg][Ii][Rr] 0[Aa]{2})|((([A-Za-z][0-9]{1,2})|(([A-Za-z][A-Ha-hJ-Yj-y][0-9]{1,2})|(([A-Za-z][0-9][A-Za-z])|([A-Za-z][A-Ha-hJ-Yj-y][0-9]?[A-Za-z])))) {0,1}[0-9][A-Za-z]{2})$"),
utilities : {
missAtrr : function (target, attrName) {
if (!target.hasAttr(attrName)){
defaults.returnError(target, "The element " + target.getOpeningTag() + " is missing the required attribute " + attrName);
}
},
isValidPostCode : function (target) {
if (!defaults.localPostCodeFormat.test(target.text())) {
defaults.returnError(target, target.getOpeningTag() + " does not have a valid post code");
}
}
},
returnError : function (target, errorMessage) {
var errorContainer = $('<span class="schemaError"></span>');
target.before(errorContainer);
errorContainer.css({
'color' : 'red',
'border': 'solid 1px red'
}).text(errorMessage);
} // more utils to be added
};
// Extend our default options with those provided.
var opts = $.extend(defaults, options);
var schemaElements = {
postalAddress : $(this).find('[itemtype*=PostalAddress]'),
itemProps : $(this).find("[itemprop]"),
emptyProps : $(this).find("[itemprop='']"),
postCode : $(this).find("[itemprop=postalCode]"),
email : $(this).find("[itemprop=email]"),
outofplaceChild : $(this).find("[itemscope]").siblings("[itemprop]")// more dom refs to be added
}
// validation stuff
//
// PostalAddress should have itemsscope
if (schemaElements.postalAddress){
defaults.utilities.missAtrr(schemaElements.postalAddress, "itemscope");
}
// No itemscope can be left empty
if (schemaElements.emptyProps){
$.each(schemaElements.emptyProps, function () {
defaults.returnError($(this), $(this).getOpeningTag() + " can not be left without a value");
});
}
// postcode should match the post code format of that country
if (schemaElements.postCode){
defaults.utilities.isValidPostCode(schemaElements.postCode);
}
// No itemprop can exist without having a itemscope parent
if (schemaElements.outofplaceChild){
$.each(schemaElements.outofplaceChild, function () {
defaults.returnError($(this), $(this).getOpeningTag() + " Does not have a itemscope parent");
});
}
// more rules to be added
};
$(function(){
$('body').validateSchema();
});