1
0
Fork 0
mirror of https://github.com/iNavFlight/inav-configurator.git synced 2025-07-13 03:19:54 +03:00

search: add search.html and search.js

This commit is contained in:
Ray Morris 2025-01-15 12:55:26 -06:00
parent 4d575a4f64
commit c0017991f5
6 changed files with 215 additions and 1 deletions

View file

@ -318,6 +318,10 @@
<li class="tab_cli"> <li class="tab_cli">
<a href="#" data-i18n="tabCLI" class="tabicon ic_cli" title="CLI"></a> <a href="#" data-i18n="tabCLI" class="tabicon ic_cli" title="CLI"></a>
</li> </li>
<li class="tab_search">
<a href="#" data-i18n="search" class="tabicon ic_search" title="Search"></a>
</li>
<!-- <li class=""><a href="#" class="tabicon ic_advanced">Advanced (spare icon)</a></li> --> <!-- <li class=""><a href="#" class="tabicon ic_advanced">Advanced (spare icon)</a></li> -->
</ul> </ul>

View file

@ -281,6 +281,10 @@ $(function() {
require('./../tabs/ez_tune'); require('./../tabs/ez_tune');
TABS.ez_tune.initialize(content_ready); TABS.ez_tune.initialize(content_ready);
break; break;
case 'search':
require('./../tabs/search');
TABS.search.initialize(content_ready);
break;
default: default:
console.log('Tab not found:' + tab); console.log('Tab not found:' + tab);
} }

View file

@ -50,7 +50,8 @@ var GUI_control = function () {
'mission_control', 'mission_control',
'mixer', 'mixer',
'programming', 'programming',
'ez_tune' 'ez_tune',
'search'
]; ];
this.allowedTabs = this.defaultAllowedTabsWhenDisconnected; this.allowedTabs = this.defaultAllowedTabsWhenDisconnected;

View file

@ -6178,5 +6178,8 @@
}, },
"currentLanguage": { "currentLanguage": {
"message": "en" "message": "en"
},
"search": {
"message": "Search"
} }
} }

19
tabs/search.html Normal file
View file

@ -0,0 +1,19 @@
<div class="tab-search">
<div class="content_wrapper">
<div class="options-section gui_box grey">
<div class="gui_box_titlebar">
<div class="spacer_box_title" data-i18n="search"></div>
</div>
<div class="spacer_box settings">
<div>
<input type="text" id="search-keyword" style="border: solid 1px black" />
<label for="search-keyword" id="search-label">🔎</label>
</div>
<div id="search-results"></div>
</div>
</div>
</div>
</div>

183
tabs/search.js Normal file
View file

@ -0,0 +1,183 @@
const { GUI, TABS } = require('./../js/gui');
const path = require('path');
const i18n = require('./../js/localization');
TABS.search = { };
tabNames = [
"adjustments",
"advanced_tuning",
"auxiliary",
"calibration",
"cli",
"configuration",
"debug_trace",
"failsafe",
"firmware_flasher",
"gps",
"landing",
"led_strip",
"logging",
"magnetometer",
"mission_control",
"mixer",
"onboard_logging",
"options",
"osd",
"outputs",
"pid_tuning",
"ports",
"programming",
"receiver",
"receiver_msp",
"sensors",
"setup",
"sitl"
];
TABS.search.searchMessages = function (keyword) {
var resultsDiv = document.getElementById('search-results');
keyword = keyword.toLowerCase();
resultsDiv.innerHTML = '';
simClick = function (evt) {
tabName = evt.currentTarget.getAttribute("tabName");
tabLink = document.getElementsByClassName("tab_".concat(tabName))[0].getElementsByTagName("a")[0];
tabLink.click();
};
for (const [key, value] of Object.entries(this.messages)) {
// Get plain text of message (with tags)
var message = value.message.toLowerCase().replace(new RegExp('<[^>]*>'), '');
if ( message.includes(keyword) ) {
if (this.key2page.get(key) ) {
var pages = this.key2page.get(key);
var kwEscaped = keyword.replace(/[\-\[\]{}()*+?.,\\\^$|#\s]/g, "\\$&");
var context = message.match( new RegExp( `([a-z]{0,10}.{0,14}${kwEscaped}.{0,14}[a-z]{0,10})`, 'i') )[1];
for (const page of pages) {
var rHTML = "<li><button class=\"searchResult\" tabName=\"{0}\">{1} tab</button>: {2}</li>".format(page, page, context);
resultsDiv.innerHTML= resultsDiv.innerHTML.concat(rHTML);
}
}
}
}
for ( result of document.getElementsByClassName("searchResult") ) {
result.addEventListener('click', simClick, false);
}
}
TABS.search.getMessages = function () {
const res_messages = fetch('locale/en/messages.json');
res_messages
.then (data => data.json())
.then (data => {
this.messages = data;
})
.catch((error) => {
console.error(error)
});
}
TABS.search.geti18nHTML = function (filename, filecontents) {
const parser = new DOMParser();
const htmlDoc = parser.parseFromString(filecontents, 'text/html');
var hasDataI18n = htmlDoc.querySelectorAll('[data-i18n]:not([data-i18n=""])');
for (const element of hasDataI18n) {
key = element.getAttribute('data-i18n');
if (! this.key2page.has(key) ) {
this.key2page.set( key, new Set() );
}
this.key2page.get(key).add(filename);
}
hasDataI18n = htmlDoc.querySelectorAll('[i18n]:not([i18n=""])');
for (const element of hasDataI18n) {
key = element.getAttribute('i18n');
if (! this.key2page.has(key) ) {
this.key2page.set( key, new Set() );
}
this.key2page.get(key).add(filename);
}
}
TABS.search.geti18nJs = function (filename, filecontents) {
var re = /(?:data-i18n=|i18n.getMessage\()["']([^"']*)['"]/g
while (match = re.exec(filecontents)) {
key = match[1];
if (! this.key2page.has(key) ) {
this.key2page.set( key, new Set() );
}
this.key2page.get(key).add(filename);
}
}
TABS.search.indexTab = async function indexTab(tabName) {
var response = fetch(`tabs/${tabName}.js`);
response
.then (data => data.text())
.then (data => {
this.geti18nJs(tabName, data);
})
.catch((error) => {
console.error(error)
});
response = fetch(`tabs/${tabName}.html`);
response
.then (data => data.text())
.then (data => {
this.geti18nHTML(tabName, data);
})
.catch((error) => {
console.error(error)
});
};
TABS.search.initialize = function (callback) {
var self = this;
this.key2page = new Map();
this.messages;
if (GUI.active_tab != 'search') {
GUI.active_tab = 'search';
}
function searchKeyword() {
TABS.search.searchMessages(document.getElementById('search-keyword').value);
}
function searchKeywordTyping() {
if (document.getElementById('search-keyword').value.length > 2) {
TABS.search.searchMessages(document.getElementById('search-keyword').value);
}
}
GUI.load(path.join(__dirname, "search.html"), function () {
i18n.localize();
document.getElementById('search-label').addEventListener('click', searchKeyword, false);
document.getElementById('search-keyword').addEventListener('keyup', searchKeywordTyping, false);
GUI.content_ready(callback);
} );
self.getMessages();
for (let tab of tabNames) {
self.indexTab(tab);
}
}
TABS.search.cleanup = function (callback) {
if (callback) callback();
};