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
21 #include "base/log/ace_scoring_log.h"
22 #include "bridge/declarative_frontend/jsview/js_textfield.h"
23 #include "bridge/declarative_frontend/jsview/js_textinput.h"
24 #include "bridge/declarative_frontend/jsview/js_view_common_def.h"
25 #include "bridge/declarative_frontend/jsview/models/search_model_impl.h"
26 #include "core/components/common/layout/constants.h"
27 #include "core/components/search/search_theme.h"
28 #include "core/components_ng/pattern/search/search_model_ng.h"
29 #include "core/components_ng/pattern/text_field/text_field_model_ng.h"
30
31 namespace OHOS::Ace {
32
33 std::unique_ptr<SearchModel> SearchModel::instance_ = nullptr;
34 std::mutex SearchModel::mutex_;
35
GetInstance()36 SearchModel* SearchModel::GetInstance()
37 {
38 if (!instance_) {
39 std::lock_guard<std::mutex> lock(mutex_);
40 if (!instance_) {
41 #ifdef NG_BUILD
42 instance_.reset(new NG::SearchModelNG());
43 #else
44 if (Container::IsCurrentUseNewPipeline()) {
45 instance_.reset(new NG::SearchModelNG());
46 } else {
47 instance_.reset(new Framework::SearchModelImpl());
48 }
49 #endif
50 }
51 }
52 return instance_.get();
53 }
54
55 } // namespace OHOS::Ace
56
57 namespace OHOS::Ace::Framework {
58 const static int32_t PLATFORM_VERSION_TEN = 10;
59 namespace {
60 const std::vector<TextAlign> TEXT_ALIGNS = { TextAlign::START, TextAlign::CENTER, TextAlign::END };
61 } // namespace
62
JSBind(BindingTarget globalObj)63 void JSSearch::JSBind(BindingTarget globalObj)
64 {
65 JSClass<JSSearch>::Declare("Search");
66 MethodOptions opt = MethodOptions::NONE;
67
68 JSClass<JSSearch>::StaticMethod("create", &JSSearch::Create, opt);
69 JSClass<JSSearch>::StaticMethod("searchButton", &JSSearch::SetSearchButton, opt);
70 JSClass<JSSearch>::StaticMethod("searchIcon", &JSSearch::SetSearchIcon, opt);
71 JSClass<JSSearch>::StaticMethod("cancelButton", &JSSearch::SetCancelButton, opt);
72 JSClass<JSSearch>::StaticMethod("fontColor", &JSSearch::SetTextColor, opt);
73 JSClass<JSSearch>::StaticMethod("caretStyle", &JSSearch::SetCaret, opt);
74 JSClass<JSSearch>::StaticMethod("placeholderColor", &JSSearch::SetPlaceholderColor, opt);
75 JSClass<JSSearch>::StaticMethod("placeholderFont", &JSSearch::SetPlaceholderFont, opt);
76 JSClass<JSSearch>::StaticMethod("textFont", &JSSearch::SetTextFont, opt);
77 JSClass<JSSearch>::StaticMethod("textAlign", &JSSearch::SetTextAlign, opt);
78 JSClass<JSSearch>::StaticMethod("onSubmit", &JSSearch::OnSubmit, opt);
79 JSClass<JSSearch>::StaticMethod("onChange", &JSSearch::OnChange, opt);
80 JSClass<JSSearch>::StaticMethod("onTextSelectionChange", &JSSearch::SetOnTextSelectionChange);
81 JSClass<JSSearch>::StaticMethod("onContentScroll", &JSSearch::SetOnScroll);
82 JSClass<JSSearch>::StaticMethod("border", &JSSearch::JsBorder);
83 JSClass<JSSearch>::StaticMethod("borderWidth", &JSSearch::JsBorderWidth);
84 JSClass<JSSearch>::StaticMethod("borderColor", &JSSearch::JsBorderColor);
85 JSClass<JSSearch>::StaticMethod("borderStyle", &JSSearch::JsBorderStyle);
86 JSClass<JSSearch>::StaticMethod("borderRadius", &JSSearch::JsBorderRadius);
87 JSClass<JSSearch>::StaticMethod("onTouch", &JSInteractableView::JsOnTouch);
88 JSClass<JSSearch>::StaticMethod("height", &JSSearch::SetHeight);
89 JSClass<JSSearch>::StaticMethod("width", &JSViewAbstract::JsWidth);
90 JSClass<JSSearch>::StaticMethod("onKeyEvent", &JSInteractableView::JsOnKey);
91 JSClass<JSSearch>::StaticMethod("onDeleteEvent", &JSInteractableView::JsOnDelete);
92 JSClass<JSSearch>::StaticMethod("onClick", &JSInteractableView::JsOnClick);
93 JSClass<JSSearch>::StaticMethod("requestKeyboardOnFocus", &JSSearch::SetEnableKeyboardOnFocus);
94 JSClass<JSSearch>::StaticMethod("enableKeyboardOnFocus", &JSSearch::SetEnableKeyboardOnFocus);
95 JSClass<JSSearch>::StaticMethod("onAppear", &JSInteractableView::JsOnAppear);
96 JSClass<JSSearch>::StaticMethod("onDisAppear", &JSInteractableView::JsOnDisAppear);
97 JSClass<JSSearch>::StaticMethod("onCopy", &JSSearch::SetOnCopy);
98 JSClass<JSSearch>::StaticMethod("onCut", &JSSearch::SetOnCut);
99 JSClass<JSSearch>::StaticMethod("onPaste", &JSSearch::SetOnPaste);
100 JSClass<JSSearch>::StaticMethod("copyOption", &JSSearch::SetCopyOption);
101 JSClass<JSSearch>::StaticMethod("textMenuOptions", &JSSearch::JsMenuOptionsExtension);
102 JSClass<JSSearch>::StaticMethod("selectionMenuHidden", &JSSearch::SetSelectionMenuHidden);
103 JSClass<JSSearch>::StaticMethod("customKeyboard", &JSSearch::SetCustomKeyboard);
104 JSClass<JSSearch>::InheritAndBind<JSViewAbstract>(globalObj);
105 }
106
ParseSearchValueObject(const JSCallbackInfo & info,const JSRef<JSVal> & changeEventVal)107 void ParseSearchValueObject(const JSCallbackInfo& info, const JSRef<JSVal>& changeEventVal)
108 {
109 CHECK_NULL_VOID(changeEventVal->IsFunction());
110
111 JsEventCallback<void(const std::string&)> onChangeEvent(
112 info.GetExecutionContext(), JSRef<JSFunc>::Cast(changeEventVal));
113 SearchModel::GetInstance()->SetOnChangeEvent(std::move(onChangeEvent));
114 }
115
Create(const JSCallbackInfo & info)116 void JSSearch::Create(const JSCallbackInfo& info)
117 {
118 std::optional<std::string> key;
119 std::optional<std::string> tip;
120 std::optional<std::string> src;
121 JSSearchController* jsController = nullptr;
122 JSRef<JSVal> changeEventVal;
123 if (info[0]->IsObject()) {
124 auto param = JSRef<JSObject>::Cast(info[0]);
125 std::string placeholder;
126 if (param->GetProperty("placeholder")->IsUndefined()) {
127 tip = "";
128 }
129 if (ParseJsString(param->GetProperty("placeholder"), placeholder)) {
130 tip = placeholder;
131 }
132 std::string text;
133 JSRef<JSVal> textValue = param->GetProperty("value");
134 if (textValue->IsObject()) {
135 JSRef<JSObject> valueObj = JSRef<JSObject>::Cast(textValue);
136 changeEventVal = valueObj->GetProperty("changeEvent");
137 if (changeEventVal->IsFunction()) {
138 textValue = valueObj->GetProperty("value");
139 }
140 if (ParseJsString(textValue, text)) {
141 key = text;
142 }
143 } else {
144 if (ParseJsString(textValue, text)) {
145 key = text;
146 }
147 }
148 std::string icon;
149 if (ParseJsString(param->GetProperty("icon"), icon)) {
150 src = icon;
151 }
152 auto controllerObj = param->GetProperty("controller");
153 if (!controllerObj->IsUndefined() && !controllerObj->IsNull()) {
154 jsController = JSRef<JSObject>::Cast(controllerObj)->Unwrap<JSSearchController>();
155 }
156 }
157 auto controller = SearchModel::GetInstance()->Create(key, tip, src);
158 if (jsController) {
159 jsController->SetController(controller);
160 }
161 SearchModel::GetInstance()->SetFocusable(true);
162 SearchModel::GetInstance()->SetFocusNode(true);
163 if (!changeEventVal->IsUndefined() && changeEventVal->IsFunction()) {
164 ParseSearchValueObject(info, changeEventVal);
165 }
166 }
167
SetEnableKeyboardOnFocus(const JSCallbackInfo & info)168 void JSSearch::SetEnableKeyboardOnFocus(const JSCallbackInfo& info)
169 {
170 if (info.Length() < 1) {
171 LOGW("EnableKeyboardOnFocus should have at least 1 param");
172 return;
173 }
174 if (info[0]->IsUndefined() || !info[0]->IsBoolean()) {
175 LOGI("The info of SetEnableKeyboardOnFocus is not correct, using default");
176 SearchModel::GetInstance()->RequestKeyboardOnFocus(true);
177 return;
178 }
179 SearchModel::GetInstance()->RequestKeyboardOnFocus(info[0]->ToBoolean());
180 }
181
SetSearchButton(const JSCallbackInfo & info)182 void JSSearch::SetSearchButton(const JSCallbackInfo& info)
183 {
184 auto theme = GetTheme<SearchTheme>();
185 CHECK_NULL_VOID_NOLOG(theme);
186 std::string buttonValue;
187 if (!ParseJsString(info[0], buttonValue)) {
188 return;
189 }
190 SearchModel::GetInstance()->SetSearchButton(buttonValue);
191 SearchModel::GetInstance()->SetSearchButtonFontSize(theme->GetFontSize());
192 SearchModel::GetInstance()->SetSearchButtonFontColor(theme->GetSearchButtonTextColor());
193
194 if (info[1]->IsObject()) {
195 auto param = JSRef<JSObject>::Cast(info[1]);
196
197 // set button font size, unit FP
198 auto fontSize = param->GetProperty("fontSize");
199 CalcDimension size = theme->GetFontSize();
200 if (ParseJsDimensionVpNG(fontSize, size) && size.Unit() != DimensionUnit::PERCENT &&
201 GreatOrEqual(size.Value(), 0.0)) {
202 ParseJsDimensionFp(fontSize, size);
203 } else {
204 size = theme->GetFontSize();
205 }
206 SearchModel::GetInstance()->SetSearchButtonFontSize(size);
207
208 // set font color
209 Color fontColor;
210 auto fontColorProp = param->GetProperty("fontColor");
211 if (fontColorProp->IsUndefined() || fontColorProp->IsNull() || !ParseJsColor(fontColorProp, fontColor)) {
212 fontColor = theme->GetSearchButtonTextColor();
213 }
214 SearchModel::GetInstance()->SetSearchButtonFontColor(fontColor);
215 }
216 }
217
SetSearchIcon(const JSCallbackInfo & info)218 void JSSearch::SetSearchIcon(const JSCallbackInfo& info)
219 {
220 if (info[0]->IsObject()) {
221 auto param = JSRef<JSObject>::Cast(info[0]);
222 auto theme = GetTheme<SearchTheme>();
223 CHECK_NULL_VOID_NOLOG(theme);
224
225 // set icon size
226 CalcDimension size;
227 auto sizeProp = param->GetProperty("size");
228 if (!sizeProp->IsUndefined() && !sizeProp->IsNull() && ParseJsDimensionVpNG(sizeProp, size)) {
229 if (LessNotEqual(size.Value(), 0.0) || size.Unit() == DimensionUnit::PERCENT) {
230 size = theme->GetIconHeight();
231 }
232 } else {
233 size = theme->GetIconHeight();
234 }
235 SearchModel::GetInstance()->SetSearchIconSize(size);
236
237 // set icon src
238 std::string src;
239 auto srcPathProp = param->GetProperty("src");
240 if (srcPathProp->IsUndefined() || srcPathProp->IsNull() || !ParseJsMedia(srcPathProp, src)) {
241 src = "";
242 }
243 SearchModel::GetInstance()->SetSearchSrcPath(src);
244
245 // set icon color
246 Color colorVal;
247 auto colorProp = param->GetProperty("color");
248 if (!colorProp->IsUndefined() && !colorProp->IsNull() && ParseJsColor(colorProp, colorVal)) {
249 SearchModel::GetInstance()->SetSearchIconColor(colorVal);
250 }
251 }
252 }
253
ConvertStrToCancelButtonStyle(const std::string & value)254 static CancelButtonStyle ConvertStrToCancelButtonStyle(const std::string& value)
255 {
256 if (value == "CONSTANT") {
257 return CancelButtonStyle::CONSTANT;
258 } else if (value == "INVISIBLE") {
259 return CancelButtonStyle::INVISIBLE;
260 } else {
261 return CancelButtonStyle::INPUT;
262 }
263 }
264
SetCancelButton(const JSCallbackInfo & info)265 void JSSearch::SetCancelButton(const JSCallbackInfo& info)
266 {
267 if (!info[0]->IsObject()) {
268 LOGI("ivalid argvs");
269 return;
270 }
271 auto param = JSRef<JSObject>::Cast(info[0]);
272 auto theme = GetTheme<SearchTheme>();
273 CHECK_NULL_VOID_NOLOG(theme);
274
275 // set style
276 std::string styleStr;
277 CancelButtonStyle cancelButtonStyle;
278 auto styleProp = param->GetProperty("style");
279 if (!styleProp->IsUndefined() && !styleProp->IsNull() && ParseJsString(styleProp, styleStr)) {
280 cancelButtonStyle = ConvertStrToCancelButtonStyle(styleStr);
281 } else {
282 cancelButtonStyle = theme->GetCancelButtonStyle();
283 }
284 SearchModel::GetInstance()->SetCancelButtonStyle(cancelButtonStyle);
285
286 auto iconProp = param->GetProperty("icon");
287 if (iconProp->IsUndefined() || iconProp->IsNull()) {
288 LOGI("icon is null");
289 SearchModel::GetInstance()->SetCancelIconSize(theme->GetIconHeight());
290 SearchModel::GetInstance()->SetCancelIconColor(theme->GetSearchIconColor());
291 SearchModel::GetInstance()->SetRightIconSrcPath("");
292 } else {
293 SetIconStyle(info);
294 }
295 }
296
SetIconStyle(const JSCallbackInfo & info)297 void JSSearch::SetIconStyle(const JSCallbackInfo& info)
298 {
299 if (!info[0]->IsObject()) {
300 return;
301 }
302 auto param = JSRef<JSObject>::Cast(info[0]);
303 auto iconJsVal = param->GetProperty("icon");
304 if (!iconJsVal->IsObject()) {
305 return;
306 }
307 auto iconParam = JSRef<JSObject>::Cast(iconJsVal);
308 // set icon size
309 CalcDimension iconSize;
310 auto iconSizeProp = iconParam->GetProperty("size");
311 auto theme = GetTheme<SearchTheme>();
312 if (!iconSizeProp->IsUndefined() && !iconSizeProp->IsNull() && ParseJsDimensionVpNG(iconSizeProp, iconSize)) {
313 if (LessOrEqual(iconSize.Value(), 0.0) || iconSize.Unit() == DimensionUnit::PERCENT) {
314 iconSize = theme->GetIconHeight();
315 }
316 } else {
317 iconSize = theme->GetIconHeight();
318 }
319 SearchModel::GetInstance()->SetCancelIconSize(iconSize);
320
321 // set icon src
322 std::string iconSrc;
323 auto iconSrcProp = iconParam->GetProperty("src");
324 if (iconSrcProp->IsUndefined() || iconSrcProp->IsNull() || !ParseJsMedia(iconSrcProp, iconSrc)) {
325 iconSrc = "";
326 }
327 SearchModel::GetInstance()->SetRightIconSrcPath(iconSrc);
328
329 // set icon color
330 Color iconColor;
331 auto iconColorProp = iconParam->GetProperty("color");
332 if (!iconColorProp->IsUndefined() && !iconColorProp->IsNull() && ParseJsColor(iconColorProp, iconColor)) {
333 SearchModel::GetInstance()->SetCancelIconColor(iconColor);
334 }
335 }
336
SetTextColor(const JSCallbackInfo & info)337 void JSSearch::SetTextColor(const JSCallbackInfo& info)
338 {
339 auto theme = GetTheme<SearchTheme>();
340 CHECK_NULL_VOID_NOLOG(theme);
341
342 auto value = JSRef<JSVal>::Cast(info[0]);
343 Color colorVal;
344 if (!ParseJsColor(value, colorVal)) {
345 colorVal = theme->GetTextColor();
346 }
347 SearchModel::GetInstance()->SetTextColor(colorVal);
348 }
349
SetCaret(const JSCallbackInfo & info)350 void JSSearch::SetCaret(const JSCallbackInfo& info)
351 {
352 if (info[0]->IsObject()) {
353 auto param = JSRef<JSObject>::Cast(info[0]);
354 auto textFieldTheme = GetTheme<TextFieldTheme>();
355 CHECK_NULL_VOID_NOLOG(textFieldTheme);
356
357 // set caret width
358 CalcDimension caretWidth = textFieldTheme->GetCursorWidth();
359 auto caretWidthProp = param->GetProperty("width");
360 if (!ParseJsDimensionVpNG(caretWidthProp, caretWidth, false) || LessNotEqual(caretWidth.Value(), 0.0)) {
361 caretWidth = textFieldTheme->GetCursorWidth();
362 }
363 SearchModel::GetInstance()->SetCaretWidth(caretWidth);
364
365 // set caret color
366 Color caretColor;
367 auto caretColorProp = param->GetProperty("color");
368 if (caretColorProp->IsUndefined() || caretColorProp->IsNull() || !ParseJsColor(caretColorProp, caretColor)) {
369 caretColor = textFieldTheme->GetCursorColor();
370 }
371 SearchModel::GetInstance()->SetCaretColor(caretColor);
372 }
373 }
374
SetPlaceholderColor(const JSCallbackInfo & info)375 void JSSearch::SetPlaceholderColor(const JSCallbackInfo& info)
376 {
377 auto value = JSRef<JSVal>::Cast(info[0]);
378 Color colorVal;
379 if (ParseJsColor(value, colorVal)) {
380 SearchModel::GetInstance()->SetPlaceholderColor(colorVal);
381 }
382 }
383
SetPlaceholderFont(const JSCallbackInfo & info)384 void JSSearch::SetPlaceholderFont(const JSCallbackInfo& info)
385 {
386 if (!info[0]->IsObject()) {
387 return;
388 }
389 auto param = JSRef<JSObject>::Cast(info[0]);
390 auto theme = GetTheme<SearchTheme>();
391 CHECK_NULL_VOID_NOLOG(theme);
392 auto themeFontSize = theme->GetFontSize();
393 Font font;
394 auto fontSize = param->GetProperty("size");
395 if (fontSize->IsNull() || fontSize->IsUndefined()) {
396 font.fontSize = themeFontSize;
397 } else {
398 auto versionTenOrLarger = PipelineBase::GetCurrentContext() &&
399 PipelineBase::GetCurrentContext()->GetMinPlatformVersion() >= PLATFORM_VERSION_TEN;
400 CalcDimension size;
401 if ((versionTenOrLarger ? ParseJsDimensionVpNG(fontSize, size) : ParseJsDimensionVp(fontSize, size)) &&
402 size.Unit() != DimensionUnit::PERCENT) {
403 ParseJsDimensionFp(fontSize, size);
404 font.fontSize = size;
405 } else {
406 font.fontSize = themeFontSize;
407 }
408 }
409
410 auto weight = param->GetProperty("weight");
411 if (!weight->IsNull()) {
412 std::string weightVal;
413 if (weight->IsNumber()) {
414 weightVal = std::to_string(weight->ToNumber<int32_t>());
415 } else {
416 ParseJsString(weight, weightVal);
417 }
418 font.fontWeight = ConvertStrToFontWeight(weightVal);
419 }
420
421 auto family = param->GetProperty("family");
422 if (!family->IsNull() && family->IsString()) {
423 auto familyVal = family->ToString();
424 font.fontFamilies = ConvertStrToFontFamilies(familyVal);
425 }
426
427 auto style = param->GetProperty("style");
428 if (!style->IsNull() && style->IsNumber()) {
429 FontStyle styleVal = static_cast<FontStyle>(style->ToNumber<int32_t>());
430 font.fontStyle = styleVal;
431 }
432 SearchModel::GetInstance()->SetPlaceholderFont(font);
433 }
434
SetTextFont(const JSCallbackInfo & info)435 void JSSearch::SetTextFont(const JSCallbackInfo& info)
436 {
437 if (info.Length() < 1 || !info[0]->IsObject()) {
438 return;
439 }
440 auto param = JSRef<JSObject>::Cast(info[0]);
441 auto theme = GetTheme<SearchTheme>();
442 CHECK_NULL_VOID_NOLOG(theme);
443 auto themeFontSize = theme->GetFontSize();
444 Font font;
445 auto fontSize = param->GetProperty("size");
446 CalcDimension size = themeFontSize;
447 if (ParseJsDimensionVpNG(fontSize, size) && size.Unit() != DimensionUnit::PERCENT &&
448 GreatOrEqual(size.Value(), 0.0)) {
449 ParseJsDimensionFp(fontSize, size);
450 } else {
451 size = themeFontSize;
452 }
453 font.fontSize = size;
454
455 auto weight = param->GetProperty("weight");
456 if (!weight->IsNull()) {
457 std::string weightVal;
458 if (weight->IsNumber()) {
459 weightVal = std::to_string(weight->ToNumber<int32_t>());
460 } else {
461 ParseJsString(weight, weightVal);
462 }
463 font.fontWeight = ConvertStrToFontWeight(weightVal);
464 }
465
466 auto family = param->GetProperty("family");
467 if (!family->IsNull() && family->IsString()) {
468 auto familyVal = family->ToString();
469 font.fontFamilies = ConvertStrToFontFamilies(familyVal);
470 }
471
472 auto style = param->GetProperty("style");
473 if (!style->IsNull() && style->IsNumber()) {
474 FontStyle styleVal = static_cast<FontStyle>(style->ToNumber<int32_t>());
475 font.fontStyle = styleVal;
476 }
477 SearchModel::GetInstance()->SetTextFont(font);
478 }
479
SetTextAlign(int32_t value)480 void JSSearch::SetTextAlign(int32_t value)
481 {
482 if (value >= 0 && value < static_cast<int32_t>(TEXT_ALIGNS.size())) {
483 SearchModel::GetInstance()->SetTextAlign(TEXT_ALIGNS[value]);
484 } else {
485 LOGE("the value is error");
486 }
487 }
488
JsBorder(const JSCallbackInfo & info)489 void JSSearch::JsBorder(const JSCallbackInfo& info)
490 {
491 JSViewAbstract::JsBorder(info);
492 if (!info[0]->IsObject()) {
493 LOGE("args is not a object. %s", info[0]->ToString().c_str());
494 return;
495 }
496 RefPtr<Decoration> decoration = nullptr;
497 JSRef<JSObject> object = JSRef<JSObject>::Cast(info[0]);
498 auto valueWidth = object->GetProperty("width");
499 if (!valueWidth->IsUndefined()) {
500 ParseBorderWidth(valueWidth);
501 }
502 auto valueColor = object->GetProperty("color");
503 if (!valueColor->IsUndefined()) {
504 ParseBorderColor(valueColor);
505 }
506 auto valueRadius = object->GetProperty("radius");
507 if (!valueRadius->IsUndefined()) {
508 ParseBorderRadius(valueRadius);
509 }
510 auto valueStyle = object->GetProperty("style");
511 if (!valueStyle->IsUndefined()) {
512 ParseBorderStyle(valueStyle);
513 }
514 SearchModel::GetInstance()->SetBackBorder();
515 info.ReturnSelf();
516 }
517
JsBorderWidth(const JSCallbackInfo & info)518 void JSSearch::JsBorderWidth(const JSCallbackInfo& info)
519 {
520 JSViewAbstract::JsBorderWidth(info);
521 if (!info[0]->IsObject() && !info[0]->IsString() && !info[0]->IsNumber()) {
522 LOGE("args need a string or number or object");
523 return;
524 }
525 SearchModel::GetInstance()->SetBackBorder();
526 }
527
JsBorderColor(const JSCallbackInfo & info)528 void JSSearch::JsBorderColor(const JSCallbackInfo& info)
529 {
530 JSViewAbstract::JsBorderColor(info);
531 if (!info[0]->IsObject() && !info[0]->IsString() && !info[0]->IsNumber()) {
532 LOGE("args need a string or number or object");
533 return;
534 }
535 SearchModel::GetInstance()->SetBackBorder();
536 }
537
JsBorderStyle(const JSCallbackInfo & info)538 void JSSearch::JsBorderStyle(const JSCallbackInfo& info)
539 {
540 JSViewAbstract::JsBorderStyle(info);
541 if (!info[0]->IsObject() && !info[0]->IsNumber()) {
542 LOGE("args need a string or number or object");
543 return;
544 }
545 SearchModel::GetInstance()->SetBackBorder();
546 }
547
JsBorderRadius(const JSCallbackInfo & info)548 void JSSearch::JsBorderRadius(const JSCallbackInfo& info)
549 {
550 JSViewAbstract::JsBorderRadius(info);
551 if (!info[0]->IsObject() && !info[0]->IsString() && !info[0]->IsNumber()) {
552 LOGE("args need a string or number or object");
553 return;
554 }
555 SearchModel::GetInstance()->SetBackBorder();
556 }
557
OnSubmit(const JSCallbackInfo & info)558 void JSSearch::OnSubmit(const JSCallbackInfo& info)
559 {
560 CHECK_NULL_VOID(info[0]->IsFunction());
561 JsEventCallback<void(const std::string&)> callback(info.GetExecutionContext(), JSRef<JSFunc>::Cast(info[0]));
562 SearchModel::GetInstance()->SetOnSubmit(std::move(callback));
563 }
564
OnChange(const JSCallbackInfo & info)565 void JSSearch::OnChange(const JSCallbackInfo& info)
566 {
567 CHECK_NULL_VOID(info[0]->IsFunction());
568 JsEventCallback<void(const std::string&)> callback(info.GetExecutionContext(), JSRef<JSFunc>::Cast(info[0]));
569 SearchModel::GetInstance()->SetOnChange(std::move(callback));
570 }
571
SetOnTextSelectionChange(const JSCallbackInfo & info)572 void JSSearch::SetOnTextSelectionChange(const JSCallbackInfo& info)
573 {
574 CHECK_NULL_VOID(info[0]->IsFunction());
575 JsEventCallback<void(int32_t, int32_t)> callback(info.GetExecutionContext(), JSRef<JSFunc>::Cast(info[0]));
576 SearchModel::GetInstance()->SetOnTextSelectionChange(std::move(callback));
577 }
578
SetOnScroll(const JSCallbackInfo & info)579 void JSSearch::SetOnScroll(const JSCallbackInfo& info)
580 {
581 CHECK_NULL_VOID(info[0]->IsFunction());
582 JsEventCallback<void(float, float)> callback(info.GetExecutionContext(), JSRef<JSFunc>::Cast(info[0]));
583 SearchModel::GetInstance()->SetOnScroll(std::move(callback));
584 }
585
SetHeight(const JSCallbackInfo & info)586 void JSSearch::SetHeight(const JSCallbackInfo& info)
587 {
588 JSViewAbstract::JsHeight(info);
589 CalcDimension value;
590 auto versionTenOrLarger = PipelineBase::GetCurrentContext() &&
591 PipelineBase::GetCurrentContext()->GetMinPlatformVersion() >= PLATFORM_VERSION_TEN;
592 if (versionTenOrLarger ? !ParseJsDimensionVpNG(info[0], value) : !ParseJsDimensionVp(info[0], value)) {
593 LOGE("The arg is wrong, it is supposed to be a number arguments");
594 return;
595 }
596 if (LessNotEqual(value.Value(), 0.0)) {
597 value.SetValue(0.0);
598 }
599 SearchModel::GetInstance()->SetHeight(value);
600 }
601
SetOnCopy(const JSCallbackInfo & info)602 void JSSearch::SetOnCopy(const JSCallbackInfo& info)
603 {
604 CHECK_NULL_VOID(info[0]->IsFunction());
605 JsEventCallback<void(const std::string&)> callback(info.GetExecutionContext(), JSRef<JSFunc>::Cast(info[0]));
606 SearchModel::GetInstance()->SetOnCopy(std::move(callback));
607 }
608
SetOnCut(const JSCallbackInfo & info)609 void JSSearch::SetOnCut(const JSCallbackInfo& info)
610 {
611 CHECK_NULL_VOID(info[0]->IsFunction());
612 JsEventCallback<void(const std::string&)> callback(info.GetExecutionContext(), JSRef<JSFunc>::Cast(info[0]));
613 SearchModel::GetInstance()->SetOnCut(std::move(callback));
614 }
615
SetOnPaste(const JSCallbackInfo & info)616 void JSSearch::SetOnPaste(const JSCallbackInfo& info)
617 {
618 CHECK_NULL_VOID(info[0]->IsFunction());
619 JsEventCallback<void(const std::string&)> callback(info.GetExecutionContext(), JSRef<JSFunc>::Cast(info[0]));
620 SearchModel::GetInstance()->SetOnPaste(std::move(callback));
621 }
622
SetCopyOption(const JSCallbackInfo & info)623 void JSSearch::SetCopyOption(const JSCallbackInfo& info)
624 {
625 if (info.Length() == 0) {
626 return;
627 }
628 if (info[0]->IsUndefined()) {
629 SearchModel::GetInstance()->SetCopyOption(CopyOptions::Local);
630 return;
631 }
632 auto copyOptions = CopyOptions::None;
633 if (info[0]->IsNumber()) {
634 auto emunNumber = info[0]->ToNumber<int>();
635 copyOptions = static_cast<CopyOptions>(emunNumber);
636 }
637 SearchModel::GetInstance()->SetCopyOption(copyOptions);
638 }
639
JsMenuOptionsExtension(const JSCallbackInfo & info)640 void JSSearch::JsMenuOptionsExtension(const JSCallbackInfo& info)
641 {
642 if (info[0]->IsArray()) {
643 std::vector<NG::MenuOptionsParam> menuOptionsItems;
644 JSViewAbstract::ParseMenuOptions(info, JSRef<JSArray>::Cast(info[0]), menuOptionsItems);
645 SearchModel::GetInstance()->SetMenuOptionItems(std::move(menuOptionsItems));
646 }
647 }
648
SetSelectionMenuHidden(const JSCallbackInfo & info)649 void JSSearch::SetSelectionMenuHidden(const JSCallbackInfo& info)
650 {
651 if (info.Length() < 1) {
652 LOGW("SelectionMenuHidden should have at least 1 param");
653 return;
654 }
655 if (info[0]->IsUndefined() || !info[0]->IsBoolean()) {
656 LOGI("The info of SetSelectionMenuHidden is not correct, using default");
657 SearchModel::GetInstance()->SetSelectionMenuHidden(false);
658 return;
659 }
660 SearchModel::GetInstance()->SetSelectionMenuHidden(info[0]->ToBoolean());
661 }
662
SetCustomKeyboard(const JSCallbackInfo & info)663 void JSSearch::SetCustomKeyboard(const JSCallbackInfo& info)
664 {
665 if (info.Length() > 0 && (info[0]->IsUndefined() || info[0]->IsNull())) {
666 SearchModel::GetInstance()->SetCustomKeyboard(nullptr);
667 return;
668 }
669 if (info.Length() < 1 || !info[0]->IsObject()) {
670 return;
671 }
672 std::function<void()> buildFunc;
673 if (JSTextField::ParseJsCustomKeyboardBuilder(info, 0, buildFunc)) {
674 SearchModel::GetInstance()->SetCustomKeyboard(std::move(buildFunc));
675 }
676 }
677
JSBind(BindingTarget globalObj)678 void JSSearchController::JSBind(BindingTarget globalObj)
679 {
680 JSClass<JSSearchController>::Declare("SearchController");
681 JSClass<JSSearchController>::Method("caretPosition", &JSSearchController::CaretPosition);
682 JSClass<JSSearchController>::CustomMethod("getTextContentRect", &JSSearchController::GetTextContentRect);
683 JSClass<JSSearchController>::CustomMethod("getTextContentLineCount", &JSSearchController::GetTextContentLinesNum);
684 JSClass<JSSearchController>::Method("stopEditing", &JSSearchController::StopEditing);
685 JSClass<JSSearchController>::Bind(globalObj, JSSearchController::Constructor, JSSearchController::Destructor);
686 }
687
Constructor(const JSCallbackInfo & args)688 void JSSearchController::Constructor(const JSCallbackInfo& args)
689 {
690 auto scroller = Referenced::MakeRefPtr<JSSearchController>();
691 scroller->IncRefCount();
692 args.SetReturnValue(Referenced::RawPtr(scroller));
693 }
694
Destructor(JSSearchController * scroller)695 void JSSearchController::Destructor(JSSearchController* scroller)
696 {
697 if (scroller != nullptr) {
698 scroller->DecRefCount();
699 }
700 }
701
CaretPosition(int32_t caretPosition)702 void JSSearchController::CaretPosition(int32_t caretPosition)
703 {
704 auto controller = controller_.Upgrade();
705 if (controller) {
706 controller->CaretPosition(caretPosition);
707 }
708 }
709
CreateRectangle(const Rect & info)710 JSRef<JSObject> JSSearchController::CreateRectangle(const Rect& info)
711 {
712 JSRef<JSObject> rectObj = JSRef<JSObject>::New();
713 rectObj->SetProperty<double>("x", info.Left());
714 rectObj->SetProperty<double>("y", info.Top());
715 rectObj->SetProperty<double>("width", info.Width());
716 rectObj->SetProperty<double>("height", info.Height());
717 return rectObj;
718 }
719
GetTextContentRect(const JSCallbackInfo & info)720 void JSSearchController::GetTextContentRect(const JSCallbackInfo& info)
721 {
722 auto controller = controller_.Upgrade();
723 if (controller) {
724 auto rectObj = CreateRectangle(controller->GetTextContentRect());
725 JSRef<JSVal> rect = JSRef<JSObject>::Cast(rectObj);
726 info.SetReturnValue(rect);
727 } else {
728 LOGE("GetTextContentRect: The JSSearchController is NULL");
729 }
730 }
731
GetTextContentLinesNum(const JSCallbackInfo & info)732 void JSSearchController::GetTextContentLinesNum(const JSCallbackInfo& info)
733 {
734 auto controller = controller_.Upgrade();
735 if (controller) {
736 auto lines = controller->GetTextContentLinesNum();
737 auto linesNum = JSVal(ToJSValue(lines));
738 auto textLines = JSRef<JSVal>::Make(linesNum);
739 info.SetReturnValue(textLines);
740 } else {
741 LOGE("GetTextContentRect: The JSSearchController is NULL");
742 }
743 }
744
StopEditing()745 void JSSearchController::StopEditing()
746 {
747 auto controller = controller_.Upgrade();
748 if (controller) {
749 controller->StopEditing();
750 }
751 }
752 } // namespace OHOS::Ace::Framework
753