diff --git a/CLAUDE.md b/CLAUDE.md index 15f587d..302c813 100644 --- a/CLAUDE.md +++ b/CLAUDE.md @@ -8,6 +8,7 @@ Greenfield project. Implementation is driven by the Vexa AI-SDLC pipeline (Jira / ├── index.html # Calculator UI (semantic HTML5) ├── styles.css # Responsive CSS layout and styling +├── validator.js # Numeric input validator (validateNumericInput) ├── README.md # Project overview └── CLAUDE.md # This file ``` diff --git a/index.html b/index.html index ccb86de..eeaf14a 100644 --- a/index.html +++ b/index.html @@ -5,6 +5,7 @@ Simple Calculator +
diff --git a/validator.js b/validator.js new file mode 100644 index 0000000..162126b --- /dev/null +++ b/validator.js @@ -0,0 +1,47 @@ +/** + * Validates a numeric input string. + * + * Allowed characters: digits 0-9, a single decimal point, a leading minus sign. + * Returns an object with: + * isValid {boolean} - true when the string represents a well-formed number + * value {number|null} - parsed numeric value, or null when invalid + * sanitized {string} - trimmed input string + */ +function validateNumericInput(input) { + var str = String(input).trim(); + var result = { isValid: false, value: null, sanitized: str }; + + if (str === '') { + return result; + } + + // Reject characters other than digits, decimal point, and minus sign + if (/[^0-9.\-]/.test(str)) { + return result; + } + + // Minus sign is only valid as the very first character + var minusCount = (str.match(/-/g) || []).length; + if (minusCount > 1 || (minusCount === 1 && str.charAt(0) !== '-')) { + return result; + } + + // Only one decimal point is allowed + if ((str.match(/\./g) || []).length > 1) { + return result; + } + + // A bare '-' or '.' is not a valid number + if (str === '-' || str === '.') { + return result; + } + + var parsed = parseFloat(str); + if (isNaN(parsed)) { + return result; + } + + result.isValid = true; + result.value = parsed; + return result; +}