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