diff --git a/MVMCoreUI.xcodeproj/project.pbxproj b/MVMCoreUI.xcodeproj/project.pbxproj index 8cf0af96..3eb70209 100644 --- a/MVMCoreUI.xcodeproj/project.pbxproj +++ b/MVMCoreUI.xcodeproj/project.pbxproj @@ -32,7 +32,7 @@ 0A21DB8C235E06EF00C160A2 /* MFDigitTextField.h in Headers */ = {isa = PBXBuildFile; fileRef = D29DF24321E6A176003B2FB9 /* MFDigitTextField.h */; settings = {ATTRIBUTES = (Public, ); }; }; 0A21DB8D235E06EF00C160A2 /* MFDigitTextField.m in Sources */ = {isa = PBXBuildFile; fileRef = D29DF24821E6A177003B2FB9 /* MFDigitTextField.m */; }; 0A21DB8E235E06EF00C160A2 /* MFDigitTextField.xib in Resources */ = {isa = PBXBuildFile; fileRef = D29DF24A21E6A177003B2FB9 /* MFDigitTextField.xib */; }; - 0A21DB91235E0EDB00C160A2 /* DigitTextBox.swift in Sources */ = {isa = PBXBuildFile; fileRef = 0A8321AE2355FE9500CB7F00 /* DigitTextBox.swift */; }; + 0A21DB91235E0EDB00C160A2 /* DigitBox.swift in Sources */ = {isa = PBXBuildFile; fileRef = 0A8321AE2355FE9500CB7F00 /* DigitBox.swift */; }; 0A21DB94235E24ED00C160A2 /* DigitEntryField.swift in Sources */ = {isa = PBXBuildFile; fileRef = 0A21DB93235E24ED00C160A2 /* DigitEntryField.swift */; }; 0A41BA6E2344FCD400D4C0BC /* CATransaction+Extension.swift in Sources */ = {isa = PBXBuildFile; fileRef = 0A41BA6D2344FCD400D4C0BC /* CATransaction+Extension.swift */; }; 0A41BA7F23453A6400D4C0BC /* TextEntryField.swift in Sources */ = {isa = PBXBuildFile; fileRef = 0A41BA7E23453A6400D4C0BC /* TextEntryField.swift */; }; @@ -220,9 +220,7 @@ 0A6BF4712360C56C0028F841 /* DropdownEntryField.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = DropdownEntryField.swift; sourceTree = ""; }; 0A7BAFA0232BE61800FB8E22 /* Checkbox.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = Checkbox.swift; sourceTree = ""; }; 0A7BAFA2232BE63400FB8E22 /* CheckboxWithLabelView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = CheckboxWithLabelView.swift; sourceTree = ""; }; - 0A8321A72355062F00CB7F00 /* MdnTextField.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = MdnTextField.swift; sourceTree = ""; }; - 0A8321AC2355FC2600CB7F00 /* DigitTextField.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = DigitTextField.swift; sourceTree = ""; }; - 0A8321AE2355FE9500CB7F00 /* DigitTextBox.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = DigitTextBox.swift; sourceTree = ""; }; + 0A8321AE2355FE9500CB7F00 /* DigitBox.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = DigitBox.swift; sourceTree = ""; }; 9455B19B234F8A0400A574DB /* MVMAnimationFramework.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = MVMAnimationFramework.framework; path = ../SharedFrameworks/MVMAnimationFramework.framework; sourceTree = ""; }; 948DB67D2326DCD90011F916 /* MultiProgress.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = MultiProgress.swift; sourceTree = ""; }; B8200E142280C4CF007245F4 /* ProgressBar.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ProgressBar.swift; sourceTree = ""; }; @@ -764,9 +762,7 @@ D29DF24821E6A177003B2FB9 /* MFDigitTextField.m */, D29DF24A21E6A177003B2FB9 /* MFDigitTextField.xib */, 0A41BA7E23453A6400D4C0BC /* TextEntryField.swift */, - 0A8321A72355062F00CB7F00 /* MdnTextField.swift */, - 0A8321AC2355FC2600CB7F00 /* DigitTextField.swift */, - 0A8321AE2355FE9500CB7F00 /* DigitTextBox.swift */, + 0A8321AE2355FE9500CB7F00 /* DigitBox.swift */, 0A21DB7E235DECC500C160A2 /* FormEntryField.swift */, 0A21DB82235DFBC500C160A2 /* MdnEntryField.swift */, 0A21DB93235E24ED00C160A2 /* DigitEntryField.swift */, @@ -1053,7 +1049,7 @@ D2C5001921F8ECDD001DA659 /* MVMCoreUIViewControllerMappingObject.m in Sources */, D29DF12E21E6851E003B2FB9 /* MVMCoreUITopAlertView.m in Sources */, D29DF2CF21E7C104003B2FB9 /* MFLoadingViewController.m in Sources */, - 0A21DB91235E0EDB00C160A2 /* DigitTextBox.swift in Sources */, + 0A21DB91235E0EDB00C160A2 /* DigitBox.swift in Sources */, D22D1F572204CE5D0077CEC0 /* MVMCoreUIStackableViewController.m in Sources */, 01DF567021FA5AB300CC099B /* TextFieldListFormViewController.swift in Sources */, D2A5145F2211DDC100345BFB /* MoleculeStackView.swift in Sources */, diff --git a/MVMCoreUI/Atoms/TextFields/DigitTextBox.swift b/MVMCoreUI/Atoms/TextFields/DigitBox.swift similarity index 86% rename from MVMCoreUI/Atoms/TextFields/DigitTextBox.swift rename to MVMCoreUI/Atoms/TextFields/DigitBox.swift index 30b2b16d..b78ee0b7 100644 --- a/MVMCoreUI/Atoms/TextFields/DigitTextBox.swift +++ b/MVMCoreUI/Atoms/TextFields/DigitBox.swift @@ -1,5 +1,5 @@ // -// DigitTextBox.swift +// DigitBox.swift // MVMCoreUI // // Created by Kevin Christiano on 10/15/19. @@ -8,11 +8,11 @@ import UIKit -@objc protocol DigitTextBoxDelegate: NSObjectProtocol { +@objc protocol DigitBoxDelegate: NSObjectProtocol { @objc optional func textFieldDidDelete(_ textField: UITextField?) } -@objcMembers open class DigitTextBox: UITextField, MVMCoreViewProtocol { +@objcMembers open class DigitBox: UITextField, MVMCoreViewProtocol { //-------------------------------------------------- // MARK: - Outlets //-------------------------------------------------- @@ -40,7 +40,7 @@ import UIKit required public init?(coder: NSCoder) { super.init(coder: coder) - fatalError("init(coder:) has not been implemented") + fatalError("DigitBox has not been implemented") } public override init(frame: CGRect) { @@ -92,11 +92,11 @@ import UIKit public func updateView(_ size: CGFloat) { DispatchQueue.main.async { [weak self] in - guard let wSelf = self else { return } + guard let self = self else { return } - if !MVMCoreGetterUtility.fequal(a: Float(size), b: Float(wSelf.previousSize)) { - MFStyler.styleTextField(wSelf) - self?.font = MFFonts.mfFont55Rg(28) + if !MVMCoreGetterUtility.fequal(a: Float(size), b: Float(self.previousSize)) { + MFStyler.styleTextField(self) + self.font = MFFonts.mfFont55Rg(28) var digitWidth: CGFloat = 0 var digitHeight: CGFloat = 0 @@ -115,9 +115,9 @@ import UIKit }) sizeObject?.performBlockBase(onSize: size) - self?.widthConstraint?.constant = digitWidth - self?.heightConstraint?.constant = digitHeight - self?.previousSize = size + self.widthConstraint?.constant = digitWidth + self.heightConstraint?.constant = digitHeight + self.previousSize = size } } } diff --git a/MVMCoreUI/Atoms/TextFields/DigitEntryField.swift b/MVMCoreUI/Atoms/TextFields/DigitEntryField.swift index 20b9965d..3d947293 100644 --- a/MVMCoreUI/Atoms/TextFields/DigitEntryField.swift +++ b/MVMCoreUI/Atoms/TextFields/DigitEntryField.swift @@ -9,7 +9,7 @@ import UIKit -class DigitEntryField: TextEntryField, DigitTextBoxDelegate { +class DigitEntryField: TextEntryField, DigitBoxDelegate { //-------------------------------------------------- // MARK: - Outlets //-------------------------------------------------- @@ -22,7 +22,7 @@ class DigitEntryField: TextEntryField, DigitTextBoxDelegate { private var numberOfDigits = 0 private var switchedAutomatically = false - public var digitFields: [DigitTextBox]? + public var digitFields: [DigitBox]? /// Setgs placeholder text in the textField. public override var feedback: String? { diff --git a/MVMCoreUI/Atoms/TextFields/DigitTextField.swift b/MVMCoreUI/Atoms/TextFields/DigitTextField.swift deleted file mode 100644 index 4ff01512..00000000 --- a/MVMCoreUI/Atoms/TextFields/DigitTextField.swift +++ /dev/null @@ -1,530 +0,0 @@ -// -// DigitTextField.swift -// MVMCoreUI -// -// Created by Kevin Christiano on 10/15/19. -// Copyright © 2019 Verizon Wireless. All rights reserved. -// - -import UIKit - - -@objcMembers open class DigitTextField: TextField, UITextFieldDelegate, DigitTextBoxDelegate { - //-------------------------------------------------- - // MARK: - Outlets - //-------------------------------------------------- - - private weak var digitFieldsView: UIView? - - //-------------------------------------------------- - // MARK: - Properties - //-------------------------------------------------- - - private var numberOfDigits = 0 - private var switchedAutomatically = false - public var digitFields: [DigitTextBox]? - - /// Setgs placeholder text in the textField. - public override var placeholder: String? { - get { - var string = "" - - for digitField in digitFields ?? [] { - if let placeholderText = digitField.attributedPlaceholder?.string { - string += placeholderText - } - } - - return !string.isEmpty ? string : nil - } - set { - guard let placeholderValue = newValue else { return } - - (digitFields as NSArray?)?.enumerateObjects({ obj, idx, stop in - - if idx < (newValue?.count ?? 0) { - - let stringForIndex = (newValue as NSString?)?.substring(with: NSRange(location: idx, length: 1)) - obj.attributedPlaceholder = NSAttributedString(string: stringForIndex ?? "", attributes: [ - NSAttributedString.Key.foregroundColor: UIColor.mfBattleshipGrey()]) - } else if stop != nil { - stop = true - } - }) - } - - // If there is already text in the textfield, set the place holder label below. - if placeholderErrorLabel.length > 0 && !errorShowing { - placeholderErrorLabel.text = newValue - - } else if !errorShowing { - placeholderErrorLabel.text = "" - } - - if label.text.length > 0 { - labelToTextFieldPin?.constant = 10 - } else { - labelToTextFieldPin?.constant = 0 - } - - // adding missing accessibilityLabel value - // if we have some value in accessibilityLabel, - // then only can append regular and picker item - textField.accessibilityLabel() = newValue ?? "" + (MVMCoreUIUtility.hardcodedString(withKey: "mfdigittextfield_regular")) - - } - - public override var text: String? { - get { - var string = "" - - for digitField in digitFields ?? [] { - if let digitText = digitField.text { - string += digitText - } - } - - return string - } - set { - (textFields as NSArray?)?.enumerateObjects( { obj, idx, stop in - - if idx < (text?.count ?? 0) { - let stringForIndex = (text as NSString?)?.substring(with: NSRange(location: idx, length: 1)) - obj.text = stringForIndex - } else if stop != nil { - stop = true - } - }) - valueChanged() - } - } - - public override var formText: String? { - get { - return formLabel?.text - } - set { - if let formText = newValue, !formText.isEmpty > 0 { - messageToTextFieldPin?.constant = 10 - } else { - messageToTextFieldPin?.constant = 0 - } - super.formText = newValue - } - } - - //-------------------------------------------------- - // MARK: - Constraints - //-------------------------------------------------- - - private weak var messageToTextFieldPin: NSLayoutConstraint? - private weak var labelToTextFieldPin: NSLayoutConstraint? - - //-------------------------------------------------- - // MARK: - Initializers - //-------------------------------------------------- - - required public init?(coder: NSCoder) { - super.init(coder: coder) - fatalError("init(coder:) has not been implemented") - } - - public init(numberOfDigits: Int) { - super.init(frame: .zero) - - self.numberOfDigits = numberOfDigits - buildTextFieldsView(size: MVMCoreUISplitViewController.getDetailViewWidth()) - } - - public init(numberOfDigits: Int, bothDelegates delegates: (UITextFieldDelegate & MFTextFieldDelegate)?) { - super.init(bothDelegates: delegates as? (TextFieldDelegate & UITextFieldDelegate)) - - self.numberOfDigits = numberOfDigits - buildTextFieldsView(size: MVMCoreUISplitViewController.getDetailViewWidth()) - } - - public init(withNumberOfDigits numberOfDigits: Int, withBothDelegates delegate: (UITextFieldDelegate & MFTextFieldDelegate)?, size: CGFloat) { - super.init(bothDelegates: delegate as? (TextFieldDelegate & UITextFieldDelegate)) - - self.numberOfDigits = numberOfDigits - buildTextFieldsView(size: size) - } - - //-------------------------------------------------- - // MARK: - Methods - //-------------------------------------------------- - - func createDigitField() -> DigitTextBox { - - let textField = DigitTextBox() - textField.delegate = self - textField.textBoxDelegate = self - - return textField - } - - func buildTextFieldsView(size: CGFloat) { - - // Remove all current UI. - if let digitFields = digitFields, !digitFields.isEmpty { - StackableViewController.remove(digitFields) - } - - if numberOfDigits > 0 { - - let digitFields = [DigitTextBox](repeating: createDigitField(), count: numberOfDigits) - - for digitField in digitFields { - digitField.updateView(size) - } - - self.digitFields = digitFields - setupTextFieldsView(forSize: size) - - } else { - digitFields = nil - } - } - - func setupTextFieldsView(forSize size: CGFloat) { - - guard let space = MFSizeObject(standardSize: 5, smalliPhoneSize: 3)?.getValueBasedOnScreenSize(), - let digitFieldsView = digitFieldsView, - let digitFields = digitFields - else { return } - - StackableViewController.populateViewHorizontally(digitFieldsView, withUIArray: digitFields, withSpacingBlock: { object in - - var inset = UIEdgeInsets(top: 0, left: space, bottom: 0, right: space) - - guard let digitFields = self.digitFields else { return inset } - - if digitFields.count == 1 { - inset.left = 0 - inset.right = 0 - - } else if let field = object as? UITextField, field == digitFields.first { - inset.left = 0 - - } else if let field = object as? UITextField, field == digitFields.last { - inset.right = 0 - } - - return inset - }) - } - - override func valueChanged() { - super.valueChanged() - - DispatchQueue.main.async { [weak self] in - guard let self = self else { return } - - if let placeholder = self.placeholder, !placeholder.isEmpty { - self.labelToTextFieldPin?.constant = 10 - - } else { - self.labelToTextFieldPin?.constant = 0 - } - } - } - - open override func updateView(_ size: CGFloat) { - super.updateView(size) - - DispatchQueue.main.async { [weak self] in - guard let self = self else { return } - - self.formLabel?.updateView(size) - - if let digitFields = self.digitFields, !digitFields.isEmpty { - - // Remove all current UI. - StackableViewController.remove(digitFields) - - // Update text boxes. - for digitField in digitFields { - digitField.updateView(size) - } - } - - // Layout text boxes. - self.setupTextFieldsView(forSize: size) - } - } - - open override func setupView() { - super.setupView() - - formLabel?.styleB2(true) - self.formText = "" - alignCenterHorizontal() - } - - //-------------------------------------------------- - // MARK: - Molecule - //-------------------------------------------------- - - open override func setWithJSON(_ json: [AnyHashable: Any]?, delegateObject: MVMCoreUIDelegateObject?, additionalData: [AnyHashable: Any]?) { - - guard let dictionary = json else { return } - - let digits = dictionary["digits"] as? Int ?? 4 - if digits != numberOfDigits { - numberOfDigits = digits - } - - buildTextFieldsView(size: MVMCoreUIUtility.getWidth()) - - super.setWithJSON(json, delegateObject: delegateObject, additionalData: additionalData) - } - - open override class func estimatedHeight(forRow json: [AnyHashable : Any]?, delegateObject: MVMCoreUIDelegateObject?) -> CGFloat { - - return 44 - } - - //-------------------------------------------------- - // MARK: - Setters - //-------------------------------------------------- - - func setAsSecureTextEntry(_ secureEntry: Bool) { - - DispatchQueue.main.async { [weak self] in - - (self.digitFields as NSArray?)?.enumerateObjects({ obj, idx, stop in - obj.isSecureTextEntry = secureEntry - - //accessibility - 33704 fix voice over will read what pin user is filling - obj.accessibilityLabel() = String(format: "PIN %lu of %lu", UInt(idx) + 1, UInt(self.textFields?.count ?? 0)) - }) - } - } - - override public func showErrorMessage(_ errorMessage: String?) { - - DispatchQueue.main.async { [weak self] in - super.showErrorMessage (errorMessage) - - if self.errorShowing { - self.labelToTextFieldPin?.constant = 10 - } - (self.textFields as NSArray?)?.enumerateObjects({ obj, idx, stop in - obj.setAsError() - }) - } - } - - public override func hideError() { - - DispatchQueue.main.async { [weak self] in - - super.hideError() - (self.textFields as NSArray?)?.enumerateObjects({ obj, idx, stop in - obj.hideError() - }) - } - } - - func setWithMap(_ map: [AnyHashable : Any]?, bothDelegates delegate: (UITextFieldDelegate & MFTextFieldDelegate)?) { - super.setWithMap(map, bothDelegates: delegate as? (TextFieldDelegate & UITextFieldDelegate)) - - if (map?.count ?? 0) > 0 { - for textField in textFields ?? [] { - MVMCoreUICommonViewsUtility.addDismissToolbar(textField, delegate: delegate) - } - } - } - - func setDefaultValidationBlock() { - - weak var weakSelf = self - - self.validationBlock = { enteredValue in - if (enteredValue?.count ?? 0) > 0 && (enteredValue?.count ?? 0) == weakSelf?.textFields?.count { - return true - } else { - return false - } - } - } - - func enable(_ enable: Bool) { - super.enable(enable) - - if enable { - formLabel?.styleB2(true) - } else { - formLabel?.textColor = UIColor.mfBattleshipGrey() - } - - for textField in textFields ?? [] { - textField.isUserInteractionEnabled = enable - textField.isEnabled = enable - - if enable { - textField.textColor = UIColor.black - } else { - textField.textColor = UIColor.mfBattleshipGrey() - } - } - } - - //-------------------------------------------------- - // MARK: - Helpers - //-------------------------------------------------- - - func selectPreviousTextField(_ currentTextField: UITextField?, clear: Bool) { - - var selectNextField = false - - (textFields as NSArray?)?.enumerateObjects(options: .reverse, using: { obj, idx, stop in - if obj == currentTextField { - selectNextField = true - } else if selectNextField { - if !clear { - self.switchedAutomatically = true - } - obj.becomeFirstResponder() - self.switchedAutomatically = false - stop = true - - //accessibility - UIAccessibility.post(notification: .layoutChanged, argument: obj) - } - }) - } - - func selectNextTextField(_ currentTextField: UITextField?, clear: Bool) { - - var selectNextField = false - (textFields as NSArray?)?.enumerateObjects({ obj, idx, stop in - - if obj == currentTextField { - selectNextField = true - - } else if selectNextField { - if !clear { - self.switchedAutomatically = true - } - obj.becomeFirstResponder() - self.switchedAutomatically = false - stop = true - - //accessibility - UIAccessibility.post(notification: .layoutChanged, argument: obj) - } - }) - } - - //-------------------------------------------------- - // MARK: - Accessinility - //-------------------------------------------------- - - open override var accessibilityElements: [Any]? { - - if (self.textFields) { - return [self.textFields arrayByAddingObject:(DigitTextBox *)self.label]; - } else { - return @[self.label]; - } - } - - //-------------------------------------------------- - // MARK: - TextFieldDelegate - //-------------------------------------------------- - - @objc public func textFieldShouldReturn(_ textField: UITextField) -> Bool { - textField.resignFirstResponder() - - if uiTextFieldDelegate!.responds(to: #selector(UITextFieldDelegate.textFieldShouldReturn(_:))) { - return uiTextFieldDelegate!.textFieldShouldReturn!(textField) - } - return true - } - - public func textField(_ textField: UITextField, shouldChangeCharactersIn range: NSRange, replacementString string: String) -> Bool { - - if !MVMCoreUIUtility.validate(string, withRegularExpression: RegularExpressionDigitOnly) { - return false - } - - if (textField.text?.count ?? 0) >= range.length + range.location { - - let oldLength = textField.text?.count ?? 0 - let replacementLength = string.count - if replacementLength > 1 { - - // Too long (Check with AKQA if they want to allow pasting the digits. - return false - } else if replacementLength == 1 && (oldLength == 1 || oldLength == 0) { - - // One character, switch old value with new, select next textfield - textField.text = string - selectNextTextField(textField, clear: false) - valueChanged() - return false - } else if replacementLength == 0 && oldLength == 1 { - // non empty cell, clear and stay. - textField.text = "" - valueChanged() - return false - } - return true - } else { - return false - } - } - - func textFieldDidDelete(_ textField: UITextField?) { - - // empty cell, go back to previous cell and clear. - selectPreviousTextField(textField, clear: true) - } - - @objc public func textFieldDidBeginEditing(_ textField: UITextField) { - - if !switchedAutomatically { - textField.text = "" - valueChanged() - } - if (uiTextFieldDelegate?.responds(to: #selector(UITextFieldDelegate.textFieldDidBeginEditing(_:))))! { - uiTextFieldDelegate?.textFieldDidBeginEditing!(textField) - } - } - - @objc public func textFieldDidEndEditing(_ textField: UITextField) { - - if uiTextFieldDelegate!.responds(to: #selector(UITextFieldDelegate.textFieldDidEndEditing(_:))) { - uiTextFieldDelegate!.textFieldDidEndEditing!(textField) - } - } - - @objc public func textFieldShouldClear(_ textField: UITextField) -> Bool { - - selectPreviousTextField(textField, clear: false) - - if uiTextFieldDelegate?.responds(to: #selector(UITextFieldDelegate.textFieldShouldClear(_:))) { - return uiTextFieldDelegate?.textFieldShouldClear(textField) - } - return true - } - - // MARK: - Passed Along TextField delegate - @objc public func textFieldShouldBeginEditing(_ textField: UITextField) -> Bool { - - if uiTextFieldDelegate?.responds(to: #selector(UITextFieldDelegate.textFieldShouldBeginEditing(_:))) { - return uiTextFieldDelegate?.textFieldShouldBeginEditing(textField) - } - return true - } - - @objc public func textFieldShouldEndEditing(_ textField: UITextField) -> Bool { - - if uiTextFieldDelegate!.responds(to: #selector(UITextFieldDelegate.textFieldShouldEndEditing(_:))) { - return uiTextFieldDelegate?.textFieldShouldEndEditing(textField) - } - return true - } -} diff --git a/MVMCoreUI/Atoms/TextFields/DropdownEntryField.swift b/MVMCoreUI/Atoms/TextFields/DropdownEntryField.swift index 2448ccef..a2a57cc4 100644 --- a/MVMCoreUI/Atoms/TextFields/DropdownEntryField.swift +++ b/MVMCoreUI/Atoms/TextFields/DropdownEntryField.swift @@ -21,12 +21,7 @@ import UIKit //-------------------------------------------------- public var dropDownCaretLabel: UILabel? - - public var enabledTextColor: UIColor? - public var disabledTextColor: UIColor? - - public var observingForChanges = false - + private var borderPath: UIBezierPath? public override var isEnabled: Bool { @@ -44,12 +39,6 @@ import UIKit } } - public var validationBlock: ((_ enteredValue: String?) -> Bool)? { - didSet { - valueChanged() - } - } - //-------------------------------------------------- // MARK: - Constraints //-------------------------------------------------- @@ -76,47 +65,18 @@ import UIKit } /// - parameter bothDelegates: Sets both MF/UI Text Field Delegates. - public init(bothDelegates: (UITextFieldDelegate & TextFieldDelegate)?) { + public override init(bothDelegates: (UITextFieldDelegate & TextFieldDelegate)?) { super.init(frame: .zero) setupView() setBothTextFieldDelegates(bothDelegates) } - /// - parameter hasDropDown: tbd - /// - parameter map: Dictionary of values to setup this TextField - /// - parameter bothDelegate: Sets both MF/UI Text Field Delegates. - public init(hasDropDown: Bool = false, map: [AnyHashable: Any]?, bothDelegates: (UITextFieldDelegate & TextFieldDelegate)?) { - super.init(frame: .zero) - setupView() - dropDownCaretLabel?.isHidden = hasDropDown - self.hasDropDown = !hasDropDown - setWithMap(map, bothDelegates: bothDelegates) - } - //-------------------------------------------------- // MARK: - Lifecycle //-------------------------------------------------- open override func setupFieldContainerContent(_ container: UIView) { - - let textField = UITextField(frame: .zero) - self.textField = textField - textField.translatesAutoresizingMaskIntoConstraints = false - textField.setContentCompressionResistancePriority(.required, for: .vertical) - textField.heightAnchor.constraint(equalToConstant: 24).isActive = true - textField.font = MFStyler.fontForTextField() - textField.smartQuotesType = .no - textField.smartDashesType = .no - textField.smartInsertDeleteType = .no - MFStyler.styleTextField(textField) - - container.addSubview(textField) - - NSLayoutConstraint.activate([ - textField.topAnchor.constraint(equalTo: container.topAnchor, constant: 10), - textField.leadingAnchor.constraint(equalTo: container.leadingAnchor, constant: 16), - container.bottomAnchor.constraint(equalTo: textField.bottomAnchor, constant: 10)]) - + let dropDownCaretLabel = Label() self.dropDownCaretLabel = dropDownCaretLabel dropDownCaretLabel.setContentHuggingPriority(UILayoutPriority(900), for: .horizontal) @@ -133,44 +93,12 @@ import UIKit dropDownCaretLabel.leadingAnchor.constraint(equalTo: textField.trailingAnchor, constant: 6).isActive = true container.trailingAnchor.constraint(equalTo: dropDownCaretLabel.trailingAnchor, constant: 16).isActive = true container.bottomAnchor.constraint(equalTo: dropDownCaretLabel.bottomAnchor).isActive = true - dropDownCarrotWidth = dropDownCaretLabel.widthAnchor.constraint(equalToConstant: 0) - dropDownCarrotWidth?.isActive = true + dropDownCaretWidth = dropDownCaretLabel.widthAnchor.constraint(equalToConstant: 0) + dropDownCaretWidth?.isActive = true } open override func updateView(_ size: CGFloat) { super.updateView(size) - - if let textField = textField { - MFStyler.styleTextField(textField) - } - - layoutIfNeeded() - } - - deinit { - mfTextFieldDelegate = nil - uiTextFieldDelegate = nil - } - - open override func draw(_ rect: CGRect) { - super.draw(rect) - - borderPath?.removeAllPoints() - - if !hideBorder, let frame = fieldContainer?.frame { - - borderPath = UIBezierPath() - borderPath?.move(to: CGPoint(x: frame.origin.x, y: frame.origin.y + frame.size.height)) - borderPath?.addLine(to: CGPoint(x: frame.origin.x, y: frame.origin.y)) - borderPath?.addLine(to: CGPoint(x: frame.origin.x + frame.size.width, y: frame.origin.y)) - borderPath?.addLine(to: CGPoint(x: frame.origin.x + frame.size.width, y: frame.origin.y + frame.size.height)) - borderPath?.lineWidth = 1 - - let strokeColor = showError ? UIColor.mfPumpkin() : UIColor.mfSilver() - strokeColor.setStroke() - - borderPath?.stroke() - } } //-------------------------------------------------- @@ -237,15 +165,6 @@ import UIKit dropDownCaretLabel?.isHidden = false self.hasDropDown = true - case "password": - textField?.isSecureTextEntry = true - - case "number": - textField?.keyboardType = .numberPad - - case "email": - textField?.keyboardType = .emailAddress - default: break } diff --git a/MVMCoreUI/Atoms/TextFields/MdnEntryField.swift b/MVMCoreUI/Atoms/TextFields/MdnEntryField.swift index 7d2ad7a7..aec24696 100644 --- a/MVMCoreUI/Atoms/TextFields/MdnEntryField.swift +++ b/MVMCoreUI/Atoms/TextFields/MdnEntryField.swift @@ -17,9 +17,7 @@ class MdnEntryField: TextEntryField, ABPeoplePickerNavigationControllerDelegate, // MARK: - Properties //-------------------------------------------------- - public weak var customDelegate: UITextFieldDelegate? - - public var isNationalMdn = false + public var isNationalMdn = true public var shouldValidateMDN = false public var mdn: String? { @@ -50,29 +48,17 @@ class MdnEntryField: TextEntryField, ABPeoplePickerNavigationControllerDelegate, //-------------------------------------------------- private func setup() { - - textField?.delegate = self - customDelegate = uiTextFieldDelegate - isNationalMdn = true + textField?.keyboardType = .numberPad let toolbar = MVMCoreUICommonViewsUtility.makeEmptyToolbar() let space = UIBarButtonItem(barButtonSystemItem: .flexibleSpace, target: nil, action: nil) let contacts = UIBarButtonItem(title: MVMCoreUIUtility.hardcodedString(withKey: "textfield_contacts_barbutton"), style: .plain, target: self, action: #selector(getContacts(_:))) - let dismissButton = UIBarButtonItem(barButtonSystemItem: .done, target: self, action: #selector(dismissFieldInput(_:))) + let dismissButton = UIBarButtonItem(barButtonSystemItem: .done, target: self, action: #selector(dismissTextFieldResponder(_:))) toolbar.items = [contacts, space, dismissButton] textField?.inputAccessoryView = toolbar } - // If you're using a MFViewController, you must set this to it. - public override weak var uiTextFieldDelegate: UITextFieldDelegate? { - get { return textField?.delegate } - set { - super.uiTextFieldDelegate = newValue - customDelegate = uiTextFieldDelegate - } - } - //-------------------------------------------------- // MARK: - Methods //-------------------------------------------------- @@ -108,11 +94,6 @@ class MdnEntryField: TextEntryField, ABPeoplePickerNavigationControllerDelegate, return true } - @objc func dismissFieldInput(_ sender: Any?) { - - textField?.resignFirstResponder() - } - func getContacts(_ sender: Any?) { let picker = CNContactPickerViewController() @@ -161,7 +142,7 @@ class MdnEntryField: TextEntryField, ABPeoplePickerNavigationControllerDelegate, textField.resignFirstResponder() - return customDelegate?.textFieldShouldReturn?(textField) ?? true + return uiTextFieldDelegate?.textFieldShouldReturn?(textField) ?? true } @objc public func textField(_ textField: UITextField, shouldChangeCharactersIn range: NSRange, replacementString string: String) -> Bool { @@ -170,18 +151,18 @@ class MdnEntryField: TextEntryField, ABPeoplePickerNavigationControllerDelegate, return false } - return customDelegate?.textField?(textField, shouldChangeCharactersIn: range, replacementString: string) ?? true + return uiTextFieldDelegate?.textField?(textField, shouldChangeCharactersIn: range, replacementString: string) ?? true } public func textFieldDidBeginEditing(_ textField: UITextField) { textField.text = MVMCoreUIUtility.removeMdnFormat(textField.text) - customDelegate?.textFieldDidBeginEditing?(textField) + uiTextFieldDelegate?.textFieldDidBeginEditing?(textField) } public func textFieldDidEndEditing(_ textField: UITextField) { - customDelegate?.textFieldDidEndEditing?(textField) + uiTextFieldDelegate?.textFieldDidEndEditing?(textField) if validateAndColor() && isNationalMdn { textField.text = MVMCoreUIUtility.formatMdn(textField.text) @@ -194,16 +175,16 @@ class MdnEntryField: TextEntryField, ABPeoplePickerNavigationControllerDelegate, @objc public func textFieldShouldBeginEditing(_ textField: UITextField) -> Bool { - return customDelegate?.textFieldShouldBeginEditing?(textField) ?? true + return uiTextFieldDelegate?.textFieldShouldBeginEditing?(textField) ?? true } @objc public func textFieldShouldEndEditing(_ textField: UITextField) -> Bool { - return customDelegate?.textFieldShouldEndEditing?(textField) ?? true + return uiTextFieldDelegate?.textFieldShouldEndEditing?(textField) ?? true } @objc public func textFieldShouldClear(_ textField: UITextField) -> Bool { - return customDelegate?.textFieldShouldClear?(textField) ?? true + return uiTextFieldDelegate?.textFieldShouldClear?(textField) ?? true } } diff --git a/MVMCoreUI/Atoms/TextFields/MdnTextField.swift b/MVMCoreUI/Atoms/TextFields/MdnTextField.swift deleted file mode 100644 index 35ab49d7..00000000 --- a/MVMCoreUI/Atoms/TextFields/MdnTextField.swift +++ /dev/null @@ -1,233 +0,0 @@ -// -// MdnTextField.swift -// MVMCoreUI -// -// Created by Kevin Christiano on 10/14/19. -// Copyright © 2019 Verizon Wireless. All rights reserved. -// - -import AddressBookUI -import ContactsUI -import UIKit -import MVMCore - - -@objcMembers open class MdnTextField: TextField, UITextFieldDelegate, ABPeoplePickerNavigationControllerDelegate, CNContactPickerDelegate { - //-------------------------------------------------- - // MARK: - Properties - //-------------------------------------------------- - - public weak var customDelegate: UITextFieldDelegate? - public var isNationalMdn = false - public var shouldValidateMDN = false - - public var mdn: String? { - get { - guard let text = text else { return nil } - - return MVMCoreUIUtility.removeMdnFormat(text) - } - set { - guard let MDN = newValue else { return } - text = MVMCoreUIUtility.formatMdn(MDN) - } - } - - //-------------------------------------------------- - // MARK: - Initializers - //-------------------------------------------------- - - public override init(frame: CGRect) { - super.init(frame: .zero) - setup() - } - - public convenience init() { - self.init(frame: .zero) - } - - required public init?(coder: NSCoder) { - super.init(coder: coder) - fatalError("init(coder:) has not been implemented") - } - - //-------------------------------------------------- - // MARK: - Setup - //-------------------------------------------------- - - private func setup() { - - textField?.delegate = self - customDelegate = uiTextFieldDelegate - isNationalMdn = true - textField?.keyboardType = .numberPad - - let toolbar = MVMCoreUICommonViewsUtility.makeEmptyToolbar() - let space = UIBarButtonItem(barButtonSystemItem: .flexibleSpace, target: nil, action: nil) - let contacts = UIBarButtonItem(title: MVMCoreUIUtility.hardcodedString(withKey: "textfield_contacts_barbutton"), style: .plain, target: self, action: #selector(getContacts(_:))) - let dismissButton = UIBarButtonItem(barButtonSystemItem: .done, target: self, action: #selector(dismissFieldInput(_:))) - toolbar.items = [contacts, space, dismissButton] - textField?.inputAccessoryView = toolbar - } - - // If you're using a MFViewController, you must set this to it. - public override weak var uiTextFieldDelegate: UITextFieldDelegate? { - get { - return textField?.delegate - } - set { - super.uiTextFieldDelegate = newValue - customDelegate = uiTextFieldDelegate - - if newValue != nil { - textField?.delegate = self - } - } - } - - //-------------------------------------------------- - // MARK: - Methods - //-------------------------------------------------- - - func hasValidMdn() -> Bool { - - guard let MDN = mdn else { return true } - - if MDN.isEmpty { - return true - } - - if isNationalMdn { - return MVMCoreUIUtility.validateMDNString(MDN) - } - - return MVMCoreUIUtility.validateInternationalMDNString(MDN) - } - - func validateAndColor() -> Bool { - - if !shouldValidateMDN { - let isValid = hasValidMdn() - - if isValid { - hideError() - } else { - self.errorMessage = getErrorMessage() ?? MVMCoreUIUtility.hardcodedString(withKey: "textfield_phone_format_error_message") - UIAccessibility.post(notification: UIAccessibility.Notification.layoutChanged, argument: textField) - } - - return isValid - } - - return true - } - - func getErrorMessage() -> String? { - - return nil - } - - @objc func dismissFieldInput(_ sender: Any?) { - - if let delegate = uiTextFieldDelegate { - delegate.perform(#selector(dismissFieldInput(_:)), with: textField) - } else { - textField?.resignFirstResponder() - } - } - - func getContacts(_ sender: Any?) { - - let picker = CNContactPickerViewController() - picker.delegate = self - picker.displayedPropertyKeys = ["phoneNumbers"] - picker.predicateForEnablingContact = NSPredicate(format: "phoneNumbers.@count > 0") - picker.predicateForSelectionOfProperty = NSPredicate(format: "key == 'phoneNumbers'") - MVMCoreNavigationHandler.shared()?.present(picker, animated: true) - } - - //-------------------------------------------------- - // MARK: - ContactPicker Delegate - //-------------------------------------------------- - - public func contactPicker(_ picker: CNContactPickerViewController, didSelect contactProperty: CNContactProperty) { - - if contactProperty.value != nil && (contactProperty.value is CNPhoneNumber) { - - let phoneNumber = contactProperty.value as? CNPhoneNumber - let MDN = phoneNumber?.stringValue - var unformattedMDN = MVMCoreUIUtility.removeMdnFormat(MDN) - - // Sometimes user add extra 1 in front of mdn in their address book - if isNationalMdn, - let unformedMDN = unformattedMDN, - unformedMDN.count == 11, - unformedMDN[(unformedMDN.index(unformedMDN.startIndex, offsetBy: 0))] == "1" { - - unformattedMDN = (unformedMDN as NSString).substring(from: 1) - } - - text = unformattedMDN - - if let textField = textField { - textFieldShouldReturn(textField) - textFieldDidEndEditing(textField) - } - } - } - - //-------------------------------------------------- - // MARK: - ImplementedTextField Delegate - //-------------------------------------------------- - - @discardableResult - @objc public func textFieldShouldReturn(_ textField: UITextField) -> Bool { - - textField.resignFirstResponder() - - return customDelegate?.textFieldShouldReturn?(textField) ?? true - } - - @objc public func textField(_ textField: UITextField, shouldChangeCharactersIn range: NSRange, replacementString string: String) -> Bool { - - if !MVMCoreUIUtility.validate(string, withRegularExpression: RegularExpressionDigitOnly) { - return false - } - - return customDelegate?.textField?(textField, shouldChangeCharactersIn: range, replacementString: string) ?? true - } - - public func textFieldDidBeginEditing(_ textField: UITextField) { - - textField.text = MVMCoreUIUtility.removeMdnFormat(textField.text) - customDelegate?.textFieldDidBeginEditing?(textField) - } - - public func textFieldDidEndEditing(_ textField: UITextField) { - - customDelegate?.textFieldDidEndEditing?(textField) - - if validateAndColor() && isNationalMdn { - textField.text = MVMCoreUIUtility.formatMdn(textField.text) - } - } - - //-------------------------------------------------- - // MARK: - Passed Along TextField delegate - //-------------------------------------------------- - - @objc public func textFieldShouldBeginEditing(_ textField: UITextField) -> Bool { - - return customDelegate?.textFieldShouldBeginEditing?(textField) ?? true - } - - @objc public func textFieldShouldEndEditing(_ textField: UITextField) -> Bool { - - return customDelegate?.textFieldShouldEndEditing?(textField) ?? true - } - - @objc public func textFieldShouldClear(_ textField: UITextField) -> Bool { - - return customDelegate?.textFieldShouldClear?(textField) ?? true - } -} diff --git a/MVMCoreUI/Atoms/TextFields/TextEntryField.swift b/MVMCoreUI/Atoms/TextFields/TextEntryField.swift index 63a5ce1b..e5da5006 100644 --- a/MVMCoreUI/Atoms/TextFields/TextEntryField.swift +++ b/MVMCoreUI/Atoms/TextFields/TextEntryField.swift @@ -200,6 +200,11 @@ import UIKit } } + @objc func dismissTextFieldResponder(_ sender: Any?) { + + textField?.resignFirstResponder() + } + //-------------------------------------------------- // MARK: - Observing for change //--------------------------------------------------