beginning to convert the code.
This commit is contained in:
parent
65672b1f04
commit
d54c63b019
@ -6,85 +6,179 @@
|
|||||||
// Copyright © 2019 Verizon Wireless. All rights reserved.
|
// Copyright © 2019 Verizon Wireless. All rights reserved.
|
||||||
//
|
//
|
||||||
|
|
||||||
import MVMCoreUI
|
|
||||||
import UIKit
|
import UIKit
|
||||||
|
|
||||||
@objc protocol MFTextFieldDelegate: NSObjectProtocol {
|
|
||||||
// Called when the entered text becomes valid based on the validation block
|
@objc protocol TextFieldDelegate: NSObjectProtocol {
|
||||||
@objc optional func entryIsValid(_ textfield: MFTextField?)
|
/// Called when the entered text becomes valid based on the validation block
|
||||||
// Called when the entered text becomes invalid based on the validation block
|
@objc optional func entryIsValid(_ textfield: TextField?)
|
||||||
@objc optional func entryIsInvalid(_ textfield: MFTextField?)
|
/// Called when the entered text becomes invalid based on the validation block
|
||||||
// Dismisses the keyboard.
|
@objc optional func entryIsInvalid(_ textfield: TextField?)
|
||||||
|
/// Dismisses the keyboard.
|
||||||
@objc optional func dismissFieldInput(_ sender: Any?)
|
@objc optional func dismissFieldInput(_ sender: Any?)
|
||||||
}
|
}
|
||||||
|
|
||||||
class MFTextField: ViewConstrainingView, MVMCoreUIMoleculeViewProtocol, FormValidationProtocol {
|
@objcMembers open class TextField: ViewConstrainingView, MVMCoreUIMoleculeViewProtocol, FormValidationProtocol {
|
||||||
weak var view: UIView?
|
//--------------------------------------------------
|
||||||
@IBOutlet weak var textFieldContainerView: UIView?
|
// MARK: - Outlets
|
||||||
@IBOutlet weak var backgroundView: UIView?
|
//--------------------------------------------------
|
||||||
@IBOutlet weak var textField: UITextField?
|
|
||||||
@IBOutlet weak var formLabel: Label?
|
var textFieldContainerView: UIView?
|
||||||
@IBOutlet weak var separatorView: UIView?
|
var backgroundView: UIView?
|
||||||
/*make it public so outsider class can know the posistion of it. */ @IBOutlet weak var heightConstraint: NSLayoutConstraint?
|
var textField: UITextField?
|
||||||
@IBOutlet weak var formLabelRightPin: NSLayoutConstraint?
|
var formLabel: Label?
|
||||||
var enabled = false
|
var separatorView: UIView?
|
||||||
// To set the placeholder and text
|
var view: UIView?
|
||||||
|
|
||||||
|
//--------------------------------------------------
|
||||||
|
// MARK: - Properties
|
||||||
|
//--------------------------------------------------
|
||||||
|
|
||||||
weak var text: String?
|
weak var text: String?
|
||||||
weak var formText: String?
|
weak var formText: String?
|
||||||
weak var fieldKey: String?
|
weak var fieldKey: String?
|
||||||
weak var placeholder: String?
|
weak var placeholder: String?
|
||||||
/* will move out in Feb release */ var hideBorder = false
|
|
||||||
|
|
||||||
weak var datePicker: UIDatePicker?
|
|
||||||
private(set) weak var toolbar: UIToolbar?
|
|
||||||
//helper
|
|
||||||
var formatter: DateFormatter?
|
|
||||||
// If you're using a MFViewController, you must set this to it
|
// If you're using a MFViewController, you must set this to it
|
||||||
weak var uiTextFieldDelegate: UITextFieldDelegate?
|
weak var uiTextFieldDelegate: UITextFieldDelegate?
|
||||||
// The delegate and block for validation. Validates if the text that the user has entered is valid or not. Checked after each change if there is a delegate.
|
// The delegate and block for validation. Validates if the text that the user has entered is valid or not. Checked after each change if there is a delegate.
|
||||||
weak var mfTextFieldDelegate: MFTextFieldDelegate?
|
weak var mfTextFieldDelegate: MFTextFieldDelegate?
|
||||||
|
|
||||||
|
/*make it public so outsider class can know the posistion of it. */
|
||||||
|
|
||||||
|
var enabled = false
|
||||||
|
// To set the placeholder and text
|
||||||
|
|
||||||
|
/* will move out in Feb release */
|
||||||
|
var hideBorder = false
|
||||||
|
|
||||||
|
weak var datePicker: UIDatePicker?
|
||||||
|
private(set) weak var toolbar: UIToolbar?
|
||||||
|
|
||||||
|
//helper
|
||||||
|
var formatter: DateFormatter?
|
||||||
|
|
||||||
var valid = false
|
var valid = false
|
||||||
var validationBlock: ((_ enteredValue: String?) -> Bool)?
|
var validationBlock: ((_ enteredValue: String?) -> Bool)?
|
||||||
// custom text colors
|
// custom text colors
|
||||||
var customEnabledTextColor: UIColor?
|
var customEnabledTextColor: UIColor?
|
||||||
var customDisabledTextColor: UIColor?
|
var customDisabledTextColor: UIColor?
|
||||||
|
|
||||||
//default error message
|
//default error message
|
||||||
var errMessage: String?
|
var errMessage: String?
|
||||||
var editCompleteAction: ((_ text: String?) -> Void)?
|
var editCompleteAction: ((_ text: String?) -> ())?
|
||||||
|
|
||||||
|
private var customPlaceHolderColor: UIColor?
|
||||||
private var customPlaceHolderColor: UIColor?
|
private var borderPath: UIBezierPath?
|
||||||
@IBOutlet private weak var separatorHeightConstraint: NSLayoutConstraint!
|
private var calendar: Calendar?
|
||||||
private var borderPath: UIBezierPath?
|
|
||||||
private var calendar: Calendar?
|
//--------------------------------------------------
|
||||||
@IBOutlet private weak var textContainerLeftPin: NSLayoutConstraint!
|
// MARK: - Constraints
|
||||||
@IBOutlet private weak var errorLableLeftPin: NSLayoutConstraint!
|
//--------------------------------------------------
|
||||||
@IBOutlet private weak var formLabelLeftPin: NSLayoutConstraint!
|
|
||||||
@IBOutlet private weak var textContainerRightPin: NSLayoutConstraint!
|
var textContainerLeftPin: NSLayoutConstraint?
|
||||||
@IBOutlet private weak var errorLableRightPin: NSLayoutConstraint!
|
var errorLableLeftPin: NSLayoutConstraint?
|
||||||
|
var formLabelLeftPin: NSLayoutConstraint?
|
||||||
|
var textContainerRightPin: NSLayoutConstraint?
|
||||||
|
var errorLableRightPin: NSLayoutConstraint?
|
||||||
|
var separatorHeightConstraint: NSLayoutConstraint?
|
||||||
|
var heightConstraint: NSLayoutConstraint?
|
||||||
|
var formLabelRightPin: NSLayoutConstraint?
|
||||||
|
|
||||||
|
//--------------------------------------------------
|
||||||
|
// MARK: - Initializations
|
||||||
|
//--------------------------------------------------
|
||||||
|
|
||||||
|
public override init(frame: CGRect) {
|
||||||
|
super.init(frame: frame)
|
||||||
|
}
|
||||||
|
|
||||||
|
public convenience init() {
|
||||||
|
self.init(frame: .zero)
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
public convenience init() {
|
||||||
|
self.init(frame: .zero)
|
||||||
|
dropDownCarrotLabel().hidden = false
|
||||||
|
hasDropDown = false
|
||||||
|
}
|
||||||
|
|
||||||
|
public convenience init(withBothDelegates delegate: (UITextFieldDelegate & MFTextFieldDelegate)?) {
|
||||||
|
self.init(frame: .zero)
|
||||||
|
bothTextFieldDelegates = delegate
|
||||||
|
}
|
||||||
|
|
||||||
|
public convenience init(withMap map: [AnyHashable : Any]?, bothDelegates delegate: (UITextFieldDelegate & MFTextFieldDelegate)?) {
|
||||||
|
self.init(frame: .zero)
|
||||||
|
translatesAutoresizingMaskIntoConstraints = false
|
||||||
|
setWithMap(map, bothDelegates: delegate)
|
||||||
|
}
|
||||||
|
|
||||||
|
public convenience init(withBothDelegates delegate: (UITextFieldDelegate & MFTextFieldDelegate)?) {
|
||||||
|
self.init(frame: .zero)
|
||||||
|
bothTextFieldDelegates = delegate
|
||||||
|
}
|
||||||
|
|
||||||
|
*/
|
||||||
|
|
||||||
|
class func mfTextField() -> Self? {
|
||||||
|
|
||||||
// MARK: - setup
|
let view = self.init()
|
||||||
func updateView(_ size: CGFloat) {
|
view?.hasDropDown = false
|
||||||
super.updateView(size)
|
return view
|
||||||
MVMCoreDispatchUtility.performBlock(onMainThread: {
|
}
|
||||||
self.formLabel.updateView(size)
|
|
||||||
self.label.font = MFStyler.fontForTextFieldUnderLabel()
|
|
||||||
MFStyler.styleTextField(self.textField)
|
|
||||||
self.dashLine.updateView(size)
|
|
||||||
})
|
|
||||||
}
|
|
||||||
|
|
||||||
func setupView() {
|
class func mfTextField(withBothDelegates delegate: (UITextFieldDelegate & MFTextFieldDelegate)?) -> Self? {
|
||||||
if !self.view {
|
|
||||||
backgroundColor = UIColor.clear
|
let textField = self.mfTextField()
|
||||||
let nib = getNib()
|
textField?.bothTextFieldDelegates = delegate
|
||||||
let views = nib?.instantiate(withOwner: self, options: nil)
|
return textField
|
||||||
|
}
|
||||||
|
|
||||||
|
class func mfTextField(withMap map: [AnyHashable : Any]?, bothDelegates delegate: (UITextFieldDelegate & MFTextFieldDelegate)?) -> Self? {
|
||||||
|
|
||||||
|
let textField = self.mfTextField()
|
||||||
|
textField?.translatesAutoresizingMaskIntoConstraints = false
|
||||||
|
textField?.setWithMap(map, bothDelegates: delegate)
|
||||||
|
return textField
|
||||||
|
}
|
||||||
|
|
||||||
|
class func mfTextFieldForDropDown() -> Self? {
|
||||||
|
|
||||||
|
let textField = self.mfTextField()
|
||||||
|
textField?.dropDownCarrotLabel().hidden = false
|
||||||
|
textField?.hasDropDown = true
|
||||||
|
return textField
|
||||||
|
}
|
||||||
|
|
||||||
|
class func mfTextFieldForDropDown(withBothDelegates delegate: (UITextFieldDelegate & MFTextFieldDelegate)?) -> Self? {
|
||||||
|
|
||||||
|
let textField = self.mfTextFieldForDropDown()
|
||||||
|
textField?.bothTextFieldDelegates = delegate
|
||||||
|
return textField
|
||||||
|
}
|
||||||
|
|
||||||
|
//--------------------------------------------------
|
||||||
|
// MARK: - Lifecycle
|
||||||
|
//--------------------------------------------------
|
||||||
|
|
||||||
|
override open func setupView() {
|
||||||
|
|
||||||
|
guard subviews.isEmpty else { return }
|
||||||
|
|
||||||
|
translatesAutoresizingMaskIntoConstraints = false
|
||||||
|
|
||||||
|
|
||||||
|
backgroundColor = .clear
|
||||||
|
|
||||||
let view = views?.first as? UIView
|
let view = views?.first as? UIView
|
||||||
view?.translatesAutoresizingMaskIntoConstraints = false
|
view?.translatesAutoresizingMaskIntoConstraints = false
|
||||||
view?.setContentHuggingPriority(.required, for: .vertical)
|
view?.setContentHuggingPriority(.required, for: .vertical)
|
||||||
view?.setContentCompressionResistancePriority(.required, for: .vertical)
|
view?.setContentCompressionResistancePriority(.required, for: .vertical)
|
||||||
self.view = view
|
self.view = view
|
||||||
view?.frame = frame
|
view?.frame = frame
|
||||||
|
|
||||||
if let view = view {
|
if let view = view {
|
||||||
addSubview(view)
|
addSubview(view)
|
||||||
}
|
}
|
||||||
@ -116,54 +210,65 @@ class MFTextField: ViewConstrainingView, MVMCoreUIMoleculeViewProtocol, FormVali
|
|||||||
textField.smartDashesType = .no
|
textField.smartDashesType = .no
|
||||||
textField.smartInsertDeleteType = .no
|
textField.smartInsertDeleteType = .no
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func updateView(_ size: CGFloat) {
|
||||||
|
|
||||||
|
super.updateView(size)
|
||||||
|
DispatchQueue.main.async { [weak self] in
|
||||||
|
self?.formLabel?.updateView(size)
|
||||||
|
self?.label.font = MFStyler.fontForTextFieldUnderLabel()
|
||||||
|
let textField = self?.textField {
|
||||||
|
MFStyler.styleTextField(textField)
|
||||||
|
}
|
||||||
|
self?.dashLine.updateView(size)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func getNib() -> UINib? {
|
deinit {
|
||||||
return UINib(nibName: NSStringFromClass(type(of: self).self), bundle: MVMCoreUIUtility.bundleForMVMCoreUI())
|
mfTextFieldDelegate = nil
|
||||||
|
uiTextFieldDelegate = nil
|
||||||
}
|
}
|
||||||
|
|
||||||
class func mfTextField() -> Self? {
|
func draw(_ rect: CGRect) {
|
||||||
let view = self.init()
|
super.draw(rect)
|
||||||
view?.hasDropDown = false
|
borderPath.removeAllPoints()
|
||||||
return view
|
if !hideBorder {
|
||||||
|
let frame = textFieldContainerView.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
|
||||||
|
|
||||||
|
var strokeColor: UIColor?
|
||||||
|
if errorShowing {
|
||||||
|
strokeColor = UIColor.mfPumpkin()
|
||||||
|
} else {
|
||||||
|
strokeColor = UIColor.mfSilver()
|
||||||
|
}
|
||||||
|
|
||||||
|
strokeColor?.setStroke()
|
||||||
|
|
||||||
|
borderPath?.stroke()
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
class func mfTextField(withBothDelegates delegate: (UITextFieldDelegate & MFTextFieldDelegate)?) -> Self? {
|
//--------------------------------------------------
|
||||||
let textField = self.mfTextField()
|
// MARK: - Methods
|
||||||
textField?.bothTextFieldDelegates = delegate
|
//--------------------------------------------------
|
||||||
return textField
|
|
||||||
}
|
|
||||||
|
|
||||||
class func mfTextField(withMap map: [AnyHashable : Any]?, bothDelegates delegate: (UITextFieldDelegate & MFTextFieldDelegate)?) -> Self? {
|
|
||||||
let textField = self.mfTextField()
|
|
||||||
textField?.translatesAutoresizingMaskIntoConstraints = false
|
|
||||||
textField?.setWithMap(map, bothDelegates: delegate)
|
|
||||||
return textField
|
|
||||||
}
|
|
||||||
|
|
||||||
class func mfTextFieldForDropDown() -> Self? {
|
|
||||||
let textField = self.mfTextField()
|
|
||||||
textField?.dropDownCarrotLabel().hidden = false
|
|
||||||
textField?.hasDropDown = true
|
|
||||||
return textField
|
|
||||||
}
|
|
||||||
|
|
||||||
class func mfTextFieldForDropDown(withBothDelegates delegate: (UITextFieldDelegate & MFTextFieldDelegate)?) -> Self? {
|
|
||||||
let textField = self.mfTextFieldForDropDown()
|
|
||||||
textField?.bothTextFieldDelegates = delegate
|
|
||||||
return textField
|
|
||||||
}
|
|
||||||
|
|
||||||
// MARK: - Utilities
|
// MARK: - Utilities
|
||||||
func createDatePicker() {
|
func createDatePicker() {
|
||||||
//tool bar
|
//tool bar
|
||||||
MVMCoreUICommonViewsUtility.addDismissToolbar(textField, delegate: textField.delegate)
|
MVMCoreUICommonViewsUtility.addDismissToolbar(textField!, delegate: textField!.delegate)
|
||||||
|
|
||||||
//date picker
|
//date picker
|
||||||
datePicker = MVMCoreUICommonViewsUtility.addDatePicker(to: textField)
|
datePicker = MVMCoreUICommonViewsUtility.addDatePicker(to: textField!)
|
||||||
|
|
||||||
let calendar = Calendar.current
|
var calendar = Calendar.current
|
||||||
calendar.timeZone = NSTimeZone.system
|
calendar.timeZone = NSTimeZone.system
|
||||||
self.calendar = calendar
|
self.calendar = calendar
|
||||||
}
|
}
|
||||||
@ -172,32 +277,32 @@ class MFTextField: ViewConstrainingView, MVMCoreUIMoleculeViewProtocol, FormVali
|
|||||||
createDatePicker()
|
createDatePicker()
|
||||||
if show {
|
if show {
|
||||||
if let fromDate = fromDate {
|
if let fromDate = fromDate {
|
||||||
if calendar.isDate(fromDate, inSameDayAs: Date()) {
|
if (calendar?.isDate(fromDate, inSameDayAs: Date()))! {
|
||||||
text = MVMCoreUIUtility.hardcodedString(withKey: "textfield_today_string")
|
text = MVMCoreUIUtility.hardcodedString(withKey: "textfield_today_string")
|
||||||
} else {
|
} else {
|
||||||
self.text = formatter.string(from: fromDate)
|
self.text = formatter.string(from: fromDate)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
datePicker.minimumDate = fromDate
|
datePicker?.minimumDate = fromDate
|
||||||
datePicker.maximumDate = toDate
|
datePicker?.maximumDate = toDate
|
||||||
}
|
}
|
||||||
|
|
||||||
func setDatePickerFrom(_ fromDate: Date?, to toDate: Date?) {
|
func setDatePickerFrom(_ fromDate: Date?, to toDate: Date?) {
|
||||||
if let fromDate = fromDate {
|
if let fromDate = fromDate {
|
||||||
if calendar.isDate(fromDate, inSameDayAs: Date()) {
|
if (calendar?.isDate(fromDate, inSameDayAs: Date()))! {
|
||||||
text = MVMCoreUIUtility.hardcodedString(withKey: "textfield_today_string")
|
text = MVMCoreUIUtility.hardcodedString(withKey: "textfield_today_string")
|
||||||
} else {
|
} else {
|
||||||
self.text = formatter.string(from: fromDate)
|
self.text = formatter.string(from: fromDate)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
datePicker.minimumDate = fromDate
|
datePicker?.minimumDate = fromDate
|
||||||
datePicker.maximumDate = toDate
|
datePicker?.maximumDate = toDate
|
||||||
datePicker.timeZone = NSTimeZone.system
|
datePicker?.timeZone = NSTimeZone.system
|
||||||
}
|
}
|
||||||
|
|
||||||
func dismissDatePicker() -> Date? {
|
func dismissDatePicker() -> Date? {
|
||||||
let pickedDate = datePicker.date
|
let pickedDate = datePicker!.date
|
||||||
if let pickedDate = pickedDate {
|
if let pickedDate = pickedDate {
|
||||||
if calendar.isDate(pickedDate, inSameDayAs: Date()) {
|
if calendar.isDate(pickedDate, inSameDayAs: Date()) {
|
||||||
text = MVMCoreUIUtility.hardcodedString(withKey: "textfield_today_string")
|
text = MVMCoreUIUtility.hardcodedString(withKey: "textfield_today_string")
|
||||||
@ -205,49 +310,49 @@ class MFTextField: ViewConstrainingView, MVMCoreUIMoleculeViewProtocol, FormVali
|
|||||||
self.text = formatter.string(from: pickedDate)
|
self.text = formatter.string(from: pickedDate)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
textField.resignFirstResponder()
|
textField?.resignFirstResponder()
|
||||||
return pickedDate
|
return pickedDate
|
||||||
}
|
}
|
||||||
|
|
||||||
func dismissPicker() {
|
func dismissPicker() {
|
||||||
textField.resignFirstResponder()
|
textField?.resignFirstResponder()
|
||||||
}
|
}
|
||||||
|
|
||||||
func setErrorMessage(_ errorMessage: String?) {
|
func setErrorMessage(_ errorMessage: String?) {
|
||||||
|
|
||||||
MVMCoreDispatchUtility.performBlock(onMainThread: {
|
DispatchQueue.main.async { [weak self] in
|
||||||
if self.enabled == true {
|
if let enabled = self?.enabled {
|
||||||
self.separatorHeightConstraint.constant = 4
|
self?.separatorHeightConstraint?.constant = 4
|
||||||
self.errorShowing = true
|
self?.errorShowing = true
|
||||||
self.separatorView.backgroundColor = UIColor.mfPumpkin()
|
self?.separatorView?.backgroundColor = UIColor.mfPumpkin()
|
||||||
self.label.text() = errorMessage
|
self?.label.text() = errorMessage
|
||||||
self.label.numberOfLines = 0
|
self?.label.numberOfLines = 0
|
||||||
self.textField.accessibilityValue() = String(format: MVMCoreUIUtility.hardcodedString(withKey: "textfield_error_message"), self.textField.text() ?? "", errorMessage ?? "")
|
self?.textField.accessibilityValue() = String(format: MVMCoreUIUtility.hardcodedString(withKey: "textfield_error_message"), self.textField.text() ?? "", errorMessage ?? "")
|
||||||
self.setNeedsDisplay()
|
self?.setNeedsDisplay()
|
||||||
self.layoutIfNeeded()
|
self?.layoutIfNeeded()
|
||||||
}
|
}
|
||||||
})
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func pushAccessibilityNotification() {
|
func pushAccessibilityNotification() {
|
||||||
MVMCoreDispatchUtility.performBlock(onMainThread: {
|
DispatchQueue.main.async { [weak self] in
|
||||||
UIAccessibilityPostNotification(UIAccessibility.Notification.layoutChanged, self.textField)
|
UIAccessibilityPostNotification(UIAccessibility.Notification.layoutChanged, self?.textField)
|
||||||
})
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func hideError() {
|
func hideError() {
|
||||||
|
|
||||||
MVMCoreDispatchUtility.performBlock(onMainThread: {
|
DispatchQueue.main.async { [weak self] in
|
||||||
self.separatorHeightConstraint.constant = 1
|
self?.separatorHeightConstraint!.constant = 1
|
||||||
self.separatorView.backgroundColor = UIColor.black
|
self?.separatorView?.backgroundColor = UIColor.black
|
||||||
self.layoutIfNeeded()
|
self?.layoutIfNeeded()
|
||||||
self.errorShowing = false
|
self?.errorShowing = false
|
||||||
self.label.textColor = UIColor.black
|
self?.label.textColor = UIColor.black
|
||||||
self.label.text() = ""
|
self?.label.text() = ""
|
||||||
self.textField.accessibilityValue() = nil
|
self?.textField?.accessibilityValue = nil
|
||||||
self.setNeedsDisplay()
|
self?.setNeedsDisplay()
|
||||||
self.layoutIfNeeded()
|
self?.layoutIfNeeded()
|
||||||
})
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func placeholder() -> String? {
|
func placeholder() -> String? {
|
||||||
@ -265,7 +370,7 @@ class MFTextField: ViewConstrainingView, MVMCoreUIMoleculeViewProtocol, FormVali
|
|||||||
// fixed crash issue
|
// fixed crash issue
|
||||||
if placeholder != nil {
|
if placeholder != nil {
|
||||||
if let color = color {
|
if let color = color {
|
||||||
textField.attributedPlaceholder = NSAttributedString(string: placeholder ?? "", attributes: [
|
textField!.attributedPlaceholder = NSAttributedString(string: placeholder ?? "", attributes: [
|
||||||
NSAttributedString.Key.foregroundColor: color
|
NSAttributedString.Key.foregroundColor: color
|
||||||
])
|
])
|
||||||
}
|
}
|
||||||
@ -285,18 +390,18 @@ class MFTextField: ViewConstrainingView, MVMCoreUIMoleculeViewProtocol, FormVali
|
|||||||
// then only can append regular and picker item
|
// then only can append regular and picker item
|
||||||
if hasDropDown {
|
if hasDropDown {
|
||||||
// MFDLog(@"Label: %@", self.textField.accessibilityLabel);
|
// MFDLog(@"Label: %@", self.textField.accessibilityLabel);
|
||||||
accessibilityString = accessibilityString ?? "" + (MVMCoreUIUtility.hardcodedString(withKey: "textfield_picker_item"))
|
accessibilityString = accessibilityString ?? "" + (MVMCoreUIUtility.hardcodedString(withKey: "textfield_picker_item")!)
|
||||||
// MFDLog(@"Label: %@", self.textField.accessibilityLabel);
|
// MFDLog(@"Label: %@", self.textField.accessibilityLabel);
|
||||||
} else {
|
} else {
|
||||||
accessibilityString = accessibilityString ?? "" + (MVMCoreUIUtility.hardcodedString(withKey: "textfield_regular"))
|
accessibilityString = accessibilityString ?? "" + (MVMCoreUIUtility.hardcodedString(withKey: "textfield_regular")!)
|
||||||
// MFDLog(@"Label: %@", self.textField.accessibilityLabel);
|
// MFDLog(@"Label: %@", self.textField.accessibilityLabel);
|
||||||
}
|
}
|
||||||
|
|
||||||
textField.accessibilityLabel() = "\(accessibilityString ?? "") \(textField.isEnabled ? "" : MVMCoreUIUtility.hardcodedString(withKey: "textfield_disabled_state"))"
|
textField!.accessibilityLabel() = "\(accessibilityString ?? "") \(textField.isEnabled ? "" : MVMCoreUIUtility.hardcodedString(withKey: "textfield_disabled_state"))"
|
||||||
}
|
}
|
||||||
|
|
||||||
func setFormText(_ formText: String?) {
|
func setFormText(_ formText: String?) {
|
||||||
formLabel.text = formText
|
formLabel?.text = formText
|
||||||
setAccessibilityString(formText)
|
setAccessibilityString(formText)
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -305,7 +410,7 @@ class MFTextField: ViewConstrainingView, MVMCoreUIMoleculeViewProtocol, FormVali
|
|||||||
}
|
}
|
||||||
|
|
||||||
func setText(_ text: String?) {
|
func setText(_ text: String?) {
|
||||||
textField.text = text
|
textField?.text = text
|
||||||
valueChanged()
|
valueChanged()
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -326,31 +431,36 @@ class MFTextField: ViewConstrainingView, MVMCoreUIMoleculeViewProtocol, FormVali
|
|||||||
|
|
||||||
func setUiTextFieldDelegate(_ uiTextFieldDelegate: UITextFieldDelegate?) {
|
func setUiTextFieldDelegate(_ uiTextFieldDelegate: UITextFieldDelegate?) {
|
||||||
self.uiTextFieldDelegate = uiTextFieldDelegate
|
self.uiTextFieldDelegate = uiTextFieldDelegate
|
||||||
textField.delegate = uiTextFieldDelegate
|
textField?.delegate = uiTextFieldDelegate
|
||||||
}
|
}
|
||||||
|
|
||||||
func setBothTextFieldDelegates(_ delegate: (UITextFieldDelegate & MFTextFieldDelegate)?) {
|
func setBothTextFieldDelegates(_ delegate: (UITextFieldDelegate & MFTextFieldDelegate)?) {
|
||||||
mfTextFieldDelegate = delegate
|
mfTextFieldDelegate = delegate
|
||||||
uiTextFieldDelegate = delegate
|
uiTextFieldDelegate = delegate
|
||||||
}
|
}
|
||||||
|
|
||||||
func setWithMap(_ map: [AnyHashable : Any]?) {
|
func setWithMap(_ map: [AnyHashable: Any]?) {
|
||||||
if map?.count == 0 {
|
|
||||||
return
|
guard let map = map, !map.isEmpty else { return }
|
||||||
}
|
|
||||||
|
var string = map.string(KeyLabel)
|
||||||
|
|
||||||
var string = map?.string(KeyLabel)
|
|
||||||
if (string?.count ?? 0) > 0 {
|
if (string?.count ?? 0) > 0 {
|
||||||
formText = string
|
formText = string
|
||||||
}
|
}
|
||||||
|
|
||||||
string = map?.string(KeyValue)
|
string = map?.string(KeyValue)
|
||||||
|
|
||||||
if (string?.count ?? 0) > 0 {
|
if (string?.count ?? 0) > 0 {
|
||||||
text = string
|
text = string
|
||||||
}
|
}
|
||||||
|
|
||||||
string = map?.string(forKey: KeyDisable)
|
string = map?.string(forKey: KeyDisable)
|
||||||
|
|
||||||
if string?.isEqual(StringY) ?? false || map?.bool(forKey: KeyDisable) != nil {
|
if string?.isEqual(StringY) ?? false || map?.bool(forKey: KeyDisable) != nil {
|
||||||
enable(false)
|
enable(false)
|
||||||
}
|
}
|
||||||
|
|
||||||
string = map?.string(KeyErrorMessage)
|
string = map?.string(KeyErrorMessage)
|
||||||
if (string?.count ?? 0) > 0 {
|
if (string?.count ?? 0) > 0 {
|
||||||
errMessage = string
|
errMessage = string
|
||||||
@ -366,12 +476,15 @@ class MFTextField: ViewConstrainingView, MVMCoreUIMoleculeViewProtocol, FormVali
|
|||||||
if (string == "dropDown") {
|
if (string == "dropDown") {
|
||||||
dropDownCarrotLabel().hidden = false
|
dropDownCarrotLabel().hidden = false
|
||||||
self.hasDropDown = true
|
self.hasDropDown = true
|
||||||
|
|
||||||
} else if (string == "password") {
|
} else if (string == "password") {
|
||||||
textField.isSecureTextEntry = true
|
textField?.isSecureTextEntry = true
|
||||||
|
|
||||||
} else if (string == "number") {
|
} else if (string == "number") {
|
||||||
textField.keyboardType = .numberPad
|
textField?.keyboardType = .numberPad
|
||||||
|
|
||||||
} else if (string == "email") {
|
} else if (string == "email") {
|
||||||
textField.keyboardType = .emailAddress
|
textField?.keyboardType = .emailAddress
|
||||||
}
|
}
|
||||||
|
|
||||||
string = map?.string("regex")
|
string = map?.string("regex")
|
||||||
@ -385,7 +498,7 @@ class MFTextField: ViewConstrainingView, MVMCoreUIMoleculeViewProtocol, FormVali
|
|||||||
}
|
}
|
||||||
|
|
||||||
func setWithMap(_ map: [AnyHashable : Any]?, bothDelegates delegate: (UITextFieldDelegate & MFTextFieldDelegate)?) {
|
func setWithMap(_ map: [AnyHashable : Any]?, bothDelegates delegate: (UITextFieldDelegate & MFTextFieldDelegate)?) {
|
||||||
MVMCoreUICommonViewsUtility.addDismissToolbar(textField, delegate: delegate)
|
MVMCoreUICommonViewsUtility.addDismissToolbar(textField!, delegate: delegate)
|
||||||
self.bothTextFieldDelegates = delegate
|
self.bothTextFieldDelegates = delegate
|
||||||
setWithMap(map)
|
setWithMap(map)
|
||||||
}
|
}
|
||||||
@ -405,23 +518,23 @@ class MFTextField: ViewConstrainingView, MVMCoreUIMoleculeViewProtocol, FormVali
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func setLeftPinConstant(_ constant: CGFloat) {
|
override func setLeftPinConstant(_ constant: CGFloat) {
|
||||||
textContainerLeftPin.constant = constant
|
textContainerLeftPin?.constant = constant
|
||||||
errorLableLeftPin.constant = constant
|
errorLableLeftPin?.constant = constant
|
||||||
formLabelLeftPin.constant = constant
|
formLabelLeftPin?.constant = constant
|
||||||
}
|
}
|
||||||
|
|
||||||
func setRightPinConstant(_ constant: CGFloat) {
|
func setRightPinConstant(_ constant: CGFloat) {
|
||||||
textContainerRightPin.constant = constant
|
textContainerRightPin?.constant = constant
|
||||||
errorLableRightPin.constant = constant
|
errorLableRightPin?.constant = constant
|
||||||
formLabelRightPin.constant = constant
|
formLabelRightPin?.constant = constant
|
||||||
}
|
}
|
||||||
|
|
||||||
deinit {
|
|
||||||
self.bothTextFieldDelegates = nil
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
|
//--------------------------------------------------
|
||||||
// MARK: - XIB Helpers
|
// MARK: - XIB Helpers
|
||||||
|
//--------------------------------------------------
|
||||||
func showDropDown(_ show: Bool) {
|
func showDropDown(_ show: Bool) {
|
||||||
if hasDropDown {
|
if hasDropDown {
|
||||||
dropDownCarrotLabel.hidden = !show
|
dropDownCarrotLabel.hidden = !show
|
||||||
@ -433,47 +546,50 @@ class MFTextField: ViewConstrainingView, MVMCoreUIMoleculeViewProtocol, FormVali
|
|||||||
|
|
||||||
func enable(_ enable: Bool) {
|
func enable(_ enable: Bool) {
|
||||||
enabled = enable //Set outside the dispatch so that registerAnimations can know about it
|
enabled = enable //Set outside the dispatch so that registerAnimations can know about it
|
||||||
MVMCoreDispatchUtility.performBlock(onMainThread: {
|
DispatchQueue.main.async { [weak self] in
|
||||||
self.isUserInteractionEnabled = enable
|
self?.isUserInteractionEnabled = enable
|
||||||
self.textField.userInteractionEnabled = enable
|
self?.textField.userInteractionEnabled = enable
|
||||||
self.textField.isEnabled = enable
|
self?.textField.isEnabled = enable
|
||||||
if enable {
|
if enable {
|
||||||
self.textField.textColor = self.customEnabledTextColor ?? UIColor.black
|
self?.textField.textColor = self.customEnabledTextColor ?? .black
|
||||||
self.formLabel.textColor = UIColor.mfBattleshipGrey()
|
self?.formLabel.textColor = UIColor.mfBattleshipGrey()
|
||||||
self.label.textColor = UIColor.black
|
self?.label.textColor = UIColor.black
|
||||||
if self.errorShowing {
|
if self!.errorShowing {
|
||||||
self.separatorView.backgroundColor = UIColor.mfPumpkin()
|
self?.separatorView.backgroundColor = UIColor.mfPumpkin()
|
||||||
} else {
|
} else {
|
||||||
self.separatorView.backgroundColor = UIColor.black
|
self?.separatorView.backgroundColor = .black
|
||||||
}
|
}
|
||||||
self.showDropDown(true)
|
self?.showDropDown(true)
|
||||||
} else {
|
} else {
|
||||||
self.textField.textColor = self.customDisabledTextColor ?? UIColor.mfSilver()
|
self?.textField.textColor = self!.customDisabledTextColor ?? UIColor.mfSilver()
|
||||||
self.formLabel.textColor = UIColor.mfSilver()
|
self?.formLabel.textColor = UIColor.mfSilver()
|
||||||
self.label.textColor = UIColor.mfSilver()
|
self?.label.textColor = UIColor.mfSilver()
|
||||||
self.showDropDown(false)
|
self?.showDropDown(false)
|
||||||
self.hideError() //should not have error if the field is disabled
|
self?.hideError() //should not have error if the field is disabled
|
||||||
self.separatorView.backgroundColor = UIColor.mfSilver()
|
self?.separatorView.backgroundColor = UIColor.mfSilver()
|
||||||
}
|
}
|
||||||
})
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func showLabel(_ show: Bool) {
|
func showLabel(_ show: Bool) {
|
||||||
label.hidden = !show
|
label?.hidden = !show
|
||||||
}
|
}
|
||||||
|
|
||||||
func dashSeperatorView(_ dash: Bool) {
|
func dashSeperatorView(_ dash: Bool) {
|
||||||
if dash {
|
if dash {
|
||||||
dashLine.hidden = false
|
dashLine?.hidden = false
|
||||||
//never hide seperator view because it could be possiblely used by other classes for positioning
|
//never hide seperator view because it could be possiblely used by other classes for positioning
|
||||||
separatorView.backgroundColor = UIColor.clear
|
separatorView?.backgroundColor = .clear
|
||||||
} else {
|
} else {
|
||||||
dashLine.hidden = true
|
dashLine?.hidden = true
|
||||||
separatorView.backgroundColor = UIColor.black
|
separatorView.backgroundColor = .black
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
//--------------------------------------------------
|
||||||
// MARK: - Observing for change
|
// MARK: - Observing for change
|
||||||
|
//--------------------------------------------------
|
||||||
|
|
||||||
func validateBlock() {
|
func validateBlock() {
|
||||||
valueChanged()
|
valueChanged()
|
||||||
}
|
}
|
||||||
@ -482,7 +598,7 @@ class MFTextField: ViewConstrainingView, MVMCoreUIMoleculeViewProtocol, FormVali
|
|||||||
|
|
||||||
// update label for placeholder
|
// update label for placeholder
|
||||||
if !errorShowing {
|
if !errorShowing {
|
||||||
label.text = ""
|
label?.text = ""
|
||||||
}
|
}
|
||||||
|
|
||||||
// Check validity.
|
// Check validity.
|
||||||
@ -499,7 +615,7 @@ class MFTextField: ViewConstrainingView, MVMCoreUIMoleculeViewProtocol, FormVali
|
|||||||
self.errorMessage = errMessage
|
self.errorMessage = errMessage
|
||||||
}
|
}
|
||||||
if mfTextFieldDelegate.responds(to: #selector(entryIsInvalid(_:))) {
|
if mfTextFieldDelegate.responds(to: #selector(entryIsInvalid(_:))) {
|
||||||
mfTextFieldDelegate.entryIsInvalid(self)
|
mfTextFieldDelegate?.entryIsInvalid(self)
|
||||||
}
|
}
|
||||||
} else if !previousValidity && valid {
|
} else if !previousValidity && valid {
|
||||||
hideError()
|
hideError()
|
||||||
@ -512,7 +628,7 @@ class MFTextField: ViewConstrainingView, MVMCoreUIMoleculeViewProtocol, FormVali
|
|||||||
func endInputing() {
|
func endInputing() {
|
||||||
if isValid {
|
if isValid {
|
||||||
hideError()
|
hideError()
|
||||||
separatorView.backgroundColor = UIColor.black
|
separatorView.backgroundColor = .black
|
||||||
} else {
|
} else {
|
||||||
if errMessage {
|
if errMessage {
|
||||||
self.errorMessage = errMessage
|
self.errorMessage = errMessage
|
||||||
@ -520,12 +636,10 @@ class MFTextField: ViewConstrainingView, MVMCoreUIMoleculeViewProtocol, FormVali
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// MARK: - helper
|
|
||||||
|
|
||||||
func startEditing() {
|
func startEditing() {
|
||||||
textField.becomeFirstResponder()
|
textField.becomeFirstResponder()
|
||||||
if !errorShowing {
|
if !errorShowing {
|
||||||
separatorView.backgroundColor = UIColor.black
|
separatorView?.backgroundColor = .black
|
||||||
separatorHeightConstraint.constant = 1
|
separatorHeightConstraint.constant = 1
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -540,8 +654,9 @@ class MFTextField: ViewConstrainingView, MVMCoreUIMoleculeViewProtocol, FormVali
|
|||||||
return enabledTextFields
|
return enabledTextFields
|
||||||
}
|
}
|
||||||
|
|
||||||
//#pragma mark - Accessibility
|
//--------------------------------------------------
|
||||||
|
// MARK: - Accessibility
|
||||||
|
//--------------------------------------------------
|
||||||
|
|
||||||
func formatter() -> DateFormatter? {
|
func formatter() -> DateFormatter? {
|
||||||
if !formatter {
|
if !formatter {
|
||||||
@ -554,65 +669,41 @@ class MFTextField: ViewConstrainingView, MVMCoreUIMoleculeViewProtocol, FormVali
|
|||||||
return formatter
|
return formatter
|
||||||
}
|
}
|
||||||
|
|
||||||
func draw(_ rect: CGRect) {
|
|
||||||
super.draw(rect)
|
|
||||||
borderPath.removeAllPoints()
|
//--------------------------------------------------
|
||||||
if !hideBorder {
|
// MARK: - Molecular
|
||||||
let frame = textFieldContainerView.frame
|
//--------------------------------------------------
|
||||||
borderPath = UIBezierPath()
|
|
||||||
borderPath.move(to: CGPoint(x: frame.origin.x, y: frame.origin.y + frame.size.height))
|
override open func setWithJSON(_ json: [AnyHashable : Any]?, delegateObject: MVMCoreUIDelegateObject?, additionalData: [AnyHashable : Any]?) {
|
||||||
borderPath.addLine(to: CGPoint(x: frame.origin.x, y: frame.origin.y))
|
if (delegateObject is MVMCoreUIDelegateObject) {
|
||||||
borderPath.addLine(to: CGPoint(x: frame.origin.x + frame.size.width, y: frame.origin.y))
|
FormValidator.setupValidation(withMolecule: self, delegate: delegateObject?.formValidationProtocol)
|
||||||
borderPath.addLine(to: CGPoint(x: frame.origin.x + frame.size.width, y: frame.origin.y + frame.size.height))
|
let formValidator = FormValidator.getForDelegate(delegateObject?.formValidationProtocol)
|
||||||
|
|
||||||
borderPath.lineWidth = 1
|
self.withMap = json
|
||||||
|
mfTextFieldDelegate = formValidator
|
||||||
var strokeColor: UIColor?
|
uiTextFieldDelegate = delegateObject?.uiTextFieldDelegate
|
||||||
if errorShowing {
|
MVMCoreUICommonViewsUtility.addDismissToolbar(textField, delegate: uiTextFieldDelegate)
|
||||||
strokeColor = UIColor.mfPumpkin()
|
|
||||||
} else {
|
|
||||||
strokeColor = UIColor.mfSilver()
|
|
||||||
}
|
|
||||||
|
|
||||||
strokeColor?.setStroke()
|
|
||||||
|
|
||||||
borderPath.stroke()
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
//////////////////////
|
override open class func estimatedHeight(forRow json: [AnyHashable : Any]?, delegateObject: MVMCoreUIDelegateObject?) -> CGFloat {
|
||||||
|
return 76
|
||||||
#pragma mark - MVMCoreUIMoleculeViewProtocol
|
|
||||||
|
|
||||||
- (void)setWithJSON:(NSDictionary *)json delegateObject:(MVMCoreUIDelegateObject *)delegateObject additionalData:(NSDictionary *)additionalData {
|
|
||||||
if ([delegateObject isKindOfClass:[MVMCoreUIDelegateObject class]]) {
|
|
||||||
[FormValidator setupValidationWithMolecule:self delegate:delegateObject.formValidationProtocol];
|
|
||||||
FormValidator *formValidator = [FormValidator getFormValidatorForDelegate:delegateObject.formValidationProtocol];
|
|
||||||
|
|
||||||
[self setWithMap:json];
|
|
||||||
self.mfTextFieldDelegate = formValidator;
|
|
||||||
self.uiTextFieldDelegate = delegateObject.uiTextFieldDelegate;
|
|
||||||
[MVMCoreUICommonViewsUtility addDismissToolbar:self.textField delegate:self.uiTextFieldDelegate];
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
//--------------------------------------------------
|
||||||
|
// MARK: - Form Validation
|
||||||
|
//--------------------------------------------------
|
||||||
|
|
||||||
+ (CGFloat)estimatedHeightForRow:(NSDictionary *)json delegateObject:(MVMCoreUIDelegateObject *)delegateObject {
|
public func isValidField() -> Bool {
|
||||||
return 76;
|
return isValid
|
||||||
}
|
}
|
||||||
|
|
||||||
#pragma mark - FormValidationProtocol
|
public func formFieldName() -> String? {
|
||||||
|
return fieldKey
|
||||||
|
|
||||||
- (BOOL)isValidField {
|
|
||||||
return self.isValid;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
- (nullable NSString *)formFieldName {
|
public func formFieldValue() -> Any? {
|
||||||
return self.fieldKey;
|
return text
|
||||||
}
|
|
||||||
|
|
||||||
- (nullable id)formFieldValue {
|
|
||||||
return self.text;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
Loading…
Reference in New Issue
Block a user