import { addStyle, DOMUtils, httpx, log, utils } from "@/env";
import { Panel } from "@components/setting/panel";
import { GestureBack } from "@components/utils/GestureBack";
import searchToolBarCSS from "./search-toolbar.css?raw";
export const BaiduSearchToolBar = {
$el: {
/** 搜索框总容器 */
$container: null as any as HTMLElement,
shadowRoot: null as any as ShadowRoot,
$toolbarContainer: null as any as HTMLDivElement,
/** 搜索框容器 */
$toolbar: null as any as HTMLDivElement,
/** 提交表单 */
$form: null as any as HTMLFormElement,
/** 输入框 */
$input: null as any as HTMLInputElement,
/** 搜索建议 */
$suggestion: null as any as HTMLDivElement,
/** 返回按钮 */
$back: null as any as HTMLDivElement,
/** 清空图标 */
$empty: null as any as HTMLDivElement,
/** 搜索按钮 */
$submit: null as any as HTMLButtonElement,
},
$data: {
gestureBack: new GestureBack({
hash: "global-search",
beforeHistoryBackCallBack(isUrlChange) {
BaiduSearchToolBar.hideToolBar();
},
}),
},
init() {
DOMUtils.onReady(() => {
this.addFloatButton();
this.addToolBar();
});
},
/**
* 添加悬浮搜索按钮
*/
addFloatButton() {
let $btn = DOMUtils.createElement("div", {
className: "gm-search-toolbar-float-btn",
innerHTML: /*html*/ `
`,
});
DOMUtils.on($btn, "click", (event) => {
DOMUtils.preventEvent(event);
this.showToolBar();
this.initDefaultSearchText();
setTimeout(() => {
this.$el.$input.focus();
this.$el.$input.select();
}, 150);
Panel.execMenu("baidu-search-global-searchToolBar-gesture-back", () => {
// 手势返回
this.$data.gestureBack.enterGestureBackMode();
});
});
addStyle(/*css*/ `
.gm-search-toolbar-float-btn {
--gm-search-toolbar-icon-size: 45px;
position: fixed;
bottom: 20px;
right: 15px;
width: var(--gm-search-toolbar-icon-size);
height: var(--gm-search-toolbar-icon-size);
z-index: 9000;
}
`);
document.body.appendChild($btn);
return $btn;
},
/**
* 添加搜索工具栏
*/
addToolBar() {
let $toolbarInner = DOMUtils.createElement("div");
$toolbarInner.className = "gm-search-toolbar";
// 使用shadow
$toolbarInner.attachShadow({ mode: "open" });
let shadowRoot = $toolbarInner.shadowRoot!;
this.$el.$container = $toolbarInner;
this.$el.shadowRoot = shadowRoot;
// 添加css
let $css = DOMUtils.createElement("style", {
innerHTML: searchToolBarCSS,
});
shadowRoot.appendChild($css);
// container
let $container = DOMUtils.createElement("div", {
className: "search-toolbar-container",
innerHTML: /*html*/ `
`,
});
this.$el.$toolbarContainer = $container;
this.$el.$toolbar = $container.querySelector(".search-toolbar")!;
this.$el.$input = $container.querySelector(".search-toolbar-input")!;
this.$el.$form = $container.querySelector(".search-form")!;
this.$el.$suggestion = $container.querySelector(".search-suggestion")!;
this.$el.$back = $container.querySelector(".search-toolbar-back")!;
this.$el.$empty = $container.querySelector(".search-toolbar-empty")!;
this.$el.$submit = $container.querySelector(".search-form-submit")!;
shadowRoot.appendChild($container);
// 添加到页面
this.hideToolBar();
document.body.appendChild($toolbarInner);
this.setInputEvent();
this.setEmptyEvent();
this.setBackEvent();
this.setFormEvent();
},
/**
* 显示搜索工具栏
*/
showToolBar() {
this.$el.$toolbarContainer.style.opacity = "";
this.$el.$toolbarContainer.style.visibility = "";
},
/**
* 隐藏搜索工具栏
*/
hideToolBar() {
this.$el.$toolbarContainer.style.opacity = "0";
this.$el.$toolbarContainer.style.visibility = "hidden";
},
/**
* 获取当前页面搜索的关键字
*/
getPageSearchText() {
let searchParams = new URLSearchParams(window.location.search);
let searchText = searchParams.get("word") || searchParams.get("wd");
return searchText!;
},
/**
* 获取搜索建议内容
* @param text 搜索内容
*/
async getSuggestionText(text: string) {
let searchParamData = {
json: 1,
prod: "wise",
callback: "baidusug",
wd: text,
};
let allowApiHostName = ["m.baidu.com", "www.baidu.com"];
let apiHostName = "m.baidu.com";
let useFetch = true;
if (allowApiHostName.includes(window.location.hostname)) {
apiHostName = window.location.hostname;
} else {
useFetch = false;
}
let response = await httpx.get(`https://${apiHostName}/sugrec?${utils.toSearchParamsStr(searchParamData)}`, {
fetch: useFetch,
allowInterceptConfig: false,
});
if (!response.status) {
log.error("获取百度搜索建议失败", response);
return;
}
let suggestion = response.data.responseText.replace(/^baidusug\(/, "").replace(/\)$/, "");
let suggestionJSON = utils.toJSON(suggestion) as {
g: {
q: string;
sa: string;
type: string;
}[];
p: boolean;
q: string;
queryid: string;
slid: string;
};
log.info(`百度搜索联想词:`, suggestionJSON);
return suggestionJSON.g || [];
},
/**
* 初始化当前页面默认的搜索关键字
*/
initDefaultSearchText() {
let searchText = this.getPageSearchText();
this.setInputText(searchText);
},
/**
* 监听输入框内容改变
*/
setInputEvent() {
DOMUtils.on(this.$el.$input, ["input", "propertychange"], () => {
// 判断是否为空,动态修改图标显示和颜色
if (this.$el.$input.value === "") {
// 空的
this.clearSuggestion();
this.$el.$empty.style.display = "none";
this.$el.$submit.setAttribute("disabled", "true");
} else {
// 非空
this.$el.$empty.style.display = "";
this.$el.$submit.removeAttribute("disabled");
}
});
DOMUtils.on(
this.$el.$input,
["input", "propertychange"],
utils.debounce(async () => {
let searchText = this.$el.$input.value;
if (searchText === "") {
return;
}
let suggestionList = await this.getSuggestionText(searchText);
if (Array.isArray(suggestionList) && suggestionList.length) {
// 清空搜索结果
this.clearSuggestion();
// if (searchText.trim() !== "") {
// this.addSuggestionItem(
// this.createSuggestionItem({
// searchText: searchText,
// suggestionText: searchText,
// isHistory: true,
// })
// );
// }
suggestionList.forEach((item) => {
if (item.type === "sug") {
this.addSuggestionItem(
this.createSuggestionItem({
searchText: searchText,
suggestionText: item.q,
isHistory: false,
})
);
}
});
}
}, 50)
);
},
/**
* 设置搜索文本内容
* @param text 搜索关键字
* @param emitEvent 是否触发事件
* @default true
*/
setInputText(text: string, emitEvent: boolean = true) {
this.$el.$input.value = text;
if (emitEvent) {
DOMUtils.emit(this.$el.$input, "input");
}
},
/**
* 设置返回按钮点击事件
*/
setBackEvent() {
DOMUtils.on(this.$el.$back, "click", (event) => {
DOMUtils.preventEvent(event);
log.success("点击返回");
this.hideToolBar();
Panel.execMenu("baidu-search-global-searchToolBar-gesture-back", () => {
// 退出手势模式
this.$data.gestureBack.quitGestureBackMode();
});
});
},
/**
* 设置清空图标点击事件
*/
setEmptyEvent() {
DOMUtils.on(this.$el.$empty, "click", (event) => {
DOMUtils.preventEvent(event);
this.setInputText("");
});
},
/**
* 设置表单事件
*/
setFormEvent() {
DOMUtils.on(this.$el.$form, "submit", (event) => {
DOMUtils.preventEvent(event);
const searchText = this.$el.$input.value;
log.success("提交表单 搜索 ==> " + searchText);
window.location.href = `${window.location.origin}/s?word=${searchText}`;
});
},
/**
* 创建搜索建议元素项
*/
createSuggestionItem(config: {
/** 搜索的关键字 */
searchText: string;
/** 搜索建议文本 */
suggestionText: string;
/** 是否是历史输入 */
isHistory: boolean;
}) {
let $suggestionItem = DOMUtils.createElement("div", {
className: "search-suggestion-item",
innerHTML: /*html*/ `
`,
});
let $leftIcon = $suggestionItem.querySelector(".search-suggestion-item-left-icon")!;
let $leftIconI = $leftIcon.querySelector(".search-icon")!;
let $text = $suggestionItem.querySelector(".search-suggestion-item-text")!;
let $rightIcon = $suggestionItem.querySelector(".search-suggestion-item-right-icon")!;
if (config.isHistory) {
// 切换图标为历史
$leftIconI.innerHTML = /*html*/ `
`;
}
// 处理搜索关键字灰色
let searchText = config.suggestionText.replaceAll(config.searchText, `${config.searchText}`);
$text.innerHTML = searchText;
DOMUtils.on($leftIcon, "click", (event) => {
DOMUtils.preventEvent(event);
});
// 搜索建议点击事件
DOMUtils.on($text, "click", (event) => {
DOMUtils.preventEvent(event);
this.setInputText(config.suggestionText, false);
this.$el.$submit.click();
});
DOMUtils.on($rightIcon, "click", (event) => {
DOMUtils.preventEvent(event);
this.setInputText(config.suggestionText);
});
return $suggestionItem;
},
/**
* 清除搜索建议
*/
clearSuggestion() {
this.$el.$suggestion.innerHTML = "";
},
/**
* 添加搜索建议
*/
addSuggestionItem($ele: HTMLElement) {
this.$el.$suggestion.appendChild($ele);
},
};