Skip to content

Instantly share code, notes, and snippets.

@chrisdew
Created June 10, 2011 13:00
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save chrisdew/1018787 to your computer and use it in GitHub Desktop.
Save chrisdew/1018787 to your computer and use it in GitHub Desktop.
hacky KnockoutJS validator - do not use
// This is a hacked-together form validation KnockoutJS plugin.
// The formatting is a bit messed up in places too.
// TODO: Refactor to allow more than one form on a page!
console.log("baz");
(function() {
var handlers = { required
: function(value) {
console.log("check required");
var valid = (/^.+$/).test(value);
if (valid) {
console.log("check required valid");
return { valid: true };
} else {
console.log("check required invalid");
return { valid: false, message: "field must not be empty" };
}
}
, number
: function(value) {
var valid = (/^\d+(\.\d+)$/).test(value);
if (valid) {
return { valid: true };
} else {
return { valid: false, message: "a decimal number is required" };
}
}
, email
: function(value) {
var valid = (/^.+@.+\..+$/).test(value);
if (valid) {
return { valid: true };
} else {
return { valid: false, message: "must be a valid email address" };
}
}
, match
: function(value, target) {
var valid = (value === target);
if (valid) {
return { valid: true };
} else {
return { valid: false, message: "fields must match" };
}
}
, match_and_non_empty
: function(value, target) {
var valid = (value === target && (/^.+$/).test(value));
if (valid) {
return { valid: true };
} else {
return { valid: false, message: "fields must match" };
}
}
, optional
: function(value) {
return { valid: true };
}
} ;
var submit = undefined;
var inputs = [];
var inputElements = [];
var inputValid = {}; // a map of booleans for the validity of fields
function clearValidation() {
console.log("clearValidation");
for (var i in inputElements) {
$(inputElements[i]).parent().removeClass("invalid");
if (inputs[i].timeout) clearTimeout(inputs[i].timeout);
}
updateSubmit();
}
function updateSubmit() {
var allValid = true;
for (var p in inputValid) {
console.log(p, inputValid[p]);
if (!inputValid[p]) {
allValid = false;
break;
}
}
// or 'foldl (&&) true inputValid'
if (allValid) {
console.log("ALL VALID");
$(submit).removeAttr("disabled").removeClass("disabled");
} else {
console.log("NOT ALL VALID");
$(submit).attr("disabled", true).addClass("disabled");
}
}
ko.bindingHandlers.validator = {
init: function(element, valueAccessor, allBindingsAccessor, viewModel) {
// This will be called when the binding is first applied to an element
// Set up any initial state, event handlers, etc. here
console.log("foo", element, valueAccessor(), allBindingsAccessor, viewModel);
// set up the submit
if (valueAccessor() === "submit") {
submit = element;
} else {
inputs.push(allBindingsAccessor().value);
inputElements.push(element);
}
// TODO: This is too hacky.
console.log("setting clearValidation", viewModel);
viewModel.clearValidation = clearValidation;
},
update: function(element, valueAccessor, allBindingsAccessor, viewModel) {
// This will be called once when the binding is first applied to an element,
// and again whenever the associated observable changes value.
// Update the DOM element based on the supplied values here.
console.log("bar", element, valueAccessor(), allBindingsAccessor(), viewModel);
var va = valueAccessor();
if (va === "submit") return;
var handler = handlers[va];
if (!handler) {
console.log("Unknown handler:", va);
return;
}
var aba = allBindingsAccessor();
var target = null;
console.log("aba.validator_target", aba.validator_target);
if (aba.validator_target) {
var targetObs = viewModel[aba.validator_target];
if (targetObs) {
target = targetObs();
}
console.log("target", target);
}
var obs = aba.value;
var value = obs();
var assessment = handler(value, target);
var valid = assessment.valid;
var message = assessment.message;
var id = $(element).attr("id")
console.log("valid:", valid);
if (valid) {
console.log("dooble");
$(element).parent().addClass("valid").removeClass("invalid");
hideError();
if (obs.timeout) clearTimeout(obs.timeout);
} else {
console.log("hooble", message);
}
// This one is a little complicated:
// If the value is neither valid nor invalid, then delay setting it
// invalid for one second, to allow typing.
if (!valid && value !== "") {
if (obs.timeout) clearTimeout(obs.timeout);
if (!$(element).parent().hasClass("valid")) {
console.log("fooble", $(element).parent().hasClass("valid"));
obs.timeout = setTimeout(function() {
console.log("fooblebaz");
showError();
}, 1000);
} else {
console.log("barble");
$(element).removeClass("valid");
showError();
}
}
if (!valid && value === "") {
$(element).parent().removeClass("valid").removeClass("invalid");
if (obs.timeout) clearTimeout(obs.timeout);
}
inputValid[id] = valid; // needed something field-unique to index on
updateSubmit();
function showError() {
hideError();
$(element).parent().addClass("invalid");
var errdiv = $('<div class="error_row ' + id + '_error">' + message + '</div>').hide();
$(element).parent().after(errdiv)
errdiv.slideDown();
}
function hideError() {
var e = $("." + id + "_error");
e.slideUp(function() {
e.remove();
});
}
}
};
})()
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment