Skip to content
1 change: 0 additions & 1 deletion _includes/head.html
Original file line number Diff line number Diff line change
Expand Up @@ -65,7 +65,6 @@
{% else %}
<meta property="twitter:image" content="https://expressjs.com/images/og.png">
{% endif %}
<script data-cfasync="false" src="//ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<script data-cfasync="false" src="/js/app.js"></script>
Comment thread
ShubhamOulkar marked this conversation as resolved.
Outdated
<script data-cfasync="false" defer src="/js/menu.js"></script>
<script data-cfasync="false" defer src="/js/copycode.js"></script>
Expand Down
2 changes: 1 addition & 1 deletion _includes/i18n-notice.html
Original file line number Diff line number Diff line change
Expand Up @@ -7,4 +7,4 @@
{% assign notice_link_text = site.data.en.general.i18n_notice_link_text %}
{% endif %}
<p>{{ notice }} <a href="{{ page.url | replace: lang_path, '/en/' }}">{{ notice_link_text}}</a>.</p>
<div id="close-i18n-notice-box" title="Close">✖</div>
<div id="close-i18n-notice-box" title="Close" role="button" aria-label="Close notice" tabindex="0">✖</div>
4 changes: 2 additions & 2 deletions _layouts/home.html
Original file line number Diff line number Diff line change
Expand Up @@ -14,8 +14,8 @@
<div id="overlay"></div>

{% if page.lang != 'en' %}
<div id="i18n-notice-box" class="doc-notice">
{% include i18n-notice.html %}
<div id="i18n-notice-box" class="doc-notice" hidden>
{% include i18n-notice.html %}
</div>
{% endif %}

Expand Down
2 changes: 1 addition & 1 deletion _layouts/page.html
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,7 @@
<div id="overlay"></div>

{% if page.lang != 'en' %}
<div id="i18n-notice-box" class="doc-notice">
<div id="i18n-notice-box" class="doc-notice" hidden>
{% include i18n-notice.html %}
</div>
{% endif %}
Expand Down
19 changes: 11 additions & 8 deletions css/style.css
Original file line number Diff line number Diff line change
Expand Up @@ -475,7 +475,7 @@ pre:has(code) button.failed {
}
}

/* top button */
/* scroll to top button */

.scroll #top {
opacity: .5;
Expand Down Expand Up @@ -612,20 +612,30 @@ table ul {
font-weight: 600;
}

/* i18n box */
.doc-notice {
padding-block: 1rem;
padding-inline: 2.5rem;
color: var(--box-fg);
border-radius: 0 6px 6px 0;
background: var(--notice-bg);
border-left: 3px solid var(--notice-accent);
margin-inline: auto;
margin-block-start: 2rem;
position: relative;
grid-area: i18n;
display: block;
}

.doc-notice a{
color: var(--notice-accent);
text-decoration: underline;
}

.doc-notice[hidden] {
display: none;
}

.doc-info {
background: var(--info-bg);
border-left: 3px solid var(--info-accent);
Expand All @@ -646,13 +656,6 @@ table ul {
text-decoration: underline;
}

#i18n-notice-box {
margin-inline: auto;
margin-block-start: 2rem;
position: relative;
grid-area: i18n;
}

