fineui是帆软报表和BI产品线所使用的前端框架。
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
 
 
 

377 lines
11 KiB

import { SearchEditor } from "@/widget/editor/editor.search.js";
import { SearcherView } from "../layer";
import {
VerticalLayout,
shortcut,
Widget,
Controller,
extend,
createWidget,
debounce,
bind,
endWith,
deepWithout,
nextTick,
isEmptyString,
isNull,
BlankSplitChar,
Events,
EVENT_RESPONSE_TIME,
Func
} from "@/core";
import { ButtonGroup } from "./group.button";
import { Maskers } from "@/base/0.base";
/**
* 搜索逻辑控件
*
* Created by GUY on 2015/9/28.
* @class Searcher
* @extends Widget
*/
@shortcut()
export class Searcher extends Widget {
static xtype = "bi.searcher";
static EVENT_CHANGE = "EVENT_CHANGE";
static EVENT_START = "EVENT_START";
static EVENT_STOP = "EVENT_STOP";
static EVENT_PAUSE = "EVENT_PAUSE";
static EVENT_SEARCHING = "EVENT_SEARCHING";
static EVENT_AFTER_INIT = "EVENT_AFTER_INIT";
_defaultConfig() {
return extend(super._defaultConfig(...arguments), {
baseCls: "bi-searcher",
lgap: 0,
rgap: 0,
tgap: 0,
bgap: 0,
vgap: 0,
hgap: 0,
isDefaultInit: false,
isAutoSearch: true, // 是否自动搜索
isAutoSync: true, // 是否自动同步数据, 即是否保持搜索面板和adapter面板状态值的统一
chooseType: ButtonGroup.CHOOSE_TYPE_SINGLE,
// isAutoSearch为false时启用
onSearch: (op, callback) => {
callback([]);
},
el: {
type: SearchEditor.xtype,
},
popup: {
type: SearcherView.xtype,
},
adapter: null,
masker: {
// masker层
offset: {},
},
});
}
render() {
const { el, lgap, rgap, tgap, bgap, vgap, hgap, isDefaultInit } = this.options;
this.editor = createWidget(el, {
type: SearchEditor.xtype,
});
createWidget({
type: VerticalLayout.xtype,
element: this,
lgap,
rgap,
tgap,
bgap,
vgap,
hgap,
items: [this.editor],
});
isDefaultInit && this._assertPopupView();
const search = debounce(bind(this._search, this), EVENT_RESPONSE_TIME, {
leading: true,
trailing: false,
});
this.editor.on(Controller.EVENT_CHANGE, type => {
switch (type) {
case Events.STARTEDIT:
this._startSearch();
break;
case Events.EMPTY:
this._stopSearch();
break;
case Events.CHANGE:
search();
break;
case Events.PAUSE:
if (endWith(this.editor.getValue(), BlankSplitChar)) {
this._pauseSearch();
}
break;
default:
break;
}
});
}
_assertPopupView() {
const { masker, popup, chooseType, isAutoSync, adapter } = this.options;
if ((masker && !Maskers.has(this.getName())) || (masker === false && !this.popupView)) {
this.popupView = createWidget(popup, {
type: SearcherView.xtype,
chooseType,
});
this.popupView.on(Controller.EVENT_CHANGE, (type, value, obj, ...args) => {
this.fireEvent(Controller.EVENT_CHANGE, type, value, obj, ...args);
if (type === Events.CLICK) {
if (isAutoSync) {
const values = adapter && adapter.getValue();
switch (chooseType) {
case ButtonGroup.CHOOSE_TYPE_SINGLE:
adapter && adapter.setValue([obj.getValue()]);
break;
case ButtonGroup.CHOOSE_TYPE_MULTI:
if (!obj.isSelected()) {
adapter && adapter.setValue(deepWithout(values, obj.getValue()));
}
values.push(obj.getValue());
adapter && adapter.setValue(values);
break;
default:
break;
}
}
this.fireEvent(Searcher.EVENT_CHANGE, value, obj);
}
});
nextTick(() => {
this.fireEvent(Searcher.EVENT_AFTER_INIT);
});
}
if (masker && !Maskers.has(this.getName())) {
Maskers.create(
this.getName(),
adapter,
extend(
{
container: this,
render: this.popupView,
},
masker
),
this
);
}
}
_startSearch() {
this._assertPopupView();
this._stop = false;
this._isSearching = true;
this.fireEvent(Searcher.EVENT_START);
this.popupView.startSearch && this.popupView.startSearch();
// 搜索前先清空dom
// Maskers.get(this.getName()).empty();
nextTick(name => {
Maskers.show(name);
}, this.getName());
}
_pauseSearch() {
this._stop = true;
nextTick(name => {
Maskers.hide(name);
}, this.getName());
if (this._isSearching === true) {
this.popupView && this.popupView.pauseSearch && this.popupView.pauseSearch();
this.fireEvent(Searcher.EVENT_PAUSE);
}
this._isSearching = false;
}
_stopSearch() {
const name = this.getName();
this._stop = true;
Maskers.hide(name);
if (this._isSearching === true) {
this.popupView && this.popupView.stopSearch && this.popupView.stopSearch();
this.fireEvent(Searcher.EVENT_STOP);
}
this._isSearching = false;
}
_search() {
const { isAutoSearch, adapter, isAutoSync, onSearch } = this.options;
const keyword = this.editor.getValue();
if (keyword === "" || this._stop) {
return;
}
if (isAutoSearch) {
const items = (adapter && ((adapter.getItems && adapter.getItems()) || adapter.attr("items"))) || [];
const finding = Func.getSearchResult(items, keyword);
const match = finding.match,
find = finding.find;
this.popupView.populate(find, match, keyword);
isAutoSync && adapter && adapter.getValue && this.popupView.setValue(adapter.getValue());
this.fireEvent(Searcher.EVENT_SEARCHING);
return;
}
this.popupView.loading && this.popupView.loading();
onSearch(
{
times: 1,
keyword,
selectedValues: adapter && adapter.getValue(),
},
(...args) => {
if (!this._stop && keyword === this.editor.getValue()) {
const _args = args;
if (_args.length > 0) {
_args.push(keyword);
}
Maskers.show(this.getName());
this.popupView.populate(..._args);
isAutoSync && adapter && adapter.getValue && this.popupView.setValue(adapter.getValue());
this.popupView.loaded && this.popupView.loaded();
this.fireEvent(Searcher.EVENT_SEARCHING);
}
}
);
}
_getLastSearchKeyword() {
if (this.isValid()) {
let res = this.editor.getValue().split(/\u200b\s\u200b/);
if (isEmptyString(res[res.length - 1])) {
res = res.slice(0, res.length - 1);
}
return isNull(res) ? "" : res[res.length - 1];
}
}
setAdapter(adapter) {
this.options.adapter = adapter;
Maskers.remove(this.getName());
}
doSearch() {
if (this.isSearching()) {
this._search();
}
}
stopSearch() {
this._stopSearch(); // 先停止搜索,然后再去设置editor为空
// important:停止搜索必须退出编辑状态,这里必须加上try(input框不显示时blur会抛异常)
try {
this.editor.blur();
} catch (e) {
if (!this.editor.blur) {
throw new Error("editor没有实现blur方法");
}
} finally {
this.editor.setValue("");
}
}
isSearching() {
return this._isSearching;
}
isViewVisible() {
return this.editor.isEnabled() && Maskers.isVisible(this.getName());
}
getView() {
return this.popupView;
}
hasMatched() {
this._assertPopupView();
return this.popupView.hasMatched();
}
adjustHeight() {
if (Maskers.has(this.getName()) && Maskers.get(this.getName()).isVisible()) {
Maskers.show(this.getName());
}
}
adjustView() {
this.isViewVisible() && Maskers.show(this.getName());
}
setValue(v) {
if (isNull(this.popupView)) {
this.options.popup.value = v;
} else {
this.popupView.setValue(v);
}
}
getKeyword() {
return this._getLastSearchKeyword();
}
getKeywords() {
return this.editor.getKeywords();
}
getValue() {
const { isAutoSync, adapter, popup } = this.options;
if (isAutoSync && adapter && adapter.getValue) {
return adapter.getValue();
}
if (this.isSearching()) {
return this.popupView.getValue();
} else if (adapter && adapter.getValue) {
return adapter.getValue();
}
if (isNull(this.popupView)) {
return popup.value;
}
return this.popupView.getValue();
}
populate(result, searchResult, keyword) {
const { isAutoSync, adapter } = this.options;
this._assertPopupView();
this.popupView.populate(...arguments);
if (isAutoSync && adapter && adapter.getValue) {
this.popupView.setValue(adapter.getValue());
}
}
empty() {
this.popupView && this.popupView.empty();
}
destroyed() {
Maskers.remove(this.getName());
}
focus() {
this.editor.focus();
}
blur() {
this.editor.blur();
}
setWaterMark(v) {
this.editor.setWaterMark(v);
}
}