joplin-plugin-explorer 1.0.2 → 1.1.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/package.json +1 -1
- package/publish/index.js +86 -3
- package/publish/manifest.json +1 -1
- package/publish/plugin.jpl +0 -0
- package/publish/webview/panel.css +80 -0
- package/publish/webview/panel.js +103 -20
package/package.json
CHANGED
package/publish/index.js
CHANGED
|
@@ -5,7 +5,9 @@ var i18nData = {
|
|
|
5
5
|
'zh_CN': {
|
|
6
6
|
newNotebook: '新建笔记本', newNote: '新建笔记', newTodo: '新建待办',
|
|
7
7
|
sort: '排序', collapseAll: '全部折叠', expandAll: '全部展开',
|
|
8
|
-
search: '
|
|
8
|
+
search: '搜索笔记内容...', searchResultCount: '找到 {count} 条结果',
|
|
9
|
+
searchNoResult: '没有找到匹配的笔记', searching: '搜索中...',
|
|
10
|
+
sync: '同步', syncing: '同步中...', syncDone: '\u2714 同步完成', loading: '加载中...',
|
|
9
11
|
sortUpdatedDesc: '\u2193 修改时间', sortUpdatedAsc: '\u2191 修改时间',
|
|
10
12
|
sortTitleAsc: '\u2191 标题', sortTitleDesc: '\u2193 标题',
|
|
11
13
|
// Folder context menu
|
|
@@ -27,7 +29,9 @@ var i18nData = {
|
|
|
27
29
|
'zh_TW': {
|
|
28
30
|
newNotebook: '新建筆記本', newNote: '新建筆記', newTodo: '新建待辦',
|
|
29
31
|
sort: '排序', collapseAll: '全部摺疊', expandAll: '全部展開',
|
|
30
|
-
search: '
|
|
32
|
+
search: '搜尋筆記內容...', searchResultCount: '找到 {count} 條結果',
|
|
33
|
+
searchNoResult: '沒有找到匹配的筆記', searching: '搜尋中...',
|
|
34
|
+
sync: '同步', syncing: '同步中...', syncDone: '\u2714 同步完成', loading: '載入中...',
|
|
31
35
|
sortUpdatedDesc: '\u2193 修改時間', sortUpdatedAsc: '\u2191 修改時間',
|
|
32
36
|
sortTitleAsc: '\u2191 標題', sortTitleDesc: '\u2193 標題',
|
|
33
37
|
ctxNewNoteHere: '在此新建筆記', ctxNewTodoHere: '在此新建待辦',
|
|
@@ -45,7 +49,9 @@ var i18nData = {
|
|
|
45
49
|
'en_US': {
|
|
46
50
|
newNotebook: 'New Notebook', newNote: 'New Note', newTodo: 'New To-do',
|
|
47
51
|
sort: 'Sort', collapseAll: 'Collapse All', expandAll: 'Expand All',
|
|
48
|
-
search: 'Search
|
|
52
|
+
search: 'Search note contents...', searchResultCount: '{count} results found',
|
|
53
|
+
searchNoResult: 'No matching notes found', searching: 'Searching...',
|
|
54
|
+
sync: 'Synchronise', syncing: 'Syncing...', syncDone: '\u2714 Sync Done', loading: 'Loading...',
|
|
49
55
|
sortUpdatedDesc: '\u2193 Updated', sortUpdatedAsc: '\u2191 Updated',
|
|
50
56
|
sortTitleAsc: '\u2191 Title', sortTitleDesc: '\u2193 Title',
|
|
51
57
|
ctxNewNoteHere: 'New Note Here', ctxNewTodoHere: 'New To-do Here',
|
|
@@ -60,6 +66,26 @@ var i18nData = {
|
|
|
60
66
|
confirmDeleteNote: 'Delete this note?',
|
|
61
67
|
promptRename: 'Enter new name:', promptMoveNote: 'Enter target notebook name:',
|
|
62
68
|
},
|
|
69
|
+
'ja_JP': {
|
|
70
|
+
newNotebook: '\u65B0\u898F\u30CE\u30FC\u30C8\u30D6\u30C3\u30AF', newNote: '\u65B0\u898F\u30CE\u30FC\u30C8', newTodo: '\u65B0\u898F\u30BF\u30B9\u30AF',
|
|
71
|
+
sort: '\u4E26\u3079\u66FF\u3048', collapseAll: '\u3059\u3079\u3066\u6298\u308A\u305F\u305F\u3080', expandAll: '\u3059\u3079\u3066\u5C55\u958B',
|
|
72
|
+
search: '\u30CE\u30FC\u30C8\u5185\u5BB9\u3092\u691C\u7D22...', searchResultCount: '{count} \u4EF6\u306E\u7D50\u679C',
|
|
73
|
+
searchNoResult: '\u4E00\u81F4\u3059\u308B\u30CE\u30FC\u30C8\u304C\u898B\u3064\u304B\u308A\u307E\u305B\u3093', searching: '\u691C\u7D22\u4E2D...',
|
|
74
|
+
sync: '\u540C\u671F', syncing: '\u540C\u671F\u4E2D...', syncDone: '\u2714 \u540C\u671F\u5B8C\u4E86', loading: '\u8AAD\u307F\u8FBC\u307F\u4E2D...',
|
|
75
|
+
sortUpdatedDesc: '\u2193 \u66F4\u65B0\u65E5\u6642', sortUpdatedAsc: '\u2191 \u66F4\u65B0\u65E5\u6642',
|
|
76
|
+
sortTitleAsc: '\u2191 \u30BF\u30A4\u30C8\u30EB', sortTitleDesc: '\u2193 \u30BF\u30A4\u30C8\u30EB',
|
|
77
|
+
ctxNewNoteHere: '\u3053\u3053\u306B\u65B0\u898F\u30CE\u30FC\u30C8', ctxNewTodoHere: '\u3053\u3053\u306B\u65B0\u898F\u30BF\u30B9\u30AF',
|
|
78
|
+
ctxNewSubNotebook: '\u65B0\u898F\u30B5\u30D6\u30CE\u30FC\u30C8\u30D6\u30C3\u30AF', ctxRenameFolder: '\u540D\u524D\u3092\u5909\u66F4',
|
|
79
|
+
ctxExportFolder: '\u30CE\u30FC\u30C8\u30D6\u30C3\u30AF\u3092\u30A8\u30AF\u30B9\u30DD\u30FC\u30C8', ctxDeleteFolder: '\u30CE\u30FC\u30C8\u30D6\u30C3\u30AF\u3092\u524A\u9664',
|
|
80
|
+
ctxOpenNote: '\u30CE\u30FC\u30C8\u3092\u958B\u304F', ctxOpenInNewWindow: '\u65B0\u3057\u3044\u30A6\u30A3\u30F3\u30C9\u30A6\u3067\u958B\u304F',
|
|
81
|
+
ctxCopyLink: 'Markdown\u30EA\u30F3\u30AF\u3092\u30B3\u30D4\u30FC', ctxDuplicateNote: '\u8907\u88FD',
|
|
82
|
+
ctxSwitchNoteType: '\u30CE\u30FC\u30C8/\u30BF\u30B9\u30AF\u5207\u308A\u66FF\u3048', ctxToggleTodo: '\u5B8C\u4E86\u72B6\u614B\u3092\u5207\u308A\u66FF\u3048',
|
|
83
|
+
ctxRenameNote: '\u540D\u524D\u3092\u5909\u66F4', ctxMoveNote: '\u30CE\u30FC\u30C8\u30D6\u30C3\u30AF\u306B\u79FB\u52D5...',
|
|
84
|
+
ctxNoteInfo: '\u30CE\u30FC\u30C8\u30D7\u30ED\u30D1\u30C6\u30A3', ctxDeleteNote: '\u30CE\u30FC\u30C8\u3092\u524A\u9664',
|
|
85
|
+
confirmDeleteFolder: '\u3053\u306E\u30CE\u30FC\u30C8\u30D6\u30C3\u30AF\u3068\u305D\u306E\u5185\u5BB9\u3092\u3059\u3079\u3066\u524A\u9664\u3057\u307E\u3059\u304B\uFF1F',
|
|
86
|
+
confirmDeleteNote: '\u3053\u306E\u30CE\u30FC\u30C8\u3092\u524A\u9664\u3057\u307E\u3059\u304B\uFF1F',
|
|
87
|
+
promptRename: '\u65B0\u3057\u3044\u540D\u524D\u3092\u5165\u529B\uFF1A', promptMoveNote: '\u79FB\u52D5\u5148\u306E\u30CE\u30FC\u30C8\u30D6\u30C3\u30AF\u540D\uFF1A',
|
|
88
|
+
},
|
|
63
89
|
};
|
|
64
90
|
|
|
65
91
|
function getI18n(locale) {
|
|
@@ -302,6 +328,7 @@ joplin.plugins.register({
|
|
|
302
328
|
+ ' <input id="search-input" type="text" placeholder="\uD83D\uDD0D ' + t.search + '" />'
|
|
303
329
|
+ ' </div>'
|
|
304
330
|
+ ' <div id="tree-container">' + treeHtml + '</div>'
|
|
331
|
+
+ ' <div id="search-results" style="display:none;"></div>'
|
|
305
332
|
+ ' <div class="bottom-bar">'
|
|
306
333
|
+ ' <button id="btn-sync" title="' + t.sync + '">\uD83D\uDD04 ' + t.sync + '</button>'
|
|
307
334
|
+ ' </div>'
|
|
@@ -340,6 +367,62 @@ joplin.plugins.register({
|
|
|
340
367
|
} else if (msg.name === 'newTodo') {
|
|
341
368
|
await joplin.commands.execute('newTodo');
|
|
342
369
|
await refreshPanel();
|
|
370
|
+
} else if (msg.name === 'search') {
|
|
371
|
+
var query = msg.query;
|
|
372
|
+
if (!query || !query.trim()) {
|
|
373
|
+
// Empty query: tell webview to clear search results
|
|
374
|
+
await joplin.views.panels.postMessage(panel, { name: 'searchResults', results: null, query: '', searchId: msg.searchId });
|
|
375
|
+
return;
|
|
376
|
+
}
|
|
377
|
+
try {
|
|
378
|
+
var searchResults = [];
|
|
379
|
+
var page = 1;
|
|
380
|
+
var hasMore = true;
|
|
381
|
+
while (hasMore && searchResults.length < 100) {
|
|
382
|
+
var result = await joplin.data.get(['search'], {
|
|
383
|
+
query: query,
|
|
384
|
+
fields: ['id', 'title', 'body', 'parent_id', 'is_todo', 'todo_completed'],
|
|
385
|
+
page: page, limit: 20,
|
|
386
|
+
});
|
|
387
|
+
searchResults = searchResults.concat(result.items);
|
|
388
|
+
hasMore = result.has_more;
|
|
389
|
+
page++;
|
|
390
|
+
}
|
|
391
|
+
// Build folder name lookup
|
|
392
|
+
var folderNameMap = {};
|
|
393
|
+
for (var i = 0; i < allFoldersCache.length; i++) {
|
|
394
|
+
folderNameMap[allFoldersCache[i].id] = allFoldersCache[i].title;
|
|
395
|
+
}
|
|
396
|
+
// Extract snippet around the matched keyword
|
|
397
|
+
var items = [];
|
|
398
|
+
for (var i = 0; i < searchResults.length; i++) {
|
|
399
|
+
var note = searchResults[i];
|
|
400
|
+
var snippet = '';
|
|
401
|
+
var body = note.body || '';
|
|
402
|
+
var lowerBody = body.toLowerCase();
|
|
403
|
+
var lowerQuery = query.toLowerCase();
|
|
404
|
+
var matchIdx = lowerBody.indexOf(lowerQuery);
|
|
405
|
+
if (matchIdx >= 0) {
|
|
406
|
+
var start = Math.max(0, matchIdx - 40);
|
|
407
|
+
var end = Math.min(body.length, matchIdx + lowerQuery.length + 80);
|
|
408
|
+
snippet = (start > 0 ? '...' : '') + body.substring(start, end).replace(/\n/g, ' ') + (end < body.length ? '...' : '');
|
|
409
|
+
} else {
|
|
410
|
+
// Title match - show beginning of body
|
|
411
|
+
snippet = body.substring(0, 120).replace(/\n/g, ' ') + (body.length > 120 ? '...' : '');
|
|
412
|
+
}
|
|
413
|
+
items.push({
|
|
414
|
+
id: note.id,
|
|
415
|
+
title: note.title || '(untitled)',
|
|
416
|
+
is_todo: note.is_todo,
|
|
417
|
+
todo_completed: note.todo_completed,
|
|
418
|
+
snippet: snippet,
|
|
419
|
+
folderName: folderNameMap[note.parent_id] || '',
|
|
420
|
+
});
|
|
421
|
+
}
|
|
422
|
+
await joplin.views.panels.postMessage(panel, { name: 'searchResults', results: items, query: query, searchId: msg.searchId });
|
|
423
|
+
} catch (err) {
|
|
424
|
+
console.error('Joplin Explorer: search error', err);
|
|
425
|
+
}
|
|
343
426
|
} else if (msg.name === 'cycleSort') {
|
|
344
427
|
var sortModes = ['updated_desc', 'updated_asc', 'title_asc', 'title_desc'];
|
|
345
428
|
var idx = sortModes.indexOf(currentSort);
|
package/publish/manifest.json
CHANGED
|
@@ -2,7 +2,7 @@
|
|
|
2
2
|
"manifest_version": 1,
|
|
3
3
|
"id": "com.github.joplin-explorer",
|
|
4
4
|
"app_min_version": "2.6.0",
|
|
5
|
-
"version": "1.
|
|
5
|
+
"version": "1.1.1",
|
|
6
6
|
"name": "Joplin Explorer",
|
|
7
7
|
"description": "A unified sidebar that displays notebooks and notes together in a single tree view",
|
|
8
8
|
"author": "user",
|
package/publish/plugin.jpl
CHANGED
|
Binary file
|
|
@@ -273,3 +273,83 @@ html, body {
|
|
|
273
273
|
.tree-item.drop-below {
|
|
274
274
|
box-shadow: 0 2px 0 0 var(--joplin-color2, #4a9cf5);
|
|
275
275
|
}
|
|
276
|
+
|
|
277
|
+
#search-results {
|
|
278
|
+
flex: 1;
|
|
279
|
+
overflow-y: scroll;
|
|
280
|
+
padding: 4px 0;
|
|
281
|
+
}
|
|
282
|
+
|
|
283
|
+
#search-results::-webkit-scrollbar {
|
|
284
|
+
width: 8px;
|
|
285
|
+
}
|
|
286
|
+
|
|
287
|
+
#search-results::-webkit-scrollbar-track {
|
|
288
|
+
background: transparent;
|
|
289
|
+
}
|
|
290
|
+
|
|
291
|
+
#search-results::-webkit-scrollbar-thumb {
|
|
292
|
+
background: var(--joplin-color-faded, #888);
|
|
293
|
+
border-radius: 4px;
|
|
294
|
+
}
|
|
295
|
+
|
|
296
|
+
/* Search results */
|
|
297
|
+
.search-status {
|
|
298
|
+
padding: 8px 12px;
|
|
299
|
+
font-size: 11px;
|
|
300
|
+
color: var(--joplin-color-faded, #888);
|
|
301
|
+
border-bottom: 1px solid var(--joplin-divider-color, #eee);
|
|
302
|
+
}
|
|
303
|
+
|
|
304
|
+
.search-result-item {
|
|
305
|
+
display: flex;
|
|
306
|
+
align-items: flex-start;
|
|
307
|
+
padding: 8px 10px;
|
|
308
|
+
gap: 8px;
|
|
309
|
+
min-height: auto;
|
|
310
|
+
}
|
|
311
|
+
|
|
312
|
+
.search-result-item .icon {
|
|
313
|
+
margin-top: 2px;
|
|
314
|
+
flex-shrink: 0;
|
|
315
|
+
}
|
|
316
|
+
|
|
317
|
+
.search-result-content {
|
|
318
|
+
flex: 1;
|
|
319
|
+
min-width: 0;
|
|
320
|
+
overflow: hidden;
|
|
321
|
+
}
|
|
322
|
+
|
|
323
|
+
.search-result-title {
|
|
324
|
+
font-weight: 600;
|
|
325
|
+
font-size: 12px;
|
|
326
|
+
line-height: 1.4;
|
|
327
|
+
white-space: nowrap;
|
|
328
|
+
overflow: hidden;
|
|
329
|
+
text-overflow: ellipsis;
|
|
330
|
+
}
|
|
331
|
+
|
|
332
|
+
.search-result-folder {
|
|
333
|
+
font-size: 10px;
|
|
334
|
+
color: var(--joplin-color-faded, #999);
|
|
335
|
+
margin-top: 1px;
|
|
336
|
+
}
|
|
337
|
+
|
|
338
|
+
.search-result-snippet {
|
|
339
|
+
font-size: 11px;
|
|
340
|
+
color: var(--joplin-color-faded, #777);
|
|
341
|
+
margin-top: 3px;
|
|
342
|
+
line-height: 1.4;
|
|
343
|
+
display: -webkit-box;
|
|
344
|
+
-webkit-line-clamp: 2;
|
|
345
|
+
-webkit-box-orient: vertical;
|
|
346
|
+
overflow: hidden;
|
|
347
|
+
word-break: break-all;
|
|
348
|
+
}
|
|
349
|
+
|
|
350
|
+
mark.search-highlight {
|
|
351
|
+
background: rgba(255, 213, 0, 0.4);
|
|
352
|
+
color: inherit;
|
|
353
|
+
padding: 0 1px;
|
|
354
|
+
border-radius: 2px;
|
|
355
|
+
}
|
package/publish/webview/panel.js
CHANGED
|
@@ -21,7 +21,6 @@ var _observer = new MutationObserver(function() {
|
|
|
21
21
|
if (!container) return;
|
|
22
22
|
|
|
23
23
|
if (_isFirstRender) {
|
|
24
|
-
// First render: scroll to selected note
|
|
25
24
|
_isFirstRender = false;
|
|
26
25
|
var selected = container.querySelector('.tree-item.note.selected');
|
|
27
26
|
if (selected) {
|
|
@@ -30,7 +29,6 @@ var _observer = new MutationObserver(function() {
|
|
|
30
29
|
}, 30);
|
|
31
30
|
}
|
|
32
31
|
} else {
|
|
33
|
-
// Subsequent renders: restore previous scroll position
|
|
34
32
|
container.scrollTop = _savedScrollTop;
|
|
35
33
|
}
|
|
36
34
|
});
|
|
@@ -213,6 +211,14 @@ webviewApi.onMessage(function(msg) {
|
|
|
213
211
|
}
|
|
214
212
|
}, 2000);
|
|
215
213
|
}
|
|
214
|
+
} else if (m.name === 'searchResults') {
|
|
215
|
+
// Ignore stale search results
|
|
216
|
+
if (m.searchId !== undefined && m.searchId !== _searchId) return;
|
|
217
|
+
if (m.results === null) {
|
|
218
|
+
if (_searchMode) exitSearchMode();
|
|
219
|
+
} else {
|
|
220
|
+
renderSearchResults(m.results, m.query);
|
|
221
|
+
}
|
|
216
222
|
} else if (m.name === 'selectNote') {
|
|
217
223
|
// Update selection without full re-render
|
|
218
224
|
document.querySelectorAll('.tree-item.note.selected').forEach(function(el) {
|
|
@@ -341,28 +347,105 @@ document.addEventListener('drop', function(e) {
|
|
|
341
347
|
});
|
|
342
348
|
});
|
|
343
349
|
|
|
344
|
-
// Search
|
|
350
|
+
// ======================== Content Search ========================
|
|
351
|
+
var _searchTimer = null;
|
|
352
|
+
var _searchMode = false;
|
|
353
|
+
var _searchId = 0;
|
|
354
|
+
|
|
355
|
+
function escapeRegex(str) {
|
|
356
|
+
return str.replace(/[.*+?^${}()|[\]\\]/g, '\\$&');
|
|
357
|
+
}
|
|
358
|
+
|
|
359
|
+
function highlightText(text, query) {
|
|
360
|
+
if (!query) return text;
|
|
361
|
+
// Escape HTML first
|
|
362
|
+
var escaped = text.replace(/&/g, '&').replace(/</g, '<').replace(/>/g, '>');
|
|
363
|
+
var regex = new RegExp('(' + escapeRegex(query) + ')', 'gi');
|
|
364
|
+
return escaped.replace(regex, '<mark class="search-highlight">$1</mark>');
|
|
365
|
+
}
|
|
366
|
+
|
|
367
|
+
function showSearchContainer(show) {
|
|
368
|
+
var tree = document.getElementById('tree-container');
|
|
369
|
+
var search = document.getElementById('search-results');
|
|
370
|
+
if (tree) tree.style.display = show ? 'none' : '';
|
|
371
|
+
if (search) search.style.display = show ? '' : 'none';
|
|
372
|
+
}
|
|
373
|
+
|
|
374
|
+
function renderSearchResults(results, query) {
|
|
375
|
+
var container = document.getElementById('search-results');
|
|
376
|
+
if (!container) return;
|
|
377
|
+
|
|
378
|
+
showSearchContainer(true);
|
|
379
|
+
|
|
380
|
+
if (!results || results.length === 0) {
|
|
381
|
+
container.innerHTML = '<div class="search-status">' + T('searchNoResult') + '</div>';
|
|
382
|
+
return;
|
|
383
|
+
}
|
|
384
|
+
|
|
385
|
+
var countText = T('searchResultCount').replace('{count}', results.length);
|
|
386
|
+
var html = '<div class="search-status">' + countText + '</div>';
|
|
387
|
+
|
|
388
|
+
for (var i = 0; i < results.length; i++) {
|
|
389
|
+
var item = results[i];
|
|
390
|
+
var icon = '\uD83D\uDCDD';
|
|
391
|
+
if (item.is_todo) {
|
|
392
|
+
icon = item.todo_completed ? '\u2611' : '\u2610';
|
|
393
|
+
}
|
|
394
|
+
html += '<div class="search-result-item tree-item note" data-id="' + item.id + '" data-type="note">';
|
|
395
|
+
html += '<span class="icon note-icon">' + icon + '</span>';
|
|
396
|
+
html += '<div class="search-result-content">';
|
|
397
|
+
html += '<div class="search-result-title">' + highlightText(item.title, query) + '</div>';
|
|
398
|
+
if (item.folderName) {
|
|
399
|
+
html += '<div class="search-result-folder">\uD83D\uDCC2 ' + item.folderName + '</div>';
|
|
400
|
+
}
|
|
401
|
+
if (item.snippet) {
|
|
402
|
+
html += '<div class="search-result-snippet">' + highlightText(item.snippet, query) + '</div>';
|
|
403
|
+
}
|
|
404
|
+
html += '</div></div>';
|
|
405
|
+
}
|
|
406
|
+
|
|
407
|
+
container.innerHTML = html;
|
|
408
|
+
_searchMode = true;
|
|
409
|
+
}
|
|
410
|
+
|
|
411
|
+
function exitSearchMode() {
|
|
412
|
+
_searchMode = false;
|
|
413
|
+
showSearchContainer(false);
|
|
414
|
+
}
|
|
415
|
+
|
|
345
416
|
document.addEventListener('input', function(e) {
|
|
346
417
|
if (e.target.id !== 'search-input') return;
|
|
347
|
-
var query = e.target.value.
|
|
418
|
+
var query = e.target.value.trim();
|
|
348
419
|
|
|
349
|
-
|
|
350
|
-
|
|
351
|
-
|
|
352
|
-
});
|
|
420
|
+
if (_searchTimer) clearTimeout(_searchTimer);
|
|
421
|
+
_searchId++;
|
|
422
|
+
var currentSearchId = _searchId;
|
|
353
423
|
|
|
354
|
-
if (query) {
|
|
355
|
-
|
|
356
|
-
|
|
424
|
+
if (!query) {
|
|
425
|
+
if (_searchMode) exitSearchMode();
|
|
426
|
+
return;
|
|
357
427
|
}
|
|
358
428
|
|
|
359
|
-
|
|
360
|
-
|
|
361
|
-
|
|
362
|
-
|
|
363
|
-
|
|
364
|
-
|
|
365
|
-
|
|
366
|
-
|
|
367
|
-
|
|
429
|
+
_searchMode = true;
|
|
430
|
+
var searchContainer = document.getElementById('search-results');
|
|
431
|
+
if (searchContainer) {
|
|
432
|
+
searchContainer.innerHTML = '<div class="search-status">' + T('searching') + '</div>';
|
|
433
|
+
}
|
|
434
|
+
showSearchContainer(true);
|
|
435
|
+
|
|
436
|
+
// Debounce: wait 400ms after typing stops
|
|
437
|
+
_searchTimer = setTimeout(function() {
|
|
438
|
+
postMsg({ name: 'search', query: query, searchId: currentSearchId });
|
|
439
|
+
}, 400);
|
|
440
|
+
});
|
|
441
|
+
|
|
442
|
+
// Handle Escape key to clear search
|
|
443
|
+
document.addEventListener('keydown', function(e) {
|
|
444
|
+
if (e.key === 'Escape') {
|
|
445
|
+
var input = document.getElementById('search-input');
|
|
446
|
+
if (input && input.value) {
|
|
447
|
+
input.value = '';
|
|
448
|
+
if (_searchMode) exitSearchMode();
|
|
449
|
+
}
|
|
450
|
+
}
|
|
368
451
|
});
|