#close-i18n-notice-box {
position: absolute;
top: 3px;
Expand Down
231 changes: 118 additions & 113 deletions js/app.js
Original file line number Diff line number Diff line change
@@ -1,122 +1,127 @@
$(function(){
var doc = $(document);

// top link
$('#top').click(function(e){
$('html, body').animate({scrollTop : 0}, 500);
return false;
});

// scrolling links
var added;
doc.scroll(function(e){
if (doc.scrollTop() > 5) {
if (added) return;
added = true;
$('body').addClass('scroll');
} else {
$('body').removeClass('scroll');
added = false;
}
})

// menu bar

var headings = $('h2, h3').map(function(i, el){
return {
top: $(el).offset().top - 200,
id: el.id
}
});

function closest() {
var h;
var top = $(window).scrollTop();
var i = headings.length;
while (i--) {
h = headings[i];
if (top >= h.top) return h;
}
document.addEventListener("DOMContentLoaded", function () {
const languageElement = document.getElementById('languageData');
const languagesData = languageElement ? JSON.parse(languageElement.dataset.languages) : [];
const langDisplay = document.getElementById('current-lang');
const i18nMsgBox = document.getElementById("i18n-notice-box");
const scrollToTopBtn = document.getElementById("top");

// display current language in language picker component
if (langDisplay) {
const currentLanguage = window.location.pathname.split('/')[1];
const matchedLang = languagesData.find(lang => lang.code === currentLanguage);
langDisplay.textContent = matchedLang ? matchedLang.name : 'English';
}

var currentApiPrefix;
var parentMenuSelector;
var lastApiPrefix;

if (document.readyState !== 'loading') {
const languageElement = document.getElementById('languageData');
const languagesData = languageElement ? JSON.parse(languageElement.dataset.languages) : [];

const langDisplay = document.getElementById('current-lang');

if (langDisplay) {
const currentLanguage = window.location.pathname.split('/')[1];
const matchedLang = languagesData.find(lang => lang.code === currentLanguage);
langDisplay.textContent = matchedLang ? matchedLang.name : 'English';
}
// scroll to top of the page
if (scrollToTopBtn) {
scrollToTopBtn.addEventListener("click", function (e) {
e.preventDefault();
window.scrollTo({
top: 0,
behavior: "smooth"
})
});
Comment thread
ShubhamOulkar marked this conversation as resolved.
Outdated
}

$(document).scroll(function() {
var h = closest();
if (!h) return;

currentApiPrefix = h.id.split('.')[0];
parentMenuSelector = '#'+ currentApiPrefix + '-menu';

$(parentMenuSelector).addClass('active');

if (lastApiPrefix && (lastApiPrefix != currentApiPrefix)) {
$('#'+ lastApiPrefix + '-menu').removeClass('active');
// add/remove class 'scroll' on scroll by 5px
const scrollTarget = document.querySelector('.logo-container');
const scrollObserver = new IntersectionObserver(
([entry]) => {
if (!entry.isIntersecting) {
document.body.classList.add('scroll');
} else {
document.body.classList.remove('scroll');
}
},
{
root: null,
threshold: 0,
rootMargin: '0px 0px 0px 0px'
}

$('#menu li a').removeClass('active');

var a = $('a[href="#' + h.id + '"]');
a.addClass('active');

lastApiPrefix = currentApiPrefix.split('.')[0];
})

// i18n notice
if (readCookie('i18nClose')) {
$('#i18n-notice-box').hide();
$("#i18n-notice-box").addClass("hidden");
}
else {
$('#close-i18n-notice-box').on('click', function () {
$('#i18n-notice-box').hide();
$("#i18n-notice-box").addClass("hidden");
createCookie('i18nClose', 1);
})
);

if (scrollTarget) scrollObserver.observe(scrollTarget);

// heighlight current Menu on scroll
const headings = Array.from(document.querySelectorAll("h2, h3"));
const menuLinks = document.querySelectorAll("#menu li a");

const observerOptions = {
root: null,
rootMargin: "-25% 0px -50px 0px",
threshold: 1,
};

const menuObserver = new IntersectionObserver((entries) => {
entries.forEach((entry) => {
if (entry.isIntersecting) {
const currentApiPrefix = entry.target.id.split(".")[0];
const parentMenuSelector = `#${currentApiPrefix}-menu`;
const parentMenuEl = document.querySelector(parentMenuSelector);

// open submenu on scroll
if (parentMenuEl) parentMenuEl.classList.add("active");

// Remove active class from last menu item
const lastActiveMenu = document.querySelector(".active[id$='-menu']");
if (lastActiveMenu && lastActiveMenu.id !== parentMenuEl.id) {
lastActiveMenu.classList.remove("active");
}

// Update active link
menuLinks.forEach((link) => link.classList.remove("active"));
const activeLink = document.querySelector(`a[href="#${entry.target.id}"]`);
if (activeLink) activeLink.classList.add("active");
}
});
}, observerOptions);

headings.forEach((heading) => menuObserver.observe(heading));

// i18n message box : this box appears hidden for all page.lang != 'en'
const isI18nCookie = readCookie('i18nClose');
if (i18nMsgBox && !isI18nCookie) {
const closeI18nBtn = document.getElementById("close-i18n-notice-box");
// show notice box
i18nMsgBox.hidden = false;
// close notice box
if (closeI18nBtn) {
closeI18nBtn.addEventListener("click", () => {
// hide notice
i18nMsgBox.hidden = true;
// set session cookie
createCookie('i18nClose', 1);
});

// keyboard a11y
closeI18nBtn.addEventListener("keydown", (e) => {
if (e.key === "Enter" || e.key === " ") {
e.preventDefault();
closeI18nBtn.click();
}
});
}
};

function createCookie(name, value, days) {
let expires = "";
if (days) {
const date = new Date();
date.setTime(date.getTime() + (days * 864e5));
expires = "; expires=" + date.toUTCString();
}
document.cookie = `${encodeURIComponent(name)}=${encodeURIComponent(value)}${expires}; path=/; SameSite=Lax; Secure`;
}
})



function createCookie(name, value, days) {
var expires;

if (days) {
var date = new Date();
date.setTime(date.getTime() + (days * 24 * 60 * 60 * 1000));
expires = "; expires=" + date.toGMTString();
} else {
expires = "";
}
document.cookie = encodeURIComponent(name) + "=" + encodeURIComponent(value) + expires + "; path=/";
}

function readCookie(name) {
var nameEQ = encodeURIComponent(name) + "=";
var ca = document.cookie.split(';');
for (var i = 0; i < ca.length; i++) {
var c = ca[i];
while (c.charAt(0) === ' ') c = c.substring(1, c.length);
if (c.indexOf(nameEQ) === 0) return decodeURIComponent(c.substring(nameEQ.length, c.length));
function readCookie(name) {
const nameEQ = encodeURIComponent(name) + "=";
const ca = document.cookie.split(';');
for (var i = 0; i < ca.length; i++) {
var c = ca[i];
while (c.charAt(0) === ' ') c = c.substring(1, c.length);
if (c.indexOf(nameEQ) === 0) return decodeURIComponent(c.substring(nameEQ.length, c.length));
}
Comment thread
ShubhamOulkar marked this conversation as resolved.
Outdated
return null;
}
return null;
}

function eraseCookie(name) {
createCookie(name, "", -1);
}
});