Skip to content

Commit 3db2fa1

Browse files
authored
Add site config option to select the location of the search input field #40 (#45)
Resolves: #40 Signed-off-by: Hofi <[email protected]>
2 parents 9b8fde2 + 22a5c16 commit 3db2fa1

File tree

12 files changed

+378
-172
lines changed

12 files changed

+378
-172
lines changed

_config.yml

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -168,6 +168,7 @@ defaults:
168168
search: true
169169
# Setting search_full_content to true could impact page load performance!
170170
search_full_content: true
171+
search_from_masthead: true
171172

172173
search_provider: lunr
173174
lunr:

_includes/masthead.html

Lines changed: 31 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -13,32 +13,51 @@
1313
{% if site.subtitle %}<span class="site-subtitle">{{ site.subtitle }}</span>{% endif %}
1414
</a>
1515

16-
<ul class="visible-links">
16+
<div class="masthead__menu-center-container">
17+
1718
{% if site.masthead.hide_navigator == false %}
19+
<ul class="visible-links">
1820
{%- for link in site.data.navigation.main -%}
1921
<li class="masthead__menu-item">
2022
<a href="{{ link.url | relative_url }}"{% if link.description %} title="{{ link.description }}"{% endif %}>{{ link.title }}</a>
2123
</li>
2224
{%- endfor -%}
25+
</ul>
26+
{% endif %}
27+
28+
{% if site.search == true %}
29+
{% if site.search_from_masthead %}
30+
{% include /search/search_input.html %}
31+
{% endif %}
2332
{% endif %}
24-
</ul>
33+
34+
</div>
2535

2636
{% if site.search == true %}
27-
{% comment %}<!-- search__toggle is kept fir bacjward compatibility -->{% endcomment %}
28-
<button id="search-button" class="masthead_button search__toggle" type="button">
29-
<span id="search_hint" class="">{{ site.data.ui-text[site.locale].search_label | default: "Toggle search (Shift + Ctrl + F or ESC to close)" }}</span>
30-
<i class="masthead_button_icon fas fa-search" style="font-size: 120%;"></i>
31-
</button>
37+
{% comment %}<!-- search__toggle is kept for backward compatibility -->{% endcomment %}
38+
<label class="sr-only" for="search-button">
39+
{{ site.data.ui-text[site.locale].search_label_text | default: 'Toggle search (Shift + Ctrl + F or ESC to close)' }}
40+
</label>
41+
<button id="search-button" class="masthead_button search__toggle" type="button">
42+
<span id="search_hint" class="">{{ site.data.ui-text[site.locale].search_label | default: "Toggle search (Shift + Ctrl + F or ESC to close)" }}</span>
43+
<i class="masthead_button_icon fas fa-search" style="font-size: 120%;"></i>
44+
</button>
3245
{% endif %}
3346

3447
{% if site.skin_switchable == true %}
35-
<i class="masthead_button_small_img fa fa-sun"></i>
36-
<button id="skin-button" class="masthead_button_with_side_image" type="button">
37-
<i class="masthead_button_icon fa fa-toggle-off" style="font-size: 150%;"></i>
38-
</button>
39-
<i class="masthead_button_small_img fa fa-moon"></i>
48+
<i class="masthead_button_small_img fa fa-sun"></i>
49+
<label class="sr-only" for="skin-button">
50+
{{ site.data.ui-text[site.locale].search_label_text | default: 'Toggle dark mode' }}
51+
</label>
52+
<button id="skin-button" class="masthead_button_with_side_image" type="button">
53+
<i class="masthead_button_icon fa fa-toggle-off" style="font-size: 150%;"></i>
54+
</button>
55+
<i class="masthead_button_small_img fa fa-moon"></i>
4056
{% endif %}
4157

58+
<label class="sr-only" for="settings-button">
59+
{{ site.data.ui-text[site.locale].search_label_text | default: 'Settings' }}
60+
</label>
4261
<button id="settings-button" class="masthead_button_last" type="button">
4362
<i class="masthead_button_icon fas fa-user-cog" style="font-size: 110%;"></i>
4463
</button>

