| /* |
| * Licensed to the Apache Software Foundation (ASF) under one |
| * or more contributor license agreements. See the NOTICE file |
| * distributed with this work for additional information |
| * regarding copyright ownership. The ASF licenses this file |
| * to you under the Apache License, Version 2.0 (the |
| * "License"); you may not use this file except in compliance |
| * with the License. You may obtain a copy of the License at |
| * |
| * http://www.apache.org/licenses/LICENSE-2.0 |
| * |
| * Unless required by applicable law or agreed to in writing, |
| * software distributed under the License is distributed on an |
| * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY |
| * KIND, either express or implied. See the License for the |
| * specific language governing permissions and limitations |
| * under the License. |
| */ |
| |
| #import "WXEditComponent.h" |
| #import "WXConvert.h" |
| #import "WXUtility.h" |
| #import "WXSDKInstance.h" |
| #import "WXSDKInstance_private.h" |
| #import "WXDefine.h" |
| #import "WXAssert.h" |
| #import "WXComponent_internal.h" |
| #import "WXComponent+PseudoClassManagement.h" |
| #import "WXTextInputComponent.h" |
| #import "WXComponent+Layout.h" |
| |
| @interface WXEditComponent() |
| { |
| CGFloat _upriseOffset; // additional space when edit is lifted by keyboard |
| } |
| |
| //@property (nonatomic, strong) WXTextInputView *inputView; |
| @property (nonatomic, strong) WXDatePickerManager *datePickerManager; |
| @property (nonatomic, strong) NSDictionary *attr; |
| //attribute |
| @property (nonatomic) NSNumber *maxLength; |
| @property (nonatomic) NSString * value; |
| @property (nonatomic) BOOL autofocus; |
| @property (nonatomic) UIReturnKeyType returnKeyType; |
| @property (nonatomic) BOOL disabled; |
| @property (nonatomic, copy) NSString *inputType; |
| @property (nonatomic) NSUInteger rows; |
| @property (nonatomic) BOOL hideDoneButton; |
| |
| //style |
| @property (nonatomic) WXPixelType fontSize; |
| @property (nonatomic) WXTextStyle fontStyle; |
| @property (nonatomic) CGFloat fontWeight; |
| @property (nonatomic, strong) NSString *fontFamily; |
| @property (nonatomic, strong) UIColor *colorForStyle; |
| @property (nonatomic)NSTextAlignment textAlignForStyle; |
| |
| //event |
| @property (nonatomic) BOOL inputEvent; |
| @property (nonatomic) BOOL clickEvent; |
| @property (nonatomic) BOOL focusEvent; |
| @property (nonatomic) BOOL blurEvent; |
| @property (nonatomic) BOOL changeEvent; |
| @property (nonatomic) BOOL returnEvent; |
| @property (nonatomic) BOOL keyboardEvent; |
| @property (nonatomic, strong) NSString *changeEventString; |
| @property (nonatomic, assign) CGSize keyboardSize; |
| |
| // formatter |
| @property (nonatomic, strong) NSString * formatRule; |
| @property (nonatomic, strong) NSString * formatReplace; |
| @property (nonatomic, strong) NSString * recoverRule; |
| @property (nonatomic, strong) NSString * recoverReplace; |
| @property (nonatomic, strong) NSDictionary * formaterData; |
| |
| // disable move rootView up as the keyboard show up. |
| @property (nonatomic, assign) BOOL disableMoveViewUp; |
| |
| // avoid keyboardWillHide executes twice |
| @property (nonatomic, assign) BOOL keyboardHidden; |
| |
| @end |
| |
| @implementation WXEditComponent |
| { |
| UIEdgeInsets _border; |
| UIEdgeInsets _padding; |
| } |
| |
| WX_EXPORT_METHOD(@selector(focus)) |
| WX_EXPORT_METHOD(@selector(blur)) |
| WX_EXPORT_METHOD(@selector(setSelectionRange:selectionEnd:)) |
| WX_EXPORT_METHOD(@selector(getSelectionRange:)) |
| WX_EXPORT_METHOD(@selector(setTextFormatter:)) |
| |
| - (instancetype)initWithRef:(NSString *)ref type:(NSString *)type styles:(NSDictionary *)styles attributes:(NSDictionary *)attributes events:(NSArray *)events weexInstance:(WXSDKInstance *)weexInstance |
| { |
| self = [super initWithRef:ref type:type styles:styles attributes:attributes events:events weexInstance:weexInstance]; |
| if (self) { |
| _inputEvent = NO; |
| _focusEvent = NO; |
| _blurEvent = NO; |
| _changeEvent = NO; |
| _returnEvent = NO; |
| _clickEvent = NO; |
| _keyboardEvent = NO; |
| _keyboardHidden = YES; |
| _textAlignForStyle = NSTextAlignmentNatural; |
| // handle attributes |
| _autofocus = [attributes[@"autofocus"] boolValue]; |
| _disabled = [attributes[@"disabled"] boolValue]; |
| _value = [WXConvert NSString:attributes[@"value"]]?:@""; |
| _placeholderString = [WXConvert NSString:attributes[@"placeholder"]]?:@""; |
| _upriseOffset = 20; // 20 for better appearance |
| |
| if (attributes[@"upriseOffset"]) { |
| _upriseOffset = [WXConvert CGFloat:attributes[@"upriseOffset"]]; |
| } |
| |
| if(attributes[@"type"]) { |
| _inputType = [WXConvert NSString:attributes[@"type"]]; |
| _attr = attributes; |
| } |
| if (attributes[@"maxlength"]) { |
| _maxLength = [NSNumber numberWithUnsignedInteger:[attributes[@"maxlength"] integerValue]]; |
| } |
| if (attributes[@"returnKeyType"]) { |
| _returnKeyType = [WXConvert UIReturnKeyType:attributes[@"returnKeyType"]]; |
| } |
| if (attributes[@"rows"]) { |
| _rows = [attributes[@"rows"] integerValue]; |
| } else { |
| _rows = 2; |
| } |
| |
| if (attributes[@"hideDoneButton"]) { |
| _hideDoneButton = [attributes[@"hideDoneButton"] boolValue]; |
| } |
| if (attributes[@"disableMoveViewUp"]) { |
| _disableMoveViewUp = [WXConvert BOOL:attributes[@"disableMoveViewUp"]]; |
| } |
| |
| // handle styles |
| if (styles[@"color"]) { |
| _colorForStyle = [WXConvert UIColor:styles[@"color"]]; |
| } |
| if (styles[@"fontSize"]) { |
| _fontSize = [WXConvert WXPixelType:styles[@"fontSize"] scaleFactor:self.weexInstance.pixelScaleFactor]; |
| } |
| if (styles[@"fontWeight"]) { |
| _fontWeight = [WXConvert WXTextWeight:styles[@"fontWeight"]]; |
| } |
| if (styles[@"fontStyle"]) { |
| _fontStyle = [WXConvert WXTextStyle:styles[@"fontStyle"]]; |
| } |
| if (styles[@"fontFamily"]) { |
| _fontFamily = styles[@"fontFamily"]; |
| } |
| if (styles[@"textAlign"]) { |
| _textAlignForStyle = [WXConvert NSTextAlignment:styles[@"textAlign"]]; |
| } |
| if (styles[@"placeholderColor"]) { |
| _placeholderColor = [WXConvert UIColor:styles[@"placeholderColor"]]; |
| }else { |
| _placeholderColor = [UIColor colorWithRed:0x99/255.0 green:0x99/255.0 blue:0x99/255.0 alpha:1.0]; |
| } |
| } |
| |
| return self; |
| } |
| |
| #pragma mark - lifeCircle |
| |
| - (void)viewDidLoad |
| { |
| UIView * view = self.view; |
| if ([view isKindOfClass:[UITextField class]]){ |
| [[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(textFiledEditChanged:) |
| name:UITextFieldTextDidChangeNotification |
| object:view]; |
| } |
| _padding = UIEdgeInsetsZero; |
| _border = UIEdgeInsetsZero; |
| self.userInteractionEnabled = YES; |
| [self setType]; |
| [self setAutofocus:_autofocus]; |
| [self setTextFont]; |
| [self setPlaceholderAttributedString]; |
| [self setTextAlignment]; |
| [self setTextColor:_colorForStyle]; |
| [self setText:_value]; |
| [self setEnabled:!_disabled]; |
| [self setRows:_rows]; |
| [self setReturnKeyType:_returnKeyType]; |
| [self updatePattern]; |
| |
| if (!self.hideDoneButton) { |
| UIBarButtonItem *barButton = [[UIBarButtonItem alloc] initWithBarButtonSystemItem:UIBarButtonSystemItemDone target:self action:@selector(closeKeyboard)]; |
| UIBarButtonItem *space = [[UIBarButtonItem alloc] initWithBarButtonSystemItem:UIBarButtonSystemItemFlexibleSpace target:nil action:nil]; |
| UIToolbar *toolbar = [[UIToolbar alloc] initWithFrame:CGRectMake(0, 0, 0, 44)]; |
| toolbar.items = [NSArray arrayWithObjects:space, barButton, nil]; |
| |
| self.inputAccessoryView = toolbar; |
| } |
| |
| [self handlePseudoClass]; |
| } |
| |
| - (void)viewWillLoad |
| { |
| [[NSNotificationCenter defaultCenter] addObserver:self |
| selector:@selector(keyboardWasShown:) |
| name:UIKeyboardWillShowNotification |
| object:nil]; |
| |
| [[NSNotificationCenter defaultCenter] addObserver:self |
| selector:@selector(keyboardWillHide:) |
| name:UIKeyboardWillHideNotification |
| object:nil]; |
| } |
| |
| - (void)dealloc |
| { |
| [[NSNotificationCenter defaultCenter] removeObserver:self]; |
| } |
| |
| - (void)layoutDirectionDidChanged:(BOOL)isRTL { |
| [self setTextAlignment]; |
| } |
| |
| -(void)focus |
| { |
| if(self.view) { |
| [self.view becomeFirstResponder]; |
| self.weexInstance.apmInstance.forceStopRecordInteractionTime = YES; |
| } |
| } |
| |
| -(void)blur |
| { |
| if(self.view) { |
| [[NSNotificationCenter defaultCenter] postNotificationName:UIKeyboardWillHideNotification object:nil]; |
| [self.view resignFirstResponder]; |
| } |
| } |
| |
| -(void)setSelectionRange:(NSInteger)selectionStart selectionEnd:(NSInteger)selectionEnd |
| { |
| if(selectionStart>self.text.length || selectionEnd>self.text.length) { |
| return; |
| } |
| [self.view becomeFirstResponder]; |
| [self setEditSelectionRange:selectionStart selectionEnd:selectionEnd]; |
| } |
| |
| -(void)getSelectionRange:(WXKeepAliveCallback)callback |
| { |
| NSDictionary *res = [self getEditSelectionRange]; |
| if(callback) { |
| callback(res,NO); |
| } |
| } |
| |
| - (void)setTextFormatter:(NSDictionary*)formater |
| { |
| _formaterData = formater; |
| if (formater[@"formatRule"]) {; |
| _formatRule = [self _preProcessInputTextFormatter:[WXConvert NSString:formater[@"formatRule"]]]; |
| } |
| if (formater[@"formatReplace"]) { |
| _formatReplace = [self _preProcessInputTextFormatter:[WXConvert NSString:formater[@"formatReplace"]]]; |
| } |
| if (formater[@"recoverRule"]) { |
| _recoverRule = [self _preProcessInputTextFormatter:[WXConvert NSString:formater[@"recoverRule"]]]; |
| } |
| if (formater[@"recoverReplace"]) { |
| _recoverReplace = [self _preProcessInputTextFormatter:[WXConvert NSString:formater[@"recoverReplace"]]]; |
| } |
| } |
| |
| - (NSString*)_preProcessInputTextFormatter:(NSString*)formater |
| { |
| NSRange start = [formater rangeOfString:@"/"]; |
| NSRange end = [formater rangeOfString:@"/g"]; |
| if (start.location == NSNotFound || end.location == NSNotFound || end.location < start.location) { |
| return formater; |
| } |
| NSRange subStringRange = NSMakeRange(start.location+1, end.location - start.location-1); |
| |
| return [formater substringWithRange:subStringRange]; |
| } |
| |
| #pragma mark - Overwrite Method |
| -(NSString *)text |
| { |
| return @""; |
| } |
| |
| - (void)setText:(NSString *)text |
| { |
| } |
| |
| -(void)setTextColor:(UIColor *)color |
| { |
| } |
| |
| - (void)setTextAlignment { |
| if ([self isDirectionRTL] && _textAlignForStyle == NSTextAlignmentNatural) { |
| [self setTextAlignment:NSTextAlignmentRight]; |
| } else { |
| [self setTextAlignment:_textAlignForStyle]; |
| } |
| } |
| |
| -(void)setTextAlignment:(NSTextAlignment)textAlignForStyle |
| { |
| } |
| |
| -(void)setUserInteractionEnabled:(BOOL)userInteractionEnabled |
| { |
| } |
| |
| -(void)setEnabled:(BOOL)enabled |
| { |
| } |
| |
| -(void)setReturnKeyType:(UIReturnKeyType)returnKeyType |
| { |
| } |
| |
| -(void)setInputAccessoryView:(UIView *)inputAccessoryView |
| { |
| } |
| |
| -(void)setEditSelectionRange:(NSInteger)selectionStart selectionEnd:(NSInteger)selectionEnd |
| { |
| } |
| |
| -(NSDictionary *)getEditSelectionRange |
| { |
| return @{}; |
| } |
| |
| -(void)setKeyboardType:(UIKeyboardType)keyboardType |
| { |
| } |
| |
| -(void)setSecureTextEntry:(BOOL)secureTextEntry |
| { |
| } |
| |
| -(void)setEditPadding:(UIEdgeInsets)padding |
| { |
| } |
| |
| -(void)setEditBorder:(UIEdgeInsets)border |
| { |
| } |
| |
| -(void)setAttributedPlaceholder:(NSMutableAttributedString *)attributedString font:(UIFont *)font |
| { |
| } |
| |
| -(void)setFont:(UIFont *)font |
| { |
| } |
| |
| -(void)setRows:(NSUInteger)rows |
| { |
| } |
| |
| #pragma mark - Add Event |
| - (void)addEvent:(NSString *)eventName |
| { |
| if ([eventName isEqualToString:@"input"]) { |
| _inputEvent = YES; |
| } |
| if ([eventName isEqualToString:@"focus"]) { |
| _focusEvent = YES; |
| } |
| if ([eventName isEqualToString:@"blur"]) { |
| _blurEvent = YES; |
| } |
| if ([eventName isEqualToString:@"change"]) { |
| _changeEvent = YES; |
| } |
| if ([eventName isEqualToString:@"return"]) { |
| _returnEvent = YES; |
| } |
| if ([eventName isEqualToString:@"click"]) { |
| _clickEvent = YES; |
| } |
| if ([eventName isEqualToString:@"keyboard"]) { |
| _keyboardEvent = YES; |
| } |
| } |
| |
| #pragma Remove Event |
| |
| -(void)removeEvent:(NSString *)eventName |
| { |
| if ([eventName isEqualToString:@"input"]) { |
| _inputEvent = NO; |
| } |
| if ([eventName isEqualToString:@"focus"]) { |
| _focusEvent = NO; |
| } |
| if ([eventName isEqualToString:@"blur"]) { |
| _blurEvent = NO; |
| } |
| if ([eventName isEqualToString:@"change"]) { |
| _changeEvent = NO; |
| } |
| if ([eventName isEqualToString:@"return"]) { |
| _returnEvent = NO; |
| } |
| if ([eventName isEqualToString:@"click"]) { |
| _clickEvent = NO; |
| } |
| if ([eventName isEqualToString:@"keyboard"]) { |
| _keyboardEvent = NO; |
| } |
| } |
| |
| #pragma mark - upate attributes |
| |
| - (void)updateAttributes:(NSDictionary *)attributes |
| { |
| _attr = attributes; |
| if (attributes[@"type"]) { |
| _inputType = [WXConvert NSString:attributes[@"type"]]; |
| [self setType]; |
| } |
| if (attributes[@"autofocus"]) { |
| self.autofocus = [attributes[@"autofocus"] boolValue]; |
| } |
| if (attributes[@"disabled"]) { |
| _disabled = [attributes[@"disabled"] boolValue]; |
| [self setEnabled:!_disabled]; |
| } |
| if (attributes[@"maxlength"]) { |
| _maxLength = [NSNumber numberWithInteger:[attributes[@"maxlength"] integerValue]]; |
| } |
| |
| if (attributes[@"disableMoveViewUp"]) { |
| _disableMoveViewUp = [WXConvert BOOL:attributes[@"disableMoveViewUp"]]; |
| } |
| if (attributes[@"value"]) { |
| _value = [WXConvert NSString:attributes[@"value"]]?:@""; |
| if (_maxLength && [_value length] > [_maxLength integerValue]&& [_maxLength integerValue] >= 0) { |
| _value = [_value substringToIndex:([_maxLength integerValue])]; |
| } |
| [self setText:_value]; |
| } |
| if (attributes[@"placeholder"]) { |
| _placeholderString = [WXConvert NSString:attributes[@"placeholder"]]?:@""; |
| [self setPlaceholderAttributedString]; |
| if(_value.length > 0){ |
| _placeHolderLabel.text = @""; |
| } |
| } |
| if (attributes[@"returnKeyType"]) { |
| _returnKeyType = [WXConvert UIReturnKeyType:attributes[@"returnKeyType"]]; |
| [self setReturnKeyType:_returnKeyType]; |
| } |
| if (attributes[@"rows"]) { |
| _rows = [attributes[@"rows"] integerValue]; |
| [self setRows:_rows]; |
| } else { |
| _rows = 2; |
| [self setRows:_rows]; |
| } |
| if (attributes[@"upriseOffset"]) { |
| _upriseOffset = [WXConvert CGFloat:attributes[@"upriseOffset"]]; |
| } |
| } |
| |
| #pragma mark - upate styles |
| |
| - (void)updateStyles:(NSDictionary *)styles |
| { |
| if (styles[@"color"]) { |
| _colorForStyle = [WXConvert UIColor:styles[@"color"]]; |
| [self setTextColor:_colorForStyle]; |
| } |
| if (styles[@"fontSize"]) { |
| _fontSize = [WXConvert WXPixelType:styles[@"fontSize"] scaleFactor:self.weexInstance.pixelScaleFactor]; |
| } |
| if (styles[@"fontWeight"]) { |
| _fontWeight = [WXConvert WXTextWeight:styles[@"fontWeight"]]; |
| } |
| if (styles[@"fontStyle"]) { |
| _fontStyle = [WXConvert WXTextStyle:styles[@"fontStyle"]]; |
| } |
| if (styles[@"fontFamily"]) { |
| _fontFamily = [WXConvert NSString:styles[@"fontFamily"]]; |
| } |
| [self setTextFont]; |
| |
| if (styles[@"textAlign"]) { |
| _textAlignForStyle = [WXConvert NSTextAlignment:styles[@"textAlign"]]; |
| [self setTextAlignment:_textAlignForStyle] ; |
| } |
| if (styles[@"placeholderColor"]) { |
| _placeholderColor = [WXConvert UIColor:styles[@"placeholderColor"]]; |
| }else { |
| _placeholderColor = [UIColor colorWithRed:0x99/255.0 green:0x99/255.0 blue:0x99/255.0 alpha:1.0]; |
| } |
| [self setPlaceholderAttributedString]; |
| [self updatePattern]; |
| } |
| |
| -(void)updatePattern |
| { |
| if (self.flexCssNode == nullptr) { |
| return; |
| } |
| |
| UIEdgeInsets padding_flex = UIEdgeInsetsMake( |
| self.flexCssNode->getPaddingTop(), |
| self.flexCssNode->getPaddingLeft(), |
| self.flexCssNode->getPaddingBottom(), |
| self.flexCssNode->getPaddingRight() |
| ); |
| |
| if (!UIEdgeInsetsEqualToEdgeInsets(padding_flex, _padding)) { |
| [self setPadding:padding_flex]; |
| } |
| |
| |
| UIEdgeInsets border_flex = UIEdgeInsetsMake(self.flexCssNode->getBorderWidthTop(), self.flexCssNode->getBorderWidthLeft(), self.flexCssNode->getBorderWidthBottom(), self.flexCssNode->getBorderWidthRight()); |
| |
| if (!UIEdgeInsetsEqualToEdgeInsets(border_flex, _border)) { |
| [self setBorder:border_flex]; |
| } |
| } |
| |
| - (CGSize (^)(CGSize))measureBlock |
| { |
| __weak typeof(self) weakSelf = self; |
| return ^CGSize (CGSize constrainedSize) { |
| __strong typeof(self) strongSelf = weakSelf; |
| if (strongSelf == nil) { |
| return CGSizeZero; |
| } |
| |
| if (strongSelf.flexCssNode == nullptr) { |
| return CGSizeZero; |
| } |
| |
| CGSize computedSize = [[[NSString alloc] init]sizeWithAttributes:nil]; |
| if (!isnan(strongSelf.flexCssNode->getMinWidth())) { |
| computedSize.width = MAX(computedSize.width, strongSelf.flexCssNode->getMinWidth()); |
| } |
| |
| if (!isnan(strongSelf.flexCssNode->getMaxWidth())) { |
| computedSize.width = MIN(computedSize.width, strongSelf.flexCssNode->getMaxWidth()); |
| } |
| |
| if (!isnan(strongSelf.flexCssNode->getMinHeight())) { |
| computedSize.height = MAX(computedSize.height, strongSelf.flexCssNode->getMinHeight()); |
| } |
| |
| if (!isnan(strongSelf.flexCssNode->getMaxHeight())) { |
| computedSize.height = MIN(computedSize.height, strongSelf.flexCssNode->getMaxHeight()); |
| } |
| return (CGSize) { |
| WXCeilPixelValue(computedSize.width), |
| WXCeilPixelValue(computedSize.height) |
| }; |
| }; |
| } |
| |
| #pragma mark WXDatePickerManagerDelegate |
| |
| -(void)fetchDatePickerValue:(NSString *)value |
| { |
| self.text = value; |
| if (_changeEvent) { |
| if (![[self text] isEqualToString:_changeEventString]) { |
| [self fireEvent:@"change" params:@{@"value":[self text]} domChanges:@{@"attrs":@{@"value":[self text]}}]; |
| } |
| } |
| } |
| |
| #pragma mark UITextFieldDelegate |
| |
| - (BOOL)textFieldShouldBeginEditing:(UITextField *)textField{ |
| if([self isDateType]) |
| { |
| [[[UIApplication sharedApplication] keyWindow] endEditing:YES]; |
| _changeEventString = [textField text]; |
| [_datePickerManager show]; |
| return NO; |
| } |
| return YES; |
| } |
| |
| #pragma mark UITextFieldDelegate |
| |
| - (void)textFieldDidBeginEditing:(UITextField *)textField |
| { |
| _changeEventString = [textField text]; |
| if (_focusEvent) { |
| [self fireEvent:@"focus" params:nil]; |
| } |
| [self handlePseudoClass]; |
| } |
| |
| - (BOOL)textField:(UITextField *)textField shouldChangeCharactersInRange:(NSRange)range replacementString:(NSString *)string |
| { |
| if (!string.length) { |
| ((WXTextInputView*)textField).deleteWords = YES; |
| ((WXTextInputView*)textField).editWords = [textField.text substringWithRange:range]; |
| } else { |
| ((WXTextInputView*)textField).deleteWords = FALSE; |
| ((WXTextInputView*)textField).editWords = string; |
| } |
| |
| if ([_inputType isEqualToString:@"tel"] || [_inputType isEqualToString:@"number"] ) { |
| if (![self isPureInt:string]) { |
| if ([string isEqualToString:@"+"]||[string isEqualToString:@"."]||[string isEqualToString:@"*"]||[string isEqualToString:@"#"]||(string.length == 0 && range.length == 1)) |
| { |
| return YES; |
| } |
| return NO; |
| } |
| } |
| return YES; |
| } |
| |
| - (void)textFieldDidEndEditing:(UITextField *)textField |
| { |
| if (_changeEvent) { |
| if (![[textField text] isEqualToString:_changeEventString]) { |
| [self fireEvent:@"change" params:@{@"value":[textField text]} domChanges:@{@"attrs":@{@"value":[textField text]}}]; |
| } |
| } |
| if (_blurEvent) { |
| [self fireEvent:@"blur" params:nil]; |
| } |
| if(self.pseudoClassStyles && [self.pseudoClassStyles count]>0){ |
| [self recoveryPseudoStyles:self.styles]; |
| } |
| } |
| |
| - (BOOL)textFieldShouldReturn:(UITextField *)textField |
| { |
| if (_returnEvent) { |
| NSString *typeStr = [WXUtility returnKeyType:_returnKeyType]; |
| [self fireEvent:@"return" params:@{@"value":[textField text],@"returnKeyType":typeStr} domChanges:@{@"attrs":@{@"value":[textField text]}}]; |
| } |
| [self blur]; |
| return YES; |
| } |
| |
| - (void)textFiledEditChanged:(NSNotification *)notifi |
| { |
| WXTextInputView *textField = (WXTextInputView *)notifi.object; |
| if (_formaterData && _recoverRule && _recoverReplace && _formatRule && _formatReplace) { |
| UITextRange * textRange = textField.selectedTextRange; |
| NSInteger cursorPosition = [textField offsetFromPosition:textField.beginningOfDocument toPosition:textRange.start]; |
| NSMutableString * preText = [[textField.text substringToIndex:cursorPosition] mutableCopy]; |
| NSMutableString * lastText = [[textField.text substringFromIndex:cursorPosition] mutableCopy]; |
| |
| NSRegularExpression *recoverRule = [NSRegularExpression regularExpressionWithPattern:_recoverRule options:NSRegularExpressionCaseInsensitive error:NULL]; |
| [recoverRule replaceMatchesInString:preText options:0 range:NSMakeRange(0, preText.length) withTemplate:_recoverReplace]; |
| [recoverRule replaceMatchesInString:lastText options:0 range:NSMakeRange(0, lastText.length) withTemplate:_recoverReplace]; |
| NSMutableString * newString = [NSMutableString stringWithFormat:@"%@%@", preText, lastText]; |
| NSRegularExpression *formatRule = [NSRegularExpression regularExpressionWithPattern:_formatRule options:NSRegularExpressionCaseInsensitive error:NULL]; |
| [formatRule replaceMatchesInString:newString options:0 range:NSMakeRange(0, newString.length) withTemplate:_formatReplace]; |
| NSString * oldText = textField.text; |
| NSInteger adjust = 0; |
| |
| if (cursorPosition == textField.text.length) { |
| adjust = newString.length-oldText.length; |
| } |
| if (!textField.deleteWords || ![textField.editWords isKindOfClass:[NSString class]] || ![_recoverRule isEqualToString:textField.editWords]) { |
| textField.text = [newString copy]; |
| UITextPosition * newPosition = [textField positionFromPosition:textField.beginningOfDocument offset:cursorPosition+adjust]; |
| textField.selectedTextRange = [textField textRangeFromPosition:newPosition toPosition:newPosition]; |
| } |
| |
| } |
| |
| if (_maxLength) { |
| NSString *toBeString = textField.text; |
| NSString *language = [[UIApplication sharedApplication] textInputMode].primaryLanguage; |
| if ([language isEqualToString:@"zh-Hans"]) { |
| UITextRange *selectedRange = [textField markedTextRange]; |
| UITextPosition *position = [textField positionFromPosition:selectedRange.start offset:0]; |
| if (!position) { |
| if (toBeString.length > _maxLength.integerValue) { |
| textField.text = [toBeString substringToIndex:_maxLength.integerValue]; |
| } |
| } |
| } else { |
| if (toBeString.length > _maxLength.integerValue) { |
| textField.text = [toBeString substringToIndex:_maxLength.integerValue]; |
| } |
| } |
| } |
| |
| if (_inputEvent) { |
| // bind each other , the key must be attrs |
| [self fireEvent:@"input" params:@{@"value":[textField text]} domChanges:@{@"attrs":@{@"value":[textField text]}}]; |
| } |
| } |
| |
| - (void)setViewMovedUp:(BOOL)movedUp |
| { |
| UIView *rootView = self.weexInstance.rootView; |
| CGRect rect = self.weexInstance.frame; |
| CGRect rootViewFrame = rootView.frame; |
| CGRect inputFrame = [self.view.superview convertRect:self.view.frame toView:rootView]; |
| if (movedUp) { |
| CGFloat inputOffset = inputFrame.size.height - (rootViewFrame.size.height - inputFrame.origin.y); |
| CGFloat offset = inputFrame.origin.y-(rootViewFrame.size.height-_keyboardSize.height- (inputOffset > 0 ? inputFrame.size.height - inputOffset : inputFrame.size.height)) + _upriseOffset; |
| if (offset > 0) { |
| rect = (CGRect){ |
| .origin.x = 0.f, |
| .origin.y = rect.origin.y - offset, |
| .size = rootViewFrame.size |
| }; |
| } |
| } |
| self.weexInstance.rootView.frame = rect; |
| } |
| |
| #pragma mark textview Delegate |
| - (BOOL)textViewShouldBeginEditing:(UITextView *)textView |
| { |
| if([self isDateType]) |
| { |
| [[[UIApplication sharedApplication] keyWindow] endEditing:YES]; |
| _changeEventString = [textView text]; |
| [_datePickerManager show]; |
| return NO; |
| } |
| return YES; |
| } |
| |
| - (void)textViewDidBeginEditing:(UITextView *)textView |
| { |
| _changeEventString = [textView text]; |
| if (_focusEvent) { |
| [self fireEvent:@"focus" params:nil]; |
| } |
| if (_clickEvent) { |
| [self fireEvent:@"click" params:nil]; |
| } |
| [textView becomeFirstResponder]; |
| [self handlePseudoClass]; |
| } |
| |
| - (void)textViewDidChange:(UITextView *)textView |
| { |
| if(textView.text && [textView.text length] > 0) { |
| self.placeHolderLabel.text = @""; |
| }else{ |
| [self setPlaceholderAttributedString]; |
| } |
| if (_inputEvent) { |
| [self fireEvent:@"input" params:@{@"value":[textView text]} domChanges:@{@"attrs":@{@"value":[textView text]}}]; |
| } |
| } |
| |
| - (void)textViewDidEndEditing:(UITextView *)textView |
| { |
| if (![textView.text length]) { |
| [self setPlaceholderAttributedString]; |
| } |
| if (_changeEvent) { |
| if (![[textView text] isEqualToString:_changeEventString]) { |
| [self fireEvent:@"change" params:@{@"value":[textView text]} domChanges:@{@"attrs":@{@"value":[textView text]}}]; |
| } |
| } |
| if (_blurEvent) { |
| [self fireEvent:@"blur" params:nil]; |
| } |
| if(self.pseudoClassStyles && [self.pseudoClassStyles count]>0){ |
| [self recoveryPseudoStyles:self.styles]; |
| } |
| } |
| |
| - (BOOL)textView:(UITextView *)textView shouldChangeTextInRange:(NSRange)range replacementText:(NSString *)text |
| { |
| if ([text isEqualToString:@"\n"]) { |
| NSString *typeStr = [WXUtility returnKeyType:_returnKeyType]; |
| if (_returnEvent) { |
| [self fireEvent:@"return" params:@{@"value":[textView text],@"returnKeyType":typeStr} domChanges:@{@"attrs":@{@"value":[textView text]}}]; |
| } |
| if(typeStr.length > 0 && ![@"default" isEqualToString:typeStr]){ |
| [self blur]; |
| return NO; |
| } |
| } |
| |
| if (_maxLength) { |
| NSUInteger oldLength = [textView.text length]; |
| NSUInteger replacementLength = [text length]; |
| NSUInteger rangeLength = range.length; |
| NSUInteger newLength = oldLength - rangeLength + replacementLength; |
| return newLength <= [_maxLength integerValue] ; |
| } |
| |
| return YES; |
| } |
| |
| #pragma mark private method |
| |
| - (BOOL)isDateType |
| { |
| if([_inputType isEqualToString:@"date"] || [_inputType isEqualToString:@"time"]) |
| return YES; |
| return NO; |
| } |
| |
| - (BOOL)isPureInt:(NSString*)textString |
| { |
| int val; |
| NSScanner* scan = [NSScanner scannerWithString:textString]; |
| return[scan scanInt:&val] && [scan isAtEnd]; |
| } |
| |
| - (void)setPlaceholderAttributedString |
| { |
| NSMutableAttributedString *attributedString = [[NSMutableAttributedString alloc] initWithString:_placeholderString]; |
| [attributedString addAttribute:NSForegroundColorAttributeName value:_placeholderColor range:NSMakeRange(0, _placeholderString.length)]; |
| UIFont *font = [WXUtility fontWithSize:_fontSize textWeight:_fontWeight textStyle:_fontStyle fontFamily:_fontFamily scaleFactor:self.weexInstance.pixelScaleFactor]; |
| [self setAttributedPlaceholder:attributedString font:font]; |
| } |
| |
| - (void)setTextFont |
| { |
| UIFont *font = [WXUtility fontWithSize:_fontSize textWeight:_fontWeight textStyle:_fontStyle fontFamily:_fontFamily scaleFactor:self.weexInstance.pixelScaleFactor]; |
| [self setFont:font]; |
| } |
| |
| - (void)setAutofocus:(BOOL)b |
| { |
| if (b) { |
| if([self isDateType]) |
| { |
| [_datePickerManager show]; |
| }else |
| { |
| [self.view becomeFirstResponder]; |
| self.weexInstance.apmInstance.forceStopRecordInteractionTime = YES; |
| } |
| } else { |
| if([self isDateType]) |
| { |
| [_datePickerManager hide]; |
| }else |
| { |
| [self.view resignFirstResponder]; |
| } |
| } |
| } |
| |
| - (void)setType |
| { |
| [self setKeyboardType:UIKeyboardTypeDefault]; |
| [self setSecureTextEntry:NO]; |
| if ([_inputType isEqualToString:@"text"]) { |
| [self setKeyboardType:UIKeyboardTypeDefault]; |
| }else if ([_inputType isEqualToString:@"password"]) { |
| [self setSecureTextEntry:YES]; |
| }else if ([_inputType isEqualToString:@"tel"]) { |
| [self setKeyboardType:UIKeyboardTypePhonePad]; |
| }else if ([_inputType isEqualToString:@"email"]) { |
| [self setKeyboardType:UIKeyboardTypeEmailAddress]; |
| }else if ([_inputType isEqualToString:@"url"]) { |
| [self setKeyboardType:UIKeyboardTypeURL]; |
| }else if ([_inputType isEqualToString:@"number"]) { |
| [self setKeyboardType:UIKeyboardTypeDecimalPad]; |
| }else if ([self isDateType]) { |
| if (!_datePickerManager) { |
| _datePickerManager = [[WXDatePickerManager alloc] init]; |
| _datePickerManager.delegate = self; |
| } |
| [_datePickerManager updateDatePicker:_attr]; |
| } |
| } |
| |
| - (void)setPadding:(UIEdgeInsets)padding |
| { |
| _padding = padding; |
| [self setEditPadding:padding]; |
| } |
| |
| - (void)setBorder:(UIEdgeInsets)border |
| { |
| _border = border; |
| [self setEditBorder:border]; |
| } |
| |
| #pragma mark update touch styles |
| -(void)handlePseudoClass |
| { |
| NSMutableDictionary *styles = [NSMutableDictionary new]; |
| NSMutableDictionary *recordStyles = [NSMutableDictionary new]; |
| if(_disabled){ |
| recordStyles = [self getPseudoClassStylesByKeys:@[@"disabled"]]; |
| [styles addEntriesFromDictionary:recordStyles]; |
| }else { |
| recordStyles = [NSMutableDictionary new]; |
| recordStyles = [self getPseudoClassStylesByKeys:@[@"enabled"]]; |
| [styles addEntriesFromDictionary:recordStyles]; |
| } |
| if ([self.view isFirstResponder]){ |
| recordStyles = [NSMutableDictionary new]; |
| recordStyles = [self getPseudoClassStylesByKeys:@[@"focus"]]; |
| [styles addEntriesFromDictionary:recordStyles]; |
| } |
| NSString *disabledStr = @"enabled"; |
| if (_disabled){ |
| disabledStr = @"disabled"; |
| } |
| if ([self.view isFirstResponder]) { |
| NSString *focusStr = @"focus"; |
| recordStyles = [NSMutableDictionary new]; |
| recordStyles = [self getPseudoClassStylesByKeys:@[focusStr,disabledStr]]; |
| [styles addEntriesFromDictionary:recordStyles]; |
| } |
| [self updatePseudoClassStyles:styles]; |
| } |
| |
| #pragma mark keyboard |
| - (void)keyboardWasShown:(NSNotification*)notification |
| { |
| if(![self.view isFirstResponder]) { |
| return; |
| } |
| |
| CGRect end = [[[notification userInfo] objectForKey:@"UIKeyboardFrameEndUserInfoKey"] CGRectValue]; |
| if (!_disableMoveViewUp) { |
| _keyboardSize = end.size; |
| UIView * rootView = self.weexInstance.rootView; |
| CGRect screenRect = [[UIScreen mainScreen] bounds]; |
| CGRect keyboardRect = (CGRect){ |
| .origin.x = 0, |
| .origin.y = CGRectGetMaxY(screenRect) - _keyboardSize.height - 54, |
| .size = _keyboardSize |
| }; |
| CGRect inputFrame = [self.view.superview convertRect:self.view.frame toView:rootView]; |
| if (keyboardRect.origin.y - inputFrame.size.height <= inputFrame.origin.y) { |
| [self setViewMovedUp:YES]; |
| self.weexInstance.isRootViewFrozen = YES; |
| } |
| } |
| |
| if (_keyboardEvent) { |
| [self fireEvent:@"keyboard" params:@{ @"isShow": @YES, @"keyboardSize": @(end.size.height / self.weexInstance.pixelScaleFactor) }]; |
| } |
| |
| _keyboardHidden = NO; |
| } |
| |
| - (void)keyboardWillHide:(NSNotification*)notification |
| { |
| if (![self.view isFirstResponder] || _keyboardHidden) { |
| return; |
| } |
| if (!_disableMoveViewUp) { |
| UIView * rootView = self.weexInstance.rootView; |
| if (!CGRectEqualToRect(self.weexInstance.frame, rootView.frame)) { |
| [self setViewMovedUp:NO]; |
| } |
| self.weexInstance.isRootViewFrozen = NO; |
| } |
| if (_keyboardEvent) { |
| [self fireEvent:@"keyboard" params:@{ @"isShow": @NO }]; |
| } |
| |
| _keyboardHidden = YES; |
| } |
| |
| - (void)closeKeyboard |
| { |
| [[NSNotificationCenter defaultCenter] postNotificationName:UIKeyboardWillHideNotification object:nil]; |
| [self.view resignFirstResponder]; |
| } |
| |
| #pragma mark -reset color |
| - (void)resetStyles:(NSArray *)styles |
| { |
| if ([styles containsObject:@"color"]) { |
| [self setTextColor:[UIColor blackColor]]; |
| } |
| if ([styles containsObject:@"fontSize"]) { |
| _fontSize = WX_TEXT_FONT_SIZE; |
| [self setTextFont]; |
| } |
| } |
| @end |
| |