blob: 49135a1f4666599e2e84511ef00d5f32de3eda75 [file] [log] [blame]
/*
* 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];
}
}
-(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]) {
// do nothing
} else {
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 offset = inputFrame.origin.y-(rootViewFrame.size.height-_keyboardSize.height-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];
}
} 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