Skip to content
Merged
Show file tree
Hide file tree
Changes from 6 commits
Commits
Show all changes
34 commits
Select commit Hold shift + click to select a range
03491d5
Update navbar design
lhsazevedo Oct 3, 2024
89c598e
Add new search modal dialog
lhsazevedo Oct 3, 2024
8650771
Add search modal e2e tests
lhsazevedo Oct 3, 2024
d0da0c8
Remove Hogan.js and typeahead.js
lhsazevedo Oct 2, 2024
831f80c
Update playwright snapshots
lhsazevedo Oct 3, 2024
b17b606
Fix e2e and visual tests
lhsazevedo Oct 4, 2024
0048ef1
Avoid page shift when opening the search modal
lhsazevedo Oct 4, 2024
b83f783
Match search label and input placeholder text
lhsazevedo Oct 4, 2024
23003ff
Increase contrast for accessibility
lhsazevedo Oct 5, 2024
cd0754b
Halve the transition duration of the search modal
lhsazevedo Oct 4, 2024
07da74b
Reduce search scrollbar width
lhsazevedo Oct 5, 2024
ec7e9b9
Darken release background to better fit the navbar
lhsazevedo Oct 5, 2024
7146752
Fallback search when Javascript is disabled
lhsazevedo Oct 6, 2024
535b25d
Remove logo alt text
lhsazevedo Oct 6, 2024
b8bb98c
Fix modal input type and aria-label
lhsazevedo Oct 6, 2024
75a3e38
Use <kbd> tag
lhsazevedo Oct 6, 2024
9fe9ed1
Use correct CSS methodology
lhsazevedo Oct 6, 2024
4c062ec
Avoid search flash on mobile
lhsazevedo Oct 6, 2024
21b220e
Fix e2e and visual tests
lhsazevedo Oct 6, 2024
afaaa2e
Progressively enhance mobile menu and search
lhsazevedo Oct 11, 2024
2f3da84
Add e2e tests for JS disabled search and menu
lhsazevedo Oct 12, 2024
ae5a14c
Invalidate old search cache format
lhsazevedo Oct 21, 2024
97a865b
Use a single kbd tag for each arrow key
lhsazevedo Oct 21, 2024
6a4dcd1
Fix leftover vars
lhsazevedo Oct 21, 2024
2d89914
Use current language in legacy global search
lhsazevedo Oct 21, 2024
e35fe6e
Add missing docblocks and improve existing ones
lhsazevedo Oct 22, 2024
1fa0853
Use language parameter from outer scope
lhsazevedo Oct 22, 2024
d2d68a0
Format search.js
lhsazevedo Oct 22, 2024
39bc218
Tone down result hover background color
lhsazevedo Oct 22, 2024
0d5a896
Update visual tests snapshots
lhsazevedo Oct 22, 2024
f97426e
Add search modal visual test
lhsazevedo Oct 23, 2024
eb7a39d
Fix visual tests snapshots
lhsazevedo Oct 23, 2024
614a1ad
Close offcanvas menu by outside click
saundefined Oct 31, 2024
d54e103
Sync class name with master
lhsazevedo Oct 31, 2024
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
48 changes: 47 additions & 1 deletion include/footer.inc
Original file line number Diff line number Diff line change
Expand Up @@ -99,7 +99,7 @@ if (!empty($_SERVER['BASE_PAGE'])
<!-- External and third party libraries. -->
<script src="https://code.jquery.com/jquery-3.6.0.min.js" integrity="sha256-/xUj+3OJU5yExlq6GSYGSHk7tPXikynS7ogEvDej/m4=" crossorigin="anonymous"></script>
<?php
$jsfiles = ["ext/hogan-3.0.2.min.js", "ext/typeahead.jquery.min.js", "ext/FuzzySearch.min.js", "ext/mousetrap.min.js", "ext/jquery.scrollTo.min.js", "search.js", "common.js"];
$jsfiles = ["ext/FuzzySearch.min.js", "ext/mousetrap.min.js", "ext/jquery.scrollTo.min.js", "search.js", "common.js"];
foreach ($jsfiles as $filename) {
$path = dirname(__DIR__) . '/js/' . $filename;
echo '<script src="/cached.php?t=' . @filemtime($path) . '&amp;f=/js/' . $filename . '"></script>' . "\n";
Expand All @@ -108,5 +108,51 @@ if (!empty($_SERVER['BASE_PAGE'])

<a id="toTop" href="javascript:;"><span id="toTopHover"></span><img width="40" height="40" alt="To Top" src="/images/[email protected]"></a>

<div id="search-modal-backdrop" class="search-modal-backdrop">
<div
role="dialog"
aria-label="Search modal"
id="search-modal"
class="search-modal"
>
<div class="search-modal-header">
<div class="search-modal-form">
<div class="search-modal-input-icon">
<!-- https://feathericons.com search -->
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><circle cx="11" cy="11" r="8"></circle><line x1="21" y1="21" x2="16.65" y2="16.65"></line></svg>
</div>
<input
type="text"
id="search-modal-input"
class="search-modal-input"
placeholder="Search PHP docs"
/>
</div>

<button aria-label="Close" class="search-modal-close-btn">
<!-- https://pictogrammers.com/library/mdi/icon/close/ -->
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24"><path d="M19,6.41L17.59,5L12,10.59L6.41,5L5,6.41L10.59,12L5,17.59L6.41,19L12,13.41L17.59,19L19,17.59L13.41,12L19,6.41Z"/></svg>
</button>
</div>
<div
role="listbox"
aria-label="Search results"
id="search-modal-results"
class="search-modal-results"
></div>
<div class="search-modal-helper-text">
<div>
<span class="search-modal-helper-key">↑ ↓</span> to navigate •
<span class="search-modal-helper-key">Enter</span> to select •
<span class="search-modal-helper-key">Esc</span> to close
</div>
<div>
Press <span class="search-modal-helper-key">Enter</span> without
selection to search using Google
</div>
</div>
</div>
</div>

</body>
</html>
87 changes: 67 additions & 20 deletions include/header.inc
Original file line number Diff line number Diff line change
Expand Up @@ -94,27 +94,74 @@ if (!isset($config["languages"])) {
</head>
<body class="<?php echo $curr; ?> <?php echo $classes; ?>">

<nav id="head-nav" class="navbar navbar-fixed-top">
<div class="navbar-inner clearfix">
<a href="/" class="brand"><img src="/images/logos/php-logo.svg" width="48" height="24" alt="php"></a>
<div id="mainmenu-toggle-overlay"></div>
<input type="checkbox" id="mainmenu-toggle">
<ul class="nav">
<li class="<?php echo $curr == "downloads" ? "active" : ""?>"><a href="/downloads">Downloads</a></li>
<li class="<?php echo $curr == "docs" ? "active" : ""?>"><a href="/docs.php">Documentation</a></li>
<li class="<?php echo $curr == "community" ? "active" : ""?>"><a href="/get-involved" >Get Involved</a></li>
<li class="<?php echo $curr == "help" ? "active" : ""?>"><a href="/support">Help</a></li>
<li class="<?php echo $curr === "php8" ? "active" : "" ?>">
<a href="/releases/8.3/index.php">
<img src="/images/php8/logo_php8_3.svg" alt="php8.3" height="22" width="60">
</a>
</li>
</ul>
<form class="navbar-search" id="topsearch" action="/search.php">
<input type="hidden" name="show" value="quickref">
<input type="search" name="pattern" class="search-query" placeholder="Search" accesskey="s">
</form>
<nav class="navbar navbar-fixed-top">
<div class="navbar-inner">
<a href="/" aria-label="PHP Home" class="brand">
<img
src="/images/logos/php-logo-white.svg"
alt="PHP Logo"
width="80"
height="40"
>
</a>

<div
id="navbar-offcanvas"
tabindex="-1"
class="navbar-offcanvas"
aria-label="Menu"
>
<button
id="navbar-menu-btn-close"
class="navbar-menu-btn navbar-menu-btn-close"
>
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24"><path d="M19,6.41L17.59,5L12,10.59L6.41,5L5,6.41L10.59,12L5,17.59L6.41,19L12,13.41L17.59,19L19,17.59L13.41,12L19,6.41Z" /></svg>
</button>
<ul class="navbar-nav">
<li class="<?= $curr == "downloads" ? "active" : ""; ?>">
<a href="/downloads">Downloads</a>
</li>
<li class="<?= $curr == "docs" ? "active" : ""; ?>">
<a href="/docs.php">Documentation</a>
</li>
<li class="<?= $curr == "community" ? "active" : ""; ?>">
<a href="/get-involved" >Get Involved</a>
</li>
<li class="<?= $curr == "help" ? "active" : ""; ?>">
<a href="/support">Help</a>
</li>
<li class="navbar-release <?= $curr === "php8" ? "active" : ""; ?>">
<a href="/releases/8.3/index.php">
<img src="/images/php8/logo_php8_3.svg" alt="php8.3">
</a>
</li>
</ul>
</div>

<div class="navbar-right">
<button class="navbar-search-btn">Search</button>

<button aria-label="Search" class="navbar-search-btn-mobile">
<!-- https://feathericons.com search -->
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><circle cx="11" cy="11" r="8"></circle><line x1="21" y1="21" x2="16.65" y2="16.65"></line></svg>
</button>
<button
id="navbar-menu-btn-open"
aria-label="Menu"
class="navbar-menu-btn navbar-menu-btn-open"
>
<!-- https://pictogrammers.com/library/mdi/icon/menu/ -->
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24"><path d="M3,6H21V8H3V6M3,11H21V13H3V11M3,16H21V18H3V16Z" /></svg>
</button>
</div>
</div>

<div
id="navbar-backdrop"
class="navbar-backdrop"
></div>
</div>

<div id="flash-message"></div>
</nav>
<?php if (!empty($config["headsup"])): ?>
Expand Down
114 changes: 86 additions & 28 deletions js/common.js
Original file line number Diff line number Diff line change
Expand Up @@ -10,10 +10,11 @@ String.prototype.toInt = function () {

var PHP_NET = {};

PHP_NET.HEADER_HEIGHT = 52;
PHP_NET.HEADER_HEIGHT = 64;

Mousetrap.bind('up up down down left right left right b a enter', function () {
$(".brand img").attr("src", "/images/php_konami.gif");
window.scrollTo(0, 0);
});
Mousetrap.bind("?", function () {
$("#trick").slideToggle();
Expand Down Expand Up @@ -100,12 +101,10 @@ Mousetrap.bind("b o r k", function () {
Mousetrap.unbind("b o r k");
});

var FIXED_HEADER_HEIGHT = 50;

function cycle(to, from) {
from.removeClass("current");
to.addClass("current");
$.scrollTo(to.offset().top - FIXED_HEADER_HEIGHT);
$.scrollTo(to.offset().top);
}

function getNextOrPreviousSibling(node, forward) {
Expand Down Expand Up @@ -253,28 +252,25 @@ function globalsearch(txt) {
cache = JSON.parse(cache);

if (cache) {
for (var type in cache.data) {
var elms = cache.data[type].elements;
for (var node in elms) {
if (elms[node].description.toLowerCase().contains(term) || elms[node].name.toLowerCase().contains(term)) {
$("#goto .results ul").append("<li><a href='/manual/en/" + elms[node].id + ".php'>" + elms[node].name + ": " + elms[node].description + "</a></li>");
if ($("#goto .results ul li") > 30) {
return;
}
for (const node of cache.data) {
if (
node.description.toLowerCase().contains(term) ||
node.name.toLowerCase().contains(term)
) {
$("#goto .results ul").append(`
<li>
<a href='/manual/en/${node.id}.php'>
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This probably should use the current language instead of directing to the English version.

Suggested change
<a href='/manual/en/${node.id}.php'>
<a href='/manual/LANG/${node.id}.php'>

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yup, it probably should. Actually, this code is part of the "global search" feature that triggers with g then a. I wasn’t aware of it until I had to adjust the code to prevent breaking due to changes in the search index structure.

Screen Shot 2024-10-21 at 20 29 51

TBH, I believe that we could just remove it and use g a as another shortcut to the new search dialog, but may be out of scope for this PR.

For now I've pushed a commit for the anchor href you pointed and the cache key a few lines before it.

${node.name}: ${node.description}
</a>
</li>`);
if ($("#goto .results ul li") > 30) {
return;
}
}
}
}
}
Mousetrap.bind("/", function (e) {
if (e.preventDefault) {
e.preventDefault();
} else {
// internet explorer
e.returnValue = false;
}
$("input[type=search]").focus();
});

var rotate = 0;
Mousetrap.bind("r o t a t e enter", function (e) {
rotate += 90;
Expand Down Expand Up @@ -462,6 +458,68 @@ $(document).ready(function () {
}
});

/*{{{ 2024 Navbar */
const offcanvasElement = document.getElementById("navbar-offcanvas");
const offcanvasSelectables =
offcanvasElement.querySelectorAll("input, button, a");
const backdropElement = document.getElementById("navbar-backdrop");

// Focus trap for offcanvas nav
const focusTrapHandler = (event) => {
if (event.key != "Tab") {
return;
}

const firstElement = offcanvasSelectables[0];
const lastElement =
offcanvasSelectables[offcanvasSelectables.length - 1];

if (event.shiftKey) {
if (document.activeElement === firstElement) {
event.preventDefault();
lastElement.focus();
}
} else if (document.activeElement === lastElement) {
event.preventDefault();
firstElement.focus();
}
};

const openOffcanvasNav = () => {
offcanvasElement.classList.add("show");
offcanvasElement.setAttribute("aria-modal", "true");
offcanvasElement.setAttribute("role", "dialog");
offcanvasElement.style.visibility = "visible";
backdropElement.classList.add("show");
offcanvasSelectables[0].focus();
document.addEventListener("keydown", focusTrapHandler);
};

const closeOffcanvasNav = () => {
offcanvasElement.classList.remove("show");
offcanvasElement.removeAttribute("aria-modal");
offcanvasElement.removeAttribute("role");
backdropElement.classList.remove("show");
document.removeEventListener("keydown", focusTrapHandler);
offcanvasElement.addEventListener(
"transitionend",
() => {
offcanvasElement.style.removeProperty("visibility");
},
{ once: true },
);
};

document
.getElementById("navbar-menu-btn-open")
.addEventListener("click", openOffcanvasNav);

document
.getElementById("navbar-menu-btn-close")
.addEventListener("click", closeOffcanvasNav);

/*}}}*/

/*{{{ Scroll to top */
(function () {
var settings = {
Expand Down Expand Up @@ -552,13 +610,13 @@ $(document).ready(function () {
});
/*}}}*/

// Search box autocomplete (for browsers that aren't IE <= 8, anyway).
if (typeof window.brokenIE === "undefined") {
jQuery("#topsearch .search-query").search({
language: getLanguage(),
limit: 30
});
}
/*{{{Search Modal*/
const language = getLanguage();
initSearchModal();
initPHPSearch(language).then((searchCallback) => {
initSearchUI({language, searchCallback, limit: 30});
});
/*}}}*/

/* {{{ Negative user notes fade-out */
var usernotes = document.getElementById('usernotes');
Expand Down
Loading