1 /*
2 * Copyright (c) 2021-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 "bridge/declarative_frontend/jsview/js_search.h"
17
18 #include <optional>
19 #include <string>
20 #if !defined(PREVIEW) && defined(OHOS_PLATFORM)
21 #include "interfaces/inner_api/ui_session/ui_session_manager.h"
22 #endif
23
24 #include "base/log/ace_scoring_log.h"
25 #include "bridge/declarative_frontend/ark_theme/theme_apply/js_search_theme.h"
26 #include "bridge/declarative_frontend/engine/functions/js_clipboard_function.h"
27 #include "bridge/declarative_frontend/engine/functions/js_function.h"
28 #include "bridge/declarative_frontend/engine/jsi/js_ui_index.h"
29 #include "bridge/declarative_frontend/jsview/js_text_editable_controller.h"
30 #include "bridge/declarative_frontend/jsview/js_textfield.h"
31 #include "bridge/declarative_frontend/jsview/js_textinput.h"
32 #include "bridge/declarative_frontend/jsview/js_view_abstract.h"
33 #include "bridge/declarative_frontend/jsview/js_view_common_def.h"
34 #include "bridge/declarative_frontend/jsview/models/search_model_impl.h"
35 #include "core/components/common/layout/constants.h"
36 #include "core/components/common/properties/text_style_parser.h"
37 #include "core/components/search/search_theme.h"
38 #include "core/components_ng/gestures/gesture_info.h"
39 #include "core/components_ng/pattern/search/search_model_ng.h"
40 #include "core/components_ng/pattern/text_field/text_field_model_ng.h"
41
42 namespace OHOS::Ace {
43
44 std::unique_ptr<SearchModel> SearchModel::instance_ = nullptr;
45 std::mutex SearchModel::mutex_;
46
GetInstance()47 SearchModel* SearchModel::GetInstance()
48 {
49 #ifdef NG_BUILD
50 static NG::SearchModelNG instance;
51 return &instance;
52 #else
53 if (Container::IsCurrentUseNewPipeline()) {
54 static NG::SearchModelNG instance;
55 return &instance;
56 } else {
57 static Framework::SearchModelImpl instance;
58 return &instance;
59 }
60 #endif
61 }
62
63 } // namespace OHOS::Ace
64
65 namespace OHOS::Ace::Framework {
66 namespace {
67 const std::vector<TextAlign> TEXT_ALIGNS = { TextAlign::START, TextAlign::CENTER, TextAlign::END };
68 constexpr double DEFAULT_OPACITY = 0.2;
69 const int32_t DEFAULT_ALPHA = 255;
70 constexpr TextDecorationStyle DEFAULT_TEXT_DECORATION_STYLE = TextDecorationStyle::SOLID;
71 const char* TOP_START_PROPERTY = "topStart";
72 const char* TOP_END_PROPERTY = "topEnd";
73 const char* BOTTOM_START_PROPERTY = "bottomStart";
74 const char* BOTTOM_END_PROPERTY = "bottomEnd";
75
ParseJsLengthMetrics(const JSRef<JSObject>& obj, CalcDimension& result)76 bool ParseJsLengthMetrics(const JSRef<JSObject>& obj, CalcDimension& result)
77 {
78 auto value = obj->GetProperty(static_cast<int32_t>(ArkUIIndex::VALUE));
79 if (!value->IsNumber()) {
80 return false;
81 }
82 auto unit = DimensionUnit::VP;
83 auto jsUnit = obj->GetProperty(static_cast<int32_t>(ArkUIIndex::UNIT));
84 if (jsUnit->IsNumber()) {
85 unit = static_cast<DimensionUnit>(jsUnit->ToNumber<int32_t>());
86 }
87 CalcDimension dimension(value->ToNumber<double>(), unit);
88 result = dimension;
89 return true;
90 }
91 } // namespace
92
JSBind(BindingTarget globalObj)93 void JSSearch::JSBind(BindingTarget globalObj)
94 {
95 JSClass<JSSearch>::Declare("Search");
96 MethodOptions opt = MethodOptions::NONE;
97
98 JSClass<JSSearch>::StaticMethod("create", &JSSearch::Create, opt);
99 JSClass<JSSearch>::StaticMethod("searchButton", &JSSearch::SetSearchButton, opt);
100 JSClass<JSSearch>::StaticMethod("searchIcon", &JSSearch::SetSearchIcon, opt);
101 JSClass<JSSearch>::StaticMethod("cancelButton", &JSSearch::SetCancelButton, opt);
102 JSClass<JSSearch>::StaticMethod("fontColor", &JSSearch::SetTextColor, opt);
103 JSClass<JSSearch>::StaticMethod("caretStyle", &JSSearch::SetCaret, opt);
104 JSClass<JSSearch>::StaticMethod("placeholderColor", &JSSearch::SetPlaceholderColor, opt);
105 JSClass<JSSearch>::StaticMethod("placeholderFont", &JSSearch::SetPlaceholderFont, opt);
106 JSClass<JSSearch>::StaticMethod("textFont", &JSSearch::SetTextFont, opt);
107 JSClass<JSSearch>::StaticMethod("textAlign", &JSSearch::SetTextAlign, opt);
108 JSClass<JSSearch>::StaticMethod("onSubmit", &JSSearch::OnSubmit, opt);
109 JSClass<JSSearch>::StaticMethod("onChange", &JSSearch::OnChange, opt);
110 JSClass<JSSearch>::StaticMethod("onTextSelectionChange", &JSSearch::SetOnTextSelectionChange);
111 JSClass<JSSearch>::StaticMethod("onContentScroll", &JSSearch::SetOnScroll);
112 JSClass<JSSearch>::StaticMethod("border", &JSSearch::JsBorder);
113 JSClass<JSSearch>::StaticMethod("borderWidth", &JSSearch::JsBorderWidth);
114 JSClass<JSSearch>::StaticMethod("borderColor", &JSSearch::JsBorderColor);
115 JSClass<JSSearch>::StaticMethod("borderStyle", &JSSearch::JsBorderStyle);
116 JSClass<JSSearch>::StaticMethod("borderRadius", &JSSearch::JsBorderRadius);
117 JSClass<JSSearch>::StaticMethod("onTouch", &JSInteractableView::JsOnTouch);
118 JSClass<JSSearch>::StaticMethod("height", &JSSearch::SetHeight);
119 JSClass<JSSearch>::StaticMethod("width", &JSViewAbstract::JsWidth);
120 JSClass<JSSearch>::StaticMethod("onKeyEvent", &JSInteractableView::JsOnKey);
121 JSClass<JSSearch>::StaticMethod("onDeleteEvent", &JSInteractableView::JsOnDelete);
122 JSClass<JSSearch>::StaticMethod("onClick", &JSInteractableView::JsOnClick);
123 JSClass<JSSearch>::StaticMethod("requestKeyboardOnFocus", &JSSearch::SetEnableKeyboardOnFocus);
124 JSClass<JSSearch>::StaticMethod("enableKeyboardOnFocus", &JSSearch::SetEnableKeyboardOnFocus);
125 JSClass<JSSearch>::StaticMethod("onAttach", &JSInteractableView::JsOnAttach);
126 JSClass<JSSearch>::StaticMethod("onAppear", &JSInteractableView::JsOnAppear);
127 JSClass<JSSearch>::StaticMethod("onDetach", &JSInteractableView::JsOnDetach);
128 JSClass<JSSearch>::StaticMethod("onDisAppear", &JSInteractableView::JsOnDisAppear);
129 JSClass<JSSearch>::StaticMethod("onCopy", &JSSearch::SetOnCopy);
130 JSClass<JSSearch>::StaticMethod("onCut", &JSSearch::SetOnCut);
131 JSClass<JSSearch>::StaticMethod("onPaste", &JSSearch::SetOnPaste);
132 JSClass<JSSearch>::StaticMethod("copyOption", &JSSearch::SetCopyOption);
133 JSClass<JSSearch>::StaticMethod("selectionMenuHidden", &JSSearch::SetSelectionMenuHidden);
134 JSClass<JSSearch>::StaticMethod("customKeyboard", &JSSearch::SetCustomKeyboard);
135 JSClass<JSSearch>::StaticMethod("enterKeyType", &JSSearch::SetEnterKeyType);
136 JSClass<JSSearch>::StaticMethod("maxLength", &JSSearch::SetMaxLength);
137 JSClass<JSSearch>::StaticMethod("type", &JSSearch::SetType);
138 JSClass<JSSearch>::StaticMethod("dragPreviewOptions", &JSSearch::SetDragPreviewOptions);
139 JSClass<JSSearch>::StaticMethod("editMenuOptions", &JSSearch::EditMenuOptions);
140 JSBindMore();
141 JSClass<JSSearch>::InheritAndBind<JSViewAbstract>(globalObj);
142 }
143
JSBindMore()144 void JSSearch::JSBindMore()
145 {
146 JSClass<JSSearch>::StaticMethod("decoration", &JSSearch::SetDecoration);
147 JSClass<JSSearch>::StaticMethod("minFontSize", &JSSearch::SetMinFontSize);
148 JSClass<JSSearch>::StaticMethod("maxFontSize", &JSSearch::SetMaxFontSize);
149 JSClass<JSSearch>::StaticMethod("letterSpacing", &JSSearch::SetLetterSpacing);
150 JSClass<JSSearch>::StaticMethod("lineHeight", &JSSearch::SetLineHeight);
151 JSClass<JSSearch>::StaticMethod("fontFeature", &JSSearch::SetFontFeature);
152 JSClass<JSSearch>::StaticMethod("id", &JSSearch::SetId);
153 JSClass<JSSearch>::StaticMethod("key", &JSSearch::SetKey);
154 JSClass<JSSearch>::StaticMethod("selectedBackgroundColor", &JSSearch::SetSelectedBackgroundColor);
155 JSClass<JSSearch>::StaticMethod("inputFilter", &JSSearch::SetInputFilter);
156 JSClass<JSSearch>::StaticMethod("onEditChange", &JSSearch::SetOnEditChange);
157 JSClass<JSSearch>::StaticMethod("textIndent", &JSSearch::SetTextIndent);
158 JSClass<JSSearch>::StaticMethod("onWillInsert", &JSSearch::OnWillInsertValue);
159 JSClass<JSSearch>::StaticMethod("onDidInsert", &JSSearch::OnDidInsertValue);
160 JSClass<JSSearch>::StaticMethod("onWillDelete", &JSSearch::OnWillDelete);
161 JSClass<JSSearch>::StaticMethod("onDidDelete", &JSSearch::OnDidDelete);
162 JSClass<JSSearch>::StaticMethod("enablePreviewText", &JSSearch::SetEnablePreviewText);
163 JSClass<JSSearch>::StaticMethod("enableHapticFeedback", &JSSearch::SetEnableHapticFeedback);
164 }
165
ParseSearchValueObject(const JSCallbackInfo& info, const JSRef<JSVal>& changeEventVal)166 void ParseSearchValueObject(const JSCallbackInfo& info, const JSRef<JSVal>& changeEventVal)
167 {
168 CHECK_NULL_VOID(changeEventVal->IsFunction());
169
170 JsEventCallback<void(const std::string&)> onChangeEvent(
171 info.GetExecutionContext(), JSRef<JSFunc>::Cast(changeEventVal));
172 SearchModel::GetInstance()->SetOnChangeEvent(std::move(onChangeEvent));
173 }
174
SetDragPreviewOptions(const JSCallbackInfo& info)175 void JSSearch::SetDragPreviewOptions(const JSCallbackInfo& info)
176 {
177 NG::DragPreviewOption option = JSViewAbstract::ParseDragPreviewOptions(info);
178 SearchModel::GetInstance()->SetDragPreviewOptions(option);
179 }
180
SetFontFeature(const JSCallbackInfo& info)181 void JSSearch::SetFontFeature(const JSCallbackInfo& info)
182 {
183 if (info.Length() < 1) {
184 return;
185 }
186
187 if (!info[0]->IsString() && !info[0]->IsObject()) {
188 return;
189 }
190 std::string fontFeatureSettings = info[0]->ToString();
191 SearchModel::GetInstance()->SetFontFeature(ParseFontFeatureSettings(fontFeatureSettings));
192 }
193
Create(const JSCallbackInfo& info)194 void JSSearch::Create(const JSCallbackInfo& info)
195 {
196 std::optional<std::string> key;
197 std::optional<std::string> tip;
198 std::optional<std::string> src;
199 JSTextEditableController* jsController = nullptr;
200 JSRef<JSVal> changeEventVal;
201 if (info[0]->IsObject()) {
202 auto param = JSRef<JSObject>::Cast(info[0]);
203 std::string placeholder;
204 if (param->GetProperty("placeholder")->IsUndefined()) {
205 tip = "";
206 }
207 if (ParseJsString(param->GetProperty("placeholder"), placeholder)) {
208 tip = placeholder;
209 }
210 std::string text;
211 JSRef<JSVal> textValue = param->GetProperty("value");
212 if (textValue->IsObject()) {
213 JSRef<JSObject> valueObj = JSRef<JSObject>::Cast(textValue);
214 changeEventVal = valueObj->GetProperty("changeEvent");
215 if (changeEventVal->IsFunction()) {
216 textValue = valueObj->GetProperty("value");
217 }
218 if (ParseJsString(textValue, text)) {
219 key = text;
220 }
221 } else if (param->HasProperty("value") && textValue->IsUndefined()) {
222 key = "";
223 } else {
224 if (ParseJsString(textValue, text)) {
225 key = text;
226 }
227 }
228 std::string icon;
229 if (ParseJsString(param->GetProperty("icon"), icon)) {
230 src = icon;
231 }
232 auto controllerObj = param->GetProperty("controller");
233 if (!controllerObj->IsUndefined() && !controllerObj->IsNull() && controllerObj->IsObject()) {
234 jsController = JSRef<JSObject>::Cast(controllerObj)->Unwrap<JSTextEditableController>();
235 }
236 }
237 auto controller = SearchModel::GetInstance()->Create(key, tip, src);
238 if (jsController) {
239 jsController->SetController(controller);
240 }
241 SearchModel::GetInstance()->SetFocusable(true);
242 SearchModel::GetInstance()->SetFocusNode(true);
243 if (!changeEventVal->IsUndefined() && changeEventVal->IsFunction()) {
244 ParseSearchValueObject(info, changeEventVal);
245 }
246 JSSeacrhTheme::ApplyTheme();
247 }
248
SetSelectedBackgroundColor(const JSCallbackInfo& info)249 void JSSearch::SetSelectedBackgroundColor(const JSCallbackInfo& info)
250 {
251 if (info.Length() < 1) {
252 return;
253 }
254 Color selectedColor;
255 if (!ParseJsColor(info[0], selectedColor)) {
256 auto pipeline = PipelineBase::GetCurrentContext();
257 CHECK_NULL_VOID(pipeline);
258 auto theme = pipeline->GetThemeManager()->GetTheme<TextFieldTheme>();
259 CHECK_NULL_VOID(theme);
260 selectedColor = theme->GetSelectedColor();
261 }
262 // Alpha = 255 means opaque
263 if (selectedColor.GetAlpha() == DEFAULT_ALPHA) {
264 // Default setting of 20% opacity
265 selectedColor = selectedColor.ChangeOpacity(DEFAULT_OPACITY);
266 }
267 SearchModel::GetInstance()->SetSelectedBackgroundColor(selectedColor);
268 }
269
SetEnableKeyboardOnFocus(const JSCallbackInfo& info)270 void JSSearch::SetEnableKeyboardOnFocus(const JSCallbackInfo& info)
271 {
272 if (info[0]->IsUndefined() || !info[0]->IsBoolean()) {
273 SearchModel::GetInstance()->RequestKeyboardOnFocus(true);
274 return;
275 }
276 SearchModel::GetInstance()->RequestKeyboardOnFocus(info[0]->ToBoolean());
277 }
278
SetId(const JSCallbackInfo& info)279 void JSSearch::SetId(const JSCallbackInfo& info)
280 {
281 JSViewAbstract::JsId(info);
282 JSRef<JSVal> arg = info[0];
283 std::string id;
284 if (arg->IsString()) {
285 id = arg->ToString();
286 }
287 SearchModel::GetInstance()->UpdateInspectorId(id);
288 }
289
SetKey(const std::string& key)290 void JSSearch::SetKey(const std::string& key)
291 {
292 JSViewAbstract::JsKey(key);
293 SearchModel::GetInstance()->UpdateInspectorId(key);
294 }
295
SetSearchButton(const JSCallbackInfo& info)296 void JSSearch::SetSearchButton(const JSCallbackInfo& info)
297 {
298 auto theme = GetTheme<SearchTheme>();
299 CHECK_NULL_VOID(theme);
300 std::string buttonValue = "";
301 if (info[0]->IsString()) {
302 buttonValue = info[0]->ToString();
303 }
304 SearchModel::GetInstance()->SetSearchButton(buttonValue);
305 // set font color
306 Color fontColor = theme->GetSearchButtonTextColor();
307 if (info[1]->IsObject()) {
308 auto param = JSRef<JSObject>::Cast(info[1]);
309
310 // set button font size, unit FP
311 auto fontSize = param->GetProperty("fontSize");
312 CalcDimension size = theme->GetFontSize();
313 if (ParseJsDimensionVpNG(fontSize, size) && size.Unit() != DimensionUnit::PERCENT &&
314 GreatOrEqual(size.Value(), 0.0)) {
315 ParseJsDimensionFp(fontSize, size);
316 } else {
317 size = theme->GetFontSize();
318 }
319 SearchModel::GetInstance()->SetSearchButtonFontSize(size);
320
321 auto fontColorProp = param->GetProperty("fontColor");
322 if (fontColorProp->IsUndefined() || fontColorProp->IsNull() || !ParseJsColor(fontColorProp, fontColor)) {
323 if (!JSSeacrhTheme::ObtainSearchButtonFontColor(fontColor)) {
324 SearchModel::GetInstance()->SetSearchButtonFontColor(fontColor);
325 }
326 } else {
327 SearchModel::GetInstance()->SetSearchButtonFontColor(fontColor);
328 }
329 } else {
330 SearchModel::GetInstance()->SetSearchButtonFontSize(theme->GetFontSize());
331 if (!JSSeacrhTheme::ObtainSearchButtonFontColor(fontColor)) {
332 SearchModel::GetInstance()->SetSearchButtonFontColor(fontColor);
333 }
334 }
335 }
336
SetSearchIcon(const JSCallbackInfo& info)337 void JSSearch::SetSearchIcon(const JSCallbackInfo& info)
338 {
339 if (info[0]->IsUndefined() || info[0]->IsNull()) {
340 SetSearchDefaultIcon();
341 return;
342 }
343 if (info[0]->IsObject()) {
344 auto param = JSRef<JSObject>::Cast(info[0]);
345 bool isSymbolIcon = param->HasProperty("fontColor"); // only SymbolGlyph has fontColor property
346 if (isSymbolIcon) {
347 SetSearchSymbolIcon(info);
348 } else {
349 SetSearchImageIcon(info);
350 }
351 }
352 }
353
SetCancelDefaultIcon()354 void JSSearch::SetCancelDefaultIcon()
355 {
356 SearchModel::GetInstance()->SetCancelDefaultIcon();
357 }
358
SetCancelSymbolIcon(const JSCallbackInfo& info)359 void JSSearch::SetCancelSymbolIcon(const JSCallbackInfo& info)
360 {
361 if (info[0]->IsObject()) {
362 std::function<void(WeakPtr<NG::FrameNode>)> iconSymbol = nullptr;
363 auto param = JSRef<JSObject>::Cast(info[0]);
364 auto iconProp = param->GetProperty("icon");
365 SetSymbolOptionApply(info, iconSymbol, iconProp);
366 SearchModel::GetInstance()->SetCancelSymbolIcon(iconSymbol);
367 }
368 }
369
SetCancelImageIcon(const JSCallbackInfo& info)370 void JSSearch::SetCancelImageIcon(const JSCallbackInfo& info)
371 {
372 if (!info[0]->IsObject()) {
373 return;
374 }
375 auto param = JSRef<JSObject>::Cast(info[0]);
376 auto theme = GetTheme<SearchTheme>();
377 CHECK_NULL_VOID(theme);
378 auto iconJsVal = param->GetProperty("icon");
379 if (!iconJsVal->IsObject()) {
380 return;
381 }
382 auto iconParam = JSRef<JSObject>::Cast(iconJsVal);
383
384 // set icon size
385 CalcDimension iconSize;
386 auto iconSizeProp = iconParam->GetProperty("size");
387 if (!iconSizeProp->IsUndefined() && !iconSizeProp->IsNull() && ParseJsDimensionVpNG(iconSizeProp, iconSize)) {
388 if (LessNotEqual(iconSize.Value(), 0.0) || iconSize.Unit() == DimensionUnit::PERCENT) {
389 iconSize = theme->GetIconHeight();
390 }
391 } else {
392 iconSize = theme->GetIconHeight();
393 }
394
395 // set icon src
396 std::string iconSrc;
397 auto iconSrcProp = iconParam->GetProperty("src");
398 if (iconSrcProp->IsUndefined() || iconSrcProp->IsNull() || !ParseJsMedia(iconSrcProp, iconSrc)) {
399 iconSrc = "";
400 }
401
402 // set icon color
403 Color iconColor = theme->GetSearchIconColor();
404 auto iconColorProp = iconParam->GetProperty("color");
405 if (!iconColorProp->IsUndefined() && !iconColorProp->IsNull() && ParseJsColor(iconColorProp, iconColor)) {
406 NG::IconOptions cancelIconOptions = NG::IconOptions(iconColor, iconSize, iconSrc, "", "");
407 SearchModel::GetInstance()->SetCancelImageIcon(cancelIconOptions);
408 } else {
409 NG::IconOptions cancelIconOptions = NG::IconOptions(iconSize, iconSrc, "", "");
410 SearchModel::GetInstance()->SetCancelImageIcon(cancelIconOptions);
411 }
412 }
413
SetSearchDefaultIcon()414 void JSSearch::SetSearchDefaultIcon()
415 {
416 SearchModel::GetInstance()->SetSearchDefaultIcon();
417 }
418
SetSearchSymbolIcon(const JSCallbackInfo& info)419 void JSSearch::SetSearchSymbolIcon(const JSCallbackInfo& info)
420 {
421 if (!info[0]->IsObject()) {
422 return;
423 }
424
425 std::function<void(WeakPtr<NG::FrameNode>)> iconSymbol = nullptr;
426 SetSymbolOptionApply(info, iconSymbol, info[0]);
427 SearchModel::GetInstance()->SetSearchSymbolIcon(iconSymbol);
428 }
429
SetSearchImageIcon(const JSCallbackInfo& info)430 void JSSearch::SetSearchImageIcon(const JSCallbackInfo& info)
431 {
432 if (!info[0]->IsObject()) {
433 return;
434 }
435 auto param = JSRef<JSObject>::Cast(info[0]);
436 auto theme = GetTheme<SearchTheme>();
437 CHECK_NULL_VOID(theme);
438
439 // set icon size
440 CalcDimension size;
441 auto sizeProp = param->GetProperty("size");
442 if (!sizeProp->IsUndefined() && !sizeProp->IsNull() && ParseJsDimensionVpNG(sizeProp, size)) {
443 if (LessNotEqual(size.Value(), 0.0) || size.Unit() == DimensionUnit::PERCENT) {
444 size = theme->GetIconHeight();
445 }
446 } else {
447 size = theme->GetIconHeight();
448 }
449
450 // set icon src
451 std::string src;
452 auto srcPathProp = param->GetProperty("src");
453 if (srcPathProp->IsUndefined() || srcPathProp->IsNull() || !ParseJsMedia(srcPathProp, src)) {
454 src = "";
455 }
456 // set icon color
457 Color colorVal = theme->GetSearchIconColor();
458 auto colorProp = param->GetProperty("color");
459 if (!colorProp->IsUndefined() && !colorProp->IsNull()) {
460 ParseJsColor(colorProp, colorVal);
461 }
462
463 std::string bundleName;
464 std::string moduleName;
465 GetJsMediaBundleInfo(srcPathProp, bundleName, moduleName);
466 NG::IconOptions searchIconOptions = NG::IconOptions(colorVal, size, src, bundleName, moduleName);
467 SearchModel::GetInstance()->SetSearchImageIcon(searchIconOptions);
468 }
469
ConvertStrToCancelButtonStyle(const std::string& value)470 static CancelButtonStyle ConvertStrToCancelButtonStyle(const std::string& value)
471 {
472 if (value == "CONSTANT") {
473 return CancelButtonStyle::CONSTANT;
474 } else if (value == "INVISIBLE") {
475 return CancelButtonStyle::INVISIBLE;
476 } else {
477 return CancelButtonStyle::INPUT;
478 }
479 }
480
SetCancelButton(const JSCallbackInfo& info)481 void JSSearch::SetCancelButton(const JSCallbackInfo& info)
482 {
483 if (!info[0]->IsObject()) {
484 return;
485 }
486 auto param = JSRef<JSObject>::Cast(info[0]);
487 auto theme = GetTheme<SearchTheme>();
488 CHECK_NULL_VOID(theme);
489
490 // set style
491 std::string styleStr;
492 CancelButtonStyle cancelButtonStyle;
493 auto styleProp = param->GetProperty("style");
494 if (!styleProp->IsUndefined() && !styleProp->IsNull() && ParseJsString(styleProp, styleStr)) {
495 cancelButtonStyle = ConvertStrToCancelButtonStyle(styleStr);
496 } else {
497 cancelButtonStyle = theme->GetCancelButtonStyle();
498 }
499 SearchModel::GetInstance()->SetCancelButtonStyle(cancelButtonStyle);
500
501 auto iconProp = param->GetProperty("icon");
502 if (iconProp->IsUndefined() || iconProp->IsNull()) {
503 SetCancelDefaultIcon();
504 } else {
505 SetIconStyle(info);
506 }
507 }
508
SetIconStyle(const JSCallbackInfo& info)509 void JSSearch::SetIconStyle(const JSCallbackInfo& info)
510 {
511 if (!info[0]->IsObject()) {
512 return;
513 }
514
515 auto param = JSRef<JSObject>::Cast(info[0]);
516 auto iconJsVal = param->GetProperty("icon");
517 if (!iconJsVal->IsObject()) {
518 return;
519 }
520
521 auto iconParam = JSRef<JSObject>::Cast(iconJsVal);
522 bool isSymbolIcon = iconParam->HasProperty("fontColor"); // only SymbolGlyph has fontColor property
523 if (isSymbolIcon) {
524 SetCancelSymbolIcon(info);
525 } else {
526 SetCancelImageIcon(info);
527 }
528 }
529
SetTextColor(const JSCallbackInfo& info)530 void JSSearch::SetTextColor(const JSCallbackInfo& info)
531 {
532 auto theme = GetTheme<SearchTheme>();
533 CHECK_NULL_VOID(theme);
534
535 auto value = JSRef<JSVal>::Cast(info[0]);
536 Color colorVal;
537 if (!ParseJsColor(value, colorVal)) {
538 colorVal = theme->GetTextColor();
539 }
540 SearchModel::GetInstance()->SetTextColor(colorVal);
541 }
542
SetCaret(const JSCallbackInfo& info)543 void JSSearch::SetCaret(const JSCallbackInfo& info)
544 {
545 if (info[0]->IsObject()) {
546 auto param = JSRef<JSObject>::Cast(info[0]);
547 auto textFieldTheme = GetTheme<TextFieldTheme>();
548 CHECK_NULL_VOID(textFieldTheme);
549
550 // set caret width
551 CalcDimension caretWidth = textFieldTheme->GetCursorWidth();
552 auto caretWidthProp = param->GetProperty("width");
553 if (!ParseJsDimensionVpNG(caretWidthProp, caretWidth, false) || LessNotEqual(caretWidth.Value(), 0.0)) {
554 caretWidth = textFieldTheme->GetCursorWidth();
555 }
556 SearchModel::GetInstance()->SetCaretWidth(caretWidth);
557
558 // set caret color
559 Color caretColor;
560 auto caretColorProp = param->GetProperty("color");
561 if (caretColorProp->IsUndefined() || caretColorProp->IsNull() || !ParseJsColor(caretColorProp, caretColor)) {
562 caretColor = textFieldTheme->GetCursorColor();
563 }
564 SearchModel::GetInstance()->SetCaretColor(caretColor);
565 }
566 }
567
SetInputFilter(const JSCallbackInfo& info)568 void JSSearch::SetInputFilter(const JSCallbackInfo& info)
569 {
570 if (info.Length() < 1) {
571 return;
572 }
573 auto tmpInfo = info[0];
574 auto errInfo = info[1];
575 std::string inputFilter;
576 if (tmpInfo->IsUndefined()) {
577 SearchModel::GetInstance()->SetInputFilter(inputFilter, nullptr);
578 return;
579 }
580 if (!ParseJsString(tmpInfo, inputFilter)) {
581 return;
582 }
583 if (!CheckRegexValid(inputFilter)) {
584 inputFilter = "";
585 }
586 if (info.Length() > 1 && errInfo->IsFunction()) {
587 auto jsFunc = AceType::MakeRefPtr<JsClipboardFunction>(JSRef<JSFunc>::Cast(errInfo));
588 auto targetNode = AceType::WeakClaim(NG::ViewStackProcessor::GetInstance()->GetMainFrameNode());
589 auto resultId = [execCtx = info.GetExecutionContext(), func = std::move(jsFunc), node = targetNode](
590 const std::string& info) {
591 JAVASCRIPT_EXECUTION_SCOPE_WITH_CHECK(execCtx);
592 PipelineContext::SetCallBackNode(node);
593 func->Execute(info);
594 };
595 SearchModel::GetInstance()->SetInputFilter(inputFilter, resultId);
596 return;
597 }
598 SearchModel::GetInstance()->SetInputFilter(inputFilter, nullptr);
599 }
600
SetOnEditChange(const JSCallbackInfo& info)601 void JSSearch::SetOnEditChange(const JSCallbackInfo& info)
602 {
603 auto tmpInfo = info[0];
604 CHECK_NULL_VOID(tmpInfo->IsFunction());
605 JsEventCallback<void(bool)> callback(info.GetExecutionContext(), JSRef<JSFunc>::Cast(tmpInfo));
606 SearchModel::GetInstance()->SetOnEditChanged(std::move(callback));
607 }
608
SetTextIndent(const JSCallbackInfo& info)609 void JSSearch::SetTextIndent(const JSCallbackInfo& info)
610 {
611 CalcDimension value;
612 if (!ParseJsDimensionVpNG(info[0], value, true)) {
613 value.Reset();
614 }
615 SearchModel::GetInstance()->SetTextIndent(value);
616 }
617
SetPlaceholderColor(const JSCallbackInfo& info)618 void JSSearch::SetPlaceholderColor(const JSCallbackInfo& info)
619 {
620 auto value = JSRef<JSVal>::Cast(info[0]);
621 Color colorVal;
622 if (!ParseJsColor(value, colorVal)) {
623 auto theme = GetTheme<SearchTheme>();
624 CHECK_NULL_VOID(theme);
625 colorVal = theme->GetPlaceholderColor();
626 }
627 SearchModel::GetInstance()->SetPlaceholderColor(colorVal);
628 }
629
SetPlaceholderFont(const JSCallbackInfo& info)630 void JSSearch::SetPlaceholderFont(const JSCallbackInfo& info)
631 {
632 if (!info[0]->IsObject()) {
633 return;
634 }
635 auto param = JSRef<JSObject>::Cast(info[0]);
636 auto theme = GetTheme<SearchTheme>();
637 CHECK_NULL_VOID(theme);
638 auto themeFontSize = theme->GetFontSize();
639 Font font;
640 auto fontSize = param->GetProperty("size");
641 if (fontSize->IsNull() || fontSize->IsUndefined()) {
642 font.fontSize = themeFontSize;
643 } else {
644 auto versionTenOrLarger = Container::GreatOrEqualAPIVersion(PlatformVersion::VERSION_TEN);
645 CalcDimension size;
646 if ((versionTenOrLarger ? ParseJsDimensionVpNG(fontSize, size) : ParseJsDimensionVp(fontSize, size)) &&
647 size.Unit() != DimensionUnit::PERCENT) {
648 ParseJsDimensionFp(fontSize, size);
649 font.fontSize = size;
650 } else {
651 font.fontSize = themeFontSize;
652 }
653 }
654
655 auto weight = param->GetProperty("weight");
656 if (!weight->IsNull()) {
657 std::string weightVal;
658 if (weight->IsNumber()) {
659 weightVal = std::to_string(weight->ToNumber<int32_t>());
660 } else {
661 ParseJsString(weight, weightVal);
662 }
663 font.fontWeight = ConvertStrToFontWeight(weightVal);
664 }
665
666 auto family = param->GetProperty("family");
667 if (!family->IsNull() && family->IsString()) {
668 auto familyVal = family->ToString();
669 font.fontFamilies = ConvertStrToFontFamilies(familyVal);
670 }
671
672 auto style = param->GetProperty("style");
673 if (!style->IsNull() && style->IsNumber()) {
674 FontStyle styleVal = static_cast<FontStyle>(style->ToNumber<int32_t>());
675 font.fontStyle = styleVal;
676 }
677 SearchModel::GetInstance()->SetPlaceholderFont(font);
678 }
679
SetTextFont(const JSCallbackInfo& info)680 void JSSearch::SetTextFont(const JSCallbackInfo& info)
681 {
682 auto theme = GetTheme<SearchTheme>();
683 CHECK_NULL_VOID(theme);
684 auto themeFontSize = theme->GetFontSize();
685 auto themeFontWeight = theme->GetFontWeight();
686 Font font { .fontWeight = themeFontWeight, .fontSize = themeFontSize, .fontStyle = Ace::FontStyle::NORMAL };
687 if (info.Length() < 1 || !info[0]->IsObject()) {
688 if (AceApplicationInfo::GetInstance().GreatOrEqualTargetAPIVersion(PlatformVersion::VERSION_TWELVE)) {
689 SearchModel::GetInstance()->SetTextFont(font);
690 }
691 return;
692 }
693 auto param = JSRef<JSObject>::Cast(info[0]);
694 auto fontSize = param->GetProperty("size");
695 CalcDimension size = themeFontSize;
696 if (ParseJsDimensionVpNG(fontSize, size) && size.Unit() != DimensionUnit::PERCENT &&
697 GreatOrEqual(size.Value(), 0.0)) {
698 ParseJsDimensionFp(fontSize, size);
699 } else {
700 size = themeFontSize;
701 }
702 font.fontSize = size;
703
704 auto weight = param->GetProperty("weight");
705 if (!weight->IsNull()) {
706 std::string weightVal;
707 if (weight->IsNumber()) {
708 weightVal = std::to_string(weight->ToNumber<int32_t>());
709 } else {
710 ParseJsString(weight, weightVal);
711 }
712 font.fontWeight = ConvertStrToFontWeight(weightVal);
713 }
714
715 auto family = param->GetProperty("family");
716 if (!family->IsNull() && family->IsString()) {
717 auto familyVal = family->ToString();
718 font.fontFamilies = ConvertStrToFontFamilies(familyVal);
719 }
720
721 auto style = param->GetProperty("style");
722 if (!style->IsNull() && style->IsNumber()) {
723 FontStyle styleVal = static_cast<FontStyle>(style->ToNumber<int32_t>());
724 font.fontStyle = styleVal;
725 }
726 SearchModel::GetInstance()->SetTextFont(font);
727 }
728
SetTextAlign(int32_t value)729 void JSSearch::SetTextAlign(int32_t value)
730 {
731 if (value >= 0 && value < static_cast<int32_t>(TEXT_ALIGNS.size())) {
732 SearchModel::GetInstance()->SetTextAlign(TEXT_ALIGNS[value]);
733 }
734 }
735
JsBorder(const JSCallbackInfo& info)736 void JSSearch::JsBorder(const JSCallbackInfo& info)
737 {
738 if (!info[0]->IsObject()) {
739 CalcDimension borderWidth;
740 ViewAbstractModel::GetInstance()->SetBorderWidth(borderWidth);
741 ViewAbstractModel::GetInstance()->SetBorderColor(Color::BLACK);
742 ViewAbstractModel::GetInstance()->SetBorderRadius(borderWidth);
743 ViewAbstractModel::GetInstance()->SetBorderStyle(BorderStyle::SOLID);
744 ViewAbstractModel::GetInstance()->SetDashGap(Dimension(-1));
745 ViewAbstractModel::GetInstance()->SetDashWidth(Dimension(-1));
746 return;
747 }
748 JSRef<JSObject> object = JSRef<JSObject>::Cast(info[0]);
749
750 auto valueWidth = object->GetProperty(static_cast<int32_t>(ArkUIIndex::WIDTH));
751 if (!valueWidth->IsUndefined()) {
752 JSViewAbstract::ParseBorderWidth(valueWidth);
753 }
754
755 // use default value when undefined.
756 JSViewAbstract::ParseBorderColor(object->GetProperty(static_cast<int32_t>(ArkUIIndex::COLOR)));
757
758 auto valueRadius = object->GetProperty(static_cast<int32_t>(ArkUIIndex::RADIUS));
759 if (!valueRadius->IsUndefined()) {
760 ParseBorderRadius(valueRadius);
761 SearchModel::GetInstance()->SetBackBorderRadius();
762 }
763 // use default value when undefined.
764 JSViewAbstract::ParseBorderStyle(object->GetProperty(static_cast<int32_t>(ArkUIIndex::STYLE)));
765
766 auto dashGap = object->GetProperty("dashGap");
767 if (!dashGap->IsUndefined()) {
768 JSViewAbstract::ParseDashGap(dashGap);
769 }
770 auto dashWidth = object->GetProperty("dashWidth");
771 if (!dashWidth->IsUndefined()) {
772 JSViewAbstract::ParseDashWidth(dashWidth);
773 }
774
775 SearchModel::GetInstance()->SetBackBorder();
776 info.ReturnSelf();
777 }
778
JsBorderWidth(const JSCallbackInfo& info)779 void JSSearch::JsBorderWidth(const JSCallbackInfo& info)
780 {
781 JSViewAbstract::JsBorderWidth(info);
782 if (!info[0]->IsObject() && !info[0]->IsString() && !info[0]->IsNumber()) {
783 return;
784 }
785 SearchModel::GetInstance()->SetBackBorder();
786 }
787
JsBorderColor(const JSCallbackInfo& info)788 void JSSearch::JsBorderColor(const JSCallbackInfo& info)
789 {
790 JSViewAbstract::JsBorderColor(info);
791 if (!info[0]->IsObject() && !info[0]->IsString() && !info[0]->IsNumber()) {
792 return;
793 }
794 SearchModel::GetInstance()->SetBackBorder();
795 }
796
JsBorderStyle(const JSCallbackInfo& info)797 void JSSearch::JsBorderStyle(const JSCallbackInfo& info)
798 {
799 JSViewAbstract::JsBorderStyle(info);
800 if (!info[0]->IsObject() && !info[0]->IsNumber()) {
801 return;
802 }
803 SearchModel::GetInstance()->SetBackBorder();
804 }
805
GetBorderRadiusByLengthMetrics(const char* key, JSRef<JSObject>& object, std::optional<CalcDimension>& radius)806 void JSSearch::GetBorderRadiusByLengthMetrics(const char* key, JSRef<JSObject>& object,
807 std::optional<CalcDimension>& radius)
808 {
809 if (object->HasProperty(key) && object->GetProperty(key)->IsObject()) {
810 JSRef<JSObject> startObj = JSRef<JSObject>::Cast(object->GetProperty(key));
811 CalcDimension value;
812 ParseJsLengthMetrics(startObj, value);
813 radius = value;
814 }
815 }
816
ParseAllBorderRadiuses(JSRef<JSObject>& object, CalcDimension& topLeft, CalcDimension& topRight, CalcDimension& bottomLeft, CalcDimension& bottomRight)817 bool JSSearch::ParseAllBorderRadiuses(JSRef<JSObject>& object, CalcDimension& topLeft,
818 CalcDimension& topRight, CalcDimension& bottomLeft, CalcDimension& bottomRight)
819 {
820 if (object->HasProperty(TOP_START_PROPERTY) || object->HasProperty(TOP_END_PROPERTY) ||
821 object->HasProperty(BOTTOM_START_PROPERTY) || object->HasProperty(BOTTOM_END_PROPERTY)) {
822 std::optional<CalcDimension> topStart;
823 std::optional<CalcDimension> topEnd;
824 std::optional<CalcDimension> bottomStart;
825 std::optional<CalcDimension> bottomEnd;
826 GetBorderRadiusByLengthMetrics(TOP_START_PROPERTY, object, topStart);
827 GetBorderRadiusByLengthMetrics(TOP_END_PROPERTY, object, topEnd);
828 GetBorderRadiusByLengthMetrics(BOTTOM_START_PROPERTY, object, bottomStart);
829 GetBorderRadiusByLengthMetrics(BOTTOM_END_PROPERTY, object, bottomEnd);
830 topLeft = topStart.has_value() ? topStart.value() : topLeft;
831 topRight = topEnd.has_value() ? topEnd.value() : topRight;
832 bottomLeft = bottomStart.has_value() ? bottomStart.value() : bottomLeft;
833 bottomRight = bottomEnd.has_value() ? bottomEnd.value() : bottomRight;
834 return true;
835 }
836 JSViewAbstract::ParseJsDimensionVp(object->GetProperty("topLeft"), topLeft);
837 JSViewAbstract::ParseJsDimensionVp(object->GetProperty("topRight"), topRight);
838 JSViewAbstract::ParseJsDimensionVp(object->GetProperty("bottomLeft"), bottomLeft);
839 JSViewAbstract::ParseJsDimensionVp(object->GetProperty("bottomRight"), bottomRight);
840 return false;
841 }
842
ParseBorderRadius(const JSRef<JSVal>& args)843 void JSSearch::ParseBorderRadius(const JSRef<JSVal>& args)
844 {
845 CalcDimension borderRadius;
846 if (ParseJsDimensionVp(args, borderRadius)) {
847 ViewAbstractModel::GetInstance()->SetBorderRadius(borderRadius);
848 } else if (args->IsObject()) {
849 auto textFieldTheme = GetTheme<TextFieldTheme>();
850 CHECK_NULL_VOID(textFieldTheme);
851 auto borderRadiusTheme = textFieldTheme->GetBorderRadius();
852 NG::BorderRadiusProperty defaultBorderRadius {
853 borderRadiusTheme.GetX(), borderRadiusTheme.GetY(),
854 borderRadiusTheme.GetY(), borderRadiusTheme.GetX(),
855 };
856
857 JSRef<JSObject> object = JSRef<JSObject>::Cast(args);
858 CalcDimension topLeft = defaultBorderRadius.radiusTopLeft.value();
859 CalcDimension topRight = defaultBorderRadius.radiusTopRight.value();
860 CalcDimension bottomLeft = defaultBorderRadius.radiusBottomLeft.value();
861 CalcDimension bottomRight = defaultBorderRadius.radiusBottomRight.value();
862 if (ParseAllBorderRadiuses(object, topLeft, topRight, bottomLeft, bottomRight)) {
863 ViewAbstractModel::GetInstance()->SetBorderRadius(
864 JSViewAbstract::GetLocalizedBorderRadius(topLeft, topRight, bottomLeft, bottomRight));
865 return;
866 }
867 ViewAbstractModel::GetInstance()->SetBorderRadius(topLeft, topRight, bottomLeft, bottomRight);
868 }
869 }
870
JsBorderRadius(const JSCallbackInfo& info)871 void JSSearch::JsBorderRadius(const JSCallbackInfo& info)
872 {
873 auto jsValue = info[0];
874 static std::vector<JSCallbackInfoType> checkList { JSCallbackInfoType::STRING,
875 JSCallbackInfoType::NUMBER, JSCallbackInfoType::OBJECT };
876 if (!CheckJSCallbackInfo("JsBorderRadius", jsValue, checkList)) {
877 auto textFieldTheme = GetTheme<TextFieldTheme>();
878 CHECK_NULL_VOID(textFieldTheme);
879 auto borderRadiusTheme = textFieldTheme->GetBorderRadius();
880 NG::BorderRadiusProperty defaultBorderRadius {
881 borderRadiusTheme.GetX(), borderRadiusTheme.GetY(),
882 borderRadiusTheme.GetY(), borderRadiusTheme.GetX(),
883 };
884 ViewAbstractModel::GetInstance()->SetBorderRadius(defaultBorderRadius);
885 return;
886 }
887 ParseBorderRadius(jsValue);
888 SearchModel::GetInstance()->SetBackBorderRadius();
889 }
890
OnSubmit(const JSCallbackInfo& info)891 void JSSearch::OnSubmit(const JSCallbackInfo& info)
892 {
893 CHECK_NULL_VOID(info[0]->IsFunction());
894 JsEventCallback<void(const std::string&)> callback(info.GetExecutionContext(), JSRef<JSFunc>::Cast(info[0]));
895 SearchModel::GetInstance()->SetOnSubmit(std::move(callback));
896 }
897
CreateJsOnChangeObj(const PreviewText& previewText)898 JSRef<JSVal> JSSearch::CreateJsOnChangeObj(const PreviewText& previewText)
899 {
900 JSRef<JSObject> previewTextObj = JSRef<JSObject>::New();
901 previewTextObj->SetProperty<int32_t>("offset", previewText.offset);
902 previewTextObj->SetProperty<std::string>("value", previewText.value);
903 return JSRef<JSVal>::Cast(previewTextObj);
904 }
905
OnChange(const JSCallbackInfo& info)906 void JSSearch::OnChange(const JSCallbackInfo& info)
907 {
908 auto jsValue = info[0];
909 CHECK_NULL_VOID(jsValue->IsFunction());
910 auto jsChangeFunc =
911 AceType::MakeRefPtr<JsCitedEventFunction<PreviewText, 2>>(JSRef<JSFunc>::Cast(jsValue), CreateJsOnChangeObj);
912 auto onChange = [execCtx = info.GetExecutionContext(), func = std::move(jsChangeFunc)](
913 const std::string& val, PreviewText& previewText) {
914 JAVASCRIPT_EXECUTION_SCOPE_WITH_CHECK(execCtx);
915 ACE_SCORING_EVENT("onChange");
916 func->Execute(val, previewText);
917 };
918 SearchModel::GetInstance()->SetOnChange(std::move(onChange));
919 }
920
SetOnTextSelectionChange(const JSCallbackInfo& info)921 void JSSearch::SetOnTextSelectionChange(const JSCallbackInfo& info)
922 {
923 CHECK_NULL_VOID(info[0]->IsFunction());
924 JsEventCallback<void(int32_t, int32_t)> callback(info.GetExecutionContext(), JSRef<JSFunc>::Cast(info[0]));
925 SearchModel::GetInstance()->SetOnTextSelectionChange(std::move(callback));
926 }
927
SetOnScroll(const JSCallbackInfo& info)928 void JSSearch::SetOnScroll(const JSCallbackInfo& info)
929 {
930 CHECK_NULL_VOID(info[0]->IsFunction());
931 JsEventCallback<void(float, float)> callback(info.GetExecutionContext(), JSRef<JSFunc>::Cast(info[0]));
932 SearchModel::GetInstance()->SetOnScroll(std::move(callback));
933 }
934
SetHeight(const JSCallbackInfo& info)935 void JSSearch::SetHeight(const JSCallbackInfo& info)
936 {
937 JSViewAbstract::JsHeight(info);
938 CalcDimension value;
939 auto versionTenOrLarger = Container::GreatOrEqualAPIVersion(PlatformVersion::VERSION_TEN);
940 if (versionTenOrLarger ? !ParseJsDimensionVpNG(info[0], value) : !ParseJsDimensionVp(info[0], value)) {
941 return;
942 }
943 if (LessNotEqual(value.Value(), 0.0)) {
944 value.SetValue(0.0);
945 }
946 SearchModel::GetInstance()->SetHeight(value);
947 }
948
SetOnCopy(const JSCallbackInfo& info)949 void JSSearch::SetOnCopy(const JSCallbackInfo& info)
950 {
951 CHECK_NULL_VOID(info[0]->IsFunction());
952 JsEventCallback<void(const std::string&)> callback(info.GetExecutionContext(), JSRef<JSFunc>::Cast(info[0]));
953 SearchModel::GetInstance()->SetOnCopy(std::move(callback));
954 }
955
SetOnCut(const JSCallbackInfo& info)956 void JSSearch::SetOnCut(const JSCallbackInfo& info)
957 {
958 CHECK_NULL_VOID(info[0]->IsFunction());
959 JsEventCallback<void(const std::string&)> callback(info.GetExecutionContext(), JSRef<JSFunc>::Cast(info[0]));
960 SearchModel::GetInstance()->SetOnCut(std::move(callback));
961 }
962
CreateJSTextCommonEvent(NG::TextCommonEvent& event)963 JSRef<JSVal> JSSearch::CreateJSTextCommonEvent(NG::TextCommonEvent& event)
964 {
965 JSRef<JSObjTemplate> objectTemplate = JSRef<JSObjTemplate>::New();
966 objectTemplate->SetInternalFieldCount(1);
967 JSRef<JSObject> object = objectTemplate->NewInstance();
968 object->SetPropertyObject("preventDefault", JSRef<JSFunc>::New<FunctionCallback>(JsPreventDefault));
969 object->Wrap<NG::TextCommonEvent>(&event);
970 return JSRef<JSVal>::Cast(object);
971 }
972
SetOnPaste(const JSCallbackInfo& info)973 void JSSearch::SetOnPaste(const JSCallbackInfo& info)
974 {
975 CHECK_NULL_VOID(info[0]->IsFunction());
976 auto jsTextFunc = AceType::MakeRefPtr<JsCitedEventFunction<NG::TextCommonEvent, 2>>(
977 JSRef<JSFunc>::Cast(info[0]), CreateJSTextCommonEvent);
978
979 auto onPaste = [execCtx = info.GetExecutionContext(), func = std::move(jsTextFunc)](
980 const std::string& val, NG::TextCommonEvent& info) {
981 JAVASCRIPT_EXECUTION_SCOPE_WITH_CHECK(execCtx);
982 ACE_SCORING_EVENT("onPaste");
983 func->Execute(val, info);
984 #if !defined(PREVIEW) && defined(OHOS_PLATFORM)
985 UiSessionManager::GetInstance().ReportComponentChangeEvent("event", "onPaste");
986 #endif
987 };
988 SearchModel::GetInstance()->SetOnPasteWithEvent(std::move(onPaste));
989 }
990
SetCopyOption(const JSCallbackInfo& info)991 void JSSearch::SetCopyOption(const JSCallbackInfo& info)
992 {
993 if (info.Length() == 0) {
994 return;
995 }
996 if (info[0]->IsUndefined()) {
997 SearchModel::GetInstance()->SetCopyOption(CopyOptions::Local);
998 return;
999 }
1000 auto copyOptions = CopyOptions::Local;
1001 if (info[0]->IsNumber()) {
1002 auto emunNumber = info[0]->ToNumber<int>();
1003 copyOptions = static_cast<CopyOptions>(emunNumber);
1004 }
1005 SearchModel::GetInstance()->SetCopyOption(copyOptions);
1006 }
1007
CreateJsAboutToIMEInputObj(const InsertValueInfo& insertValue)1008 JSRef<JSVal> JSSearch::CreateJsAboutToIMEInputObj(const InsertValueInfo& insertValue)
1009 {
1010 JSRef<JSObject> aboutToIMEInputObj = JSRef<JSObject>::New();
1011 aboutToIMEInputObj->SetProperty<int32_t>("insertOffset", insertValue.insertOffset);
1012 aboutToIMEInputObj->SetProperty<std::string>("insertValue", insertValue.insertValue);
1013 return JSRef<JSVal>::Cast(aboutToIMEInputObj);
1014 }
1015
OnWillInsertValue(const JSCallbackInfo& info)1016 void JSSearch::OnWillInsertValue(const JSCallbackInfo& info)
1017 {
1018 auto jsValue = info[0];
1019 CHECK_NULL_VOID(jsValue->IsFunction());
1020 auto jsAboutToIMEInputFunc = AceType::MakeRefPtr<JsEventFunction<InsertValueInfo, 1>>(
1021 JSRef<JSFunc>::Cast(jsValue), CreateJsAboutToIMEInputObj);
1022 auto callback = [execCtx = info.GetExecutionContext(), func = std::move(jsAboutToIMEInputFunc)](
1023 const InsertValueInfo& insertValue) -> bool {
1024 JAVASCRIPT_EXECUTION_SCOPE_WITH_CHECK(execCtx, true);
1025 auto ret = func->ExecuteWithValue(insertValue);
1026 if (ret->IsBoolean()) {
1027 return ret->ToBoolean();
1028 }
1029 return true;
1030 };
1031 SearchModel::GetInstance()->SetOnWillInsertValueEvent(std::move(callback));
1032 }
1033
CreateJsDeleteToIMEObj(const DeleteValueInfo& deleteValueInfo)1034 JSRef<JSVal> JSSearch::CreateJsDeleteToIMEObj(const DeleteValueInfo& deleteValueInfo)
1035 {
1036 JSRef<JSObject> aboutToIMEInputObj = JSRef<JSObject>::New();
1037 aboutToIMEInputObj->SetProperty<int32_t>("deleteOffset", deleteValueInfo.deleteOffset);
1038 aboutToIMEInputObj->SetProperty<int32_t>("direction", static_cast<int32_t>(deleteValueInfo.direction));
1039 aboutToIMEInputObj->SetProperty<std::string>("deleteValue", deleteValueInfo.deleteValue);
1040 return JSRef<JSVal>::Cast(aboutToIMEInputObj);
1041 }
1042
OnDidInsertValue(const JSCallbackInfo& info)1043 void JSSearch::OnDidInsertValue(const JSCallbackInfo& info)
1044 {
1045 auto jsValue = info[0];
1046 CHECK_NULL_VOID(jsValue->IsFunction());
1047 auto jsAboutToIMEInputFunc = AceType::MakeRefPtr<JsEventFunction<InsertValueInfo, 1>>(
1048 JSRef<JSFunc>::Cast(jsValue), CreateJsAboutToIMEInputObj);
1049 auto callback = [execCtx = info.GetExecutionContext(), func = std::move(jsAboutToIMEInputFunc)](
1050 const InsertValueInfo& insertValue) {
1051 JAVASCRIPT_EXECUTION_SCOPE_WITH_CHECK(execCtx);
1052 func->ExecuteWithValue(insertValue);
1053 };
1054 SearchModel::GetInstance()->SetOnDidInsertValueEvent(std::move(callback));
1055 }
1056
OnWillDelete(const JSCallbackInfo& info)1057 void JSSearch::OnWillDelete(const JSCallbackInfo& info)
1058 {
1059 auto jsValue = info[0];
1060 CHECK_NULL_VOID(jsValue->IsFunction());
1061 auto jsAboutToIMEInputFunc =
1062 AceType::MakeRefPtr<JsEventFunction<DeleteValueInfo, 1>>(JSRef<JSFunc>::Cast(jsValue), CreateJsDeleteToIMEObj);
1063 auto callback = [execCtx = info.GetExecutionContext(), func = std::move(jsAboutToIMEInputFunc)](
1064 const DeleteValueInfo& deleteValue) {
1065 JAVASCRIPT_EXECUTION_SCOPE_WITH_CHECK(execCtx, true);
1066 auto ret = func->ExecuteWithValue(deleteValue);
1067 if (ret->IsBoolean()) {
1068 return ret->ToBoolean();
1069 }
1070 return true;
1071 };
1072 SearchModel::GetInstance()->SetOnWillDeleteEvent(std::move(callback));
1073 }
1074
OnDidDelete(const JSCallbackInfo& info)1075 void JSSearch::OnDidDelete(const JSCallbackInfo& info)
1076 {
1077 auto jsValue = info[0];
1078 CHECK_NULL_VOID(jsValue->IsFunction());
1079 auto jsAboutToIMEInputFunc =
1080 AceType::MakeRefPtr<JsEventFunction<DeleteValueInfo, 1>>(JSRef<JSFunc>::Cast(jsValue), CreateJsDeleteToIMEObj);
1081 auto callback = [execCtx = info.GetExecutionContext(), func = std::move(jsAboutToIMEInputFunc)](
1082 const DeleteValueInfo& deleteValue) {
1083 JAVASCRIPT_EXECUTION_SCOPE_WITH_CHECK(execCtx);
1084 func->ExecuteWithValue(deleteValue);
1085 };
1086 SearchModel::GetInstance()->SetOnDidDeleteEvent(std::move(callback));
1087 }
1088
SetSelectionMenuHidden(const JSCallbackInfo& info)1089 void JSSearch::SetSelectionMenuHidden(const JSCallbackInfo& info)
1090 {
1091 if (info[0]->IsUndefined() || !info[0]->IsBoolean()) {
1092 SearchModel::GetInstance()->SetSelectionMenuHidden(false);
1093 return;
1094 }
1095 SearchModel::GetInstance()->SetSelectionMenuHidden(info[0]->ToBoolean());
1096 }
1097
SetCustomKeyboard(const JSCallbackInfo& info)1098 void JSSearch::SetCustomKeyboard(const JSCallbackInfo& info)
1099 {
1100 if (info.Length() > 0 && (info[0]->IsUndefined() || info[0]->IsNull())) {
1101 SearchModel::GetInstance()->SetCustomKeyboard(nullptr);
1102 return;
1103 }
1104 if (info.Length() < 1 || !info[0]->IsObject()) {
1105 return;
1106 }
1107 bool supportAvoidance = false;
1108 if (info.Length() == 2 && info[1]->IsObject()) { // 2 here refers to the number of parameters
1109 auto paramObject = JSRef<JSObject>::Cast(info[1]);
1110 auto isSupportAvoidance = paramObject->GetProperty("supportAvoidance");
1111 if (!isSupportAvoidance->IsNull() && isSupportAvoidance->IsBoolean()) {
1112 supportAvoidance = isSupportAvoidance->ToBoolean();
1113 }
1114 }
1115 std::function<void()> buildFunc;
1116 if (JSTextField::ParseJsCustomKeyboardBuilder(info, 0, buildFunc)) {
1117 SearchModel::GetInstance()->SetCustomKeyboard(std::move(buildFunc), supportAvoidance);
1118 }
1119 }
1120
SetType(const JSCallbackInfo& info)1121 void JSSearch::SetType(const JSCallbackInfo& info)
1122 {
1123 if (info.Length() < 1) {
1124 return;
1125 }
1126 if (info[0]->IsUndefined()) {
1127 SearchModel::GetInstance()->SetType(TextInputType::UNSPECIFIED);
1128 return;
1129 }
1130 if (!info[0]->IsNumber()) {
1131 return;
1132 }
1133 TextInputType textInputType = CastToTextInputType(info[0]->ToNumber<int32_t>());
1134 SearchModel::GetInstance()->SetType(textInputType);
1135 }
1136
JSBind(BindingTarget globalObj)1137 void JSSearchController::JSBind(BindingTarget globalObj)
1138 {
1139 JSClass<JSTextEditableController>::Declare("SearchController");
1140 JSTextEditableController::JSBind(globalObj);
1141 }
1142
SetEnterKeyType(const JSCallbackInfo& info)1143 void JSSearch::SetEnterKeyType(const JSCallbackInfo& info)
1144 {
1145 if (info.Length() < 1) {
1146 return;
1147 }
1148 if (info[0]->IsUndefined()) {
1149 SearchModel::GetInstance()->SetSearchEnterKeyType(TextInputAction::SEARCH);
1150 return;
1151 }
1152 if (!info[0]->IsNumber()) {
1153 return;
1154 }
1155 TextInputAction textInputAction = CastToTextInputAction(info[0]->ToNumber<int32_t>());
1156 SearchModel::GetInstance()->SetSearchEnterKeyType(textInputAction);
1157 }
1158
SetMaxLength(const JSCallbackInfo& info)1159 void JSSearch::SetMaxLength(const JSCallbackInfo& info)
1160 {
1161 int32_t maxLength = 0;
1162 if (info[0]->IsUndefined()) {
1163 SearchModel::GetInstance()->ResetMaxLength();
1164 return;
1165 } else if (!info[0]->IsNumber()) {
1166 SearchModel::GetInstance()->ResetMaxLength();
1167 return;
1168 }
1169 maxLength = info[0]->ToNumber<int32_t>();
1170 if (std::isinf(info[0]->ToNumber<float>())) {
1171 maxLength = INT32_MAX; // Infinity
1172 }
1173 if (GreatOrEqual(maxLength, 0)) {
1174 SearchModel::GetInstance()->SetMaxLength(maxLength);
1175 } else {
1176 SearchModel::GetInstance()->ResetMaxLength();
1177 }
1178 }
1179
SetDecoration(const JSCallbackInfo& info)1180 void JSSearch::SetDecoration(const JSCallbackInfo& info)
1181 {
1182 do {
1183 auto tmpInfo = info[0];
1184 if (!tmpInfo->IsObject()) {
1185 SearchModel::GetInstance()->SetTextDecoration(TextDecoration::NONE);
1186 SearchModel::GetInstance()->SetTextDecorationColor(Color::BLACK);
1187 SearchModel::GetInstance()->SetTextDecorationStyle(TextDecorationStyle::SOLID);
1188 break;
1189 }
1190 JSRef<JSObject> obj = JSRef<JSObject>::Cast(tmpInfo);
1191 JSRef<JSVal> typeValue = obj->GetProperty("type");
1192 JSRef<JSVal> colorValue = obj->GetProperty("color");
1193 JSRef<JSVal> styleValue = obj->GetProperty("style");
1194
1195 auto pipelineContext = PipelineBase::GetCurrentContext();
1196 CHECK_NULL_VOID(pipelineContext);
1197 auto theme = pipelineContext->GetTheme<SearchTheme>();
1198 CHECK_NULL_VOID(theme);
1199 TextDecoration textDecoration = theme->GetTextStyle().GetTextDecoration();
1200 if (typeValue->IsNumber()) {
1201 textDecoration = static_cast<TextDecoration>(typeValue->ToNumber<int32_t>());
1202 }
1203 Color result = theme->GetTextStyle().GetTextDecorationColor();
1204 ParseJsColor(colorValue, result, Color::BLACK);
1205 std::optional<TextDecorationStyle> textDecorationStyle;
1206 if (styleValue->IsNumber()) {
1207 textDecorationStyle = static_cast<TextDecorationStyle>(styleValue->ToNumber<int32_t>());
1208 } else {
1209 textDecorationStyle = DEFAULT_TEXT_DECORATION_STYLE;
1210 }
1211 SearchModel::GetInstance()->SetTextDecoration(textDecoration);
1212 SearchModel::GetInstance()->SetTextDecorationColor(result);
1213 if (textDecorationStyle) {
1214 SearchModel::GetInstance()->SetTextDecorationStyle(textDecorationStyle.value());
1215 }
1216 } while (false);
1217 }
1218
SetMinFontSize(const JSCallbackInfo& info)1219 void JSSearch::SetMinFontSize(const JSCallbackInfo& info)
1220 {
1221 if (info.Length() < 1) {
1222 return;
1223 }
1224 CalcDimension minFontSize;
1225 if (!ParseJsDimensionFpNG(info[0], minFontSize, false)) {
1226 SearchModel::GetInstance()->SetAdaptMinFontSize(CalcDimension());
1227 return;
1228 }
1229 if (minFontSize.IsNegative()) {
1230 minFontSize = CalcDimension();
1231 }
1232 SearchModel::GetInstance()->SetAdaptMinFontSize(minFontSize);
1233 }
1234
SetMaxFontSize(const JSCallbackInfo& info)1235 void JSSearch::SetMaxFontSize(const JSCallbackInfo& info)
1236 {
1237 if (info.Length() < 1) {
1238 return;
1239 }
1240 auto pipelineContext = PipelineBase::GetCurrentContext();
1241 CHECK_NULL_VOID(pipelineContext);
1242 auto theme = pipelineContext->GetTheme<SearchTheme>();
1243 CHECK_NULL_VOID(theme);
1244 CalcDimension maxFontSize = theme->GetTextStyle().GetAdaptMaxFontSize();
1245 if (!ParseJsDimensionFpNG(info[0], maxFontSize, false)) {
1246 maxFontSize = theme->GetTextStyle().GetAdaptMaxFontSize();
1247 SearchModel::GetInstance()->SetAdaptMaxFontSize(maxFontSize);
1248 return;
1249 }
1250 if (maxFontSize.IsNegative()) {
1251 maxFontSize = theme->GetTextStyle().GetAdaptMaxFontSize();
1252 }
1253 SearchModel::GetInstance()->SetAdaptMaxFontSize(maxFontSize);
1254 }
1255
SetLetterSpacing(const JSCallbackInfo& info)1256 void JSSearch::SetLetterSpacing(const JSCallbackInfo& info)
1257 {
1258 CalcDimension value;
1259 if (!ParseJsDimensionFpNG(info[0], value, false)) {
1260 value.Reset();
1261 SearchModel::GetInstance()->SetLetterSpacing(value);
1262 return;
1263 }
1264 SearchModel::GetInstance()->SetLetterSpacing(value);
1265 }
1266
SetLineHeight(const JSCallbackInfo& info)1267 void JSSearch::SetLineHeight(const JSCallbackInfo& info)
1268 {
1269 CalcDimension value;
1270 if (!ParseJsDimensionFpNG(info[0], value)) {
1271 value.Reset();
1272 SearchModel::GetInstance()->SetLineHeight(value);
1273 return;
1274 }
1275 if (value.IsNegative()) {
1276 value.Reset();
1277 }
1278 SearchModel::GetInstance()->SetLineHeight(value);
1279 }
1280
EditMenuOptions(const JSCallbackInfo& info)1281 void JSSearch::EditMenuOptions(const JSCallbackInfo& info)
1282 {
1283 NG::OnCreateMenuCallback onCreateMenuCallback;
1284 NG::OnMenuItemClickCallback onMenuItemClick;
1285 JSViewAbstract::ParseEditMenuOptions(info, onCreateMenuCallback, onMenuItemClick);
1286 SearchModel::GetInstance()->SetSelectionMenuOptions(std::move(onCreateMenuCallback), std::move(onMenuItemClick));
1287 }
1288
SetEnablePreviewText(const JSCallbackInfo& info)1289 void JSSearch::SetEnablePreviewText(const JSCallbackInfo& info)
1290 {
1291 auto jsValue = info[0];
1292 if (!jsValue->IsBoolean()) {
1293 SearchModel::GetInstance()->SetEnablePreviewText(true);
1294 return;
1295 }
1296 SearchModel::GetInstance()->SetEnablePreviewText(jsValue->ToBoolean());
1297 }
1298
SetEnableHapticFeedback(const JSCallbackInfo& info)1299 void JSSearch::SetEnableHapticFeedback(const JSCallbackInfo& info)
1300 {
1301 bool state = true;
1302 if (info.Length() > 0 && info[0]->IsBoolean()) {
1303 state = info[0]->ToBoolean();
1304 }
1305 SearchModel::GetInstance()->SetEnableHapticFeedback(state);
1306 }
1307 } // namespace OHOS::Ace::Framework
1308