Files
mixly3/common/modules/mixly-modules/common/toolbox-searcher.js

208 lines
6.8 KiB
JavaScript

goog.loadJs('common', () => {
goog.require('path');
goog.require('Blockly');
goog.require('Mixly.Env');
goog.require('Mixly.XML');
goog.require('Mixly.Msg');
goog.require('Mixly.HTMLTemplate');
goog.require('Mixly.Debug');
goog.provide('Mixly.ToolboxSearcher');
const {
Env,
XML,
Msg,
HTMLTemplate,
Debug
} = Mixly;
class ToolboxSearcher {
static {
this.searchHtmlTemplate = new HTMLTemplate(
goog.readFileSync(path.join(Env.templatePath, 'html/search-div.html'))
);
}
constructor(mainWorkspace) {
this.mainWorkspace = mainWorkspace;
this.searchWorkspace = new Blockly.Workspace(new Blockly.Options({
toolbox: null
}));
this.mainToolbox = this.mainWorkspace.getToolbox();
this.$search = $(ToolboxSearcher.searchHtmlTemplate.render({
search: Msg.Lang['toolboxSearcher.search']
}));
this.$i = this.$search.find('i');
this.$input = this.$search.find('input');
this.prevText = '';
$(this.mainToolbox.HtmlDiv).append(this.$search);
this.addEventsListener();
}
addEventsListener() {
this.$input.change(() => this.startSearch());
this.$input.bind('input propertychange', (event) => {
const searchCategory = this.mainToolbox.getToolboxItemById('catSearch');
const keyText = event.target.value;
if (!keyText.replaceAll(' ', '')) {
searchCategory.hide();
this.$i.addClass('disabled');
return;
} else {
searchCategory.show();
}
this.scrollTop();
if (keyText === this.prevText) {
this.$i.addClass('disabled');
} else {
this.$i.removeClass('disabled');
}
});
}
scrollTop() {
const { HtmlDiv } = this.mainToolbox;
$(HtmlDiv).scrollTop(HtmlDiv.scrollHeight);
}
checkBlock(blockxml, keys) {
this.searchWorkspace.clear();
try {
Blockly.Xml.domToBlock(blockxml, this.searchWorkspace);
} catch (error) {
Debug.error(error);
return false;
}
const blocks = this.searchWorkspace.getAllBlocks(true);
let select = false;
for (let block of blocks) {
const { inputList } = block;
for (let input of inputList) {
const { fieldRow } = input;
for (let field of fieldRow) {
const fieldText = field.getText().toLowerCase();
let times = 0;
for (let key = 0; key < keys.length; key++) {
if (fieldText.indexOf(keys[key]) === -1) {
continue;
}
times++;
}
if (keys.length === times) {
return true;
}
}
}
}
return false;
}
searchBlocks(keys) {
return new Promise((resolve, reject) => {
const searchCategory = this.mainToolbox.getToolboxItemById('catSearch');
let outputXML = [];
let selectedBlocksLen = 0;
const categories = this.mainToolbox.getToolboxItems();
for (let j = 0; categories[j]; j++) {
const category = categories[j];
if (category.id_ === 'catSearch') continue;
if (typeof category.getContents !== 'function') continue;
const blocksList = category.getContents();
let addLabel = true;
for (let blockDef of blocksList) {
const { type, kind, blockxml } = blockDef;
if (kind !== 'BLOCK') {
continue;
}
if (!this.checkBlock(blockxml, keys)) {
continue;
}
if (addLabel) {
const categoryPath = this.getCategoryPath(category);
outputXML.push({
kind: 'LABEL',
text: categoryPath
});
addLabel = false;
}
outputXML.push(blockDef);
selectedBlocksLen++;
if (selectedBlocksLen > 30) {
break;
}
}
if (selectedBlocksLen > 30) {
outputXML.unshift({
kind: 'LABEL',
text: Msg.Lang['toolboxSearcher.tooManyResultsInfo']
});
break;
}
}
this.searchWorkspace.clear();
searchCategory.updateFlyoutContents(
outputXML.length ?
outputXML : [{
kind: 'LABEL',
text: Msg.Lang['toolboxSearcher.empty']
}]
);
this.mainToolbox.refreshSelection();
this.mainToolbox.setSelectedItem(searchCategory);
const { selectedItem_ } = this.mainToolbox;
if (selectedItem_ && selectedItem_.isCollapsible()) {
selectedItem_.setExpanded(true);
}
this.scrollTop();
resolve();
});
}
getCategoryPath(category) {
let categoryPath = '';
for (; category; category = category.getParent()) {
categoryPath = category.toolboxItemDef_.name + (categoryPath && (' > ' + categoryPath));
}
return categoryPath;
}
startSearch() {
if (this.$i.hasClass('disabled')) {
return
};
let text = this.$input.val();
this.prevText = text;
try {
if (!text.replaceAll(' ', '')) {
return;
}
} catch(error) {
Debug.error(error);
}
this.$input.attr('disabled', true);
this.$i.removeClass('codicon-search-fuzzy');
this.$i.addClass('codicon-loading layui-anim-rotate layui-anim-loop');
setTimeout(() => {
let keys = text.toLowerCase().split(' ');
this.searchBlocks(keys)
.catch(Debug.error)
.finally(() => {
this.$i.removeClass('codicon-loading layui-anim-rotate layui-anim-loop');
this.$i.addClass('codicon-search-fuzzy disabled');
this.$input.removeAttr('disabled');
});
}, 100);
}
restart() {
this.prevText = '';
const searchCategory = this.mainToolbox.getToolboxItemById('catSearch');
this.$input.val('');
searchCategory.hide();
}
}
Mixly.ToolboxSearcher = ToolboxSearcher;
});