Exact page matches in search
This commit is contained in:
@@ -11,9 +11,58 @@ function rebuildIndex() {
|
||||
});
|
||||
}
|
||||
|
||||
function encodeSearchPath(p) {
|
||||
if (p === '/' || p === '') return '/';
|
||||
return '/' + p.replace(/^\/+/, '').split('/').map(encodeURIComponent).join('/');
|
||||
}
|
||||
|
||||
// createSearchPage runs the new-page flow (pick a parent folder, then confirm
|
||||
// the name) starting from the search query, so a query with no exact page can
|
||||
// be turned into that page in one step. The name field is pre-filled with the
|
||||
// query but stays editable.
|
||||
function createSearchPage(name) {
|
||||
var current = decodeURIComponent(window.location.pathname).replace(/\/+$/, '') || '/';
|
||||
openTreePicker({
|
||||
title: 'New page — where?',
|
||||
mode: 'folder',
|
||||
initialPath: current,
|
||||
preselect: current,
|
||||
hideFiles: true,
|
||||
confirmLabel: 'NEXT',
|
||||
onSelect: function (parentPath) {
|
||||
var input = document.createElement('input');
|
||||
input.type = 'text';
|
||||
input.className = 'input';
|
||||
input.placeholder = 'Page name';
|
||||
input.value = name || '';
|
||||
openModal({
|
||||
title: 'New page — name?',
|
||||
body: input,
|
||||
confirm: {
|
||||
label: 'CREATE',
|
||||
onConfirm: function () {
|
||||
var finalName = input.value.trim();
|
||||
if (!finalName) return;
|
||||
var base = parentPath === '/' ? '/' : encodeSearchPath(parentPath) + '/';
|
||||
window.location.href = base + encodeURIComponent(finalName) + '/?edit';
|
||||
}
|
||||
}
|
||||
});
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
document.addEventListener('DOMContentLoaded', function () {
|
||||
wireDropdown(document.querySelector('[data-action="actions-drop"]'));
|
||||
|
||||
var createLink = document.querySelector('[data-create-page]');
|
||||
if (createLink) {
|
||||
createLink.addEventListener('click', function (e) {
|
||||
e.preventDefault();
|
||||
createSearchPage(createLink.getAttribute('data-create-page'));
|
||||
});
|
||||
}
|
||||
|
||||
// Focus the search input on results pages so Tab steps directly into the
|
||||
// first match — the input sits immediately before the results in DOM
|
||||
// order, so the natural tab sequence is input → first result → next, …
|
||||
|
||||
+11
-4
@@ -4,7 +4,17 @@
|
||||
|
||||
{{define "content"}}
|
||||
{{if .Query}}
|
||||
{{if or .Pages .Files}}
|
||||
{{if .Exact}}
|
||||
<h2 class="search-section">Exact Match</h2>
|
||||
{{range .Exact}}
|
||||
<article class="search-card">
|
||||
<a href="{{.URL}}">{{.Name}}</a>
|
||||
<div class="muted">/{{.Path}}</div>
|
||||
</article>
|
||||
{{end}}
|
||||
{{else}}
|
||||
<p class="muted">No page named “{{.Query}}” — <button class="btn btn-small" data-create-page="{{.Query}}">create it</button></p>
|
||||
{{end}}
|
||||
{{if .Pages}}
|
||||
<h2 class="search-section">Matching Pages <span class="muted">{{.PageTotal}}</span></h2>
|
||||
{{range .Pages}}
|
||||
@@ -27,9 +37,6 @@
|
||||
</article>
|
||||
{{end}}
|
||||
{{end}}
|
||||
{{else}}
|
||||
<p class="empty">No matches for “{{.Query}}”.</p>
|
||||
{{end}}
|
||||
{{else}}
|
||||
<p class="empty">Enter a query above.</p>
|
||||
{{end}}
|
||||
|
||||
Reference in New Issue
Block a user