_includes/search/search_form.html

Lines changed: 13 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -1,27 +1,21 @@
11
<div class="search-content__inner-wrap">
22
{%- assign search_provider = site.search_provider | default: "lunr" -%}
33
{%- case search_provider -%}
4+
45
{%- when "lunr" -%}
5-
<form class="search-content__form" onkeydown="return event.key != 'Enter';" role="search">
6-
<label class="sr-only" for="search">
7-
{{ site.data.ui-text[site.locale].search_label_text | default: 'Enter your search term...' }}
8-
</label>
9-
<input type="search" id="search" class="search-input" placeholder="{{ site.data.ui-text[site.locale].search_placeholder_text | default: 'Enter your search term...' }}" />
10-
<a class="search-help content-tooltip full-content-tooltip nav-link" href="/lunr_search_help.html">[ Hover or click for search help ]</a>
11-
</form>
12-
<div id="results" class="results"></div>
6+
{% if site.search_from_masthead == false %}
7+
{% include /search/search_input.html %}
8+
{% endif %}
9+
<div id="results" class="results {% if site.search_from_masthead %}from-masthead{% else %}from-search-content{% endif %}"></div>
10+
1311
{%- when "google" -%}
14-
<form onsubmit="return googleCustomSearchExecute();" id="cse-search-box-form-id" role="search">
15-
<label class="sr-only" for="cse-search-input-box-id">
16-
{{ site.data.ui-text[site.locale].search_label_text | default: 'Enter your search term...' }}
17-
</label>
18-
<input type="search" id="cse-search-input-box-id" class="search-input" placeholder="{{ site.data.ui-text[site.locale].search_placeholder_text | default: 'Enter your search term...' }}" />
19-
</form>
20-
<div id="results" class="results">
21-
<gcse:searchresults-only></gcse:searchresults-only>
22-
</div>
12+
{% include /search/search_input.html %}
13+
<div id="results" class="results">
14+
<gcse:searchresults-only></gcse:searchresults-only>
15+
</div>
16+
2317
{%- when "algolia" -%}
24-
<div class="search-searchbar"></div>
25-
<div class="search-hits"></div>
18+
{% include /search/search_input.html %}
19+
<div class="search-hits"></div>
2620
{%- endcase -%}
2721
</div>

_includes/search/search_input.html

Lines changed: 26 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,26 @@
1+
{%- assign search_provider = site.search_provider | default: "lunr" -%}
2+
{%- case search_provider -%}
3+
4+
{%- when "lunr" -%}
5+
<form class="search-content__form {% if site.search_from_masthead %}from-masthead{% else %}from-search-content{% endif %}"
6+
onkeydown="return event.key != 'Enter';" role="search">
7+
<label class="sr-only" for="search">
8+
{{ site.data.ui-text[site.locale].search_label_text | default: 'Enter your search term...' }}
9+
</label>
10+
<input type="search" id="search" class="search-input {% if site.search_from_masthead %}from-masthead{% else %}from-search-content{% endif %}"
11+
placeholder="{{ site.data.ui-text[site.locale].search_placeholder_text | default: 'Enter your search term...' }}" />
12+
<a class="search-help content-tooltip tooltip-align-center full-content-tooltip nav-link fas fa-info-circle" href="{{ '/lunr_search_help.html' | relative_url }}"></a>
13+
</form>
14+
15+
{%- when "google" -%}
16+
<form onsubmit="return googleCustomSearchExecute();" id="cse-search-box-form-id" role="search">
17+
<label class="sr-only" for="cse-search-input-box-id">
18+
{{ site.data.ui-text[site.locale].search_label_text | default: 'Enter your search term...' }}
19+
</label>
20+
<input type="search" id="cse-search-input-box-id" class="search-input"
21+
placeholder="{{ site.data.ui-text[site.locale].search_placeholder_text | default: 'Enter your search term...' }}" />
22+
</form>
23+
24+
{%- when "algolia" -%}
25+
<div class="search-searchbar"></div>
26+
{%- endcase -%}

