Reduce sidebar flashing on navigation

by moving some dynamic HTML generation to templates.
Also fixes no-js CSS a bit by hiding useless elements.
This commit is contained in:
Franciszek Stachura 2024-08-20 14:28:16 +02:00
parent 7d629429bf
commit e8da1bf578
5 changed files with 47 additions and 61 deletions

View file

@ -2,39 +2,10 @@
var versions = document.querySelector('.versions')
var dropdown = document.querySelector('.select-projects')
var div = document.createElement('div')
var button = document.createElement('button')
var a = document.createElement('a')
var span = document.createElement('span')
var input = document.createElement('input')
a.title = 'Close Menu'
a.className = 'close-menu icon-cross'
// a.innerText = 'Close Menu'
div.className = 'filter'
span.className = 'screenreader'
button.className = 'icon-filter'
input.placeholder = 'Filter tags'
span.innerText = 'Filter tags'
// As filtering happen on typing
// the filter button is just for decoration
button.tabIndex = -1
button.appendChild(span)
div.appendChild(input)
div.appendChild(button)
div.appendChild(a)
var input = document.querySelector('.filter-input')
var sidebar = document.querySelector('.sidebar')
var detachDropdown = dropdown.parentElement.removeChild(dropdown)
div.insertBefore(detachDropdown, div.firstChild)
sidebar.insertBefore(div, sidebar.firstChild)
var nav = document.querySelector('.sidebar nav')
var results = document.createElement('div')
results.className = 'filter-results'
nav.appendChild(results)
var results = document.querySelector('.filter-results')
var tags = {}
function getTags () {
@ -101,21 +72,6 @@ versions.onclick = function (e) {
}
}
function expandVersion (version) {
var version = document.querySelector('.versions .active')
if (version && version.parentNode) {
var targ = version.parentNode.previousElementSibling
while (targ && targ.tagName === 'SPAN') {
targ.classList.add('active')
targ = targ.parentNode.parentNode
targ = targ.previousElementSibling
}
}
}
// Auto expand menu to display current version
window.setTimeout(expandVersion, 1)
var tag = document.querySelector('.version em')
var openMenu = document.querySelector('.open-menu')
var wrapper = document.querySelector('.wrapper')

View file

@ -613,6 +613,19 @@ h2 {
display: none;
}
.no-js .select-projects {
display: none;
}
.no-js .filter-input {
display: none;
}
.no-js .icon-filter {
display: none;
}
/* filter results */

View file

@ -71,6 +71,7 @@ def get_error_page(basedir, title, details=None):
template_ctx = {
'projects': get_projects(basedir),
'topbar_families': TOPBAR_FAMILIES,
'current_version_path': (None, None, None),
'error_title': title,
}
@ -256,13 +257,18 @@ def get_projects(basedir):
# Used to render version list in the sidebar
VersionEntry = namedtuple('VersionEntry', 'version, url')
# Takes result of Query.query('version') and prepares it for the sidebar template
# Takes result of Query.query('version') and prepares it for the sidebar template.
# Returns an OrderedDict with version information and optionally a triple with
# (major, minor, version) of current_version. The triple is useful, because sometimes
# the major or minor of a version (in this context) is a custom string (ex. FIXME).
# versions: OrderedDict with major parts of versions as keys, values are OrderedDicts
# with minor version parts as keys and complete version strings as values
# get_url: function that takes a version string and returns the URL
# for that version. Meaning of the URL can depend on the context
def get_versions(versions, get_url):
# current_version: string with currently browsed version
def get_versions(versions, get_url, current_version):
result = OrderedDict()
current_version_path = (None, None, None)
for major, minor_verions in versions.items():
for minor, patch_versions in minor_verions.items():
for v in patch_versions:
@ -271,19 +277,23 @@ def get_versions(versions, get_url):
if minor not in result[major]:
result[major][minor] = []
result[major][minor].append(VersionEntry(v, get_url(v)))
if v == current_version:
current_version_path = (major, minor, v)
return result
return result, current_version_path
# Retruns template context used by the layout template
# q: Query object
# base: directory with project
# basedir: directory with projects
# get_url_with_new_version: see get_url parameter of get_versions
# project: name of the project
# version: version of the project
def get_layout_template_context(q, basedir, get_url_with_new_version, project, version):
versions, current_version_path = get_versions(q.query('versions'), get_url_with_new_version, version)
return {
'projects': get_projects(basedir),
'versions': get_versions(q.query('versions'), get_url_with_new_version),
'versions': versions,
'current_version_path': current_version_path,
'topbar_families': TOPBAR_FAMILIES,
'source_base_url': f'/{ project }/{ version }/source',

View file

@ -14,7 +14,7 @@
Elixir Cross Referencer - Explore source code in your browser - Particularly useful for the Linux kernel and other low-level projects in C/C++ (bootloaders, C libraries...)
{%- endblock %}">
<meta name="viewport" content="user-scalable=no, initial-scale=1, maximum-scale=1, minimum-scale=1" />
<link rel="stylesheet" href="/style.css?v=6">
<link rel="stylesheet" href="/style.css?v=7">
<link rel="stylesheet" href="/banner.css">
<link rel="stylesheet" href="/autocomplete.css">
<script>document.documentElement.className = 'js'</script>
@ -48,7 +48,7 @@
<span class="poweredby">powered by <a target="_blank" href="https://github.com/bootlin/elixir">Elixir 2.2</a></span>
</footer>
</div>
<script src="/script.js?v=4"></script>
<script src="/script.js?v=5"></script>
<script src="/dynamic-references.js?v=4"></script>
<script src="/autocomplete.js" project="{{ current_project }}"></script>
</body>

View file

@ -1,9 +1,14 @@
<aside class="sidebar" id="menu">
<select class="select-projects" onchange="window.location.href=this.value">
{%- for p in projects %}
<option {% if p.name == current_project -%} selected {%- endif %} value="{{ p.url }}">{{ p.name }}</option>
{%- endfor %}
</select>
<div class="filter">
<select class="select-projects" onchange="window.location.href=this.value">
{%- for p in projects %}
<option {% if p.name == current_project -%} selected {%- endif %} value="{{ p.url }}">{{ p.name }}</option>
{%- endfor %}
</select>
<input class="filter-input" placeholder="Filter tags">
<button class="icon-filter" tabindex="-1"><span class="screenreader">Filter tags</span></button>
<a title="Close Menu" class="close-menu icon-cross"></a>
</div>
<nav>
<h3 class="screenreader">Projects</h3>
<ul class="projects">
@ -14,18 +19,19 @@
<h3 class="screenreader">Versions</h3>
<ul class="versions">
{% set current_major, current_minor, current_version = current_version_path %}
{% for major, major_versions in (versions|default({})).items() %}
<li>
<span>{{ major }}</span>
<span class="{{ 'active' if current_major == major else '' }}">{{ major }}</span>
<ul>
{% for minor, minor_versions in major_versions.items() %}
{% if minor == minor_versions[0] and minor_versions|length == 1 %}
<li class="li-link {{ 'active' if minor == current_tag else '' }}">
<li class="li-link">
<a href="{{ minor_versions[0].url }}">{{ minor_versions[0].version }}</a>
</li>
{% else %}
<li>
<span>{{ minor }}</span>
<span class="{{ 'active' if minor == current_minor else '' }}">{{ minor }}</span>
<ul>
{% for v in minor_versions %}
<li class="li-link {{ 'active' if v.version == current_tag else '' }}">
@ -43,5 +49,6 @@
{% endfor %}
</ul>
<div class="filter-results"></div>
</nav>
</aside>