• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (c) 2022-2023 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 <vector>
21 
22 #include "base/geometry/dimension.h"
23 #include "base/log/ace_scoring_log.h"
24 #include "base/utils/utils.h"
25 #include "bridge/common/utils/utils.h"
26 #include "bridge/declarative_frontend/engine/functions/js_click_function.h"
27 #include "bridge/declarative_frontend/engine/functions/js_clipboard_function.h"
28 #include "bridge/declarative_frontend/engine/functions/js_function.h"
29 #include "bridge/declarative_frontend/jsview/js_container_base.h"
30 #include "bridge/declarative_frontend/jsview/js_interactable_view.h"
31 #include "bridge/declarative_frontend/jsview/js_textarea.h"
32 #include "bridge/declarative_frontend/jsview/js_text_editable_controller.h"
33 #include "bridge/declarative_frontend/jsview/js_textinput.h"
34 #include "bridge/declarative_frontend/jsview/js_view_abstract.h"
35 #include "bridge/declarative_frontend/jsview/js_view_common_def.h"
36 #include "bridge/declarative_frontend/jsview/models/text_field_model_impl.h"
37 #include "core/common/container.h"
38 #include "core/common/ime/text_input_action.h"
39 #include "core/common/ime/text_input_type.h"
40 #include "core/components/common/layout/constants.h"
41 #include "core/components/text_field/textfield_theme.h"
42 #include "core/components_ng/base/view_abstract.h"
43 #include "core/components_ng/pattern/text_field/text_field_model.h"
44 #include "core/components_ng/pattern/text_field/text_field_model_ng.h"
45 #include "core/pipeline/pipeline_base.h"
46 
47 namespace OHOS::Ace {
48 
49 std::unique_ptr<TextFieldModel> TextFieldModel::instance_ = nullptr;
50 std::mutex TextFieldModel::mutex_;
51 
GetInstance()52 TextFieldModel* TextFieldModel::GetInstance()
53 {
54     if (!instance_) {
55         std::lock_guard<std::mutex> lock(mutex_);
56         if (!instance_) {
57 #ifdef NG_BUILD
58             instance_.reset(new NG::TextFieldModelNG());
59 #else
60             if (Container::IsCurrentUseNewPipeline()) {
61                 instance_.reset(new NG::TextFieldModelNG());
62             } else {
63                 instance_.reset(new Framework::TextFieldModelImpl());
64             }
65 #endif
66         }
67     }
68     return instance_.get();
69 }
70 
71 } // namespace OHOS::Ace
72 
73 namespace OHOS::Ace::Framework {
74 
75 namespace {
76 
77 const std::vector<TextAlign> TEXT_ALIGNS = { TextAlign::START, TextAlign::CENTER, TextAlign::END, TextAlign::JUSTIFY };
78 const std::vector<FontStyle> FONT_STYLES = { FontStyle::NORMAL, FontStyle::ITALIC };
79 const std::vector<std::string> INPUT_FONT_FAMILY_VALUE = { "sans-serif" };
80 constexpr uint32_t MAX_LINES = 3;
81 constexpr uint32_t MINI_VAILD_VALUE = 1;
82 constexpr uint32_t MAX_VAILD_VALUE = 100;
83 constexpr uint32_t ILLEGAL_VALUE = 0;
84 constexpr uint32_t DEFAULT_MODE = -1;
85 } // namespace
86 
ParseTextFieldTextObject(const JSCallbackInfo & info,const JSRef<JSVal> & changeEventVal)87 void ParseTextFieldTextObject(const JSCallbackInfo& info, const JSRef<JSVal>& changeEventVal)
88 {
89     CHECK_NULL_VOID(changeEventVal->IsFunction());
90 
91     JsEventCallback<void(const std::string&)> onChangeEvent(
92         info.GetExecutionContext(), JSRef<JSFunc>::Cast(changeEventVal));
93     TextFieldModel::GetInstance()->SetOnChangeEvent(std::move(onChangeEvent));
94 }
95 
CreateTextInput(const JSCallbackInfo & info)96 void JSTextField::CreateTextInput(const JSCallbackInfo& info)
97 {
98     std::optional<std::string> placeholderSrc;
99     std::optional<std::string> value;
100     JSTextEditableController* jsController = nullptr;
101     JSRef<JSVal> changeEventVal = JSRef<JSVal>::Make();
102     if (info[0]->IsObject()) {
103         auto paramObject = JSRef<JSObject>::Cast(info[0]);
104         std::string placeholder;
105         if (ParseJsString(paramObject->GetProperty("placeholder"), placeholder)) {
106             placeholderSrc = placeholder;
107         }
108         std::string text;
109         JSRef<JSVal> textValue = paramObject->GetProperty("text");
110         if (textValue->IsObject()) {
111             JSRef<JSObject> valueObj = JSRef<JSObject>::Cast(textValue);
112             changeEventVal = valueObj->GetProperty("changeEvent");
113             if (changeEventVal->IsFunction()) {
114                 textValue = valueObj->GetProperty("value");
115             }
116             if (ParseJsString(textValue, text)) {
117                 value = text;
118             }
119         } else if (paramObject->HasProperty("text")) {
120             if (ParseJsString(textValue, text)) {
121                 value = text;
122             }
123             if (textValue->IsUndefined()) {
124                 value = "";
125             }
126         }
127         auto controllerObj = paramObject->GetProperty("controller");
128         if (!controllerObj->IsUndefined() && !controllerObj->IsNull()) {
129             jsController = JSRef<JSObject>::Cast(controllerObj)->Unwrap<JSTextEditableController>();
130         }
131     }
132 
133     auto controller = TextFieldModel::GetInstance()->CreateTextInput(placeholderSrc, value);
134     if (jsController) {
135         jsController->SetController(controller);
136     }
137     if (!changeEventVal->IsUndefined() && changeEventVal->IsFunction()) {
138         ParseTextFieldTextObject(info, changeEventVal);
139     }
140 
141     TextFieldModel::GetInstance()->SetFocusableAndFocusNode();
142 }
143 
CreateTextArea(const JSCallbackInfo & info)144 void JSTextField::CreateTextArea(const JSCallbackInfo& info)
145 {
146     std::optional<std::string> placeholderSrc;
147     std::optional<std::string> value;
148     JSTextEditableController* jsController = nullptr;
149     JSRef<JSVal> changeEventVal = JSRef<JSVal>::Make();
150     if (info[0]->IsObject()) {
151         auto paramObject = JSRef<JSObject>::Cast(info[0]);
152         std::string placeholder;
153         if (ParseJsString(paramObject->GetProperty("placeholder"), placeholder)) {
154             placeholderSrc = placeholder;
155         }
156         std::string text;
157         JSRef<JSVal> textValue = paramObject->GetProperty("text");
158         if (textValue->IsObject()) {
159             JSRef<JSObject> valueObj = JSRef<JSObject>::Cast(textValue);
160             changeEventVal = valueObj->GetProperty("changeEvent");
161             if (changeEventVal->IsFunction()) {
162                 textValue = valueObj->GetProperty("value");
163             }
164             if (ParseJsString(textValue, text)) {
165                 value = text;
166             }
167         } else if (paramObject->HasProperty("text")) {
168             if (ParseJsString(textValue, text)) {
169                 value = text;
170             }
171             if (textValue->IsUndefined()) {
172                 value = "";
173             }
174         }
175         auto controllerObj = paramObject->GetProperty("controller");
176         if (!controllerObj->IsUndefined() && !controllerObj->IsNull()) {
177             jsController = JSRef<JSObject>::Cast(controllerObj)->Unwrap<JSTextEditableController>();
178         }
179     }
180     auto controller = TextFieldModel::GetInstance()->CreateTextArea(placeholderSrc, value);
181     if (jsController) {
182         jsController->SetController(controller);
183     }
184     if (!changeEventVal->IsUndefined() && changeEventVal->IsFunction()) {
185         ParseTextFieldTextObject(info, changeEventVal);
186     }
187 
188     TextFieldModel::GetInstance()->SetFocusableAndFocusNode();
189 }
190 
SetType(const JSCallbackInfo & info)191 void JSTextField::SetType(const JSCallbackInfo& info)
192 {
193     if (info.Length() < 1) {
194         return;
195     }
196     if (info[0]->IsUndefined()) {
197         TextFieldModel::GetInstance()->SetType(TextInputType::UNSPECIFIED);
198         return;
199     }
200     if (!info[0]->IsNumber()) {
201         return;
202     }
203     TextInputType textInputType = static_cast<TextInputType>(info[0]->ToNumber<int32_t>());
204     TextFieldModel::GetInstance()->SetType(textInputType);
205 }
206 
SetPlaceholderColor(const JSCallbackInfo & info)207 void JSTextField::SetPlaceholderColor(const JSCallbackInfo& info)
208 {
209     if (info.Length() < 1) {
210         return;
211     }
212 
213     auto theme = GetTheme<TextFieldTheme>();
214     CHECK_NULL_VOID(theme);
215     Color color = theme->GetPlaceholderColor();
216     CheckColor(info[0], color, V2::TEXTINPUT_ETS_TAG, "PlaceholderColor");
217     TextFieldModel::GetInstance()->SetPlaceholderColor(color);
218 }
219 
SetPlaceholderFont(const JSCallbackInfo & info)220 void JSTextField::SetPlaceholderFont(const JSCallbackInfo& info)
221 {
222     if (info.Length() < 1 || !info[0]->IsObject()) {
223         return;
224     }
225     Font font;
226     auto paramObject = JSRef<JSObject>::Cast(info[0]);
227     auto fontSize = paramObject->GetProperty("size");
228     if (fontSize->IsNull() || fontSize->IsUndefined()) {
229         font.fontSize = Dimension(-1);
230     } else {
231         CalcDimension size;
232         auto theme = GetTheme<TextFieldTheme>();
233         CHECK_NULL_VOID(theme);
234         if (fontSize->IsString()) {
235             auto result = StringUtils::StringToDimensionWithThemeValue(
236                 fontSize->ToString(), true, Dimension(theme->GetFontSize()));
237             if (result.Unit() == DimensionUnit::PERCENT) {
238                 result = theme->GetFontSize();
239             }
240             font.fontSize = result;
241         } else if (ParseJsDimensionFp(fontSize, size) && size.Unit() != DimensionUnit::PERCENT) {
242             font.fontSize = size;
243         } else {
244             font.fontSize = Dimension(theme->GetFontSize());
245         }
246     }
247 
248     std::string weight;
249     auto fontWeight = paramObject->GetProperty("weight");
250     if (!fontWeight->IsNull()) {
251         if (fontWeight->IsNumber()) {
252             weight = std::to_string(fontWeight->ToNumber<int32_t>());
253         } else {
254             ParseJsString(fontWeight, weight);
255         }
256         font.fontWeight = ConvertStrToFontWeight(weight);
257     }
258 
259     auto fontFamily = paramObject->GetProperty("family");
260     if (!fontFamily->IsNull()) {
261         std::vector<std::string> fontFamilies;
262         if (ParseJsFontFamilies(fontFamily, fontFamilies)) {
263             font.fontFamilies = fontFamilies;
264         }
265     }
266 
267     auto style = paramObject->GetProperty("style");
268     if (!style->IsNull()) {
269         font.fontStyle = static_cast<FontStyle>(style->ToNumber<int32_t>());
270     }
271     TextFieldModel::GetInstance()->SetPlaceholderFont(font);
272 }
273 
SetEnterKeyType(const JSCallbackInfo & info)274 void JSTextField::SetEnterKeyType(const JSCallbackInfo& info)
275 {
276     if (info.Length() < 1) {
277         return;
278     }
279     if (info[0]->IsUndefined()) {
280         TextFieldModel::GetInstance()->SetEnterKeyType(TextInputAction::UNSPECIFIED);
281         return;
282     }
283     if (!info[0]->IsNumber()) {
284         return;
285     }
286     TextInputAction textInputAction = CastToTextInputAction(info[0]->ToNumber<int32_t>());
287     TextFieldModel::GetInstance()->SetEnterKeyType(textInputAction);
288 }
289 
SetTextAlign(int32_t value)290 void JSTextField::SetTextAlign(int32_t value)
291 {
292     if (value >= 0 && value < static_cast<int32_t>(TEXT_ALIGNS.size())) {
293         TextFieldModel::GetInstance()->SetTextAlign(TEXT_ALIGNS[value]);
294     }
295 }
296 
SetInputStyle(const JSCallbackInfo & info)297 void JSTextField::SetInputStyle(const JSCallbackInfo& info)
298 {
299     if (info.Length() < 1) {
300         return;
301     }
302     auto styleString = info[0]->ToString();
303     if (styleString == "Inline") {
304         TextFieldModel::GetInstance()->SetInputStyle(InputStyle::INLINE);
305     } else {
306         TextFieldModel::GetInstance()->SetInputStyle(InputStyle::DEFAULT);
307     }
308 }
309 
SetCaretColor(const JSCallbackInfo & info)310 void JSTextField::SetCaretColor(const JSCallbackInfo& info)
311 {
312     if (info.Length() < 1) {
313         return;
314     }
315 
316     Color color;
317     if (!ParseJsColor(info[0], color)) {
318         return;
319     }
320 
321     TextFieldModel::GetInstance()->SetCaretColor(color);
322 }
323 
SetCaretStyle(const JSCallbackInfo & info)324 void JSTextField::SetCaretStyle(const JSCallbackInfo& info)
325 {
326     if (info.Length() < 1 || !info[0]->IsObject()) {
327         return;
328     }
329     CaretStyle caretStyle;
330     auto paramObject = JSRef<JSObject>::Cast(info[0]);
331     auto caretWidth = paramObject->GetProperty("width");
332 
333     auto pipeline = PipelineBase::GetCurrentContext();
334     CHECK_NULL_VOID(pipeline);
335     auto theme = pipeline->GetThemeManager()->GetTheme<TextFieldTheme>();
336     CHECK_NULL_VOID(theme);
337     if (caretWidth->IsNull() || caretWidth->IsUndefined()) {
338         caretStyle.caretWidth = theme->GetCursorWidth();
339     } else {
340         CalcDimension width;
341         if (!ParseJsDimensionVpNG(caretWidth, width, false)) {
342             width = theme->GetCursorWidth();
343         }
344         if (LessNotEqual(width.Value(), 0.0)) {
345             width = theme->GetCursorWidth();
346         }
347         caretStyle.caretWidth = width;
348     }
349     TextFieldModel::GetInstance()->SetCaretStyle(caretStyle);
350 }
351 
SetCaretPosition(const JSCallbackInfo & info)352 void JSTextField::SetCaretPosition(const JSCallbackInfo& info)
353 {
354     if (info.Length() < 1) {
355         return;
356     }
357 
358     int32_t caretPosition = 0;
359     if (!ParseJsInt32(info[0], caretPosition)) {
360         return;
361     }
362     if (caretPosition < 0) {
363         return;
364     }
365     TextFieldModel::GetInstance()->SetCaretPosition(caretPosition);
366 }
367 
SetSelectedBackgroundColor(const JSCallbackInfo & info)368 void JSTextField::SetSelectedBackgroundColor(const JSCallbackInfo& info)
369 {
370     if (info.Length() < 1) {
371         return;
372     }
373 
374     Color selectedColor;
375     if (!ParseJsColor(info[0], selectedColor)) {
376         auto pipeline = PipelineBase::GetCurrentContext();
377         CHECK_NULL_VOID(pipeline);
378         auto theme = pipeline->GetThemeManager()->GetTheme<TextFieldTheme>();
379         CHECK_NULL_VOID(theme);
380         selectedColor = theme->GetSelectedColor();
381     }
382     // Alpha = 255 means opaque
383     if (selectedColor.GetAlpha() == 255) {
384         // Default setting of 20% opacity
385         selectedColor = selectedColor.ChangeOpacity(0.2);
386     }
387     TextFieldModel::GetInstance()->SetSelectedBackgroundColor(selectedColor);
388 }
389 
SetMaxLength(const JSCallbackInfo & info)390 void JSTextField::SetMaxLength(const JSCallbackInfo& info)
391 {
392     if (info.Length() < 1) {
393         return;
394     }
395     int32_t maxLength = 0;
396     if (info[0]->IsUndefined()) {
397         TextFieldModel::GetInstance()->ResetMaxLength();
398         return;
399     } else if (!info[0]->IsNumber()) {
400         TextFieldModel::GetInstance()->ResetMaxLength();
401         return;
402     }
403     maxLength = info[0]->ToNumber<int32_t>();
404     if (GreatOrEqual(maxLength, 0)) {
405         TextFieldModel::GetInstance()->SetMaxLength(maxLength);
406     } else {
407         TextFieldModel::GetInstance()->ResetMaxLength();
408     }
409 }
410 
SetFontSize(const JSCallbackInfo & info)411 void JSTextField::SetFontSize(const JSCallbackInfo& info)
412 {
413     if (info.Length() < 1) {
414         return;
415     }
416     CalcDimension fontSize;
417     if (!ParseJsDimensionNG(info[0], fontSize, DimensionUnit::FP, false)) {
418         auto theme = GetTheme<TextFieldTheme>();
419         CHECK_NULL_VOID(theme);
420         fontSize = theme->GetFontSize();
421     }
422     TextFieldModel::GetInstance()->SetFontSize(fontSize);
423 }
424 
SetFontWeight(const std::string & value)425 void JSTextField::SetFontWeight(const std::string& value)
426 {
427     TextFieldModel::GetInstance()->SetFontWeight(ConvertStrToFontWeight(value));
428 }
429 
SetTextColor(const JSCallbackInfo & info)430 void JSTextField::SetTextColor(const JSCallbackInfo& info)
431 {
432     if (info.Length() < 1) {
433         return;
434     }
435     Color textColor;
436     if (!ParseJsColor(info[0], textColor)) {
437         auto theme = GetTheme<TextFieldTheme>();
438         CHECK_NULL_VOID(theme);
439         textColor = theme->GetTextColor();
440     }
441     TextFieldModel::GetInstance()->SetTextColor(textColor);
442 }
443 
SetForegroundColor(const JSCallbackInfo & info)444 void JSTextField::SetForegroundColor(const JSCallbackInfo& info)
445 {
446     if (info.Length() < 1) {
447         return;
448     }
449     ForegroundColorStrategy strategy;
450     if (ParseJsColorStrategy(info[0], strategy)) {
451         ViewAbstractModel::GetInstance()->SetForegroundColorStrategy(strategy);
452         TextFieldModel::GetInstance()->SetForegroundColor(Color::FOREGROUND);
453         return;
454     }
455     Color foregroundColor;
456     if (!ParseJsColor(info[0], foregroundColor)) {
457         return;
458     }
459     ViewAbstractModel::GetInstance()->SetForegroundColor(foregroundColor);
460     TextFieldModel::GetInstance()->SetForegroundColor(foregroundColor);
461 }
462 
SetFontStyle(int32_t value)463 void JSTextField::SetFontStyle(int32_t value)
464 {
465     if (value >= 0 && value < static_cast<int32_t>(FONT_STYLES.size())) {
466         TextFieldModel::GetInstance()->SetFontStyle(FONT_STYLES[value]);
467     }
468 }
469 
SetFontFamily(const JSCallbackInfo & info)470 void JSTextField::SetFontFamily(const JSCallbackInfo& info)
471 {
472     if (info.Length() < 1) {
473         return;
474     }
475     std::vector<std::string> fontFamilies;
476     if (!ParseJsFontFamilies(info[0], fontFamilies)) {
477         return;
478     }
479     TextFieldModel::GetInstance()->SetFontFamily(fontFamilies);
480 }
481 
SetInputFilter(const JSCallbackInfo & info)482 void JSTextField::SetInputFilter(const JSCallbackInfo& info)
483 {
484     if (info.Length() < 1) {
485         return;
486     }
487     std::string inputFilter;
488     if (info[0]->IsUndefined()) {
489         TextFieldModel::GetInstance()->SetInputFilter(inputFilter, nullptr);
490         return;
491     }
492     if (!ParseJsString(info[0], inputFilter)) {
493         return;
494     }
495     if (!CheckRegexValid(inputFilter)) {
496         inputFilter = "";
497     }
498     if (info.Length() > 1 && info[1]->IsFunction()) {
499         auto jsFunc = AceType::MakeRefPtr<JsClipboardFunction>(JSRef<JSFunc>::Cast(info[1]));
500         WeakPtr<NG::FrameNode> targetNode = NG::ViewStackProcessor::GetInstance()->GetMainFrameNode();
501         auto resultId = [execCtx = info.GetExecutionContext(), func = std::move(jsFunc), node = targetNode](
502                             const std::string& info) {
503             JAVASCRIPT_EXECUTION_SCOPE_WITH_CHECK(execCtx);
504             PipelineContext::SetCallBackNode(node);
505             func->Execute(info);
506         };
507         TextFieldModel::GetInstance()->SetInputFilter(inputFilter, resultId);
508         return;
509     }
510     TextFieldModel::GetInstance()->SetInputFilter(inputFilter, nullptr);
511 }
512 
SetShowPasswordIcon(const JSCallbackInfo & info)513 void JSTextField::SetShowPasswordIcon(const JSCallbackInfo& info)
514 {
515     if (!info[0]->IsBoolean()) {
516         TextFieldModel::GetInstance()->SetShowPasswordIcon(true);
517         return;
518     }
519 
520     bool isShowPasswordIcon = info[0]->ToBoolean();
521     TextFieldModel::GetInstance()->SetShowPasswordIcon(isShowPasswordIcon);
522 }
523 
SetBackgroundColor(const JSCallbackInfo & info)524 void JSTextField::SetBackgroundColor(const JSCallbackInfo& info)
525 {
526     if (info.Length() < 1) {
527         return;
528     }
529     Color backgroundColor;
530     bool tmp = !ParseJsColor(info[0], backgroundColor);
531     TextFieldModel::GetInstance()->SetBackgroundColor(backgroundColor, tmp);
532 }
533 
JsHeight(const JSCallbackInfo & info)534 void JSTextField::JsHeight(const JSCallbackInfo& info)
535 {
536     JSViewAbstract::JsHeight(info);
537     if (info.Length() < 1) {
538         return;
539     }
540     CalcDimension value;
541     if (!ParseJsDimensionVp(info[0], value)) {
542         return;
543     }
544     if (LessNotEqual(value.Value(), 0.0)) {
545         ViewAbstractModel::GetInstance()->ClearWidthOrHeight(false);
546         return;
547     }
548     TextFieldModel::GetInstance()->SetHeight(value);
549 }
550 
JsWidth(const JSCallbackInfo & info)551 void JSTextField::JsWidth(const JSCallbackInfo& info)
552 {
553     if (info.Length() < 1) {
554         return;
555     }
556     if (info[0]->IsString() && info[0]->ToString().empty()) {
557         return;
558     }
559     if (info[0]->IsString() && info[0]->ToString() == "auto") {
560         ViewAbstractModel::GetInstance()->ClearWidthOrHeight(true);
561         TextFieldModel::GetInstance()->SetWidthAuto(true);
562         return;
563     }
564 
565     TextFieldModel::GetInstance()->SetWidthAuto(false);
566     CalcDimension value;
567     if (!ParseJsDimensionVp(info[0], value)) {
568         return;
569     }
570     if (LessNotEqual(value.Value(), 0.0)) {
571         return;
572     }
573     ViewAbstractModel::GetInstance()->SetWidth(value);
574 }
575 
CheckIsIllegalString(const std::string & value)576 bool CheckIsIllegalString(const std::string& value)
577 {
578     if (value.empty()) {
579         return true;
580     }
581     errno = 0;
582     char* pEnd = nullptr;
583     std::strtod(value.c_str(), &pEnd);
584     return (pEnd == value.c_str() || errno == ERANGE);
585 }
586 
JsPadding(const JSCallbackInfo & info)587 void JSTextField::JsPadding(const JSCallbackInfo& info)
588 {
589     if (info[0]->IsUndefined() || (info[0]->IsString() && CheckIsIllegalString(info[0]->ToString()))) {
590         return;
591     };
592     CalcDimension length;
593     ParseJsDimensionVp(info[0], length);
594     if (length.IsNegative()) {
595         return;
596     }
597     bool tmp = !info[0]->IsString() && !info[0]->IsNumber() && !info[0]->IsObject();
598 
599     NG::PaddingProperty newPadding = GetNewPadding(info);
600     Edge oldPadding = Edge(GetOldPadding(info));
601     TextFieldModel::GetInstance()->SetPadding(newPadding, oldPadding, tmp);
602 }
603 
GetOldPadding(const JSCallbackInfo & info)604 Edge JSTextField::GetOldPadding(const JSCallbackInfo& info)
605 {
606     Edge padding;
607     if (info[0]->IsNumber() || info[0]->IsString()) {
608         CalcDimension edgeValue;
609         if (ParseJsDimensionVp(info[0], edgeValue)) {
610             padding = Edge(edgeValue);
611         }
612     }
613     if (info[0]->IsObject()) {
614         JSRef<JSObject> object = JSRef<JSObject>::Cast(info[0]);
615         CalcDimension left = CalcDimension(0.0, DimensionUnit::VP);
616         CalcDimension top = CalcDimension(0.0, DimensionUnit::VP);
617         CalcDimension right = CalcDimension(0.0, DimensionUnit::VP);
618         CalcDimension bottom = CalcDimension(0.0, DimensionUnit::VP);
619         ParseJsDimensionVp(object->GetProperty("left"), left);
620         ParseJsDimensionVp(object->GetProperty("top"), top);
621         ParseJsDimensionVp(object->GetProperty("right"), right);
622         ParseJsDimensionVp(object->GetProperty("bottom"), bottom);
623         padding = Edge(left, top, right, bottom);
624     }
625     return padding;
626 }
627 
GetNewPadding(const JSCallbackInfo & info)628 NG::PaddingProperty JSTextField::GetNewPadding(const JSCallbackInfo& info)
629 {
630     NG::PaddingProperty padding;
631     if (info[0]->IsObject()) {
632         std::optional<CalcDimension> left;
633         std::optional<CalcDimension> right;
634         std::optional<CalcDimension> top;
635         std::optional<CalcDimension> bottom;
636         JSRef<JSObject> paddingObj = JSRef<JSObject>::Cast(info[0]);
637 
638         CalcDimension leftDimen;
639         if (ParseJsDimensionVp(paddingObj->GetProperty("left"), leftDimen)) {
640             left = leftDimen;
641         }
642         CalcDimension rightDimen;
643         if (ParseJsDimensionVp(paddingObj->GetProperty("right"), rightDimen)) {
644             right = rightDimen;
645         }
646         CalcDimension topDimen;
647         if (ParseJsDimensionVp(paddingObj->GetProperty("top"), topDimen)) {
648             top = topDimen;
649         }
650         CalcDimension bottomDimen;
651         if (ParseJsDimensionVp(paddingObj->GetProperty("bottom"), bottomDimen)) {
652             bottom = bottomDimen;
653         }
654         if (left.has_value() || right.has_value() || top.has_value() || bottom.has_value()) {
655             padding = SetPaddings(top, bottom, left, right);
656             return padding;
657         }
658     }
659 
660     CalcDimension length;
661     if (!ParseJsDimensionVp(info[0], length)) {
662         // use default value.
663         length.Reset();
664     }
665     padding.SetEdges(NG::CalcLength(length.IsNonNegative() ? length : CalcDimension()));
666     return padding;
667 }
668 
SetPaddings(const std::optional<CalcDimension> & top,const std::optional<CalcDimension> & bottom,const std::optional<CalcDimension> & left,const std::optional<CalcDimension> & right)669 NG::PaddingProperty JSTextField::SetPaddings(const std::optional<CalcDimension>& top,
670     const std::optional<CalcDimension>& bottom, const std::optional<CalcDimension>& left,
671     const std::optional<CalcDimension>& right)
672 {
673     NG::PaddingProperty paddings;
674     if (top.has_value()) {
675         if (top.value().Unit() == DimensionUnit::CALC) {
676             paddings.top =
677                 NG::CalcLength(top.value().IsNonNegative() ? top.value().CalcValue() : CalcDimension().CalcValue());
678         } else {
679             paddings.top = NG::CalcLength(top.value().IsNonNegative() ? top.value() : CalcDimension());
680         }
681     }
682     if (bottom.has_value()) {
683         if (bottom.value().Unit() == DimensionUnit::CALC) {
684             paddings.bottom = NG::CalcLength(
685                 bottom.value().IsNonNegative() ? bottom.value().CalcValue() : CalcDimension().CalcValue());
686         } else {
687             paddings.bottom = NG::CalcLength(bottom.value().IsNonNegative() ? bottom.value() : CalcDimension());
688         }
689     }
690     if (left.has_value()) {
691         if (left.value().Unit() == DimensionUnit::CALC) {
692             paddings.left =
693                 NG::CalcLength(left.value().IsNonNegative() ? left.value().CalcValue() : CalcDimension().CalcValue());
694         } else {
695             paddings.left = NG::CalcLength(left.value().IsNonNegative() ? left.value() : CalcDimension());
696         }
697     }
698     if (right.has_value()) {
699         if (right.value().Unit() == DimensionUnit::CALC) {
700             paddings.right =
701                 NG::CalcLength(right.value().IsNonNegative() ? right.value().CalcValue() : CalcDimension().CalcValue());
702         } else {
703             paddings.right = NG::CalcLength(right.value().IsNonNegative() ? right.value() : CalcDimension());
704         }
705     }
706 
707     return paddings;
708 }
709 
JsBorder(const JSCallbackInfo & info)710 void JSTextField::JsBorder(const JSCallbackInfo& info)
711 {
712     if (!info[0]->IsObject()) {
713         return;
714     }
715     JSRef<JSObject> object = JSRef<JSObject>::Cast(info[0]);
716     auto valueWidth = object->GetProperty("width");
717     if (!valueWidth->IsUndefined()) {
718         ParseBorderWidth(valueWidth);
719     }
720     auto valueColor = object->GetProperty("color");
721     if (!valueColor->IsUndefined()) {
722         ParseBorderColor(valueColor);
723     }
724     auto valueRadius = object->GetProperty("radius");
725     if (!valueRadius->IsUndefined()) {
726         ParseBorderRadius(valueRadius);
727     }
728     auto valueStyle = object->GetProperty("style");
729     if (!valueStyle->IsUndefined()) {
730         ParseBorderStyle(valueStyle);
731     }
732     JSViewAbstract::JsBorder(info);
733     TextFieldModel::GetInstance()->SetBackBorder();
734     info.ReturnSelf();
735 }
736 
JsBorderWidth(const JSCallbackInfo & info)737 void JSTextField::JsBorderWidth(const JSCallbackInfo& info)
738 {
739     if (!info[0]->IsObject() && !info[0]->IsString() && !info[0]->IsNumber()) {
740         return;
741     }
742     JSViewAbstract::JsBorderWidth(info);
743     TextFieldModel::GetInstance()->SetBackBorder();
744 }
745 
JsBorderColor(const JSCallbackInfo & info)746 void JSTextField::JsBorderColor(const JSCallbackInfo& info)
747 {
748     if (!info[0]->IsObject() && !info[0]->IsString() && !info[0]->IsNumber()) {
749         return;
750     }
751     JSViewAbstract::JsBorderColor(info);
752     TextFieldModel::GetInstance()->SetBackBorder();
753 }
754 
JsBorderStyle(const JSCallbackInfo & info)755 void JSTextField::JsBorderStyle(const JSCallbackInfo& info)
756 {
757     if (!info[0]->IsObject() && !info[0]->IsNumber()) {
758         return;
759     }
760     JSViewAbstract::JsBorderStyle(info);
761     TextFieldModel::GetInstance()->SetBackBorder();
762 }
763 
JsBorderRadius(const JSCallbackInfo & info)764 void JSTextField::JsBorderRadius(const JSCallbackInfo& info)
765 {
766     if (!info[0]->IsObject() && !info[0]->IsString() && !info[0]->IsNumber()) {
767         return;
768     }
769     JSViewAbstract::JsBorderRadius(info);
770     TextFieldModel::GetInstance()->SetBackBorder();
771 }
772 
JsHoverEffect(const JSCallbackInfo & info)773 void JSTextField::JsHoverEffect(const JSCallbackInfo& info)
774 {
775     if (!info[0]->IsNumber()) {
776         return;
777     }
778     TextFieldModel::GetInstance()->SetHoverEffect(static_cast<HoverEffectType>(info[0]->ToNumber<int32_t>()));
779 }
780 
SetOnEditChanged(const JSCallbackInfo & info)781 void JSTextField::SetOnEditChanged(const JSCallbackInfo& info)
782 {
783     CHECK_NULL_VOID(info[0]->IsFunction());
784     JsEventCallback<void(bool)> callback(info.GetExecutionContext(), JSRef<JSFunc>::Cast(info[0]));
785     TextFieldModel::GetInstance()->SetOnEditChanged(std::move(callback));
786 }
787 
JsKeepEditableState(panda::JsiRuntimeCallInfo * info)788 Local<JSValueRef> JSTextField::JsKeepEditableState(panda::JsiRuntimeCallInfo *info)
789 {
790     Local<JSValueRef> thisObj = info->GetThisRef();
791     auto eventInfo = static_cast<NG::TextFieldCommonEvent*>(
792         panda::Local<panda::ObjectRef>(thisObj)->GetNativePointerField(0));
793     if (eventInfo) {
794         eventInfo->SetKeepEditable(true);
795     }
796     return JSValueRef::Undefined(info->GetVM());
797 }
798 
CreateJsTextFieldCommonEvent(const JSCallbackInfo & info)799 void JSTextField::CreateJsTextFieldCommonEvent(const JSCallbackInfo &info)
800 {
801     auto jsTextFunc = AceType::MakeRefPtr<JsCommonEventFunction<NG::TextFieldCommonEvent, 2>>(
802         JSRef<JSFunc>::Cast(info[0]));
803     WeakPtr<NG::FrameNode> targetNode = NG::ViewStackProcessor::GetInstance()->GetMainFrameNode();
804     auto callback = [execCtx = info.GetExecutionContext(), func = std::move(jsTextFunc), node = targetNode](int32_t key,
805                        NG::TextFieldCommonEvent& event) {
806         JAVASCRIPT_EXECUTION_SCOPE_WITH_CHECK(execCtx);
807         ACE_SCORING_EVENT("onSubmit");
808         PipelineContext::SetCallBackNode(node);
809         JSRef<JSObjTemplate> objectTemplate = JSRef<JSObjTemplate>::New();
810         objectTemplate->SetInternalFieldCount(2);
811         JSRef<JSObject> object = objectTemplate->NewInstance();
812         object->SetProperty<std::string>("text", event.GetText());
813         object->SetPropertyObject("keepEditableState", JSRef<JSFunc>::New<FunctionCallback>(JsKeepEditableState));
814         object->Wrap<NG::TextFieldCommonEvent>(&event);
815         JSRef<JSVal> keyEvent = JSRef<JSVal>::Make(ToJSValue(key));
816         JSRef<JSVal> dataObject = JSRef<JSVal>::Cast(object);
817         JSRef<JSVal> param[2] = {keyEvent, dataObject};
818         func->Execute(param);
819     };
820     TextFieldModel::GetInstance()->SetOnSubmit(std::move(callback));
821 }
822 
SetOnSubmit(const JSCallbackInfo & info)823 void JSTextField::SetOnSubmit(const JSCallbackInfo& info)
824 {
825     CHECK_NULL_VOID(info[0]->IsFunction());
826 #ifdef NG_BUILD
827     CreateJsTextFieldCommonEvent(info);
828 #else
829     if (Container::IsCurrentUseNewPipeline()) {
830         CreateJsTextFieldCommonEvent(info);
831     } else {
832         JsEventCallback<void(int32_t)> callback(info.GetExecutionContext(), JSRef<JSFunc>::Cast(info[0]));
833         TextFieldModel::GetInstance()->SetOnSubmit(std::move(callback));
834     }
835 #endif
836 }
837 
SetOnChange(const JSCallbackInfo & info)838 void JSTextField::SetOnChange(const JSCallbackInfo& info)
839 {
840     CHECK_NULL_VOID(info[0]->IsFunction());
841     JsEventCallback<void(const std::string&)> callback(info.GetExecutionContext(), JSRef<JSFunc>::Cast(info[0]));
842     TextFieldModel::GetInstance()->SetOnChange(std::move(callback));
843 }
844 
SetOnTextSelectionChange(const JSCallbackInfo & info)845 void JSTextField::SetOnTextSelectionChange(const JSCallbackInfo& info)
846 {
847     CHECK_NULL_VOID(info[0]->IsFunction());
848     JsEventCallback<void(int32_t, int32_t)> callback(info.GetExecutionContext(), JSRef<JSFunc>::Cast(info[0]));
849     TextFieldModel::GetInstance()->SetOnTextSelectionChange(std::move(callback));
850 }
851 
SetOnContentScroll(const JSCallbackInfo & info)852 void JSTextField::SetOnContentScroll(const JSCallbackInfo& info)
853 {
854     CHECK_NULL_VOID(info[0]->IsFunction());
855     JsEventCallback<void(float, float)> callback(info.GetExecutionContext(), JSRef<JSFunc>::Cast(info[0]));
856     TextFieldModel::GetInstance()->SetOnContentScroll(std::move(callback));
857 }
858 
SetOnCopy(const JSCallbackInfo & info)859 void JSTextField::SetOnCopy(const JSCallbackInfo& info)
860 {
861     CHECK_NULL_VOID(info[0]->IsFunction());
862     JsEventCallback<void(const std::string&)> callback(info.GetExecutionContext(), JSRef<JSFunc>::Cast(info[0]));
863     TextFieldModel::GetInstance()->SetOnCopy(std::move(callback));
864 }
865 
SetOnCut(const JSCallbackInfo & info)866 void JSTextField::SetOnCut(const JSCallbackInfo& info)
867 {
868     CHECK_NULL_VOID(info[0]->IsFunction());
869     JsEventCallback<void(const std::string&)> callback(info.GetExecutionContext(), JSRef<JSFunc>::Cast(info[0]));
870     TextFieldModel::GetInstance()->SetOnCut(std::move(callback));
871 }
872 
CreateJSTextCommonEvent(NG::TextCommonEvent & event)873 JSRef<JSVal> JSTextField::CreateJSTextCommonEvent(NG::TextCommonEvent& event)
874 {
875     JSRef<JSObjTemplate> objectTemplate = JSRef<JSObjTemplate>::New();
876     objectTemplate->SetInternalFieldCount(1);
877     JSRef<JSObject> object = objectTemplate->NewInstance();
878     object->SetPropertyObject("preventDefault", JSRef<JSFunc>::New<FunctionCallback>(JsPreventDefault));
879     object->Wrap<NG::TextCommonEvent>(&event);
880     return JSRef<JSVal>::Cast(object);
881 }
882 
SetOnPaste(const JSCallbackInfo & info)883 void JSTextField::SetOnPaste(const JSCallbackInfo& info)
884 {
885     CHECK_NULL_VOID(info[0]->IsFunction());
886     auto jsTextFunc = AceType::MakeRefPtr<JsCitedEventFunction<NG::TextCommonEvent, 2>>(
887         JSRef<JSFunc>::Cast(info[0]), CreateJSTextCommonEvent);
888 
889     auto onPaste = [execCtx = info.GetExecutionContext(), func = std::move(jsTextFunc)](
890         const std::string& val, NG::TextCommonEvent& info) {
891         JAVASCRIPT_EXECUTION_SCOPE_WITH_CHECK(execCtx);
892         ACE_SCORING_EVENT("onPaste");
893         func->Execute(val, info);
894     };
895     TextFieldModel::GetInstance()->SetOnPasteWithEvent(std::move(onPaste));
896 }
897 
SetOnClick(const JSCallbackInfo & info)898 void JSTextField::SetOnClick(const JSCallbackInfo& info)
899 {
900     if (Container::IsCurrentUseNewPipeline()) {
901         JSInteractableView::JsOnClick(info);
902         return;
903     }
904     JsEventCallback<void(const ClickInfo&)> callback(info.GetExecutionContext(), JSRef<JSFunc>::Cast(info[0]));
905     TextFieldModel::GetInstance()->SetOnClick(std::move(callback));
906     info.ReturnSelf();
907 }
908 
SetCopyOption(const JSCallbackInfo & info)909 void JSTextField::SetCopyOption(const JSCallbackInfo& info)
910 {
911     if (info.Length() == 0) {
912         return;
913     }
914     if (info[0]->IsUndefined()) {
915         TextFieldModel::GetInstance()->SetCopyOption(CopyOptions::Local);
916         return;
917     }
918     auto copyOptions = CopyOptions::None;
919     if (info[0]->IsNumber()) {
920         auto emunNumber = info[0]->ToNumber<int>();
921         copyOptions = static_cast<CopyOptions>(emunNumber);
922     }
923     TextFieldModel::GetInstance()->SetCopyOption(copyOptions);
924 }
925 
JsMenuOptionsExtension(const JSCallbackInfo & info)926 void JSTextField::JsMenuOptionsExtension(const JSCallbackInfo& info)
927 {
928     if (info[0]->IsArray()) {
929         std::vector<NG::MenuOptionsParam> menuOptionsItems;
930         JSViewAbstract::ParseMenuOptions(info, JSRef<JSArray>::Cast(info[0]), menuOptionsItems);
931         TextFieldModel::GetInstance()->SetMenuOptionItems(std::move(menuOptionsItems));
932     }
933 }
934 
SetShowUnderline(const JSCallbackInfo & info)935 void JSTextField::SetShowUnderline(const JSCallbackInfo& info)
936 {
937     if (!info[0]->IsBoolean()) {
938         TextFieldModel::GetInstance()->SetShowUnderline(false);
939         return;
940     }
941     TextFieldModel::GetInstance()->SetShowUnderline(info[0]->ToBoolean());
942 }
943 
SetPasswordIcon(const JSCallbackInfo & info)944 void JSTextField::SetPasswordIcon(const JSCallbackInfo& info)
945 {
946     if (!Container::IsCurrentUseNewPipeline()) {
947         return;
948     }
949     if (!info[0]->IsObject()) {
950         return;
951     }
952     JSRef<JSObject> jsObj = JSRef<JSObject>::Cast(info[0]);
953     JSRef<JSVal> showVal = jsObj->GetProperty("onIconSrc");
954     JSRef<JSVal> hideVal = jsObj->GetProperty("offIconSrc");
955     PasswordIcon passwordIcon;
956     if (showVal->IsString()) {
957         passwordIcon.showResult = showVal->ToString();
958     }
959     if (hideVal->IsString()) {
960         passwordIcon.hideResult = hideVal->ToString();
961     }
962     if (showVal->IsObject()) {
963         JSRef<JSVal> bundleName = JSRef<JSObject>::Cast(showVal)->GetProperty("bundleName");
964         JSRef<JSVal> moduleName = JSRef<JSObject>::Cast(showVal)->GetProperty("moduleName");
965         if (bundleName->IsString()) {
966             passwordIcon.showBundleName = bundleName->ToString();
967         }
968         if (moduleName->IsString()) {
969             passwordIcon.showModuleName = moduleName->ToString();
970         }
971         ParseJsMedia(JSRef<JSObject>::Cast(showVal), passwordIcon.showResult);
972     }
973     if (hideVal->IsObject()) {
974         JSRef<JSVal> bundleName = JSRef<JSObject>::Cast(hideVal)->GetProperty("bundleName");
975         JSRef<JSVal> moduleName = JSRef<JSObject>::Cast(hideVal)->GetProperty("moduleName");
976         if (bundleName->IsString()) {
977             passwordIcon.hideBundleName = bundleName->ToString();
978         }
979         if (moduleName->IsString()) {
980             passwordIcon.hideModuleName = moduleName->ToString();
981         }
982         ParseJsMedia(JSRef<JSObject>::Cast(hideVal), passwordIcon.hideResult);
983     }
984     if (!showVal->IsString() && !showVal->IsObject()) {
985         passwordIcon.showResult = "";
986     }
987     if (!hideVal->IsString() && !hideVal->IsObject()) {
988         passwordIcon.hideResult = "";
989     }
990     TextFieldModel::GetInstance()->SetPasswordIcon(passwordIcon);
991 }
992 
UpdateDecoration(const RefPtr<BoxComponent> & boxComponent,const RefPtr<TextFieldComponent> & component,const Border & boxBorder,const OHOS::Ace::RefPtr<OHOS::Ace::TextFieldTheme> & textFieldTheme)993 void JSTextField::UpdateDecoration(const RefPtr<BoxComponent>& boxComponent,
994     const RefPtr<TextFieldComponent>& component, const Border& boxBorder,
995     const OHOS::Ace::RefPtr<OHOS::Ace::TextFieldTheme>& textFieldTheme)
996 {
997     if (!textFieldTheme) {
998         return;
999     }
1000 
1001     RefPtr<Decoration> decoration = component->GetDecoration();
1002     RefPtr<Decoration> boxDecoration = boxComponent->GetBackDecoration();
1003     if (!decoration) {
1004         decoration = AceType::MakeRefPtr<Decoration>();
1005     }
1006     if (boxDecoration) {
1007         Border border = decoration->GetBorder();
1008         border.SetLeftEdge(boxBorder.Left());
1009         border.SetRightEdge(boxBorder.Right());
1010         border.SetTopEdge(boxBorder.Top());
1011         border.SetBottomEdge(boxBorder.Bottom());
1012         border.SetBorderRadius(textFieldTheme->GetBorderRadius());
1013         decoration->SetBorder(border);
1014         component->SetOriginBorder(decoration->GetBorder());
1015 
1016         if (boxDecoration->GetImage() || boxDecoration->GetGradient().IsValid()) {
1017             // clear box properties except background image and radius.
1018             boxDecoration->SetBackgroundColor(Color::TRANSPARENT);
1019             Border border;
1020             border.SetBorderRadius(textFieldTheme->GetBorderRadius());
1021             boxDecoration->SetBorder(border);
1022         }
1023     } else {
1024         boxDecoration = AceType::MakeRefPtr<Decoration>();
1025         boxDecoration->SetBorderRadius(textFieldTheme->GetBorderRadius());
1026         boxComponent->SetBackDecoration(boxDecoration);
1027     }
1028 }
1029 
SetShowUnit(const JSCallbackInfo & info)1030 void JSTextField::SetShowUnit(const JSCallbackInfo& info)
1031 {
1032     if (!info[0]->IsFunction()) {
1033         return;
1034     }
1035 
1036     auto builderFunc = AceType::MakeRefPtr<JsFunction>(JSRef<JSFunc>::Cast(info[0]));
1037     auto unitFunc = [builderFunc]() { builderFunc->Execute(); };
1038     TextFieldModel::GetInstance()->SetShowUnit(std::move(unitFunc));
1039 }
1040 
SetShowError(const JSCallbackInfo & info)1041 void JSTextField::SetShowError(const JSCallbackInfo& info)
1042 {
1043     if (Container::IsCurrentUseNewPipeline()) {
1044         if (!info[0]->IsUndefined() && !info[0]->IsString()) {
1045             TextFieldModel::GetInstance()->SetShowError("", false);
1046             return;
1047         }
1048         TextFieldModel::GetInstance()->SetShowError(
1049             info[0]->IsString() ? info[0]->ToString() : "", info[0]->IsUndefined() ? false : true);
1050     }
1051 }
1052 
SetShowCounter(const JSCallbackInfo & info)1053 void JSTextField::SetShowCounter(const JSCallbackInfo& info)
1054 {
1055     if ((!info[0]->IsBoolean() && !info[1]->IsObject())) {
1056         TextFieldModel::GetInstance()->SetShowCounter(false);
1057         return;
1058     }
1059     if (info[1]->IsObject()) {
1060         auto paramObject = JSRef<JSObject>::Cast(info[1]);
1061         auto param = paramObject->GetProperty("highlightBorder");
1062         auto isBorderShow = param->ToBoolean();
1063         if (!param->IsBoolean() || param->IsUndefined() || param->IsNull()) {
1064             TextFieldModel::GetInstance()->SetShowCounterBorder(true);
1065         } else {
1066             TextFieldModel::GetInstance()->SetShowCounterBorder(isBorderShow);
1067         }
1068         auto parameter = paramObject->GetProperty("thresholdPercentage");
1069         auto inputNumber = parameter->ToNumber<int32_t>();
1070         TextFieldModel::GetInstance()->SetCounterType(inputNumber);
1071         if (parameter->IsNull() || parameter->IsUndefined()) {
1072             TextFieldModel::GetInstance()->SetShowCounter(info[0]->ToBoolean());
1073             TextFieldModel::GetInstance()->SetCounterType(DEFAULT_MODE);
1074             return;
1075         }
1076         if (static_cast<uint32_t>(inputNumber) < MINI_VAILD_VALUE ||
1077             static_cast<uint32_t>(inputNumber) > MAX_VAILD_VALUE) {
1078             LOGI("The info is wrong, it is supposed to be a right number");
1079             TextFieldModel::GetInstance()->SetCounterType(ILLEGAL_VALUE);
1080             TextFieldModel::GetInstance()->SetShowCounter(false);
1081             return;
1082         }
1083         TextFieldModel::GetInstance()->SetShowCounter(info[0]->ToBoolean());
1084         return;
1085     }
1086     TextFieldModel::GetInstance()->SetShowCounter(info[0]->ToBoolean());
1087     TextFieldModel::GetInstance()->SetCounterType(DEFAULT_MODE);
1088     TextFieldModel::GetInstance()->SetShowCounterBorder(true);
1089 }
1090 
SetBarState(const JSCallbackInfo & info)1091 void JSTextField::SetBarState(const JSCallbackInfo& info)
1092 {
1093     if (info.Length() < 1 || !info[0]->IsNumber()) {
1094         TextFieldModel::GetInstance()->SetBarState(DisplayMode::AUTO);
1095         return;
1096     }
1097     DisplayMode displayMode = static_cast<DisplayMode>(info[0]->ToNumber<int32_t>());
1098     TextFieldModel::GetInstance()->SetBarState(displayMode);
1099 }
1100 
SetMaxLines(const JSCallbackInfo & info)1101 void JSTextField::SetMaxLines(const JSCallbackInfo& info)
1102 {
1103     if (info.Length() < 1 || !info[0]->IsNumber()) {
1104         TextFieldModel::GetInstance()->SetMaxViewLines(MAX_LINES);
1105         return;
1106     }
1107     if (info[0]->ToNumber<int32_t>() <= 0) {
1108         TextFieldModel::GetInstance()->SetMaxViewLines(MAX_LINES);
1109         return;
1110     }
1111     TextFieldModel::GetInstance()->SetMaxViewLines(info[0]->ToNumber<uint32_t>());
1112 }
1113 
SetEnableKeyboardOnFocus(const JSCallbackInfo & info)1114 void JSTextField::SetEnableKeyboardOnFocus(const JSCallbackInfo& info)
1115 {
1116     if (info.Length() < 1) {
1117         return;
1118     }
1119     if (info[0]->IsUndefined() || !info[0]->IsBoolean()) {
1120         TextFieldModel::GetInstance()->RequestKeyboardOnFocus(true);
1121         return;
1122     }
1123     TextFieldModel::GetInstance()->RequestKeyboardOnFocus(info[0]->ToBoolean());
1124 }
1125 
SetSelectionMenuHidden(const JSCallbackInfo & info)1126 void JSTextField::SetSelectionMenuHidden(const JSCallbackInfo& info)
1127 {
1128     if (info.Length() < 1) {
1129         return;
1130     }
1131     if (info[0]->IsUndefined() || !info[0]->IsBoolean()) {
1132         TextFieldModel::GetInstance()->SetSelectionMenuHidden(false);
1133         return;
1134     }
1135     TextFieldModel::GetInstance()->SetSelectionMenuHidden(info[0]->ToBoolean());
1136 }
1137 
ParseJsCustomKeyboardBuilder(const JSCallbackInfo & info,int32_t index,std::function<void ()> & buildFunc)1138 bool JSTextField::ParseJsCustomKeyboardBuilder(
1139     const JSCallbackInfo& info, int32_t index, std::function<void()>& buildFunc)
1140 {
1141     if (info.Length() <= index) {
1142         return false;
1143     }
1144     JSRef<JSObject> obj = JSRef<JSObject>::Cast(info[index]);
1145     auto builder = obj->GetProperty("builder");
1146     if (!builder->IsFunction()) {
1147         return false;
1148     }
1149     auto builderFunc = AceType::MakeRefPtr<JsFunction>(JSRef<JSFunc>::Cast(builder));
1150     CHECK_NULL_RETURN(builderFunc, false);
1151     WeakPtr<NG::FrameNode> targetNode = NG::ViewStackProcessor::GetInstance()->GetMainFrameNode();
1152     buildFunc = [execCtx = info.GetExecutionContext(), func = std::move(builderFunc), node = targetNode]() {
1153         JAVASCRIPT_EXECUTION_SCOPE_WITH_CHECK(execCtx);
1154         ACE_SCORING_EVENT("CustomKeyboard");
1155         PipelineContext::SetCallBackNode(node);
1156         func->Execute();
1157     };
1158     return true;
1159 }
1160 
SetCustomKeyboard(const JSCallbackInfo & info)1161 void JSTextField::SetCustomKeyboard(const JSCallbackInfo& info)
1162 {
1163     if (info.Length() > 0 && (info[0]->IsUndefined() || info[0]->IsNull())) {
1164         TextFieldModel::GetInstance()->SetCustomKeyboard(nullptr);
1165         return;
1166     }
1167     if (info.Length() < 1 || !info[0]->IsObject()) {
1168         return;
1169     }
1170     std::function<void()> buildFunc;
1171     if (ParseJsCustomKeyboardBuilder(info, 0, buildFunc)) {
1172         TextFieldModel::GetInstance()->SetCustomKeyboard(std::move(buildFunc));
1173     }
1174 }
1175 
SetPasswordRules(const JSCallbackInfo & info)1176 void JSTextField::SetPasswordRules(const JSCallbackInfo& info)
1177 {
1178     if (!info[0]->IsString()) {
1179         return;
1180     }
1181     auto passwordRules = info[0]->ToString();
1182     TextFieldModel::GetInstance()->SetPasswordRules(passwordRules);
1183 }
1184 
SetEnableAutoFill(const JSCallbackInfo & info)1185 void JSTextField::SetEnableAutoFill(const JSCallbackInfo& info)
1186 {
1187     if (!info[0]->IsBoolean()) {
1188         TextFieldModel::GetInstance()->SetEnableAutoFill(true);
1189         return;
1190     }
1191     TextFieldModel::GetInstance()->SetEnableAutoFill(info[0]->ToBoolean());
1192 }
1193 
ConvertStrToCleanNodeStyle(const std::string & value)1194 static CleanNodeStyle ConvertStrToCleanNodeStyle(const std::string& value)
1195 {
1196     if (value == "CONSTANT") {
1197         return CleanNodeStyle::CONSTANT;
1198     } else if (value == "INVISIBLE") {
1199         return CleanNodeStyle::INVISIBLE;
1200     } else {
1201         return CleanNodeStyle::INPUT;
1202     }
1203 }
1204 
SetCancelButton(const JSCallbackInfo & info)1205 void JSTextField::SetCancelButton(const JSCallbackInfo& info)
1206 {
1207     if (info.Length() < 1 || !info[0]->IsObject()) {
1208         return;
1209     }
1210     auto param = JSRef<JSObject>::Cast(info[0]);
1211     auto theme = GetTheme<TextFieldTheme>();
1212     std::string styleStr;
1213     CleanNodeStyle cleanNodeStyle;
1214     auto styleProp = param->GetProperty("style");
1215     if (!styleProp->IsNull() && ParseJsString(styleProp, styleStr)) {
1216         cleanNodeStyle = ConvertStrToCleanNodeStyle(styleStr);
1217     } else {
1218         cleanNodeStyle = CleanNodeStyle::INPUT;
1219     }
1220     TextFieldModel::GetInstance()->SetCleanNodeStyle(cleanNodeStyle);
1221     TextFieldModel::GetInstance()->SetIsShowCancelButton(true);
1222     auto iconJsVal = param->GetProperty("icon");
1223     if (iconJsVal->IsUndefined() || iconJsVal->IsNull() || !iconJsVal->IsObject()) {
1224         TextFieldModel::GetInstance()->SetCancelIconColor(Color());
1225         TextFieldModel::GetInstance()->SetCancelIconSize(theme->GetIconSize());
1226         TextFieldModel::GetInstance()->SetCanacelIconSrc(std::string());
1227         return;
1228     }
1229     auto iconParam = JSRef<JSObject>::Cast(iconJsVal);
1230     // set icon size
1231     CalcDimension iconSize;
1232     auto iconSizeProp = iconParam->GetProperty("size");
1233     if (!iconSizeProp->IsUndefined() && !iconSizeProp->IsNull() && ParseJsDimensionVpNG(iconSizeProp, iconSize)) {
1234         if (LessNotEqual(iconSize.Value(), 0.0) || iconSize.Unit() == DimensionUnit::PERCENT) {
1235             iconSize = theme->GetIconSize();
1236         }
1237     } else {
1238         iconSize = theme->GetIconSize();
1239     }
1240     TextFieldModel::GetInstance()->SetCancelIconSize(iconSize);
1241     // set icon src
1242     std::string iconSrc;
1243     auto iconSrcProp = iconParam->GetProperty("src");
1244     if (iconSrcProp->IsUndefined() || iconSrcProp->IsNull() || !ParseJsMedia(iconSrcProp, iconSrc)) {
1245         iconSrc = "";
1246     }
1247     TextFieldModel::GetInstance()->SetCanacelIconSrc(iconSrc);
1248     // set icon color
1249     Color iconColor;
1250     auto iconColorProp = iconParam->GetProperty("color");
1251     if (!iconColorProp->IsUndefined() && !iconColorProp->IsNull() && ParseJsColor(iconColorProp, iconColor)) {
1252         TextFieldModel::GetInstance()->SetCancelIconColor(iconColor);
1253     } else {
1254         TextFieldModel::GetInstance()->SetCancelIconColor(iconColor);
1255     }
1256 }
1257 
SetSelectAllValue(const JSCallbackInfo & info)1258 void JSTextField::SetSelectAllValue(const JSCallbackInfo& info)
1259 {
1260     auto infoValue = info[0];
1261     if (!infoValue->IsBoolean() || infoValue->IsUndefined() || infoValue->IsNull()) {
1262         TextFieldModel::GetInstance()->SetSelectAllValue(false);
1263         return;
1264     }
1265 
1266     bool isSetSelectAllValue = infoValue->ToBoolean();
1267     TextFieldModel::GetInstance()->SetSelectAllValue(isSetSelectAllValue);
1268 }
1269 } // namespace OHOS::Ace::Framework
1270