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