Initial commit: Klammertext source distribution
Curated source subset assembled by klammertext-dev's doc/make_dist.sh: the Klammermachine (mac), the Standard Klammer Set (sks), the commands (com), editor plugins and install guides (doc), a test subset (tst), and lib/bin placeholders. Builds with 'make -C com'. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
This commit is contained in:
313
sks/document/js/search.js
Normal file
313
sks/document/js/search.js
Normal file
@@ -0,0 +1,313 @@
|
||||
|
||||
|
||||
/*
|
||||
address article aside blockquote details dialog dd
|
||||
div dl dt fieldset figcaption figure footer form
|
||||
h1 h2 h3 h4 h5 h6 header hgroup hr li
|
||||
main nav ol p section table ul td tr pre
|
||||
*/
|
||||
|
||||
function blocks(root) {
|
||||
let selector = [];
|
||||
"blockquote kt-chapter div dd dt kt-part h1 h2 h3 h4 h5 li p td pre"
|
||||
.split(" ").forEach(function (e) {
|
||||
//selector.push("#pagecache .content_page " + e);
|
||||
selector.push(root + " " + e);
|
||||
});
|
||||
return document.querySelectorAll(selector.join(", "));
|
||||
}
|
||||
|
||||
function page_cache_blocks() {
|
||||
return blocks("#pagecache .content_page");
|
||||
}
|
||||
|
||||
function current_blocks() {
|
||||
return blocks("#text");
|
||||
}
|
||||
|
||||
function visible_toc_sections() {
|
||||
let elements = current_blocks();
|
||||
let last_heading = null;
|
||||
let text_window = K.get("#text");
|
||||
let text_top = text_window.scrollTop;
|
||||
let text_bottom = text_top + K.height(text_window);
|
||||
//console.log("text_top: " + text_top);
|
||||
//console.log("text_bottom: " + text_bottom);
|
||||
|
||||
let result = [];
|
||||
|
||||
elements.forEach(function (elt) {
|
||||
if (K.attr(elt, "data-level")) {
|
||||
last_heading = elt;
|
||||
//console.log("");
|
||||
//console.log("LAST_HEADING:");
|
||||
//console.log(last_heading);
|
||||
}
|
||||
//let elt_top = K.top(elt) - K.top(text_window);
|
||||
let elt_top = elt.offsetTop; //
|
||||
K.top(elt);
|
||||
//console.log("");
|
||||
//console.log("elt: " + elt_top);
|
||||
//console.log(elt);
|
||||
/*
|
||||
if (elt_top >= text_top &&
|
||||
elt_top <= text_bottom &&
|
||||
!result.includes(last_heading)) {
|
||||
*/
|
||||
if (elt_top >= text_top &&
|
||||
elt_top <= text_bottom) {
|
||||
//console.log(" add: "
|
||||
// + last_heading.children[0].textContent.trim());
|
||||
if (!result.includes(last_heading)) {
|
||||
result.push(last_heading);
|
||||
}
|
||||
}
|
||||
});
|
||||
if (result.length == 0) {
|
||||
result.push(last_heading);
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
|
||||
function buttons_before_search() {
|
||||
//console.log("buttons_before_search()");
|
||||
K.get("#search_clear").hidden = true;
|
||||
K.get("#search_back_label").hidden = true;
|
||||
K.get("#search_clear_input").hidden = true;
|
||||
K.get("#search_label").hidden = false;
|
||||
show_navigation_items();
|
||||
}
|
||||
|
||||
function buttons_during_search() {
|
||||
//console.log("buttons_during_search()");
|
||||
K.get("#search_clear").hidden = true;
|
||||
K.get("#search_back_label").hidden = false;
|
||||
K.get("#search_clear_input").hidden = false;
|
||||
K.get("#search_label").hidden = false;
|
||||
show_navigation_items(false);
|
||||
}
|
||||
|
||||
function buttons_after_search() {
|
||||
//console.log("buttons_after_search()");
|
||||
K.get("#search_clear").hidden = false;
|
||||
K.get("#search_back_label").hidden = false;
|
||||
K.get("#search_clear_input").hidden = false;
|
||||
K.get("#search_label").hidden = false;
|
||||
show_navigation_items();
|
||||
}
|
||||
|
||||
function show_match(str) {
|
||||
return "<span class=\"search_target\">" + str + "</span>";
|
||||
}
|
||||
|
||||
function show_all_matches(page, rgx) {
|
||||
//let cached_page = K.get("#pagecache #_page_" + id[2]);
|
||||
let text_contents = page.innerHTML;
|
||||
text_contents = text_contents.replaceAll(rgx, show_match);
|
||||
page.innerHTML = text_contents;
|
||||
}
|
||||
|
||||
function unhighlight_search_targets() {
|
||||
K.getv(".search_target").forEach(function(e) {
|
||||
e.outerHTML = e.innerHTML;
|
||||
});
|
||||
}
|
||||
|
||||
var saved_toc_width = 0;
|
||||
|
||||
function make_toc_visible(visible)
|
||||
{
|
||||
if (!visible) {
|
||||
let current_width = K.width("#toc");
|
||||
if (current_width > 0) {
|
||||
saved_toc_width = current_width;
|
||||
}
|
||||
}
|
||||
K.get("#toc").hidden = !visible;
|
||||
K.get("#resizer").hidden = !visible;
|
||||
if (visible) {
|
||||
if (saved_toc_width > 0) {
|
||||
K.width("#toc", saved_toc_width);
|
||||
resize_text_width(saved_toc_width);
|
||||
}
|
||||
resize_toc();
|
||||
} else {
|
||||
resize_text_width();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
function blocks_with_text(search_string) {
|
||||
const rgx = new RegExp(search_string, "g");
|
||||
const id_rgx = new RegExp("id=\"(.*?)\" data-basename=\"(.*?)\"");
|
||||
let modified_blocks = [];
|
||||
page_cache_blocks().forEach(function (o) {
|
||||
let element_text = o.textContent;
|
||||
if (element_text.search(rgx) > -1) {
|
||||
//console.log(id_rgx);
|
||||
//console.log(element_text);
|
||||
let id = o.outerHTML.match(id_rgx);
|
||||
//console.log("id: " + id);
|
||||
//let element_contents = o.innerHTML;
|
||||
let element_contents = o.outerHTML;
|
||||
//element_contents = unhighlight_searches_in_text(element_contents);
|
||||
//console.log(element_contents);
|
||||
//console.log("\n----------------\n");
|
||||
element_contents = element_contents.replaceAll(rgx, show_match);
|
||||
|
||||
//let modified = document.createElement("div");
|
||||
//K.attr(modified, "class", "search_result");
|
||||
let modified = document.createElement("a");
|
||||
|
||||
K.attr(modified, "class", "search_result");
|
||||
K.attr(modified, "href", "#" + id[2] + "#" + id[1])
|
||||
modified.innerHTML = element_contents;
|
||||
modified_blocks.push(modified);
|
||||
|
||||
modified.addEventListener("click", function (event) {
|
||||
event.preventDefault();
|
||||
unhighlight_search_targets();
|
||||
go_to_section(null, id[2], id[1], true, function() {
|
||||
show_all_matches(displayed_text(), rgx);
|
||||
});
|
||||
make_toc_visible(true);
|
||||
buttons_after_search();
|
||||
});
|
||||
}
|
||||
});
|
||||
return modified_blocks;
|
||||
}
|
||||
|
||||
|
||||
function search_heading(search_string, count) {
|
||||
let heading = document.createElement("h1");
|
||||
if (count > 0) {
|
||||
heading.innerHTML = count + " occurrences of \"" + search_string + "\"";
|
||||
} else {
|
||||
heading.innerHTML = "No occurrences of \"" + search_string + "\"";
|
||||
}
|
||||
return heading;
|
||||
}
|
||||
|
||||
function show_search_results(search_string) {
|
||||
if (search_string.length === 0) {
|
||||
return;
|
||||
}
|
||||
unhighlight_search_targets();
|
||||
let search_page = K.get("#search_page");
|
||||
search_page.innerHTML = "";
|
||||
//search_page.style.width = K.width("#text");
|
||||
|
||||
let results = blocks_with_text(search_string);
|
||||
search_page.append(search_heading(search_string, results.length));
|
||||
if (results) {
|
||||
results.forEach(function (o) {
|
||||
search_page.append(o);
|
||||
});
|
||||
}
|
||||
make_toc_visible(false);
|
||||
buttons_during_search();
|
||||
|
||||
//let width = K.get("#text").clientWidth;
|
||||
//console.log("outerWidth: " + width);
|
||||
|
||||
K.get("#text").replaceWith(search_page);
|
||||
K.attr("#search_page", "id", "text");
|
||||
search_page = document.createElement("div");
|
||||
K.attr(search_page, "id", "search_page");
|
||||
K.get("#pagecache").append(search_page);
|
||||
|
||||
}
|
||||
|
||||
|
||||
window.addEventListener("load", function (event) {
|
||||
|
||||
|
||||
K.get("#search_input").addEventListener("keyup", function (e) {
|
||||
event.preventDefault();
|
||||
let search_string = K.get("#search_input").value;
|
||||
if (search_string.length > 0) {
|
||||
let enter_key = 13;
|
||||
if (e.which === enter_key) {
|
||||
//console.log("save position with button");
|
||||
unhighlight_search_targets();
|
||||
save_position();
|
||||
buttons_during_search();
|
||||
//console.log("ENTER " + K.get("#search_input").value);
|
||||
show_search_results(search_string);
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
|
||||
K.get("#search_label").addEventListener("click", function (e) {
|
||||
event.preventDefault();
|
||||
let search_string = K.get("#search_input").value;
|
||||
if (search_string.length > 0) {
|
||||
//console.log("save position with return");
|
||||
save_position();
|
||||
buttons_during_search();
|
||||
show_search_results(search_string);
|
||||
} else {
|
||||
let input_box = K.get("#search_input");
|
||||
K.style(input_box, "background-color", "var(--nav_background_color)");
|
||||
K.style(input_box, "font-style", "italic");
|
||||
input_box.value = "Enter search text here";
|
||||
setTimeout(function() {
|
||||
K.style(input_box, "background-color", "white");
|
||||
input_box.value = "";
|
||||
K.style(input_box, "font-style", "normal");
|
||||
}, 1500);
|
||||
}
|
||||
});
|
||||
|
||||
K.get("#search_clear").addEventListener("click", function (e) {
|
||||
unhighlight_search_targets();
|
||||
/*
|
||||
text_elt.innerHTML = text_elt.innerHTML.replaceAll(id_rgx, "$1");
|
||||
let text_contents = text_elt.innerHTML;
|
||||
text_contents = text_contents.replaceAll(id_rgx, "$1");
|
||||
text_elt.innerHTML = text_contents;
|
||||
*/
|
||||
//K.get("#search_clear").hidden = true;
|
||||
buttons_before_search();
|
||||
add_scrolling_to_text();
|
||||
});
|
||||
|
||||
|
||||
K.get("#search_clear_input").addEventListener("click", function (e) {
|
||||
K.get("#search_input").value = "";
|
||||
e.srcElement.hidden = true;
|
||||
//K.attr("#text", "style", "background-color: var(--nav_background_color)");
|
||||
//K.attr("#text", "style", "color: var(--nav_background_color)");
|
||||
});
|
||||
|
||||
K.get("#search_back_label").addEventListener("click", function (e) {
|
||||
//console.log("back");
|
||||
make_toc_visible(true);
|
||||
buttons_before_search();
|
||||
add_scrolling_to_text();
|
||||
restore_position();
|
||||
unhighlight_search_targets();
|
||||
});
|
||||
|
||||
|
||||
K.get("html").addEventListener("keyup", function (event) {
|
||||
let uppercase = "S".charCodeAt();
|
||||
let lowercase = uppercase + 32;
|
||||
if (search_not_active()) {
|
||||
if (event.which === uppercase || event.which === lowercase) {
|
||||
buttons_before_search();
|
||||
K.get("#search_input").focus();
|
||||
K.get("#search_input").value = "";
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
|
||||
|
||||
|
||||
//define_keypress("B", "#search_back_label");
|
||||
|
||||
});
|
||||
Reference in New Issue
Block a user