mirror of
https://github.com/fverdugo/XM_40017.git
synced 2025-12-29 10:18:31 +01:00
build based on 57c8db5
This commit is contained in:
@@ -104,7 +104,7 @@ $(document).on(
|
||||
.prop("title", articleToggleTitle);
|
||||
parent.siblings("section").slideToggle();
|
||||
});
|
||||
}
|
||||
},
|
||||
);
|
||||
|
||||
$(document).on("click", ".docs-article-toggle-button", function (event) {
|
||||
@@ -239,6 +239,20 @@ $(document).ready(function () {
|
||||
type: "click",
|
||||
noToggleAnimation: true,
|
||||
});
|
||||
|
||||
setTimeout(function () {
|
||||
if (window.location.hash) {
|
||||
const targetId = window.location.hash.substring(1);
|
||||
const targetElement = document.getElementById(targetId);
|
||||
|
||||
if (targetElement) {
|
||||
targetElement.scrollIntoView({
|
||||
behavior: "smooth",
|
||||
block: "center",
|
||||
});
|
||||
}
|
||||
}
|
||||
}, 100);
|
||||
}
|
||||
});
|
||||
|
||||
@@ -312,7 +326,7 @@ update_search
|
||||
|
||||
function worker_function(documenterSearchIndex, documenterBaseURL, filters) {
|
||||
importScripts(
|
||||
"https://cdn.jsdelivr.net/npm/minisearch@6.1.0/dist/umd/index.min.js"
|
||||
"https://cdn.jsdelivr.net/npm/minisearch@6.1.0/dist/umd/index.min.js",
|
||||
);
|
||||
|
||||
let data = documenterSearchIndex.map((x, key) => {
|
||||
@@ -523,8 +537,8 @@ function worker_function(documenterSearchIndex, documenterBaseURL, filters) {
|
||||
Math.max(textindex.index - 100, 0),
|
||||
Math.min(
|
||||
textindex.index + querystring.length + 100,
|
||||
result.text.length
|
||||
)
|
||||
result.text.length,
|
||||
),
|
||||
)
|
||||
: ""; // cut-off text before and after from the match
|
||||
|
||||
@@ -534,7 +548,7 @@ function worker_function(documenterSearchIndex, documenterBaseURL, filters) {
|
||||
? "..." +
|
||||
text.replace(
|
||||
new RegExp(`${escape(searchstring)}`, "i"), // For first occurrence
|
||||
'<span class="search-result-highlight py-1">$&</span>'
|
||||
'<span class="search-result-highlight py-1">$&</span>',
|
||||
) +
|
||||
"..."
|
||||
: ""; // highlights the match
|
||||
@@ -547,7 +561,7 @@ function worker_function(documenterSearchIndex, documenterBaseURL, filters) {
|
||||
// We encode the full url to escape some special characters which can lead to broken links
|
||||
let result_div = `
|
||||
<a href="${encodeURI(
|
||||
documenterBaseURL + "/" + result.location
|
||||
documenterBaseURL + "/" + result.location,
|
||||
)}" class="search-result-link w-100 is-flex is-flex-direction-column gap-2 px-4 py-2">
|
||||
<div class="w-100 is-flex is-flex-wrap-wrap is-justify-content-space-between is-align-items-flex-start">
|
||||
<div class="search-result-title has-text-weight-bold ${
|
||||
@@ -612,176 +626,256 @@ function worker_function(documenterSearchIndex, documenterBaseURL, filters) {
|
||||
};
|
||||
}
|
||||
|
||||
// `worker = Threads.@spawn worker_function(documenterSearchIndex)`, but in JavaScript!
|
||||
const filters = [
|
||||
...new Set(documenterSearchIndex["docs"].map((x) => x.category)),
|
||||
];
|
||||
const worker_str =
|
||||
"(" +
|
||||
worker_function.toString() +
|
||||
")(" +
|
||||
JSON.stringify(documenterSearchIndex["docs"]) +
|
||||
"," +
|
||||
JSON.stringify(documenterBaseURL) +
|
||||
"," +
|
||||
JSON.stringify(filters) +
|
||||
")";
|
||||
const worker_blob = new Blob([worker_str], { type: "text/javascript" });
|
||||
const worker = new Worker(URL.createObjectURL(worker_blob));
|
||||
|
||||
/////// SEARCH MAIN ///////
|
||||
|
||||
// Whether the worker is currently handling a search. This is a boolean
|
||||
// as the worker only ever handles 1 or 0 searches at a time.
|
||||
var worker_is_running = false;
|
||||
function runSearchMainCode() {
|
||||
// `worker = Threads.@spawn worker_function(documenterSearchIndex)`, but in JavaScript!
|
||||
const filters = [
|
||||
...new Set(documenterSearchIndex["docs"].map((x) => x.category)),
|
||||
];
|
||||
const worker_str =
|
||||
"(" +
|
||||
worker_function.toString() +
|
||||
")(" +
|
||||
JSON.stringify(documenterSearchIndex["docs"]) +
|
||||
"," +
|
||||
JSON.stringify(documenterBaseURL) +
|
||||
"," +
|
||||
JSON.stringify(filters) +
|
||||
")";
|
||||
const worker_blob = new Blob([worker_str], { type: "text/javascript" });
|
||||
const worker = new Worker(URL.createObjectURL(worker_blob));
|
||||
|
||||
// The last search text that was sent to the worker. This is used to determine
|
||||
// if the worker should be launched again when it reports back results.
|
||||
var last_search_text = "";
|
||||
// Whether the worker is currently handling a search. This is a boolean
|
||||
// as the worker only ever handles 1 or 0 searches at a time.
|
||||
var worker_is_running = false;
|
||||
|
||||
// The results of the last search. This, in combination with the state of the filters
|
||||
// in the DOM, is used compute the results to display on calls to update_search.
|
||||
var unfiltered_results = [];
|
||||
// The last search text that was sent to the worker. This is used to determine
|
||||
// if the worker should be launched again when it reports back results.
|
||||
var last_search_text = "";
|
||||
|
||||
// Which filter is currently selected
|
||||
var selected_filter = "";
|
||||
// The results of the last search. This, in combination with the state of the filters
|
||||
// in the DOM, is used compute the results to display on calls to update_search.
|
||||
var unfiltered_results = [];
|
||||
|
||||
$(document).on("input", ".documenter-search-input", function (event) {
|
||||
if (!worker_is_running) {
|
||||
launch_search();
|
||||
}
|
||||
});
|
||||
// Which filter is currently selected
|
||||
var selected_filter = "";
|
||||
|
||||
function launch_search() {
|
||||
worker_is_running = true;
|
||||
last_search_text = $(".documenter-search-input").val();
|
||||
worker.postMessage(last_search_text);
|
||||
}
|
||||
|
||||
worker.onmessage = function (e) {
|
||||
if (last_search_text !== $(".documenter-search-input").val()) {
|
||||
launch_search();
|
||||
} else {
|
||||
worker_is_running = false;
|
||||
}
|
||||
|
||||
unfiltered_results = e.data;
|
||||
update_search();
|
||||
};
|
||||
|
||||
$(document).on("click", ".search-filter", function () {
|
||||
if ($(this).hasClass("search-filter-selected")) {
|
||||
document.addEventListener("reset-filter", function () {
|
||||
selected_filter = "";
|
||||
} else {
|
||||
selected_filter = $(this).text().toLowerCase();
|
||||
}
|
||||
update_search();
|
||||
});
|
||||
|
||||
// This updates search results and toggles classes for UI:
|
||||
update_search();
|
||||
});
|
||||
//update the url with search query
|
||||
function updateSearchURL(query) {
|
||||
const url = new URL(window.location);
|
||||
|
||||
/**
|
||||
* Make/Update the search component
|
||||
*/
|
||||
function update_search() {
|
||||
let querystring = $(".documenter-search-input").val();
|
||||
|
||||
if (querystring.trim()) {
|
||||
if (selected_filter == "") {
|
||||
results = unfiltered_results;
|
||||
if (query && query.trim() !== "") {
|
||||
url.searchParams.set("q", query);
|
||||
} else {
|
||||
results = unfiltered_results.filter((result) => {
|
||||
return selected_filter == result.category.toLowerCase();
|
||||
});
|
||||
// remove the 'q' param if it exists
|
||||
if (url.searchParams.has("q")) {
|
||||
url.searchParams.delete("q");
|
||||
}
|
||||
}
|
||||
|
||||
let search_result_container = ``;
|
||||
let modal_filters = make_modal_body_filters();
|
||||
let search_divider = `<div class="search-divider w-100"></div>`;
|
||||
|
||||
if (results.length) {
|
||||
let links = [];
|
||||
let count = 0;
|
||||
let search_results = "";
|
||||
|
||||
for (var i = 0, n = results.length; i < n && count < 200; ++i) {
|
||||
let result = results[i];
|
||||
if (result.location && !links.includes(result.location)) {
|
||||
search_results += result.div;
|
||||
count++;
|
||||
links.push(result.location);
|
||||
}
|
||||
// Add or remove the filter parameter based on selected_filter
|
||||
if (selected_filter && selected_filter.trim() !== "") {
|
||||
url.searchParams.set("filter", selected_filter);
|
||||
} else {
|
||||
// remove the 'filter' param if it exists
|
||||
if (url.searchParams.has("filter")) {
|
||||
url.searchParams.delete("filter");
|
||||
}
|
||||
}
|
||||
|
||||
if (count == 1) {
|
||||
count_str = "1 result";
|
||||
} else if (count == 200) {
|
||||
count_str = "200+ results";
|
||||
// Only update history if there are parameters, otherwise use the base URL
|
||||
if (url.search) {
|
||||
window.history.replaceState({}, "", url);
|
||||
} else {
|
||||
window.history.replaceState({}, "", url.pathname + url.hash);
|
||||
}
|
||||
}
|
||||
|
||||
$(document).on("input", ".documenter-search-input", function (event) {
|
||||
if (!worker_is_running) {
|
||||
launch_search();
|
||||
}
|
||||
});
|
||||
|
||||
function launch_search() {
|
||||
worker_is_running = true;
|
||||
last_search_text = $(".documenter-search-input").val();
|
||||
updateSearchURL(last_search_text);
|
||||
worker.postMessage(last_search_text);
|
||||
}
|
||||
|
||||
worker.onmessage = function (e) {
|
||||
if (last_search_text !== $(".documenter-search-input").val()) {
|
||||
launch_search();
|
||||
} else {
|
||||
worker_is_running = false;
|
||||
}
|
||||
|
||||
unfiltered_results = e.data;
|
||||
update_search();
|
||||
};
|
||||
|
||||
$(document).on("click", ".search-filter", function () {
|
||||
let search_input = $(".documenter-search-input");
|
||||
let cursor_position = search_input[0].selectionStart;
|
||||
|
||||
if ($(this).hasClass("search-filter-selected")) {
|
||||
selected_filter = "";
|
||||
} else {
|
||||
selected_filter = $(this).text().toLowerCase();
|
||||
}
|
||||
|
||||
// This updates search results and toggles classes for UI:
|
||||
update_search();
|
||||
|
||||
search_input.focus();
|
||||
search_input.setSelectionRange(cursor_position, cursor_position);
|
||||
});
|
||||
|
||||
/**
|
||||
* Make/Update the search component
|
||||
*/
|
||||
function update_search() {
|
||||
let querystring = $(".documenter-search-input").val();
|
||||
updateSearchURL(querystring);
|
||||
|
||||
if (querystring.trim()) {
|
||||
if (selected_filter == "") {
|
||||
results = unfiltered_results;
|
||||
} else {
|
||||
count_str = count + " results";
|
||||
results = unfiltered_results.filter((result) => {
|
||||
return selected_filter == result.category.toLowerCase();
|
||||
});
|
||||
}
|
||||
let result_count = `<div class="is-size-6">${count_str}</div>`;
|
||||
|
||||
search_result_container = `
|
||||
let search_result_container = ``;
|
||||
let modal_filters = make_modal_body_filters();
|
||||
let search_divider = `<div class="search-divider w-100"></div>`;
|
||||
|
||||
if (results.length) {
|
||||
let links = [];
|
||||
let count = 0;
|
||||
let search_results = "";
|
||||
|
||||
for (var i = 0, n = results.length; i < n && count < 200; ++i) {
|
||||
let result = results[i];
|
||||
if (result.location && !links.includes(result.location)) {
|
||||
search_results += result.div;
|
||||
count++;
|
||||
links.push(result.location);
|
||||
}
|
||||
}
|
||||
|
||||
if (count == 1) {
|
||||
count_str = "1 result";
|
||||
} else if (count == 200) {
|
||||
count_str = "200+ results";
|
||||
} else {
|
||||
count_str = count + " results";
|
||||
}
|
||||
let result_count = `<div class="is-size-6">${count_str}</div>`;
|
||||
|
||||
search_result_container = `
|
||||
<div class="is-flex is-flex-direction-column gap-2 is-align-items-flex-start">
|
||||
${modal_filters}
|
||||
${search_divider}
|
||||
${result_count}
|
||||
<div class="is-clipped w-100 is-flex is-flex-direction-column gap-2 is-align-items-flex-start has-text-justified mt-1">
|
||||
${search_results}
|
||||
</div>
|
||||
</div>
|
||||
`;
|
||||
} else {
|
||||
search_result_container = `
|
||||
<div class="is-flex is-flex-direction-column gap-2 is-align-items-flex-start">
|
||||
${modal_filters}
|
||||
${search_divider}
|
||||
${result_count}
|
||||
<div class="is-clipped w-100 is-flex is-flex-direction-column gap-2 is-align-items-flex-start has-text-justified mt-1">
|
||||
${search_results}
|
||||
</div>
|
||||
</div>
|
||||
<div class="is-size-6">0 result(s)</div>
|
||||
</div>
|
||||
<div class="has-text-centered my-5 py-5">No result found!</div>
|
||||
`;
|
||||
}
|
||||
|
||||
if ($(".search-modal-card-body").hasClass("is-justify-content-center")) {
|
||||
$(".search-modal-card-body").removeClass("is-justify-content-center");
|
||||
}
|
||||
|
||||
$(".search-modal-card-body").html(search_result_container);
|
||||
} else {
|
||||
search_result_container = `
|
||||
<div class="is-flex is-flex-direction-column gap-2 is-align-items-flex-start">
|
||||
${modal_filters}
|
||||
${search_divider}
|
||||
<div class="is-size-6">0 result(s)</div>
|
||||
</div>
|
||||
<div class="has-text-centered my-5 py-5">No result found!</div>
|
||||
`;
|
||||
if (!$(".search-modal-card-body").hasClass("is-justify-content-center")) {
|
||||
$(".search-modal-card-body").addClass("is-justify-content-center");
|
||||
}
|
||||
|
||||
$(".search-modal-card-body").html(`
|
||||
<div class="has-text-centered my-5 py-5">Type something to get started!</div>
|
||||
`);
|
||||
}
|
||||
}
|
||||
|
||||
//url param checking
|
||||
function checkURLForSearch() {
|
||||
const urlParams = new URLSearchParams(window.location.search);
|
||||
const searchQuery = urlParams.get("q");
|
||||
const filterParam = urlParams.get("filter");
|
||||
|
||||
// Set the selected filter if present in URL
|
||||
if (filterParam) {
|
||||
selected_filter = filterParam.toLowerCase();
|
||||
}
|
||||
|
||||
if ($(".search-modal-card-body").hasClass("is-justify-content-center")) {
|
||||
$(".search-modal-card-body").removeClass("is-justify-content-center");
|
||||
// Trigger input event if there's a search query to perform the search
|
||||
if (searchQuery) {
|
||||
$(".documenter-search-input").val(searchQuery).trigger("input");
|
||||
}
|
||||
}
|
||||
setTimeout(checkURLForSearch, 100);
|
||||
|
||||
$(".search-modal-card-body").html(search_result_container);
|
||||
} else {
|
||||
if (!$(".search-modal-card-body").hasClass("is-justify-content-center")) {
|
||||
$(".search-modal-card-body").addClass("is-justify-content-center");
|
||||
}
|
||||
/**
|
||||
* Make the modal filter html
|
||||
*
|
||||
* @returns string
|
||||
*/
|
||||
function make_modal_body_filters() {
|
||||
let str = filters
|
||||
.map((val) => {
|
||||
if (selected_filter == val.toLowerCase()) {
|
||||
return `<a href="javascript:;" class="search-filter search-filter-selected"><span>${val}</span></a>`;
|
||||
} else {
|
||||
return `<a href="javascript:;" class="search-filter"><span>${val}</span></a>`;
|
||||
}
|
||||
})
|
||||
.join("");
|
||||
|
||||
$(".search-modal-card-body").html(`
|
||||
<div class="has-text-centered my-5 py-5">Type something to get started!</div>
|
||||
`);
|
||||
return `
|
||||
<div class="is-flex gap-2 is-flex-wrap-wrap is-justify-content-flex-start is-align-items-center search-filters">
|
||||
<span class="is-size-6">Filters:</span>
|
||||
${str}
|
||||
</div>`;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Make the modal filter html
|
||||
*
|
||||
* @returns string
|
||||
*/
|
||||
function make_modal_body_filters() {
|
||||
let str = filters
|
||||
.map((val) => {
|
||||
if (selected_filter == val.toLowerCase()) {
|
||||
return `<a href="javascript:;" class="search-filter search-filter-selected"><span>${val}</span></a>`;
|
||||
} else {
|
||||
return `<a href="javascript:;" class="search-filter"><span>${val}</span></a>`;
|
||||
}
|
||||
})
|
||||
.join("");
|
||||
|
||||
return `
|
||||
<div class="is-flex gap-2 is-flex-wrap-wrap is-justify-content-flex-start is-align-items-center search-filters">
|
||||
<span class="is-size-6">Filters:</span>
|
||||
${str}
|
||||
</div>`;
|
||||
function waitUntilSearchIndexAvailable() {
|
||||
// It is possible that the documenter.js script runs before the page
|
||||
// has finished loading and documenterSearchIndex gets defined.
|
||||
// So we need to wait until the search index actually loads before setting
|
||||
// up all the search-related stuff.
|
||||
if (typeof documenterSearchIndex !== "undefined") {
|
||||
runSearchMainCode();
|
||||
} else {
|
||||
console.warn("Search Index not available, waiting");
|
||||
setTimeout(waitUntilSearchIndexAvailable, 1000);
|
||||
}
|
||||
}
|
||||
|
||||
// The actual entry point to the search code
|
||||
waitUntilSearchIndexAvailable();
|
||||
|
||||
})
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
require(['jquery'], function($) {
|
||||
@@ -812,8 +906,9 @@ $(document).ready(function () {
|
||||
<div class="field mb-0 w-100">
|
||||
<p class="control has-icons-right">
|
||||
<input class="input documenter-search-input" type="text" placeholder="Search" />
|
||||
<span class="icon is-small is-right has-text-primary-dark">
|
||||
<i class="fas fa-magnifying-glass"></i>
|
||||
<span class="icon is-small is-right has-text-primary-dark gap-2">
|
||||
<i class="fas fa-link link-icon is-clickable"></i>
|
||||
<i class="fas fa-magnifying-glass mr-4"></i>
|
||||
</span>
|
||||
</p>
|
||||
</div>
|
||||
@@ -849,9 +944,22 @@ $(document).ready(function () {
|
||||
${search_modal_footer}
|
||||
</div>
|
||||
</div>
|
||||
`
|
||||
`,
|
||||
);
|
||||
|
||||
function checkURLForSearch() {
|
||||
const urlParams = new URLSearchParams(window.location.search);
|
||||
const searchQuery = urlParams.get("q");
|
||||
|
||||
if (searchQuery) {
|
||||
//only if there is a search query, open the modal
|
||||
openModal();
|
||||
}
|
||||
}
|
||||
|
||||
//this function will be called whenever the page will load
|
||||
checkURLForSearch();
|
||||
|
||||
document.querySelector(".docs-search-query").addEventListener("click", () => {
|
||||
openModal();
|
||||
});
|
||||
@@ -876,6 +984,25 @@ $(document).ready(function () {
|
||||
return false;
|
||||
});
|
||||
|
||||
//event listener for the link icon to copy the URL
|
||||
$(document).on("click", ".link-icon", function () {
|
||||
const currentUrl = window.location.href;
|
||||
|
||||
navigator.clipboard
|
||||
.writeText(currentUrl)
|
||||
.then(() => {
|
||||
const $linkIcon = $(this);
|
||||
$linkIcon.removeClass("fa-link").addClass("fa-check");
|
||||
|
||||
setTimeout(() => {
|
||||
$linkIcon.removeClass("fa-check").addClass("fa-link");
|
||||
}, 1000);
|
||||
})
|
||||
.catch((err) => {
|
||||
console.error("Failed to copy URL: ", err);
|
||||
});
|
||||
});
|
||||
|
||||
// Functions to open and close a modal
|
||||
function openModal() {
|
||||
let searchModal = document.querySelector("#search-modal");
|
||||
@@ -890,15 +1017,17 @@ $(document).ready(function () {
|
||||
<div class="has-text-centered my-5 py-5">Type something to get started!</div>
|
||||
`;
|
||||
|
||||
$(".documenter-search-input").val("");
|
||||
$(".search-modal-card-body").html(initial_search_body);
|
||||
|
||||
document.dispatchEvent(new CustomEvent("reset-filter"));
|
||||
|
||||
searchModal.classList.remove("is-active");
|
||||
document.querySelector(".documenter-search-input").blur();
|
||||
|
||||
if (!$(".search-modal-card-body").hasClass("is-justify-content-center")) {
|
||||
$(".search-modal-card-body").addClass("is-justify-content-center");
|
||||
}
|
||||
|
||||
$(".documenter-search-input").val("");
|
||||
$(".search-modal-card-body").html(initial_search_body);
|
||||
}
|
||||
|
||||
document
|
||||
@@ -1027,7 +1156,7 @@ $(document).ready(function () {
|
||||
var option = $(
|
||||
"<option value='#' selected='selected'>" +
|
||||
DOCUMENTER_CURRENT_VERSION +
|
||||
"</option>"
|
||||
"</option>",
|
||||
);
|
||||
version_selector_select.append(option);
|
||||
}
|
||||
@@ -1044,7 +1173,7 @@ $(document).ready(function () {
|
||||
// otherwise update the old option with the URL and enable it
|
||||
if (existing_id == -1) {
|
||||
var option = $(
|
||||
"<option value='" + version_url + "'>" + each + "</option>"
|
||||
"<option value='" + version_url + "'>" + each + "</option>",
|
||||
);
|
||||
version_selector_select.append(option);
|
||||
} else {
|
||||
|
||||
Reference in New Issue
Block a user