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