_includes/skins.html

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -26,6 +26,8 @@
2626
const docRoot = '{{ site.baseurl }}';
2727
const darkSkin = 'midnight';
2828
const lightSkin = 'default';
29+
const searchEnabled = {% if site.search == true %} true {% else %} false {% endif %};
30+
const searchFromMastHead = {% if site.search_from_masthead == true %} true {% else %} false {% endif %};
2931

3032
function docPrefix() {
3133
return (docRoot != '' ? docRoot + '/' : '');

_js/custom/navigation.js

Lines changed: 82 additions & 64 deletions
Original file line numberDiff line numberDiff line change
@@ -402,63 +402,77 @@ $(function () {
402402
// -------------
403403
// Tooltip generation and handling
404404
// -------------
405-
const toolTipArrowSize = 10;
405+
/* _variables.scss & _navigation.scss - .tooltip:before */
406+
const toolTipArrowHalfSize = 10; /* $tooltip-arrow-half-size */
406407
var tooltip = null;
408+
var tooltipRenderer = null;
407409
var tooltipTarget = null;
408410
var elementUnderCursor = null;
409411
var shouldShowTooltip = false;
410412
var showTimeoutFuncID;
411413
var hideTimeoutFuncID;
412414

413-
function getTooltipPos(event, tooltipTarget) {
414-
const mouseX = event.clientX;
415+
function setTooltipPos(event, tooltipTarget, alignment) {
415416
const rect = tooltipTarget.getBoundingClientRect();
416-
var computedStyle = window.getComputedStyle(tooltipTarget);
417-
var lineHeight = parseFloat(computedStyle.getPropertyValue('line-height'));
418-
417+
var computedTargetStyle = window.getComputedStyle(tooltipTarget);
418+
var lineHeight = parseFloat(computedTargetStyle.getPropertyValue('line-height'));
419+
// NOTE: The content of the targeted tooltip is still not yet calculated correctly here, as it is invisible, and getting visible is animated multiple ways
420+
// use, the always visible, not animated at all, but offscreen pair of it (tooltipRenderer) for rendered size calculations.
421+
// To get this work all the animation styles must be removed in the css (_navigations.scss) for #tooltipRenderer
422+
// TODO: Now we have the correct tooltip content via teh tooltipRenderer trick.
423+
// Prevent tooltip overflow on window edges in all directions.
424+
var tooltipRect = tooltipRenderer.getBoundingClientRect();
425+
var tooltipWidth = tooltipRect.width;
419426
var pos = new DOMPoint();
427+
428+
const mouseX = event.clientX;
429+
var xShift = (alignment == 'tooltip-align-left' ? tooltipWidth : (alignment == 'tooltip-align-center' ? tooltipWidth / 2 : 0));
420430
pos.x = mouseX; // Use now mouse X instead - Math.max(0, pos.x + document.documentElement.scrollLeft + rect.left);
431+
pos.x -= xShift;
432+
421433
// If the occupied space of the tooltip target is bigger than its line height, it means it spanws to multiple lines
422434
// align to the upper line part in that case if the mouse is on the right side of the middle of its rect, otherwise align to the bottom row part
423435
var multilineUpperPart = (rect.height > lineHeight && mouseX > rect.x + rect.width / 2);
424436
pos.y = pos.y + document.documentElement.scrollTop + rect.top + rect.height / (multilineUpperPart ? 2 : 1);
425437

426-
return pos;
438+
var tooltipArrowHorizontalPadding = (4 * toolTipArrowHalfSize) * (alignment == 'tooltip-align-left' ? 1 : (alignment == 'tooltip-align-right' ? -1 : 0));
439+
setArrowPosition('--tooltip-arrow-left', xShift - tooltipArrowHorizontalPadding - toolTipArrowHalfSize);
440+
setArrowPosition('--tooltip-arrow-top', -1 * toolTipArrowHalfSize);
441+
442+
tooltip.style.left = pos.x + tooltipArrowHorizontalPadding + 'px';
443+
tooltip.style.top = pos.y + toolTipArrowHalfSize + 'px';
427444
}
428445

429446
function setArrowPosition(posName, position) {
430447
var newPosition = position + 'px';
431448
tooltip.style.setProperty(posName, newPosition);
432449
}
433450

434-
function showTooltip(event, tooltipText, isFullPageContent) {
451+
function showTooltip(event, tooltipText, alignment, isFullPageContent) {
452+
435453
tooltip.innerHTML = tooltipText.innerHTML;
454+
tooltipRenderer.innerHTML = tooltipText.innerHTML;
436455

437-
if (isFullPageContent)
456+
if (isFullPageContent) {
438457
tooltip.classList.add("full-content-tooltip");
439-
else
458+
tooltipRenderer.classList.add("full-content-tooltip");
459+
}
460+
else {
440461
tooltip.classList.remove("full-content-tooltip");
441-
442-
var tooltipPos = getTooltipPos(event, tooltipTarget)
443-
var tooltipArrowLeftShift = 2 * toolTipArrowSize;
444-
445-
setArrowPosition('--tooltip-arrow-top', -1 * toolTipArrowSize);
446-
setArrowPosition('--tooltip-arrow-left', tooltipArrowLeftShift + toolTipArrowSize / 2);
447-
448-
tooltip.style.left = tooltipPos.x - 2 * tooltipArrowLeftShift + 'px';
449-
tooltip.style.top = tooltipPos.y + toolTipArrowSize + 'px';
450-
462+
tooltipRenderer.classList.remove("full-content-tooltip");
463+
}
464+
tooltip.classList.remove('tooltip-align-left', 'tooltip-align-center', 'tooltip-align-right');
465+
tooltipRenderer.classList.remove('tooltip-align-left', 'tooltip-align-center', 'tooltip-align-right');
466+
tooltip.classList.add(alignment);
467+
tooltipRenderer.classList.add(alignment);
468+
451469
shouldShowTooltip = true;
452470

453471
clearTimeout(hideTimeoutFuncID);
454472
clearTimeout(showTimeoutFuncID);
455473
showTimeoutFuncID = setTimeout(function () {
456474
if (shouldShowTooltip) {
457-
// Size is still not yet calculated correctly here
458-
// var rect = tooltip.getBoundingClientRect();
459-
// tooltip.style.top = (tooltipPos.y + rect.height) + 'px';
460-
// tooltip.style.left = (tooltipPos.x + rect.width / 2) + 'px';
461-
475+
setTooltipPos(event, tooltipTarget, alignment);
462476
tooltip.classList.add('visible');
463477
}
464478
}, 100);
@@ -490,6 +504,7 @@ $(function () {
490504
function addContentTooltips() {
491505
var tooltipElements = document.querySelectorAll('.content-tooltip');
492506
tooltip = document.getElementById('tooltip');
507+
tooltipRenderer = document.getElementById('tooltipRenderer');
493508
hideTooltip();
494509

495510
tooltipElements.forEach(function (element) {
@@ -500,6 +515,7 @@ $(function () {
500515

501516
element.addEventListener('mouseover', function (event) {
502517
var isFullPageContent = element.classList.contains('full-content-tooltip');
518+
var alignment = (element.classList.contains('tooltip-align-left') ? 'tooltip-align-left' : (element.classList.contains('tooltip-align-center') ? 'tooltip-align-center' : 'tooltip-align-right'));
503519

504520
tooltipTarget = element;
505521

@@ -512,10 +528,9 @@ $(function () {
512528
newContent = newContent.innerHTML;
513529
newContent = alterContentForTooltip(newContent, url. isFullPageContent);
514530

515-
if (newContent.length > 0) {
516-
// cache for reuse
517-
tooltipText.innerHTML = newContent;
518-
showTooltip(event, tooltipText, isFullPageContent);
531+
if (newContent.length > 0) {
532+
tooltipText.innerHTML = newContent; // cache for reuse
533+
showTooltip(event, tooltipText, alignment, isFullPageContent);
519534
}
520535
else {
521536
// Quick navigation from another link with tooltip to this link would keep alive the previous tooltip
@@ -539,7 +554,7 @@ $(function () {
539554
}
540555
}
541556
else
542-
showTooltip(event, tooltipText, isFullPageContent);
557+
showTooltip(event, tooltipText, alignment, isFullPageContent);
543558
});
544559
});
545560

@@ -598,47 +613,50 @@ $(function () {
598613
// Search
599614
// -------------
600615

601-
// Close search screen with Esc key or toggle with predefined hotKey
602-
$(document).on('keyup', function (event) {
603-
// Define the desired hotkey (in this case, Ctrl + Shift + F)
604-
var searchHotkey = { ctrlKey: true, shiftKey: true, key: 'F' };
616+
if (searchEnabled) {
617+
// Close search screen with Esc key or toggle with predefined hotKey
618+
$(document).on('keyup', function (event) {
619+
// Define the desired hotkey (in this case, Ctrl + Shift + F)
620+
var searchHotkey = { ctrlKey: true, shiftKey: true, key: 'F' };
605621

606-
if (event.keyCode === 27) {
607-
if ($(".initial-content").hasClass("is--hidden"))
622+
if (event.keyCode === 27) {
623+
if ($(".initial-content").hasClass("is--hidden"))
624+
toggleSearch(event);
625+
}
626+
else if (event.ctrlKey === searchHotkey.ctrlKey &&
627+
event.shiftKey === searchHotkey.shiftKey &&
628+
event.key === searchHotkey.key) {
608629
toggleSearch(event);
609-
}
610-
else if (event.ctrlKey === searchHotkey.ctrlKey &&
611-
event.shiftKey === searchHotkey.shiftKey &&
612-
event.key === searchHotkey.key) {
613-
toggleSearch(event);
614-
}
615-
});
630+
}
631+
});
616632

617-
function toggleSearch(event) {
618-
$(".search-content").toggleClass("is--visible");
619-
$(".initial-content").toggleClass("is--hidden");
620-
621-
if ($(".initial-content").hasClass("is--hidden")) {
622-
// set focus on input
623-
setTimeout(function () {
624-
var input = $(".search-content").find("input");
625-
input.trigger("focus");
626-
input.trigger("select");
627-
}, 250);
628-
}
629-
else {
630-
// set focus back to the initial content otherwise the focus will not get back to the search input once again
631-
$(".initial-content").find("input").focus();
633+
function toggleSearch(event) {
634+
$(".search-content").toggleClass("is--visible");
635+
$(".search-content__form").toggleClass("is--visible");
636+
$(".initial-content").toggleClass("is--hidden");
637+
638+
if ($(".initial-content").hasClass("is--hidden")) {
639+
// set focus on input
640+
setTimeout(function () {
641+
var input = $(".search-content__form").find("input");
642+
input.trigger("focus");
643+
input.trigger("select");
644+
}, 100);
645+
}
646+
else {
647+
// set focus back via the initial content otherwise the focus will not get back to the search input once again
648+
$(".initial-content").find("input").focus();
649+
}
650+
651+
if (tooltipTarget)
652+
hideTooltip(true);
653+
// NOTE: event.target is not always the toggle here, use it directly instead of the event
654+
$("#search-button").trigger('blur');
632655
}
633656

634-
if (tooltipTarget)
635-
hideTooltip(true);
636-
// NOTE: event.target is not always the toggle here, use it directly instead of the event
637-
$("#search-button").trigger('blur');
657+
$("#search-button").on('click', toggleSearch);
638658
}
639659

640-
$("#search-button").on('click', toggleSearch);
641-
642660
// -------------
643661
// Startup
644662
// -------------

0 commit comments

Comments
 (0)