From 978db6482376ea5c11b4bc6c5336683e59e58dd1 Mon Sep 17 00:00:00 2001 From: Matt Bruce Date: Wed, 8 May 2024 15:59:43 -0500 Subject: [PATCH] updated rules Signed-off-by: Matt Bruce --- .../TextFields/InputField/InputField.swift | 90 ++++++++++++++----- .../TextFields/Rules/CharacterCountRule.swift | 20 ++++- 2 files changed, 88 insertions(+), 22 deletions(-) diff --git a/VDS/Components/TextFields/InputField/InputField.swift b/VDS/Components/TextFields/InputField/InputField.swift index 4a78203f..9a079000 100644 --- a/VDS/Components/TextFields/InputField/InputField.swift +++ b/VDS/Components/TextFields/InputField/InputField.swift @@ -280,17 +280,8 @@ open class InputField: EntryFieldBase { var actionModel: InputField.TextLinkModel? var toolTipModel: Tooltip.TooltipModel? = tooltipModel var isSecureTextEntry = false - var rules = [AnyRule]() var placeholderText: String? - if self.isRequired { - let rule = RequiredRule() - if let errorText { - rule.errorMessage = errorText - } - rules.append(.init(rule)) - } - switch fieldType { case .text: break @@ -329,7 +320,12 @@ open class InputField: EntryFieldBase { case .date: minWidth = 114.0 placeholderText = dateFormat.placeholderText - + let rule = CharacterCountRule().copyWith { + $0.maxLength = dateFormat.maxLength + $0.compareType = .equals + $0.errorMessage = "Enter a valid date" + } + rules.append(.init(rule)) case .securityCode: minWidth = 88.0 @@ -372,8 +368,26 @@ open class InputField: EntryFieldBase { //tooltip tooltipModel = toolTipModel + } + override func updateRules() { + super.updateRules() + + switch fieldType { + case .date: + let rule = CharacterCountRule().copyWith { + $0.maxLength = dateFormat.maxLength + $0.compareType = .equals + $0.errorMessage = "Enter a valid date" + } + rules.append(.init(rule)) + + default: break + + } + } + /// Used to update any Accessibility properties. open override func updateAccessibility() { super.updateAccessibility() @@ -433,6 +447,22 @@ open class InputField: EntryFieldBase { //-------------------------------------------------- open var dateFormat: DateFormat = .mmddyy { didSet { setNeedsUpdate() } } + private func formatDate(_ input: String) -> String { + var formattedInput = input.filter { $0.isNumber } // Remove any existing slashes + var formattedString = "" + var currentIndex = formattedInput.startIndex + + for index in 0.. String { @@ -466,12 +496,11 @@ open class InputField: EntryFieldBase { return formattedNumber } - private func getNewCursorPosition(textField: UITextField, range: NSRange, replacementString string: String, rawNumber: String, formattedNumber: String) -> UITextPosition? { + private func getTelCursorPosition(textField: UITextField, range: NSRange, replacementString string: String, rawNumber: String, formattedNumber: String) -> UITextPosition? { let start = range.location let length = string.count let newCursorLocation = start + length - let rawNumberCount = rawNumber.count // Adjust the cursor position to skip over formatting characters var formattedCharacterCount = 0 @@ -518,10 +547,24 @@ extension InputField: UITextFieldDelegate { switch fieldType { case .date: // Allow only numbers and limit the length of text. - let allowedCharacters = CharacterSet.decimalDigits - let characterSet = CharacterSet(charactersIn: string) - return allowedCharacters.isSuperset(of: characterSet) && ((textField.text?.count ?? 0) + string.count - range.length) <= dateFormat.maxLength + guard let oldText = textField.text, + let textRange = Range(range, in: oldText), + string.rangeOfCharacter(from: CharacterSet.decimalDigits.inverted) == nil else { + return false + } + let newText = oldText.replacingCharacters(in: textRange, with: string) + if newText.count > dateFormat.maxLength { + return false + } + + if newText.count <= dateFormat.maxLength { + textField.text = formatDate(newText) + return false + } else { + return true + } + case .number: // Allow only numbers let allowedCharacters = CharacterSet.decimalDigits @@ -548,7 +591,7 @@ extension InputField: UITextFieldDelegate { textField.text = formattedNumber // Calculate the new cursor position - if let newPosition = getNewCursorPosition(textField: textField, + if let newPosition = getTelCursorPosition(textField: textField, range: range, replacementString: string, rawNumber: rawNumber, @@ -596,7 +639,7 @@ extension InputField { case mmyy case mmddyy case mmddyyyy - + public var placeholderText: String { switch self { case .mmyy: "MM/YY" @@ -604,7 +647,7 @@ extension InputField { case .mmddyyyy: "MM/DD/YYYY" } } - + public var formatString: String { switch self { case .mmyy: "MM/yy" @@ -612,7 +655,7 @@ extension InputField { case .mmddyyyy: "MM/dd/yyyy" } } - + public var maxLength: Int { switch self { case .mmyy: 5 @@ -620,6 +663,13 @@ extension InputField { case .mmddyyyy: 10 } } - + + internal var separatorIndices: [Int] { + switch self { + case .mmyy: [2] + case .mmddyy: [2,4] + case .mmddyyyy: [2,4] + } + } } } diff --git a/VDS/Components/TextFields/Rules/CharacterCountRule.swift b/VDS/Components/TextFields/Rules/CharacterCountRule.swift index f26ccafc..46cbed05 100644 --- a/VDS/Components/TextFields/Rules/CharacterCountRule.swift +++ b/VDS/Components/TextFields/Rules/CharacterCountRule.swift @@ -7,12 +7,28 @@ import Foundation -class CharacterCountRule: Rule { +class CharacterCountRule: Rule, Withable { + enum CompareType { + case equals, greaterThanEquals, lessThan, lessThanEquals + } var maxLength: Int? var errorMessage: String = "You have exceeded the character limit." + var compareType: CompareType = .lessThanEquals func isValid(value: String?) -> Bool { guard let text = value, let maxLength, maxLength > 0 else { return true } - return text.count <= maxLength + switch compareType { + case .equals: + return text.count == maxLength + + case .greaterThanEquals: + return text.count >= maxLength + + case .lessThan: + return text.count < maxLength + + case .lessThanEquals: + return text.count <= maxLength + } } }