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