Created
June 10, 2011 13:00
-
-
Save chrisdew/1018787 to your computer and use it in GitHub Desktop.
hacky KnockoutJS validator - do not use
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
// 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" }; | |
} | |
} | |
: 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