1 /*
2  * Copyright (c) 2022-2024 Huawei Device Co., Ltd.
3  * Licensed under the Apache License, Version 2.0 (the "License");
4  * you may not use this file except in compliance with the License.
5  * You may obtain a copy of the License at
6  *
7  *     http://www.apache.org/licenses/LICENSE-2.0
8  *
9  * Unless required by applicable law or agreed to in writing, software
10  * distributed under the License is distributed on an "AS IS" BASIS,
11  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12  * See the License for the specific language governing permissions and
13  * limitations under the License.
14  */
15 
16 #include "frameworks/bridge/declarative_frontend/jsview/js_textfield.h"
17 
18 #include <algorithm>
19 #include <cstdint>
20 #include <string>
21 #include <vector>
22 #if !defined(PREVIEW) && defined(OHOS_PLATFORM)
23 #include "interfaces/inner_api/ui_session/ui_session_manager.h"
24 #endif
25 
26 #include "base/geometry/dimension.h"
27 #include "base/log/ace_scoring_log.h"
28 #include "base/utils/utils.h"
29 #include "bridge/common/utils/utils.h"
30 #include "bridge/declarative_frontend/engine/functions/js_click_function.h"
31 #include "bridge/declarative_frontend/engine/functions/js_clipboard_function.h"
32 #include "bridge/declarative_frontend/engine/functions/js_function.h"
33 #include "bridge/declarative_frontend/engine/jsi/js_ui_index.h"
34 #include "bridge/declarative_frontend/jsview/js_container_base.h"
35 #include "bridge/declarative_frontend/jsview/js_interactable_view.h"
36 #include "bridge/declarative_frontend/jsview/js_text_editable_controller.h"
37 #include "bridge/declarative_frontend/jsview/js_textarea.h"
38 #include "bridge/declarative_frontend/jsview/js_textinput.h"
39 #include "bridge/declarative_frontend/jsview/js_view_abstract.h"
40 #include "bridge/declarative_frontend/jsview/js_view_common_def.h"
41 #include "bridge/declarative_frontend/jsview/models/text_field_model_impl.h"
42 #include "core/common/container.h"
43 #include "core/common/ime/text_input_action.h"
44 #include "core/common/ime/text_input_type.h"
45 #include "core/components/common/layout/constants.h"
46 #include "core/components/common/properties/text_style_parser.h"
47 #include "core/components/text_field/textfield_theme.h"
48 #include "core/components_ng/base/view_abstract.h"
49 #include "core/components_ng/pattern/text_field/text_content_type.h"
50 #include "core/components_ng/pattern/text_field/text_field_model_ng.h"
51 #include "core/image/image_source_info.h"
52 
53 namespace OHOS::Ace {
54 
55 std::unique_ptr<TextFieldModel> TextFieldModel::instance_ = nullptr;
56 std::mutex TextFieldModel::mutex_;
57 
GetInstance()58 TextFieldModel* TextFieldModel::GetInstance()
59 {
60 #ifdef NG_BUILD
61     static NG::TextFieldModelNG instance;
62     return &instance;
63 #else
64     if (Container::IsCurrentUseNewPipeline()) {
65         static NG::TextFieldModelNG instance;
66         return &instance;
67     } else {
68         static Framework::TextFieldModelImpl instance;
69         return &instance;
70     }
71 #endif
72 }
73 
74 } // namespace OHOS::Ace
75 
76 namespace OHOS::Ace::Framework {
77 
78 namespace {
79 
80 const std::vector<TextAlign> TEXT_ALIGNS = { TextAlign::START, TextAlign::CENTER, TextAlign::END, TextAlign::JUSTIFY };
81 const std::vector<LineBreakStrategy> LINE_BREAK_STRATEGY_TYPES = { LineBreakStrategy::GREEDY,
82     LineBreakStrategy::HIGH_QUALITY, LineBreakStrategy::BALANCED };
83 const std::vector<FontStyle> FONT_STYLES = { FontStyle::NORMAL, FontStyle::ITALIC };
84 const std::vector<std::string> INPUT_FONT_FAMILY_VALUE = { "sans-serif" };
85 const std::vector<WordBreak> WORD_BREAK_TYPES = { WordBreak::NORMAL, WordBreak::BREAK_ALL, WordBreak::BREAK_WORD };
86 const std::vector<TextOverflow> TEXT_OVERFLOWS = { TextOverflow::NONE, TextOverflow::CLIP, TextOverflow::ELLIPSIS,
87     TextOverflow::MARQUEE, TextOverflow::DEFAULT };
88 constexpr uint32_t MAX_LINES = 3;
89 constexpr uint32_t MINI_VAILD_VALUE = 1;
90 constexpr uint32_t MAX_VAILD_VALUE = 100;
91 constexpr uint32_t ILLEGAL_VALUE = 0;
92 constexpr uint32_t DEFAULT_MODE = -1;
93 constexpr uint32_t DEFAULT_OVERFLOW = 4;
94 const char* TOP_START_PROPERTY = "topStart";
95 const char* TOP_END_PROPERTY = "topEnd";
96 const char* BOTTOM_START_PROPERTY = "bottomStart";
97 const char* BOTTOM_END_PROPERTY = "bottomEnd";
98 const std::vector<TextHeightAdaptivePolicy> HEIGHT_ADAPTIVE_POLICY = { TextHeightAdaptivePolicy::MAX_LINES_FIRST,
99     TextHeightAdaptivePolicy::MIN_FONT_SIZE_FIRST, TextHeightAdaptivePolicy::LAYOUT_CONSTRAINT_FIRST };
100 constexpr TextDecorationStyle DEFAULT_TEXT_DECORATION_STYLE = TextDecorationStyle::SOLID;
101 
ParseJsLengthMetrics(const JSRef<JSObject>& obj, CalcDimension& result)102 bool ParseJsLengthMetrics(const JSRef<JSObject>& obj, CalcDimension& result)
103 {
104     auto value = obj->GetProperty(static_cast<int32_t>(ArkUIIndex::VALUE));
105     if (!value->IsNumber()) {
106         return false;
107     }
108     auto unit = DimensionUnit::VP;
109     auto jsUnit = obj->GetProperty(static_cast<int32_t>(ArkUIIndex::UNIT));
110     if (jsUnit->IsNumber()) {
111         unit = static_cast<DimensionUnit>(jsUnit->ToNumber<int32_t>());
112     }
113     CalcDimension dimension(value->ToNumber<double>(), unit);
114     result = dimension;
115     return true;
116 }
117 } // namespace
118 
ParseTextFieldTextObject(const JSCallbackInfo& info, const JSRef<JSVal>& changeEventVal)119 void ParseTextFieldTextObject(const JSCallbackInfo& info, const JSRef<JSVal>& changeEventVal)
120 {
121     CHECK_NULL_VOID(changeEventVal->IsFunction());
122 
123     JsEventCallback<void(const std::string&)> onChangeEvent(
124         info.GetExecutionContext(), JSRef<JSFunc>::Cast(changeEventVal));
125     TextFieldModel::GetInstance()->SetOnChangeEvent(std::move(onChangeEvent));
126 }
127 
CreateTextInput(const JSCallbackInfo& info)128 void JSTextField::CreateTextInput(const JSCallbackInfo& info)
129 {
130     std::optional<std::string> placeholderSrc;
131     std::optional<std::string> value;
132     JSTextEditableController* jsController = nullptr;
133     JSRef<JSVal> changeEventVal = JSRef<JSVal>::Make();
134     auto jsValue = info[0];
135     if (jsValue->IsObject()) {
136         auto paramObject = JSRef<JSObject>::Cast(jsValue);
137         std::string placeholder;
138         if (ParseJsString(paramObject->GetProperty("placeholder"), placeholder)) {
139             placeholderSrc = placeholder;
140         }
141         std::string text;
142         JSRef<JSVal> textValue = paramObject->GetProperty("text");
143         if (textValue->IsObject()) {
144             JSRef<JSObject> valueObj = JSRef<JSObject>::Cast(textValue);
145             changeEventVal = valueObj->GetProperty("changeEvent");
146             if (changeEventVal->IsFunction()) {
147                 textValue = valueObj->GetProperty("value");
148             }
149             value = "";
150             if (ParseJsString(textValue, text)) {
151                 value = text;
152             }
153         } else if (paramObject->HasProperty("text")) {
154             if (ParseJsString(textValue, text)) {
155                 value = text;
156             }
157             if (textValue->IsUndefined()) {
158                 value = "";
159             }
160         }
161         auto controllerObj = paramObject->GetProperty("controller");
162         if (!controllerObj->IsUndefined() && !controllerObj->IsNull()) {
163             jsController = JSRef<JSObject>::Cast(controllerObj)->Unwrap<JSTextEditableController>();
164         }
165     }
166 
167     auto controller = TextFieldModel::GetInstance()->CreateTextInput(placeholderSrc, value);
168     if (jsController) {
169         jsController->SetController(controller);
170     }
171     if (!changeEventVal->IsUndefined() && changeEventVal->IsFunction()) {
172         ParseTextFieldTextObject(info, changeEventVal);
173     }
174 
175     TextFieldModel::GetInstance()->SetFocusableAndFocusNode();
176 }
177 
CreateTextArea(const JSCallbackInfo& info)178 void JSTextField::CreateTextArea(const JSCallbackInfo& info)
179 {
180     std::optional<std::string> placeholderSrc;
181     std::optional<std::string> value;
182     JSTextEditableController* jsController = nullptr;
183     JSRef<JSVal> changeEventVal = JSRef<JSVal>::Make();
184     auto jsValue = info[0];
185     if (jsValue->IsObject()) {
186         auto paramObject = JSRef<JSObject>::Cast(jsValue);
187         std::string placeholder;
188         if (ParseJsString(paramObject->GetProperty("placeholder"), placeholder)) {
189             placeholderSrc = placeholder;
190         }
191         std::string text;
192         JSRef<JSVal> textValue = paramObject->GetProperty("text");
193         if (textValue->IsObject()) {
194             JSRef<JSObject> valueObj = JSRef<JSObject>::Cast(textValue);
195             changeEventVal = valueObj->GetProperty("changeEvent");
196             if (changeEventVal->IsFunction()) {
197                 textValue = valueObj->GetProperty("value");
198             }
199             if (ParseJsString(textValue, text)) {
200                 value = text;
201             }
202         } else if (paramObject->HasProperty("text")) {
203             if (ParseJsString(textValue, text)) {
204                 value = text;
205             }
206             if (textValue->IsUndefined()) {
207                 value = "";
208             }
209         }
210         auto controllerObj = paramObject->GetProperty("controller");
211         if (!controllerObj->IsUndefined() && !controllerObj->IsNull()) {
212             jsController = JSRef<JSObject>::Cast(controllerObj)->Unwrap<JSTextEditableController>();
213         }
214     }
215     auto controller = TextFieldModel::GetInstance()->CreateTextArea(placeholderSrc, value);
216     if (jsController) {
217         jsController->SetController(controller);
218     }
219     if (!changeEventVal->IsUndefined() && changeEventVal->IsFunction()) {
220         ParseTextFieldTextObject(info, changeEventVal);
221     }
222 
223     TextFieldModel::GetInstance()->SetFocusableAndFocusNode();
224 }
225 
SetType(const JSCallbackInfo& info)226 void JSTextField::SetType(const JSCallbackInfo& info)
227 {
228     if (info.Length() < 1) {
229         return;
230     }
231     auto jsValue = info[0];
232     if (jsValue->IsUndefined()) {
233         TextFieldModel::GetInstance()->SetType(TextInputType::UNSPECIFIED);
234         return;
235     }
236     if (!jsValue->IsNumber()) {
237         return;
238     }
239     TextInputType textInputType = CastToTextInputType(jsValue->ToNumber<int32_t>());
240     TextFieldModel::GetInstance()->SetType(textInputType);
241 }
242 
SetContentType(const JSCallbackInfo& info)243 void JSTextField::SetContentType(const JSCallbackInfo& info)
244 {
245     if (info.Length() < 1) {
246         return;
247     }
248     auto jsValue = info[0];
249     if (jsValue->IsUndefined()) {
250         TextFieldModel::GetInstance()->SetContentType(NG::TextContentType::UNSPECIFIED);
251         return;
252     }
253     if (!jsValue->IsNumber()) {
254         return;
255     }
256     NG::TextContentType textContentType = static_cast<NG::TextContentType>(jsValue->ToNumber<int32_t>());
257     TextFieldModel::GetInstance()->SetContentType(textContentType);
258 }
259 
SetPlaceholderColor(const JSCallbackInfo& info)260 void JSTextField::SetPlaceholderColor(const JSCallbackInfo& info)
261 {
262     if (info.Length() < 1) {
263         return;
264     }
265 
266     auto theme = GetTheme<TextFieldTheme>();
267     CHECK_NULL_VOID(theme);
268     Color color = theme->GetPlaceholderColor();
269     CheckColor(info[0], color, V2::TEXTINPUT_ETS_TAG, "PlaceholderColor");
270     TextFieldModel::GetInstance()->SetPlaceholderColor(color);
271 }
272 
SetPlaceholderFont(const JSCallbackInfo& info)273 void JSTextField::SetPlaceholderFont(const JSCallbackInfo& info)
274 {
275     if (info.Length() < 1 || !info[0]->IsObject()) {
276         return;
277     }
278     Font font;
279     auto paramObject = JSRef<JSObject>::Cast(info[0]);
280     auto fontSize = paramObject->GetProperty("size");
281     if (fontSize->IsNull() || fontSize->IsUndefined()) {
282         font.fontSize = Dimension(-1);
283     } else {
284         CalcDimension size;
285         auto theme = GetTheme<TextFieldTheme>();
286         CHECK_NULL_VOID(theme);
287         if (fontSize->IsString()) {
288             auto result = StringUtils::StringToDimensionWithThemeValue(
289                 fontSize->ToString(), true, Dimension(theme->GetFontSize()));
290             if (result.Unit() == DimensionUnit::PERCENT) {
291                 result = theme->GetFontSize();
292             }
293             font.fontSize = result;
294         } else if (ParseJsDimensionFp(fontSize, size) && size.Unit() != DimensionUnit::PERCENT) {
295             font.fontSize = size;
296         } else {
297             font.fontSize = Dimension(theme->GetFontSize());
298         }
299     }
300 
301     std::string weight;
302     auto fontWeight = paramObject->GetProperty("weight");
303     if (!fontWeight->IsNull()) {
304         if (fontWeight->IsNumber()) {
305             weight = std::to_string(fontWeight->ToNumber<int32_t>());
306         } else {
307             ParseJsString(fontWeight, weight);
308         }
309         font.fontWeight = ConvertStrToFontWeight(weight);
310     }
311 
312     auto fontFamily = paramObject->GetProperty("family");
313     if (!fontFamily->IsNull()) {
314         std::vector<std::string> fontFamilies;
315         if (ParseJsFontFamilies(fontFamily, fontFamilies)) {
316             font.fontFamilies = fontFamilies;
317         }
318     }
319 
320     auto style = paramObject->GetProperty("style");
321     if (!style->IsNull()) {
322         font.fontStyle = static_cast<FontStyle>(style->ToNumber<int32_t>());
323     }
324     TextFieldModel::GetInstance()->SetPlaceholderFont(font);
325 }
326 
SetEnterKeyType(const JSCallbackInfo& info)327 void JSTextField::SetEnterKeyType(const JSCallbackInfo& info)
328 {
329     if (info.Length() < 1) {
330         return;
331     }
332     auto jsValue = info[0];
333     if (jsValue->IsUndefined()) {
334         TextFieldModel::GetInstance()->SetEnterKeyType(TextInputAction::UNSPECIFIED);
335         return;
336     }
337     if (!jsValue->IsNumber()) {
338         return;
339     }
340     TextInputAction textInputAction = CastToTextInputAction(jsValue->ToNumber<int32_t>());
341     TextFieldModel::GetInstance()->SetEnterKeyType(textInputAction);
342 }
343 
SetTextAlign(int32_t value)344 void JSTextField::SetTextAlign(int32_t value)
345 {
346     if (value >= 0 && value < static_cast<int32_t>(TEXT_ALIGNS.size())) {
347         TextFieldModel::GetInstance()->SetTextAlign(TEXT_ALIGNS[value]);
348     }
349 }
350 
SetLineBreakStrategy(const JSCallbackInfo& info)351 void JSTextField::SetLineBreakStrategy(const JSCallbackInfo& info)
352 {
353     if (info.Length() < 1) {
354         TextFieldModel::GetInstance()->SetLineBreakStrategy(LineBreakStrategy::GREEDY);
355         return;
356     }
357     if (!info[0]->IsNumber()) {
358         TextFieldModel::GetInstance()->SetLineBreakStrategy(LineBreakStrategy::GREEDY);
359         return;
360     }
361     auto index = info[0]->ToNumber<int32_t>();
362     if (index < 0 || index >= static_cast<int32_t>(LINE_BREAK_STRATEGY_TYPES.size())) {
363         TextFieldModel::GetInstance()->SetLineBreakStrategy(LineBreakStrategy::GREEDY);
364         return;
365     }
366     TextFieldModel::GetInstance()->SetLineBreakStrategy(LINE_BREAK_STRATEGY_TYPES[index]);
367 }
368 
SetInputStyle(const JSCallbackInfo& info)369 void JSTextField::SetInputStyle(const JSCallbackInfo& info)
370 {
371     if (info.Length() < 1) {
372         return;
373     }
374     auto styleString = info[0]->ToString();
375     if (styleString == "Inline") {
376         TextFieldModel::GetInstance()->SetInputStyle(InputStyle::INLINE);
377     } else {
378         TextFieldModel::GetInstance()->SetInputStyle(InputStyle::DEFAULT);
379     }
380 }
381 
SetCaretColor(const JSCallbackInfo& info)382 void JSTextField::SetCaretColor(const JSCallbackInfo& info)
383 {
384     if (info.Length() < 1) {
385         return;
386     }
387 
388     Color color;
389     if (!ParseJsColor(info[0], color)) {
390         return;
391     }
392 
393     TextFieldModel::GetInstance()->SetCaretColor(color);
394 }
395 
SetCaretStyle(const JSCallbackInfo& info)396 void JSTextField::SetCaretStyle(const JSCallbackInfo& info)
397 {
398     if (info.Length() < 1) {
399         return;
400     }
401     auto jsValue = info[0];
402     if (jsValue->IsObject()) {
403         CaretStyle caretStyle;
404         auto paramObject = JSRef<JSObject>::Cast(jsValue);
405         auto caretWidth = paramObject->GetProperty("width");
406 
407         auto pipeline = PipelineBase::GetCurrentContext();
408         CHECK_NULL_VOID(pipeline);
409         auto theme = pipeline->GetThemeManager()->GetTheme<TextFieldTheme>();
410         CHECK_NULL_VOID(theme);
411         if (caretWidth->IsNull() || caretWidth->IsUndefined()) {
412             caretStyle.caretWidth = theme->GetCursorWidth();
413         } else {
414             CalcDimension width;
415             if (!ParseJsDimensionVpNG(caretWidth, width, false)) {
416                 width = theme->GetCursorWidth();
417             }
418             if (LessNotEqual(width.Value(), 0.0)) {
419                 width = theme->GetCursorWidth();
420             }
421             caretStyle.caretWidth = width;
422         }
423         TextFieldModel::GetInstance()->SetCaretStyle(caretStyle);
424 
425         // set caret color
426         Color caretColor;
427         if (!paramObject->HasProperty("color")) {
428             return;
429         } else {
430             auto caretColorProp = paramObject->GetProperty("color");
431             if (caretColorProp->IsUndefined() || caretColorProp->IsNull()
432                 || !ParseJsColor(caretColorProp, caretColor)) {
433                 caretColor = theme->GetCursorColor();
434             }
435             TextFieldModel::GetInstance()->SetCaretColor(caretColor);
436         }
437     }
438 }
439 
SetCaretPosition(const JSCallbackInfo& info)440 void JSTextField::SetCaretPosition(const JSCallbackInfo& info)
441 {
442     if (info.Length() < 1) {
443         return;
444     }
445     int32_t caretPosition = 0;
446     auto tempInfo = info[0];
447     if (AceApplicationInfo::GetInstance().GreatOrEqualTargetAPIVersion(PlatformVersion::VERSION_TWELVE)) {
448         if (!ParseJsInt32(tempInfo, caretPosition) || caretPosition < 0) {
449             caretPosition = 0;
450         }
451     } else {
452         if (!ParseJsInt32(tempInfo, caretPosition)) {
453             return;
454         }
455         if (caretPosition < 0) {
456             return;
457         }
458     }
459     TextFieldModel::GetInstance()->SetCaretPosition(caretPosition);
460 }
461 
SetSelectedBackgroundColor(const JSCallbackInfo& info)462 void JSTextField::SetSelectedBackgroundColor(const JSCallbackInfo& info)
463 {
464     if (info.Length() < 1) {
465         return;
466     }
467 
468     Color selectedColor;
469     if (!ParseJsColor(info[0], selectedColor)) {
470         auto pipeline = PipelineBase::GetCurrentContext();
471         CHECK_NULL_VOID(pipeline);
472         auto theme = pipeline->GetThemeManager()->GetTheme<TextFieldTheme>();
473         CHECK_NULL_VOID(theme);
474         selectedColor = theme->GetSelectedColor();
475     }
476     // Alpha = 255 means opaque
477     if (selectedColor.GetAlpha() == 255) {
478         // Default setting of 20% opacity
479         selectedColor = selectedColor.ChangeOpacity(0.2);
480     }
481     TextFieldModel::GetInstance()->SetSelectedBackgroundColor(selectedColor);
482 }
483 
SetMaxLength(const JSCallbackInfo& info)484 void JSTextField::SetMaxLength(const JSCallbackInfo& info)
485 {
486     if (info.Length() < 1) {
487         return;
488     }
489     auto jsValue = info[0];
490     int32_t maxLength = 0;
491     if (jsValue->IsUndefined()) {
492         TextFieldModel::GetInstance()->ResetMaxLength();
493         return;
494     } else if (!jsValue->IsNumber()) {
495         TextFieldModel::GetInstance()->ResetMaxLength();
496         return;
497     }
498     maxLength = jsValue->ToNumber<int32_t>();
499     if (std::isinf(jsValue->ToNumber<float>())) {
500         maxLength = INT32_MAX; // Infinity
501     }
502     if (GreatOrEqual(maxLength, 0)) {
503         TextFieldModel::GetInstance()->SetMaxLength(maxLength);
504     } else {
505         TextFieldModel::GetInstance()->ResetMaxLength();
506     }
507 }
508 
SetFontSize(const JSCallbackInfo& info)509 void JSTextField::SetFontSize(const JSCallbackInfo& info)
510 {
511     if (info.Length() < 1) {
512         return;
513     }
514     CalcDimension fontSize;
515     if (!ParseJsDimensionNG(info[0], fontSize, DimensionUnit::FP, false)) {
516         auto theme = GetTheme<TextFieldTheme>();
517         CHECK_NULL_VOID(theme);
518         fontSize = theme->GetFontSize();
519     }
520     TextFieldModel::GetInstance()->SetFontSize(fontSize);
521 }
522 
SetFontWeight(const std::string& value)523 void JSTextField::SetFontWeight(const std::string& value)
524 {
525     TextFieldModel::GetInstance()->SetFontWeight(ConvertStrToFontWeight(value));
526 }
527 
SetTextColor(const JSCallbackInfo& info)528 void JSTextField::SetTextColor(const JSCallbackInfo& info)
529 {
530     if (info.Length() < 1) {
531         return;
532     }
533     Color textColor;
534     if (!ParseJsColor(info[0], textColor)) {
535         auto theme = GetTheme<TextFieldTheme>();
536         CHECK_NULL_VOID(theme);
537         textColor = theme->GetTextColor();
538     }
539     TextFieldModel::GetInstance()->SetTextColor(textColor);
540 }
541 
SetWordBreak(const JSCallbackInfo& info)542 void JSTextField::SetWordBreak(const JSCallbackInfo& info)
543 {
544     if (info.Length() < 1) {
545         return;
546     }
547     auto jsValue = info[0];
548     if (!jsValue->IsNumber()) {
549         TextFieldModel::GetInstance()->SetWordBreak(WordBreak::BREAK_WORD);
550         return;
551     }
552     auto index = jsValue->ToNumber<int32_t>();
553     if (index < 0 || index >= static_cast<int32_t>(WORD_BREAK_TYPES.size())) {
554         TextFieldModel::GetInstance()->SetWordBreak(WordBreak::BREAK_WORD);
555         return;
556     }
557     TextFieldModel::GetInstance()->SetWordBreak(WORD_BREAK_TYPES[index]);
558 }
559 
SetForegroundColor(const JSCallbackInfo& info)560 void JSTextField::SetForegroundColor(const JSCallbackInfo& info)
561 {
562     if (info.Length() < 1) {
563         return;
564     }
565     auto jsValue = info[0];
566     ForegroundColorStrategy strategy;
567     if (ParseJsColorStrategy(jsValue, strategy)) {
568         ViewAbstractModel::GetInstance()->SetForegroundColorStrategy(strategy);
569         TextFieldModel::GetInstance()->SetForegroundColor(Color::FOREGROUND);
570         return;
571     }
572     Color foregroundColor;
573     if (!ParseJsColor(jsValue, foregroundColor)) {
574         return;
575     }
576     ViewAbstractModel::GetInstance()->SetForegroundColor(foregroundColor);
577     TextFieldModel::GetInstance()->SetForegroundColor(foregroundColor);
578 }
579 
SetFontStyle(int32_t value)580 void JSTextField::SetFontStyle(int32_t value)
581 {
582     if (value >= 0 && value < static_cast<int32_t>(FONT_STYLES.size())) {
583         TextFieldModel::GetInstance()->SetFontStyle(FONT_STYLES[value]);
584     }
585 }
586 
SetFontFamily(const JSCallbackInfo& info)587 void JSTextField::SetFontFamily(const JSCallbackInfo& info)
588 {
589     if (info.Length() < 1) {
590         return;
591     }
592     std::vector<std::string> fontFamilies;
593     if (!ParseJsFontFamilies(info[0], fontFamilies)) {
594         return;
595     }
596     TextFieldModel::GetInstance()->SetFontFamily(fontFamilies);
597 }
598 
SetInputFilter(const JSCallbackInfo& info)599 void JSTextField::SetInputFilter(const JSCallbackInfo& info)
600 {
601     if (info.Length() < 1) {
602         return;
603     }
604     auto jsValue = info[0];
605     std::string inputFilter;
606     if (jsValue->IsUndefined()) {
607         TextFieldModel::GetInstance()->SetInputFilter(inputFilter, nullptr);
608         return;
609     }
610     if (!ParseJsString(jsValue, inputFilter)) {
611         return;
612     }
613     if (!CheckRegexValid(inputFilter)) {
614         inputFilter = "";
615     }
616     if (info.Length() > 1 && info[1]->IsFunction()) {
617         auto jsFunc = AceType::MakeRefPtr<JsClipboardFunction>(JSRef<JSFunc>::Cast(info[1]));
618         auto targetNode = AceType::WeakClaim(NG::ViewStackProcessor::GetInstance()->GetMainFrameNode());
619         auto resultId = [execCtx = info.GetExecutionContext(), func = std::move(jsFunc), node = targetNode](
620                             const std::string& info) {
621             JAVASCRIPT_EXECUTION_SCOPE_WITH_CHECK(execCtx);
622             PipelineContext::SetCallBackNode(node);
623             func->Execute(info);
624         };
625         TextFieldModel::GetInstance()->SetInputFilter(inputFilter, resultId);
626         return;
627     }
628     TextFieldModel::GetInstance()->SetInputFilter(inputFilter, nullptr);
629 }
630 
SetShowPasswordIcon(const JSCallbackInfo& info)631 void JSTextField::SetShowPasswordIcon(const JSCallbackInfo& info)
632 {
633     auto jsValue = info[0];
634     if (!jsValue->IsBoolean()) {
635         TextFieldModel::GetInstance()->SetShowPasswordIcon(true);
636         return;
637     }
638 
639     bool isShowPasswordIcon = jsValue->ToBoolean();
640     TextFieldModel::GetInstance()->SetShowPasswordIcon(isShowPasswordIcon);
641 }
642 
ShowPasswordText(const JSCallbackInfo& info)643 void JSTextField::ShowPasswordText(const JSCallbackInfo& info)
644 {
645     auto tmpInfo = info[0];
646     if (!tmpInfo->IsBoolean()) {
647         TextFieldModel::GetInstance()->SetShowPasswordText(false);
648         return;
649     }
650 
651     bool showPassword = tmpInfo->ToBoolean();
652     TextFieldModel::GetInstance()->SetShowPasswordText(showPassword);
653 }
654 
SetBackgroundColor(const JSCallbackInfo& info)655 void JSTextField::SetBackgroundColor(const JSCallbackInfo& info)
656 {
657     if (info.Length() < 1) {
658         return;
659     }
660     Color backgroundColor;
661     bool tmp = !ParseJsColor(info[0], backgroundColor);
662     TextFieldModel::GetInstance()->SetBackgroundColor(backgroundColor, tmp);
663 }
664 
JsHeight(const JSCallbackInfo& info)665 void JSTextField::JsHeight(const JSCallbackInfo& info)
666 {
667     JSViewAbstract::JsHeight(info);
668     if (info.Length() < 1) {
669         return;
670     }
671     CalcDimension value;
672     if (!ParseJsDimensionVp(info[0], value)) {
673         return;
674     }
675     if (LessNotEqual(value.Value(), 0.0)) {
676         ViewAbstractModel::GetInstance()->ClearWidthOrHeight(false);
677         return;
678     }
679     TextFieldModel::GetInstance()->SetHeight(value);
680 }
681 
JsWidth(const JSCallbackInfo& info)682 void JSTextField::JsWidth(const JSCallbackInfo& info)
683 {
684     if (info.Length() < 1) {
685         return;
686     }
687     auto jsValue = info[0];
688     if (jsValue->IsString() && jsValue->ToString().empty()) {
689         return;
690     }
691     if (jsValue->IsString() && jsValue->ToString() == "auto") {
692         ViewAbstractModel::GetInstance()->ClearWidthOrHeight(true);
693         TextFieldModel::GetInstance()->SetWidthAuto(true);
694         return;
695     }
696 
697     TextFieldModel::GetInstance()->SetWidthAuto(false);
698     CalcDimension value;
699     if (!ParseJsDimensionVp(jsValue, value)) {
700         return;
701     }
702     if (LessNotEqual(value.Value(), 0.0)) {
703         return;
704     }
705     ViewAbstractModel::GetInstance()->SetWidth(value);
706 }
707 
CheckIsIllegalString(const std::string& value)708 bool CheckIsIllegalString(const std::string& value)
709 {
710     if (value.empty()) {
711         return true;
712     }
713     errno = 0;
714     char* pEnd = nullptr;
715     std::strtod(value.c_str(), &pEnd);
716     return (pEnd == value.c_str() || errno == ERANGE);
717 }
718 
JsMargin(const JSCallbackInfo& info)719 void JSTextField::JsMargin(const JSCallbackInfo& info)
720 {
721     JSViewAbstract::JsMargin(info);
722     TextFieldModel::GetInstance()->SetMargin();
723 }
724 
JsPadding(const JSCallbackInfo& info)725 void JSTextField::JsPadding(const JSCallbackInfo& info)
726 {
727     auto jsValue = info[0];
728     if (jsValue->IsUndefined() || (jsValue->IsString() && CheckIsIllegalString(jsValue->ToString()))) {
729         return;
730     };
731     CalcDimension length;
732     ParseJsDimensionVp(jsValue, length);
733     if (length.IsNegative()) {
734         TextFieldModel::GetInstance()->SetPadding(NG::PaddingProperty(), Edge(), true);
735         return;
736     }
737     bool tmp = !jsValue->IsString() && !jsValue->IsNumber() && !jsValue->IsObject();
738 
739     NG::PaddingProperty newPadding = GetNewPadding(info);
740     Edge oldPadding = Edge(GetOldPadding(info));
741     TextFieldModel::GetInstance()->SetPadding(newPadding, oldPadding, tmp);
742 }
743 
GetOldPadding(const JSCallbackInfo& info)744 Edge JSTextField::GetOldPadding(const JSCallbackInfo& info)
745 {
746     Edge padding;
747     auto jsValue = info[0];
748     if (jsValue->IsNumber() || jsValue->IsString()) {
749         CalcDimension edgeValue;
750         if (ParseJsDimensionVp(jsValue, edgeValue)) {
751             padding = Edge(edgeValue);
752         }
753     }
754     if (jsValue->IsObject()) {
755         JSRef<JSObject> object = JSRef<JSObject>::Cast(jsValue);
756         CalcDimension left = CalcDimension(0.0, DimensionUnit::VP);
757         CalcDimension top = CalcDimension(0.0, DimensionUnit::VP);
758         CalcDimension right = CalcDimension(0.0, DimensionUnit::VP);
759         CalcDimension bottom = CalcDimension(0.0, DimensionUnit::VP);
760         ParseJsDimensionVp(object->GetProperty("left"), left);
761         ParseJsDimensionVp(object->GetProperty("top"), top);
762         ParseJsDimensionVp(object->GetProperty("right"), right);
763         ParseJsDimensionVp(object->GetProperty("bottom"), bottom);
764         padding = Edge(left, top, right, bottom);
765     }
766     return padding;
767 }
768 
GetNewPadding(const JSCallbackInfo& info)769 NG::PaddingProperty JSTextField::GetNewPadding(const JSCallbackInfo& info)
770 {
771     NG::PaddingProperty padding;
772     auto jsValue = info[0];
773     if (jsValue->IsObject()) {
774         JSRef<JSObject> paddingObj = JSRef<JSObject>::Cast(jsValue);
775         CommonCalcDimension commonCalcDimension;
776         ParseCommonMarginOrPaddingCorner(paddingObj, commonCalcDimension);
777         if (commonCalcDimension.left.has_value() || commonCalcDimension.right.has_value() ||
778             commonCalcDimension.top.has_value() || commonCalcDimension.bottom.has_value()) {
779             padding = SetPaddings(commonCalcDimension.top, commonCalcDimension.bottom, commonCalcDimension.left,
780                 commonCalcDimension.right);
781             return padding;
782         }
783     }
784 
785     CalcDimension length;
786     if (!ParseJsDimensionVp(jsValue, length)) {
787         // use default value.
788         length.Reset();
789     }
790     padding.SetEdges(NG::CalcLength(length.IsNonNegative() ? length : CalcDimension()));
791     return padding;
792 }
793 
SetPaddings(const std::optional<CalcDimension>& top, const std::optional<CalcDimension>& bottom, const std::optional<CalcDimension>& left, const std::optional<CalcDimension>& right)794 NG::PaddingProperty JSTextField::SetPaddings(const std::optional<CalcDimension>& top,
795     const std::optional<CalcDimension>& bottom, const std::optional<CalcDimension>& left,
796     const std::optional<CalcDimension>& right)
797 {
798     NG::PaddingProperty paddings;
799     if (top.has_value()) {
800         if (top.value().Unit() == DimensionUnit::CALC) {
801             paddings.top =
802                 NG::CalcLength(top.value().IsNonNegative() ? top.value().CalcValue() : CalcDimension().CalcValue());
803         } else {
804             paddings.top = NG::CalcLength(top.value().IsNonNegative() ? top.value() : CalcDimension());
805         }
806     }
807     if (bottom.has_value()) {
808         if (bottom.value().Unit() == DimensionUnit::CALC) {
809             paddings.bottom = NG::CalcLength(
810                 bottom.value().IsNonNegative() ? bottom.value().CalcValue() : CalcDimension().CalcValue());
811         } else {
812             paddings.bottom = NG::CalcLength(bottom.value().IsNonNegative() ? bottom.value() : CalcDimension());
813         }
814     }
815     if (left.has_value()) {
816         if (left.value().Unit() == DimensionUnit::CALC) {
817             paddings.left =
818                 NG::CalcLength(left.value().IsNonNegative() ? left.value().CalcValue() : CalcDimension().CalcValue());
819         } else {
820             paddings.left = NG::CalcLength(left.value().IsNonNegative() ? left.value() : CalcDimension());
821         }
822     }
823     if (right.has_value()) {
824         if (right.value().Unit() == DimensionUnit::CALC) {
825             paddings.right =
826                 NG::CalcLength(right.value().IsNonNegative() ? right.value().CalcValue() : CalcDimension().CalcValue());
827         } else {
828             paddings.right = NG::CalcLength(right.value().IsNonNegative() ? right.value() : CalcDimension());
829         }
830     }
831 
832     return paddings;
833 }
834 
JsBorder(const JSCallbackInfo& info)835 void JSTextField::JsBorder(const JSCallbackInfo& info)
836 {
837     if (!info[0]->IsObject()) {
838         CalcDimension borderWidth;
839         ViewAbstractModel::GetInstance()->SetBorderWidth(borderWidth);
840         ViewAbstractModel::GetInstance()->SetBorderColor(Color::BLACK);
841         ViewAbstractModel::GetInstance()->SetBorderRadius(borderWidth);
842         ViewAbstractModel::GetInstance()->SetBorderStyle(BorderStyle::SOLID);
843         ViewAbstractModel::GetInstance()->SetDashGap(Dimension(-1));
844         ViewAbstractModel::GetInstance()->SetDashWidth(Dimension(-1));
845         return;
846     }
847     JSRef<JSObject> object = JSRef<JSObject>::Cast(info[0]);
848 
849     auto valueWidth = object->GetProperty(static_cast<int32_t>(ArkUIIndex::WIDTH));
850     if (!valueWidth->IsUndefined()) {
851         JSViewAbstract::ParseBorderWidth(valueWidth);
852     }
853 
854     // use default value when undefined.
855     JSViewAbstract::ParseBorderColor(object->GetProperty(static_cast<int32_t>(ArkUIIndex::COLOR)));
856 
857     auto valueRadius = object->GetProperty(static_cast<int32_t>(ArkUIIndex::RADIUS));
858     if (!valueRadius->IsUndefined()) {
859         ParseBorderRadius(valueRadius);
860     }
861     // use default value when undefined.
862     JSViewAbstract::ParseBorderStyle(object->GetProperty(static_cast<int32_t>(ArkUIIndex::STYLE)));
863 
864     auto dashGap = object->GetProperty("dashGap");
865     if (!dashGap->IsUndefined()) {
866         JSViewAbstract::ParseDashGap(dashGap);
867     }
868     auto dashWidth = object->GetProperty("dashWidth");
869     if (!dashWidth->IsUndefined()) {
870         JSViewAbstract::ParseDashWidth(dashWidth);
871     }
872 
873     TextFieldModel::GetInstance()->SetBackBorder();
874     info.ReturnSelf();
875 }
876 
JsBorderWidth(const JSCallbackInfo& info)877 void JSTextField::JsBorderWidth(const JSCallbackInfo& info)
878 {
879     auto jsValue = info[0];
880     if (!jsValue->IsObject() && !jsValue->IsString() && !jsValue->IsNumber()) {
881         return;
882     }
883     JSViewAbstract::JsBorderWidth(info);
884     TextFieldModel::GetInstance()->SetBackBorder();
885 }
886 
JsBorderColor(const JSCallbackInfo& info)887 void JSTextField::JsBorderColor(const JSCallbackInfo& info)
888 {
889     auto jsValue = info[0];
890     if (!jsValue->IsObject() && !jsValue->IsString() && !jsValue->IsNumber()) {
891         return;
892     }
893     JSViewAbstract::JsBorderColor(info);
894     TextFieldModel::GetInstance()->SetBackBorder();
895 }
896 
JsBorderStyle(const JSCallbackInfo& info)897 void JSTextField::JsBorderStyle(const JSCallbackInfo& info)
898 {
899     auto jsValue = info[0];
900     if (!jsValue->IsObject() && !jsValue->IsNumber()) {
901         return;
902     }
903     JSViewAbstract::JsBorderStyle(info);
904     TextFieldModel::GetInstance()->SetBackBorder();
905 }
906 
GetBorderRadiusByLengthMetrics(const char* key, JSRef<JSObject>& object, std::optional<CalcDimension>& radius)907 void JSTextField::GetBorderRadiusByLengthMetrics(const char* key, JSRef<JSObject>& object,
908     std::optional<CalcDimension>& radius)
909 {
910     if (object->HasProperty(key) && object->GetProperty(key)->IsObject()) {
911         JSRef<JSObject> startObj = JSRef<JSObject>::Cast(object->GetProperty(key));
912         CalcDimension value;
913         ParseJsLengthMetrics(startObj, value);
914         radius = value;
915     }
916 }
917 
ParseAllBorderRadiuses(JSRef<JSObject>& object, CalcDimension& topLeft, CalcDimension& topRight, CalcDimension& bottomLeft, CalcDimension& bottomRight)918 bool JSTextField::ParseAllBorderRadiuses(JSRef<JSObject>& object, CalcDimension& topLeft,
919     CalcDimension& topRight, CalcDimension& bottomLeft, CalcDimension& bottomRight)
920 {
921     if (object->HasProperty(TOP_START_PROPERTY) || object->HasProperty(TOP_END_PROPERTY) ||
922         object->HasProperty(BOTTOM_START_PROPERTY) || object->HasProperty(BOTTOM_END_PROPERTY)) {
923         std::optional<CalcDimension> topStart;
924         std::optional<CalcDimension> topEnd;
925         std::optional<CalcDimension> bottomStart;
926         std::optional<CalcDimension> bottomEnd;
927         GetBorderRadiusByLengthMetrics(TOP_START_PROPERTY, object, topStart);
928         GetBorderRadiusByLengthMetrics(TOP_END_PROPERTY, object, topEnd);
929         GetBorderRadiusByLengthMetrics(BOTTOM_START_PROPERTY, object, bottomStart);
930         GetBorderRadiusByLengthMetrics(BOTTOM_END_PROPERTY, object, bottomEnd);
931         topLeft = topStart.has_value() ? topStart.value() : topLeft;
932         topRight = topEnd.has_value() ? topEnd.value() : topRight;
933         bottomLeft = bottomStart.has_value() ? bottomStart.value() : bottomLeft;
934         bottomRight = bottomEnd.has_value() ? bottomEnd.value() : bottomRight;
935         return true;
936     }
937     JSViewAbstract::ParseJsDimensionVp(object->GetProperty("topLeft"), topLeft);
938     JSViewAbstract::ParseJsDimensionVp(object->GetProperty("topRight"), topRight);
939     JSViewAbstract::ParseJsDimensionVp(object->GetProperty("bottomLeft"), bottomLeft);
940     JSViewAbstract::ParseJsDimensionVp(object->GetProperty("bottomRight"), bottomRight);
941     return false;
942 }
943 
ParseBorderRadius(const JSRef<JSVal>& args)944 void JSTextField::ParseBorderRadius(const JSRef<JSVal>& args)
945 {
946     CalcDimension borderRadius;
947     if (ParseJsDimensionVp(args, borderRadius)) {
948         ViewAbstractModel::GetInstance()->SetBorderRadius(borderRadius);
949     } else if (args->IsObject()) {
950         auto textFieldTheme = GetTheme<TextFieldTheme>();
951         CHECK_NULL_VOID(textFieldTheme);
952         auto borderRadiusTheme = textFieldTheme->GetBorderRadius();
953         NG::BorderRadiusProperty defaultBorderRadius {
954             borderRadiusTheme.GetX(), borderRadiusTheme.GetY(),
955             borderRadiusTheme.GetY(), borderRadiusTheme.GetX(),
956         };
957 
958         JSRef<JSObject> object = JSRef<JSObject>::Cast(args);
959         CalcDimension topLeft = defaultBorderRadius.radiusTopLeft.value();
960         CalcDimension topRight = defaultBorderRadius.radiusTopRight.value();
961         CalcDimension bottomLeft = defaultBorderRadius.radiusBottomLeft.value();
962         CalcDimension bottomRight = defaultBorderRadius.radiusBottomRight.value();
963         if (ParseAllBorderRadiuses(object, topLeft, topRight, bottomLeft, bottomRight)) {
964             ViewAbstractModel::GetInstance()->SetBorderRadius(
965                 JSViewAbstract::GetLocalizedBorderRadius(topLeft, topRight, bottomLeft, bottomRight));
966                 return;
967         }
968         ViewAbstractModel::GetInstance()->SetBorderRadius(topLeft, topRight, bottomLeft, bottomRight);
969     }
970 }
971 
JsBorderRadius(const JSCallbackInfo& info)972 void JSTextField::JsBorderRadius(const JSCallbackInfo& info)
973 {
974     auto jsValue = info[0];
975     static std::vector<JSCallbackInfoType> checkList { JSCallbackInfoType::STRING,
976         JSCallbackInfoType::NUMBER, JSCallbackInfoType::OBJECT };
977     if (!CheckJSCallbackInfo("JsBorderRadius", jsValue, checkList)) {
978         auto textFieldTheme = GetTheme<TextFieldTheme>();
979         CHECK_NULL_VOID(textFieldTheme);
980         auto borderRadiusTheme = textFieldTheme->GetBorderRadius();
981         NG::BorderRadiusProperty defaultBorderRadius {
982             borderRadiusTheme.GetX(), borderRadiusTheme.GetY(),
983             borderRadiusTheme.GetY(), borderRadiusTheme.GetX(),
984         };
985         ViewAbstractModel::GetInstance()->SetBorderRadius(defaultBorderRadius);
986         return;
987     }
988     ParseBorderRadius(jsValue);
989     TextFieldModel::GetInstance()->SetBackBorder();
990 }
991 
JsHoverEffect(const JSCallbackInfo& info)992 void JSTextField::JsHoverEffect(const JSCallbackInfo& info)
993 {
994     auto jsValue = info[0];
995     if (!jsValue->IsNumber()) {
996         return;
997     }
998     TextFieldModel::GetInstance()->SetHoverEffect(static_cast<HoverEffectType>(jsValue->ToNumber<int32_t>()));
999 }
1000 
SetOnEditChanged(const JSCallbackInfo& info)1001 void JSTextField::SetOnEditChanged(const JSCallbackInfo& info)
1002 {
1003     auto jsValue = info[0];
1004     CHECK_NULL_VOID(jsValue->IsFunction());
1005     JsEventCallback<void(bool)> callback(info.GetExecutionContext(), JSRef<JSFunc>::Cast(jsValue));
1006     TextFieldModel::GetInstance()->SetOnEditChanged(std::move(callback));
1007 }
1008 
JsKeepEditableState(panda::JsiRuntimeCallInfo *info)1009 Local<JSValueRef> JSTextField::JsKeepEditableState(panda::JsiRuntimeCallInfo *info)
1010 {
1011     Local<JSValueRef> thisObj = info->GetThisRef();
1012     auto eventInfo = static_cast<NG::TextFieldCommonEvent*>(
1013         panda::Local<panda::ObjectRef>(thisObj)->GetNativePointerField(info->GetVM(), 0));
1014     if (eventInfo) {
1015         eventInfo->SetKeepEditable(true);
1016     }
1017     return JSValueRef::Undefined(info->GetVM());
1018 }
1019 
CreateJsTextFieldCommonEvent(const JSCallbackInfo &info)1020 void JSTextField::CreateJsTextFieldCommonEvent(const JSCallbackInfo &info)
1021 {
1022     if (info.Length() < 1 || !info[0]->IsObject()) {
1023         return;
1024     }
1025     auto jsValue = info[0];
1026     auto jsTextFunc = AceType::MakeRefPtr<JsCommonEventFunction<NG::TextFieldCommonEvent, 2>>(
1027         JSRef<JSFunc>::Cast(jsValue));
1028     WeakPtr<NG::FrameNode> targetNode = AceType::WeakClaim(NG::ViewStackProcessor::GetInstance()->GetMainFrameNode());
1029     auto callback = [execCtx = info.GetExecutionContext(), func = std::move(jsTextFunc), node = targetNode](int32_t key,
1030                        NG::TextFieldCommonEvent& event) {
1031         JAVASCRIPT_EXECUTION_SCOPE_WITH_CHECK(execCtx);
1032         ACE_SCORING_EVENT("onSubmit");
1033         PipelineContext::SetCallBackNode(node);
1034         JSRef<JSObjTemplate> objectTemplate = JSRef<JSObjTemplate>::New();
1035         objectTemplate->SetInternalFieldCount(2);
1036         JSRef<JSObject> object = objectTemplate->NewInstance();
1037         object->SetProperty<std::string>("text", event.GetText());
1038         object->SetPropertyObject("keepEditableState", JSRef<JSFunc>::New<FunctionCallback>(JsKeepEditableState));
1039         object->Wrap<NG::TextFieldCommonEvent>(&event);
1040         JSRef<JSVal> keyEvent = JSRef<JSVal>::Make(ToJSValue(key));
1041         JSRef<JSVal> dataObject = JSRef<JSVal>::Cast(object);
1042         JSRef<JSVal> param[2] = {keyEvent, dataObject};
1043         func->Execute(param);
1044 #if !defined(PREVIEW) && defined(OHOS_PLATFORM)
1045         UiSessionManager::GetInstance().ReportComponentChangeEvent("event", "onSubmit");
1046 #endif
1047     };
1048     TextFieldModel::GetInstance()->SetOnSubmit(std::move(callback));
1049 }
1050 
SetOnSubmit(const JSCallbackInfo& info)1051 void JSTextField::SetOnSubmit(const JSCallbackInfo& info)
1052 {
1053     auto jsValue = info[0];
1054     CHECK_NULL_VOID(jsValue->IsFunction());
1055 #ifdef NG_BUILD
1056     CreateJsTextFieldCommonEvent(info);
1057 #else
1058     if (Container::IsCurrentUseNewPipeline()) {
1059         CreateJsTextFieldCommonEvent(info);
1060     } else {
1061         JsEventCallback<void(int32_t)> callback(info.GetExecutionContext(), JSRef<JSFunc>::Cast(jsValue));
1062         TextFieldModel::GetInstance()->SetOnSubmit(std::move(callback));
1063     }
1064 #endif
1065 }
1066 
CreateJsOnChangeObj(const PreviewText& previewText)1067 JSRef<JSVal> JSTextField::CreateJsOnChangeObj(const PreviewText& previewText)
1068 {
1069     JSRef<JSObject> previewTextObj = JSRef<JSObject>::New();
1070     previewTextObj->SetProperty<int32_t>("offset", previewText.offset);
1071     previewTextObj->SetProperty<std::string>("value", previewText.value);
1072     return JSRef<JSVal>::Cast(previewTextObj);
1073 }
1074 
SetOnChange(const JSCallbackInfo& info)1075 void JSTextField::SetOnChange(const JSCallbackInfo& info)
1076 {
1077     auto jsValue = info[0];
1078     CHECK_NULL_VOID(jsValue->IsFunction());
1079     auto jsChangeFunc = AceType::MakeRefPtr<JsCitedEventFunction<PreviewText, 2>>(
1080         JSRef<JSFunc>::Cast(jsValue), CreateJsOnChangeObj);
1081     auto onChange = [execCtx = info.GetExecutionContext(), func = std::move(jsChangeFunc)](
1082         const std::string& val, PreviewText& previewText) {
1083         JAVASCRIPT_EXECUTION_SCOPE_WITH_CHECK(execCtx);
1084         ACE_SCORING_EVENT("onChange");
1085         func->Execute(val, previewText);
1086     };
1087     TextFieldModel::GetInstance()->SetOnChange(std::move(onChange));
1088 }
1089 
SetOnTextSelectionChange(const JSCallbackInfo& info)1090 void JSTextField::SetOnTextSelectionChange(const JSCallbackInfo& info)
1091 {
1092     auto jsValue = info[0];
1093     CHECK_NULL_VOID(jsValue->IsFunction());
1094     JsEventCallback<void(int32_t, int32_t)> callback(info.GetExecutionContext(), JSRef<JSFunc>::Cast(jsValue));
1095     TextFieldModel::GetInstance()->SetOnTextSelectionChange(std::move(callback));
1096 }
1097 
SetOnSecurityStateChange(const JSCallbackInfo& info)1098 void JSTextField::SetOnSecurityStateChange(const JSCallbackInfo& info)
1099 {
1100     auto jsValue = info[0];
1101     CHECK_NULL_VOID(jsValue->IsFunction());
1102     JsEventCallback<void(bool)> callback(info.GetExecutionContext(), JSRef<JSFunc>::Cast(jsValue));
1103     TextFieldModel::GetInstance()->SetOnSecurityStateChange(std::move(callback));
1104 }
1105 
SetOnContentScroll(const JSCallbackInfo& info)1106 void JSTextField::SetOnContentScroll(const JSCallbackInfo& info)
1107 {
1108     auto jsValue = info[0];
1109     CHECK_NULL_VOID(jsValue->IsFunction());
1110     JsEventCallback<void(float, float)> callback(info.GetExecutionContext(), JSRef<JSFunc>::Cast(jsValue));
1111     TextFieldModel::GetInstance()->SetOnContentScroll(std::move(callback));
1112 }
1113 
SetOnCopy(const JSCallbackInfo& info)1114 void JSTextField::SetOnCopy(const JSCallbackInfo& info)
1115 {
1116     auto jsValue = info[0];
1117     CHECK_NULL_VOID(jsValue->IsFunction());
1118     JsEventCallback<void(const std::string&)> callback(info.GetExecutionContext(), JSRef<JSFunc>::Cast(jsValue));
1119     TextFieldModel::GetInstance()->SetOnCopy(std::move(callback));
1120 }
1121 
SetOnCut(const JSCallbackInfo& info)1122 void JSTextField::SetOnCut(const JSCallbackInfo& info)
1123 {
1124     auto jsValue = info[0];
1125     CHECK_NULL_VOID(jsValue->IsFunction());
1126     JsEventCallback<void(const std::string&)> callback(info.GetExecutionContext(), JSRef<JSFunc>::Cast(jsValue));
1127     TextFieldModel::GetInstance()->SetOnCut(std::move(callback));
1128 }
1129 
CreateJSTextCommonEvent(NG::TextCommonEvent& event)1130 JSRef<JSVal> JSTextField::CreateJSTextCommonEvent(NG::TextCommonEvent& event)
1131 {
1132     JSRef<JSObjTemplate> objectTemplate = JSRef<JSObjTemplate>::New();
1133     objectTemplate->SetInternalFieldCount(1);
1134     JSRef<JSObject> object = objectTemplate->NewInstance();
1135     object->SetPropertyObject("preventDefault", JSRef<JSFunc>::New<FunctionCallback>(JsPreventDefault));
1136     object->Wrap<NG::TextCommonEvent>(&event);
1137     return JSRef<JSVal>::Cast(object);
1138 }
1139 
SetOnPaste(const JSCallbackInfo& info)1140 void JSTextField::SetOnPaste(const JSCallbackInfo& info)
1141 {
1142     auto jsValue = info[0];
1143     CHECK_NULL_VOID(jsValue->IsFunction());
1144     auto jsTextFunc = AceType::MakeRefPtr<JsCitedEventFunction<NG::TextCommonEvent, 2>>(
1145         JSRef<JSFunc>::Cast(jsValue), CreateJSTextCommonEvent);
1146 
1147     auto onPaste = [execCtx = info.GetExecutionContext(), func = std::move(jsTextFunc)](
1148         const std::string& val, NG::TextCommonEvent& info) {
1149         JAVASCRIPT_EXECUTION_SCOPE_WITH_CHECK(execCtx);
1150         ACE_SCORING_EVENT("onPaste");
1151         func->Execute(val, info);
1152 #if !defined(PREVIEW) && defined(OHOS_PLATFORM)
1153         UiSessionManager::GetInstance().ReportComponentChangeEvent("event", "onPaste");
1154 #endif
1155     };
1156     TextFieldModel::GetInstance()->SetOnPasteWithEvent(std::move(onPaste));
1157 }
1158 
SetOnClick(const JSCallbackInfo& info)1159 void JSTextField::SetOnClick(const JSCallbackInfo& info)
1160 {
1161     if (Container::IsCurrentUseNewPipeline()) {
1162         JSInteractableView::JsOnClick(info);
1163         return;
1164     }
1165     JsEventCallback<void(const ClickInfo&)> callback(info.GetExecutionContext(), JSRef<JSFunc>::Cast(info[0]));
1166     TextFieldModel::GetInstance()->SetOnClick(std::move(callback));
1167     info.ReturnSelf();
1168 }
1169 
SetCopyOption(const JSCallbackInfo& info)1170 void JSTextField::SetCopyOption(const JSCallbackInfo& info)
1171 {
1172     if (info.Length() == 0) {
1173         return;
1174     }
1175     auto jsValue = info[0];
1176     if (jsValue->IsUndefined()) {
1177         TextFieldModel::GetInstance()->SetCopyOption(CopyOptions::Local);
1178         return;
1179     }
1180     auto copyOptions = CopyOptions::Local;
1181     if (jsValue->IsNumber()) {
1182         auto emunNumber = jsValue->ToNumber<int>();
1183         copyOptions = static_cast<CopyOptions>(emunNumber);
1184     }
1185     TextFieldModel::GetInstance()->SetCopyOption(copyOptions);
1186 }
1187 
SetShowUnderline(const JSCallbackInfo& info)1188 void JSTextField::SetShowUnderline(const JSCallbackInfo& info)
1189 {
1190     auto jsValue = info[0];
1191     if (!jsValue->IsBoolean()) {
1192         TextFieldModel::GetInstance()->SetShowUnderline(false);
1193         return;
1194     }
1195     TextFieldModel::GetInstance()->SetShowUnderline(jsValue->ToBoolean());
1196 }
1197 
SetUnderlineColor(const JSCallbackInfo& info)1198 void JSTextField::SetUnderlineColor(const JSCallbackInfo& info)
1199 {
1200     if (info.Length() < 1) {
1201         return;
1202     }
1203     auto jsValue = info[0];
1204     Color underlineColor;
1205     if (ParseJsColor(jsValue, underlineColor)) {
1206         TextFieldModel::GetInstance()->SetNormalUnderlineColor(underlineColor);
1207     } else if (jsValue->IsObject()) {
1208         auto param = JSRef<JSObject>::Cast(jsValue);
1209         UserUnderlineColor userColor = UserUnderlineColor();
1210         auto typingColorProp = param->GetProperty("typing");
1211         Color typing;
1212         if (ParseJsColor(typingColorProp, typing)) {
1213             userColor.typing = typing;
1214         }
1215         auto normalColorProp = param->GetProperty("normal");
1216         Color normal;
1217         if (ParseJsColor(normalColorProp, normal)) {
1218             userColor.normal = normal;
1219         }
1220         auto errorColorProp = param->GetProperty("error");
1221         Color error;
1222         if (ParseJsColor(errorColorProp, error)) {
1223             userColor.error = error;
1224         }
1225         auto disableColorProp = param->GetProperty("disable");
1226         Color disable;
1227         if (ParseJsColor(disableColorProp, disable)) {
1228             userColor.disable = disable;
1229         }
1230         TextFieldModel::GetInstance()->SetUserUnderlineColor(userColor);
1231     } else {
1232         TextFieldModel::GetInstance()->SetUserUnderlineColor(UserUnderlineColor());
1233     }
1234 }
1235 
SetPasswordIcon(const JSCallbackInfo& info)1236 void JSTextField::SetPasswordIcon(const JSCallbackInfo& info)
1237 {
1238     if (!Container::IsCurrentUseNewPipeline()) {
1239         return;
1240     }
1241     auto jsValue = info[0];
1242     if (!jsValue->IsObject()) {
1243         return;
1244     }
1245     JSRef<JSObject> jsObj = JSRef<JSObject>::Cast(jsValue);
1246     JSRef<JSVal> showVal = jsObj->GetProperty("onIconSrc");
1247     JSRef<JSVal> hideVal = jsObj->GetProperty("offIconSrc");
1248     PasswordIcon passwordIcon;
1249     if (showVal->IsString()) {
1250         passwordIcon.showResult = showVal->ToString();
1251     }
1252     if (hideVal->IsString()) {
1253         passwordIcon.hideResult = hideVal->ToString();
1254     }
1255     if (showVal->IsObject()) {
1256         JSRef<JSVal> bundleName = JSRef<JSObject>::Cast(showVal)->GetProperty("bundleName");
1257         JSRef<JSVal> moduleName = JSRef<JSObject>::Cast(showVal)->GetProperty("moduleName");
1258         if (bundleName->IsString()) {
1259             passwordIcon.showBundleName = bundleName->ToString();
1260         }
1261         if (moduleName->IsString()) {
1262             passwordIcon.showModuleName = moduleName->ToString();
1263         }
1264         ParseJsMedia(JSRef<JSObject>::Cast(showVal), passwordIcon.showResult);
1265     }
1266     if (hideVal->IsObject()) {
1267         JSRef<JSVal> bundleName = JSRef<JSObject>::Cast(hideVal)->GetProperty("bundleName");
1268         JSRef<JSVal> moduleName = JSRef<JSObject>::Cast(hideVal)->GetProperty("moduleName");
1269         if (bundleName->IsString()) {
1270             passwordIcon.hideBundleName = bundleName->ToString();
1271         }
1272         if (moduleName->IsString()) {
1273             passwordIcon.hideModuleName = moduleName->ToString();
1274         }
1275         ParseJsMedia(JSRef<JSObject>::Cast(hideVal), passwordIcon.hideResult);
1276     }
1277     if (!showVal->IsString() && !showVal->IsObject()) {
1278         passwordIcon.showResult = "";
1279     }
1280     if (!hideVal->IsString() && !hideVal->IsObject()) {
1281         passwordIcon.hideResult = "";
1282     }
1283     TextFieldModel::GetInstance()->SetPasswordIcon(passwordIcon);
1284 }
1285 
UpdateDecoration(const RefPtr<BoxComponent>& boxComponent, const RefPtr<TextFieldComponent>& component, const Border& boxBorder, const OHOS::Ace::RefPtr<OHOS::Ace::TextFieldTheme>& textFieldTheme)1286 void JSTextField::UpdateDecoration(const RefPtr<BoxComponent>& boxComponent,
1287     const RefPtr<TextFieldComponent>& component, const Border& boxBorder,
1288     const OHOS::Ace::RefPtr<OHOS::Ace::TextFieldTheme>& textFieldTheme)
1289 {
1290     if (!textFieldTheme) {
1291         return;
1292     }
1293 
1294     RefPtr<Decoration> decoration = component->GetDecoration();
1295     RefPtr<Decoration> boxDecoration = boxComponent->GetBackDecoration();
1296     if (!decoration) {
1297         decoration = AceType::MakeRefPtr<Decoration>();
1298     }
1299     if (boxDecoration) {
1300         Border border = decoration->GetBorder();
1301         border.SetLeftEdge(boxBorder.Left());
1302         border.SetRightEdge(boxBorder.Right());
1303         border.SetTopEdge(boxBorder.Top());
1304         border.SetBottomEdge(boxBorder.Bottom());
1305         border.SetBorderRadius(textFieldTheme->GetBorderRadius());
1306         decoration->SetBorder(border);
1307         component->SetOriginBorder(decoration->GetBorder());
1308 
1309         if (boxDecoration->GetImage() || boxDecoration->GetGradient().IsValid()) {
1310             // clear box properties except background image and radius.
1311             boxDecoration->SetBackgroundColor(Color::TRANSPARENT);
1312             Border border;
1313             border.SetBorderRadius(textFieldTheme->GetBorderRadius());
1314             boxDecoration->SetBorder(border);
1315         }
1316     } else {
1317         boxDecoration = AceType::MakeRefPtr<Decoration>();
1318         boxDecoration->SetBorderRadius(textFieldTheme->GetBorderRadius());
1319         boxComponent->SetBackDecoration(boxDecoration);
1320     }
1321 }
1322 
SetShowUnit(const JSCallbackInfo& info)1323 void JSTextField::SetShowUnit(const JSCallbackInfo& info)
1324 {
1325     auto jsValue = info[0];
1326     if (!jsValue->IsFunction()) {
1327         TextFieldModel::GetInstance()->SetShowUnit(nullptr);
1328         return;
1329     }
1330 
1331     auto builderFunc = AceType::MakeRefPtr<JsFunction>(JSRef<JSFunc>::Cast(jsValue));
1332     auto unitFunc = [builderFunc]() { builderFunc->Execute(); };
1333     TextFieldModel::GetInstance()->SetShowUnit(std::move(unitFunc));
1334 }
1335 
SetShowError(const JSCallbackInfo& info)1336 void JSTextField::SetShowError(const JSCallbackInfo& info)
1337 {
1338     auto jsValue = info[0];
1339     if (Container::IsCurrentUseNewPipeline()) {
1340         bool isVisible = false;
1341         std::string errorText;
1342         if (ParseJsString(jsValue, errorText)) {
1343             isVisible = true;
1344         }
1345         TextFieldModel::GetInstance()->SetShowError(errorText, isVisible);
1346     }
1347 }
1348 
SetShowCounter(const JSCallbackInfo& info)1349 void JSTextField::SetShowCounter(const JSCallbackInfo& info)
1350 {
1351     auto jsValue = info[0];
1352     auto secondJSValue = info[1];
1353     if ((!jsValue->IsBoolean() && !secondJSValue->IsObject())) {
1354         TextFieldModel::GetInstance()->SetShowCounter(false);
1355         return;
1356     }
1357     if (secondJSValue->IsObject()) {
1358         auto paramObject = JSRef<JSObject>::Cast(secondJSValue);
1359         auto param = paramObject->GetProperty("highlightBorder");
1360         auto isBorderShow = param->ToBoolean();
1361         if (!param->IsBoolean() || param->IsUndefined() || param->IsNull()) {
1362             TextFieldModel::GetInstance()->SetShowCounterBorder(true);
1363         } else {
1364             TextFieldModel::GetInstance()->SetShowCounterBorder(isBorderShow);
1365         }
1366         auto parameter = paramObject->GetProperty("thresholdPercentage");
1367         auto inputNumber = parameter->ToNumber<int32_t>();
1368         TextFieldModel::GetInstance()->SetCounterType(inputNumber);
1369         if (parameter->IsNull() || parameter->IsUndefined()) {
1370             TextFieldModel::GetInstance()->SetShowCounter(jsValue->ToBoolean());
1371             TextFieldModel::GetInstance()->SetCounterType(DEFAULT_MODE);
1372             return;
1373         }
1374         if (static_cast<uint32_t>(inputNumber) < MINI_VAILD_VALUE ||
1375             static_cast<uint32_t>(inputNumber) > MAX_VAILD_VALUE) {
1376             LOGI("The info is wrong, it is supposed to be a right number");
1377             TextFieldModel::GetInstance()->SetCounterType(ILLEGAL_VALUE);
1378             TextFieldModel::GetInstance()->SetShowCounter(false);
1379             return;
1380         }
1381         TextFieldModel::GetInstance()->SetShowCounter(jsValue->ToBoolean());
1382         return;
1383     }
1384     TextFieldModel::GetInstance()->SetShowCounter(jsValue->ToBoolean());
1385     TextFieldModel::GetInstance()->SetCounterType(DEFAULT_MODE);
1386     TextFieldModel::GetInstance()->SetShowCounterBorder(true);
1387 }
1388 
SetBarState(const JSCallbackInfo& info)1389 void JSTextField::SetBarState(const JSCallbackInfo& info)
1390 {
1391     if (info.Length() < 1) {
1392         TextFieldModel::GetInstance()->SetBarState(DisplayMode::AUTO);
1393         return;
1394     }
1395     auto jsValue = info[0];
1396     if (!jsValue->IsNumber()) {
1397         TextFieldModel::GetInstance()->SetBarState(DisplayMode::AUTO);
1398         return;
1399     }
1400     DisplayMode displayMode = static_cast<DisplayMode>(jsValue->ToNumber<int32_t>());
1401     TextFieldModel::GetInstance()->SetBarState(displayMode);
1402 }
1403 
SetMaxLines(const JSCallbackInfo& info)1404 void JSTextField::SetMaxLines(const JSCallbackInfo& info)
1405 {
1406     if (info.Length() < 1) {
1407         TextFieldModel::GetInstance()->SetMaxViewLines(MAX_LINES);
1408         return;
1409     }
1410     auto jsValue = info[0];
1411     if (!jsValue->IsNumber() || jsValue->ToNumber<int32_t>() <= 0) {
1412         TextFieldModel::GetInstance()->SetMaxViewLines(MAX_LINES);
1413         return;
1414     }
1415     TextFieldModel::GetInstance()->SetMaxViewLines(jsValue->ToNumber<uint32_t>());
1416 }
1417 
SetEnableKeyboardOnFocus(const JSCallbackInfo& info)1418 void JSTextField::SetEnableKeyboardOnFocus(const JSCallbackInfo& info)
1419 {
1420     if (info.Length() < 1) {
1421         return;
1422     }
1423     auto jsValue = info[0];
1424     if (jsValue->IsUndefined() || !jsValue->IsBoolean()) {
1425         TextFieldModel::GetInstance()->RequestKeyboardOnFocus(true);
1426         return;
1427     }
1428     TextFieldModel::GetInstance()->RequestKeyboardOnFocus(jsValue->ToBoolean());
1429 }
1430 
SetSelectionMenuHidden(const JSCallbackInfo& info)1431 void JSTextField::SetSelectionMenuHidden(const JSCallbackInfo& info)
1432 {
1433     if (info.Length() < 1) {
1434         return;
1435     }
1436     auto jsValue = info[0];
1437     if (jsValue->IsUndefined() || !jsValue->IsBoolean()) {
1438         TextFieldModel::GetInstance()->SetSelectionMenuHidden(false);
1439         return;
1440     }
1441     TextFieldModel::GetInstance()->SetSelectionMenuHidden(jsValue->ToBoolean());
1442 }
1443 
ParseJsCustomKeyboardBuilder( const JSCallbackInfo& info, int32_t index, std::function<void()>& buildFunc)1444 bool JSTextField::ParseJsCustomKeyboardBuilder(
1445     const JSCallbackInfo& info, int32_t index, std::function<void()>& buildFunc)
1446 {
1447     if (info.Length() <= index || !info[index]->IsObject()) {
1448         return false;
1449     }
1450     JSRef<JSObject> obj = JSRef<JSObject>::Cast(info[index]);
1451     auto builder = obj->GetProperty("builder");
1452     if (!builder->IsFunction()) {
1453         return false;
1454     }
1455     auto builderFunc = AceType::MakeRefPtr<JsFunction>(JSRef<JSFunc>::Cast(builder));
1456     CHECK_NULL_RETURN(builderFunc, false);
1457     WeakPtr<NG::FrameNode> targetNode = AceType::WeakClaim(NG::ViewStackProcessor::GetInstance()->GetMainFrameNode());
1458     buildFunc = [execCtx = info.GetExecutionContext(), func = std::move(builderFunc), node = targetNode]() {
1459         JAVASCRIPT_EXECUTION_SCOPE_WITH_CHECK(execCtx);
1460         ACE_SCORING_EVENT("CustomKeyboard");
1461         PipelineContext::SetCallBackNode(node);
1462         func->Execute();
1463     };
1464     return true;
1465 }
1466 
SetCustomKeyboard(const JSCallbackInfo& info)1467 void JSTextField::SetCustomKeyboard(const JSCallbackInfo& info)
1468 {
1469     if (info.Length() < 1) {
1470         return;
1471     }
1472     auto jsValue = info[0];
1473     if (jsValue->IsUndefined() || jsValue->IsNull() || !jsValue->IsObject()) {
1474         TextFieldModel::GetInstance()->SetCustomKeyboard(nullptr);
1475         return;
1476     }
1477     bool supportAvoidance = false;
1478     if (info.Length() == 2 && info[1]->IsObject()) {  //  2 here refers to the number of parameters
1479         auto paramObject = JSRef<JSObject>::Cast(info[1]);
1480         auto isSupportAvoidance = paramObject->GetProperty("supportAvoidance");
1481         if (!isSupportAvoidance->IsNull() && isSupportAvoidance->IsBoolean()) {
1482             supportAvoidance = isSupportAvoidance->ToBoolean();
1483         }
1484     }
1485     std::function<void()> buildFunc;
1486     if (ParseJsCustomKeyboardBuilder(info, 0, buildFunc)) {
1487         TextFieldModel::GetInstance()->SetCustomKeyboard(std::move(buildFunc), supportAvoidance);
1488     }
1489 }
1490 
SetPasswordRules(const JSCallbackInfo& info)1491 void JSTextField::SetPasswordRules(const JSCallbackInfo& info)
1492 {
1493     auto jsValue = info[0];
1494     if (!jsValue->IsString()) {
1495         return;
1496     }
1497     auto passwordRules = jsValue->ToString();
1498     TextFieldModel::GetInstance()->SetPasswordRules(passwordRules);
1499 }
1500 
SetEnableAutoFill(const JSCallbackInfo& info)1501 void JSTextField::SetEnableAutoFill(const JSCallbackInfo& info)
1502 {
1503     auto jsValue = info[0];
1504     if (!jsValue->IsBoolean()) {
1505         TextFieldModel::GetInstance()->SetEnableAutoFill(true);
1506         return;
1507     }
1508     TextFieldModel::GetInstance()->SetEnableAutoFill(jsValue->ToBoolean());
1509 }
1510 
ConvertStrToCleanNodeStyle(const std::string& value)1511 static CleanNodeStyle ConvertStrToCleanNodeStyle(const std::string& value)
1512 {
1513     if (value == "CONSTANT") {
1514         return CleanNodeStyle::CONSTANT;
1515     } else if (value == "INVISIBLE") {
1516         return CleanNodeStyle::INVISIBLE;
1517     } else {
1518         return CleanNodeStyle::INPUT;
1519     }
1520 }
1521 
SetCancelButton(const JSCallbackInfo& info)1522 void JSTextField::SetCancelButton(const JSCallbackInfo& info)
1523 {
1524     if (info.Length() < 1 || !info[0]->IsObject()) {
1525         return;
1526     }
1527     auto param = JSRef<JSObject>::Cast(info[0]);
1528     auto theme = GetTheme<TextFieldTheme>();
1529     CHECK_NULL_VOID(theme);
1530 
1531     // set style
1532     std::string styleStr;
1533     CleanNodeStyle cleanNodeStyle;
1534     auto styleProp = param->GetProperty("style");
1535     if (!styleProp->IsNull() && ParseJsString(styleProp, styleStr)) {
1536         cleanNodeStyle = ConvertStrToCleanNodeStyle(styleStr);
1537     } else {
1538         cleanNodeStyle = CleanNodeStyle::INPUT;
1539     }
1540     TextFieldModel::GetInstance()->SetCleanNodeStyle(cleanNodeStyle);
1541     TextFieldModel::GetInstance()->SetIsShowCancelButton(true);
1542 
1543     // set default icon
1544     auto iconJsVal = param->GetProperty("icon");
1545     if (iconJsVal->IsUndefined() || iconJsVal->IsNull() || !iconJsVal->IsObject()) {
1546         SetCancelDefaultIcon();
1547         return;
1548     }
1549 
1550     auto iconParam = JSRef<JSObject>::Cast(iconJsVal);
1551     bool isSymbolIcon = iconParam->HasProperty("fontColor"); // only SymbolGlyph has fontColor property
1552     if (isSymbolIcon) {
1553         SetCancelSymbolIcon(info);
1554         return;
1555     }
1556 
1557     // set icon size
1558     CalcDimension iconSize;
1559     auto iconSizeProp = iconParam->GetProperty("size");
1560     if (!iconSizeProp->IsUndefined() && !iconSizeProp->IsNull() && ParseJsDimensionVpNG(iconSizeProp, iconSize)) {
1561         if (LessNotEqual(iconSize.Value(), 0.0) || iconSize.Unit() == DimensionUnit::PERCENT) {
1562             iconSize = theme->GetIconSize();
1563         }
1564     } else {
1565         iconSize = theme->GetIconSize();
1566     }
1567     TextFieldModel::GetInstance()->SetCancelIconSize(iconSize);
1568     SetCancelIconColorAndIconSrc(iconParam);
1569 }
1570 
SetCancelDefaultIcon()1571 void JSTextField::SetCancelDefaultIcon()
1572 {
1573     auto theme = GetTheme<TextFieldTheme>();
1574     CHECK_NULL_VOID(theme);
1575     if (SystemProperties::GetColorMode() == ColorMode::DARK) {
1576         TextFieldModel::GetInstance()->SetCancelIconColor(theme->GetCancelButtonIconColor());
1577     } else {
1578         TextFieldModel::GetInstance()->SetCancelIconColor(Color());
1579     }
1580     TextFieldModel::GetInstance()->SetCancelIconSize(theme->GetIconSize());
1581     TextFieldModel::GetInstance()->SetCanacelIconSrc(std::string(), std::string(), std::string());
1582     TextFieldModel::GetInstance()->SetCancelSymbolIcon(nullptr);
1583     TextFieldModel::GetInstance()->SetCancelButtonSymbol(true);
1584 }
1585 
SetCancelSymbolIcon(const JSCallbackInfo& info)1586 void JSTextField::SetCancelSymbolIcon(const JSCallbackInfo& info)
1587 {
1588     if (info[0]->IsObject()) {
1589         std::function<void(WeakPtr<NG::FrameNode>)> iconSymbol = nullptr;
1590         auto param = JSRef<JSObject>::Cast(info[0]);
1591         auto iconProp = param->GetProperty("icon");
1592         SetSymbolOptionApply(info, iconSymbol, iconProp);
1593         TextFieldModel::GetInstance()->SetCancelSymbolIcon(iconSymbol);
1594         TextFieldModel::GetInstance()->SetCancelButtonSymbol(true);
1595     }
1596 }
1597 
SetCancelIconColorAndIconSrc(const JSRef<JSObject>& iconParam)1598 void JSTextField::SetCancelIconColorAndIconSrc(const JSRef<JSObject>& iconParam)
1599 {
1600     auto theme = GetTheme<TextFieldTheme>();
1601     CHECK_NULL_VOID(theme);
1602     // set icon src
1603     std::string iconSrc;
1604     std::string bundleName;
1605     std::string moduleName;
1606     auto iconSrcProp = iconParam->GetProperty("src");
1607     if (iconSrcProp->IsUndefined() || iconSrcProp->IsNull() || !ParseJsMedia(iconSrcProp, iconSrc)) {
1608         iconSrc = "";
1609     }
1610     GetJsMediaBundleInfo(iconSrcProp, bundleName, moduleName);
1611     TextFieldModel::GetInstance()->SetCanacelIconSrc(iconSrc, bundleName, moduleName);
1612     TextFieldModel::GetInstance()->SetCancelButtonSymbol(false);
1613     // set icon color
1614     Color iconColor;
1615     auto iconColorProp = iconParam->GetProperty("color");
1616     if (!iconColorProp->IsUndefined() && !iconColorProp->IsNull() && ParseJsColor(iconColorProp, iconColor)) {
1617         TextFieldModel::GetInstance()->SetCancelIconColor(iconColor);
1618         return;
1619     }
1620     auto info = ImageSourceInfo(iconSrc, bundleName, moduleName);
1621     if (info.IsSvg() && iconSrc != "") {
1622         // svg need not default color, otherwise multi color svg will render fault
1623         return;
1624     }
1625     if (SystemProperties::GetColorMode() == ColorMode::DARK) {
1626         TextFieldModel::GetInstance()->SetCancelIconColor(theme->GetCancelButtonIconColor());
1627     } else {
1628         TextFieldModel::GetInstance()->SetCancelIconColor(iconColor);
1629     }
1630 }
1631 
SetSelectAllValue(const JSCallbackInfo& info)1632 void JSTextField::SetSelectAllValue(const JSCallbackInfo& info)
1633 {
1634     auto infoValue = info[0];
1635     if (!infoValue->IsBoolean() || infoValue->IsUndefined() || infoValue->IsNull()) {
1636         TextFieldModel::GetInstance()->SetSelectAllValue(false);
1637         return;
1638     }
1639 
1640     bool isSetSelectAllValue = infoValue->ToBoolean();
1641     TextFieldModel::GetInstance()->SetSelectAllValue(isSetSelectAllValue);
1642 }
1643 
SetDecoration(const JSCallbackInfo& info)1644 void JSTextField::SetDecoration(const JSCallbackInfo& info)
1645 {
1646     do {
1647         auto tmpInfo = info[0];
1648         if (!tmpInfo->IsObject()) {
1649             TextFieldModel::GetInstance()->SetTextDecoration(TextDecoration::NONE);
1650             TextFieldModel::GetInstance()->SetTextDecorationColor(Color::BLACK);
1651             TextFieldModel::GetInstance()->SetTextDecorationStyle(TextDecorationStyle::SOLID);
1652             break;
1653         }
1654         JSRef<JSObject> obj = JSRef<JSObject>::Cast(tmpInfo);
1655         JSRef<JSVal> typeValue = obj->GetProperty("type");
1656         JSRef<JSVal> colorValue = obj->GetProperty("color");
1657         JSRef<JSVal> styleValue = obj->GetProperty("style");
1658 
1659         auto pipelineContext = PipelineBase::GetCurrentContext();
1660         CHECK_NULL_VOID(pipelineContext);
1661         auto theme = pipelineContext->GetTheme<TextFieldTheme>();
1662         CHECK_NULL_VOID(theme);
1663         TextDecoration textDecoration = theme->GetTextStyle().GetTextDecoration();
1664         if (typeValue->IsNumber()) {
1665             textDecoration = static_cast<TextDecoration>(typeValue->ToNumber<int32_t>());
1666         }
1667         Color result = theme->GetTextStyle().GetTextDecorationColor();
1668         ParseJsColor(colorValue, result, Color::BLACK);
1669         std::optional<TextDecorationStyle> textDecorationStyle;
1670         if (styleValue->IsNumber()) {
1671             textDecorationStyle = static_cast<TextDecorationStyle>(styleValue->ToNumber<int32_t>());
1672         } else {
1673             textDecorationStyle = DEFAULT_TEXT_DECORATION_STYLE;
1674         }
1675         TextFieldModel::GetInstance()->SetTextDecoration(textDecoration);
1676         TextFieldModel::GetInstance()->SetTextDecorationColor(result);
1677         if (textDecorationStyle) {
1678             TextFieldModel::GetInstance()->SetTextDecorationStyle(textDecorationStyle.value());
1679         }
1680     } while (false);
1681 }
1682 
SetMinFontSize(const JSCallbackInfo& info)1683 void JSTextField::SetMinFontSize(const JSCallbackInfo& info)
1684 {
1685     if (info.Length() < 1) {
1686         return;
1687     }
1688     CalcDimension minFontSize;
1689     if (!ParseJsDimensionFpNG(info[0], minFontSize, false)) {
1690         TextFieldModel::GetInstance()->SetAdaptMinFontSize(CalcDimension());
1691         return;
1692     }
1693     if (minFontSize.IsNegative()) {
1694         minFontSize = CalcDimension();
1695     }
1696     TextFieldModel::GetInstance()->SetAdaptMinFontSize(minFontSize);
1697 }
1698 
SetMaxFontSize(const JSCallbackInfo& info)1699 void JSTextField::SetMaxFontSize(const JSCallbackInfo& info)
1700 {
1701     if (info.Length() < 1) {
1702         return;
1703     }
1704     auto pipelineContext = PipelineBase::GetCurrentContext();
1705     CHECK_NULL_VOID(pipelineContext);
1706     auto theme = pipelineContext->GetTheme<TextFieldTheme>();
1707     CHECK_NULL_VOID(theme);
1708     CalcDimension maxFontSize = theme->GetTextStyle().GetAdaptMaxFontSize();
1709     if (!ParseJsDimensionFpNG(info[0], maxFontSize, false)) {
1710         maxFontSize = theme->GetTextStyle().GetAdaptMaxFontSize();
1711         TextFieldModel::GetInstance()->SetAdaptMaxFontSize(maxFontSize);
1712         return;
1713     }
1714     if (maxFontSize.IsNegative()) {
1715         maxFontSize = theme->GetTextStyle().GetAdaptMaxFontSize();
1716     }
1717     TextFieldModel::GetInstance()->SetAdaptMaxFontSize(maxFontSize);
1718 }
1719 
SetHeightAdaptivePolicy(int32_t value)1720 void JSTextField::SetHeightAdaptivePolicy(int32_t value)
1721 {
1722     if (value < 0 || value >= static_cast<int32_t>(HEIGHT_ADAPTIVE_POLICY.size())) {
1723         value = 0;
1724     }
1725     TextFieldModel::GetInstance()->SetHeightAdaptivePolicy(HEIGHT_ADAPTIVE_POLICY[value]);
1726 }
1727 
SetLetterSpacing(const JSCallbackInfo& info)1728 void JSTextField::SetLetterSpacing(const JSCallbackInfo& info)
1729 {
1730     CalcDimension value;
1731     if (!ParseJsDimensionFpNG(info[0], value, false)) {
1732         value.Reset();
1733         TextFieldModel::GetInstance()->SetLetterSpacing(value);
1734         return;
1735     }
1736     TextFieldModel::GetInstance()->SetLetterSpacing(value);
1737 }
1738 
SetLineHeight(const JSCallbackInfo& info)1739 void JSTextField::SetLineHeight(const JSCallbackInfo& info)
1740 {
1741     CalcDimension value;
1742     if (!ParseJsDimensionFpNG(info[0], value)) {
1743         value.Reset();
1744         TextFieldModel::GetInstance()->SetLineHeight(value);
1745         return;
1746     }
1747     if (value.IsNegative()) {
1748         value.Reset();
1749     }
1750     TextFieldModel::GetInstance()->SetLineHeight(value);
1751 }
1752 
SetLineSpacing(const JSCallbackInfo& info)1753 void JSTextField::SetLineSpacing(const JSCallbackInfo& info)
1754 {
1755     CalcDimension value;
1756     if (!ParseLengthMetricsToPositiveDimension(info[0], value)) {
1757         value.Reset();
1758     }
1759     if (value.IsNegative()) {
1760         value.Reset();
1761     }
1762     TextFieldModel::GetInstance()->SetLineSpacing(value);
1763 }
1764 
SetFontFeature(const JSCallbackInfo& info)1765 void JSTextField::SetFontFeature(const JSCallbackInfo& info)
1766 {
1767     if (info.Length() < 1) {
1768         return;
1769     }
1770     auto jsValue = info[0];
1771     std::string fontFeatureSettings = "";
1772     if (jsValue->IsString()) {
1773         fontFeatureSettings = jsValue->ToString();
1774     }
1775     TextFieldModel::GetInstance()->SetFontFeature(ParseFontFeatureSettings(fontFeatureSettings));
1776 }
1777 
SetTextOverflow(const JSCallbackInfo& info)1778 void JSTextField::SetTextOverflow(const JSCallbackInfo& info)
1779 {
1780     do {
1781         auto tmpInfo = info[0];
1782         int32_t overflow = 0;
1783         if (info.Length() < 1) {
1784             break;
1785         }
1786         if (tmpInfo->IsUndefined() || tmpInfo->IsNull() || !tmpInfo->IsNumber()) {
1787             overflow = DEFAULT_OVERFLOW;
1788         } else if (tmpInfo->IsNumber()) {
1789             overflow = tmpInfo->ToNumber<int32_t>();
1790             if (overflow < 0 || overflow >= static_cast<int32_t>(TEXT_OVERFLOWS.size())) {
1791                 overflow = DEFAULT_OVERFLOW;
1792             }
1793         }
1794         TextFieldModel::GetInstance()->SetTextOverflow(TEXT_OVERFLOWS[overflow]);
1795     } while (false);
1796 
1797     info.SetReturnValue(info.This());
1798 }
1799 
SetTextIndent(const JSCallbackInfo& info)1800 void JSTextField::SetTextIndent(const JSCallbackInfo& info)
1801 {
1802     CalcDimension value;
1803     if (!ParseJsDimensionVpNG(info[0], value, true)) {
1804         value.Reset();
1805     }
1806     TextFieldModel::GetInstance()->SetTextIndent(value);
1807 }
1808 
CreateJsAboutToIMEInputObj(const InsertValueInfo& insertValue)1809 JSRef<JSVal> JSTextField::CreateJsAboutToIMEInputObj(const InsertValueInfo& insertValue)
1810 {
1811     JSRef<JSObject> aboutToIMEInputObj = JSRef<JSObject>::New();
1812     aboutToIMEInputObj->SetProperty<int32_t>("insertOffset", insertValue.insertOffset);
1813     aboutToIMEInputObj->SetProperty<std::string>("insertValue", insertValue.insertValue);
1814     return JSRef<JSVal>::Cast(aboutToIMEInputObj);
1815 }
1816 
OnWillInsertValue(const JSCallbackInfo& info)1817 void JSTextField::OnWillInsertValue(const JSCallbackInfo& info)
1818 {
1819     auto jsValue = info[0];
1820     CHECK_NULL_VOID(jsValue->IsFunction());
1821     auto jsAboutToIMEInputFunc = AceType::MakeRefPtr<JsEventFunction<InsertValueInfo, 1>>(
1822         JSRef<JSFunc>::Cast(jsValue), CreateJsAboutToIMEInputObj);
1823     auto callback = [execCtx = info.GetExecutionContext(), func = std::move(jsAboutToIMEInputFunc)](
1824                         const InsertValueInfo& insertValue) -> bool {
1825         JAVASCRIPT_EXECUTION_SCOPE_WITH_CHECK(execCtx, true);
1826         auto ret = func->ExecuteWithValue(insertValue);
1827         if (ret->IsBoolean()) {
1828             return ret->ToBoolean();
1829         }
1830         return true;
1831     };
1832     TextFieldModel::GetInstance()->SetOnWillInsertValueEvent(std::move(callback));
1833 }
1834 
CreateJsDeleteToIMEObj(const DeleteValueInfo& deleteValueInfo)1835 JSRef<JSVal> JSTextField::CreateJsDeleteToIMEObj(const DeleteValueInfo& deleteValueInfo)
1836 {
1837     JSRef<JSObject> aboutToIMEInputObj = JSRef<JSObject>::New();
1838     aboutToIMEInputObj->SetProperty<int32_t>("deleteOffset", deleteValueInfo.deleteOffset);
1839     aboutToIMEInputObj->SetProperty<int32_t>("direction", static_cast<int32_t>(deleteValueInfo.direction));
1840     aboutToIMEInputObj->SetProperty<std::string>("deleteValue", deleteValueInfo.deleteValue);
1841     return JSRef<JSVal>::Cast(aboutToIMEInputObj);
1842 }
1843 
OnDidInsertValue(const JSCallbackInfo& info)1844 void JSTextField::OnDidInsertValue(const JSCallbackInfo& info)
1845 {
1846     auto jsValue = info[0];
1847     CHECK_NULL_VOID(jsValue->IsFunction());
1848     auto jsAboutToIMEInputFunc = AceType::MakeRefPtr<JsEventFunction<InsertValueInfo, 1>>(
1849         JSRef<JSFunc>::Cast(jsValue), CreateJsAboutToIMEInputObj);
1850     auto callback = [execCtx = info.GetExecutionContext(), func = std::move(jsAboutToIMEInputFunc)](
1851                         const InsertValueInfo& insertValue) {
1852         JAVASCRIPT_EXECUTION_SCOPE_WITH_CHECK(execCtx);
1853         func->ExecuteWithValue(insertValue);
1854     };
1855     TextFieldModel::GetInstance()->SetOnDidInsertValueEvent(std::move(callback));
1856 }
1857 
OnWillDelete(const JSCallbackInfo& info)1858 void JSTextField::OnWillDelete(const JSCallbackInfo& info)
1859 {
1860     auto jsValue = info[0];
1861     CHECK_NULL_VOID(jsValue->IsFunction());
1862     auto jsAboutToIMEInputFunc =
1863         AceType::MakeRefPtr<JsEventFunction<DeleteValueInfo, 1>>(JSRef<JSFunc>::Cast(jsValue), CreateJsDeleteToIMEObj);
1864     auto callback = [execCtx = info.GetExecutionContext(), func = std::move(jsAboutToIMEInputFunc)](
1865                         const DeleteValueInfo& deleteValue) {
1866         JAVASCRIPT_EXECUTION_SCOPE_WITH_CHECK(execCtx, true);
1867         auto ret = func->ExecuteWithValue(deleteValue);
1868         if (ret->IsBoolean()) {
1869             return ret->ToBoolean();
1870         }
1871         return true;
1872     };
1873     TextFieldModel::GetInstance()->SetOnWillDeleteEvent(std::move(callback));
1874 }
1875 
OnDidDelete(const JSCallbackInfo& info)1876 void JSTextField::OnDidDelete(const JSCallbackInfo& info)
1877 {
1878     auto jsValue = info[0];
1879     CHECK_NULL_VOID(jsValue->IsFunction());
1880     auto jsAboutToIMEInputFunc =
1881         AceType::MakeRefPtr<JsEventFunction<DeleteValueInfo, 1>>(JSRef<JSFunc>::Cast(jsValue), CreateJsDeleteToIMEObj);
1882     auto callback = [execCtx = info.GetExecutionContext(), func = std::move(jsAboutToIMEInputFunc)](
1883                         const DeleteValueInfo& deleteValue) {
1884         JAVASCRIPT_EXECUTION_SCOPE_WITH_CHECK(execCtx);
1885         func->ExecuteWithValue(deleteValue);
1886     };
1887     TextFieldModel::GetInstance()->SetOnDidDeleteEvent(std::move(callback));
1888 }
1889 
EditMenuOptions(const JSCallbackInfo& info)1890 void JSTextField::EditMenuOptions(const JSCallbackInfo& info)
1891 {
1892     NG::OnCreateMenuCallback onCreateMenuCallback;
1893     NG::OnMenuItemClickCallback onMenuItemClick;
1894     JSViewAbstract::ParseEditMenuOptions(info, onCreateMenuCallback, onMenuItemClick);
1895     TextFieldModel::GetInstance()->SetSelectionMenuOptions(std::move(onCreateMenuCallback), std::move(onMenuItemClick));
1896 }
1897 
SetEnablePreviewText(const JSCallbackInfo& info)1898 void JSTextField::SetEnablePreviewText(const JSCallbackInfo& info)
1899 {
1900     auto jsValue = info[0];
1901     if (!jsValue->IsBoolean()) {
1902         TextFieldModel::GetInstance()->SetEnablePreviewText(true);
1903         return;
1904     }
1905     TextFieldModel::GetInstance()->SetEnablePreviewText(jsValue->ToBoolean());
1906 }
1907 
SetEnableHapticFeedback(const JSCallbackInfo& info)1908 void JSTextField::SetEnableHapticFeedback(const JSCallbackInfo& info)
1909 {
1910     bool state = true;
1911     if (info.Length() > 0 && info[0]->IsBoolean()) {
1912         state = info[0]->ToBoolean();
1913     }
1914     TextFieldModel::GetInstance()->SetEnableHapticFeedback(state);
1915 }
1916 
1917 } // namespace OHOS::Ace::Framework
1918