Added keyboard events to search modal

This commit is contained in:
squidfunk 2017-03-23 22:41:08 +01:00 committed by Martin Donath
parent 544b1243aa
commit 931465af9f
4 changed files with 84 additions and 48 deletions

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

View File

@ -151,7 +151,7 @@
{% endblock %} {% endblock %}
</div> </div>
{% block scripts %} {% block scripts %}
<script src="{{ base_url }}/assets/javascripts/application-269373cb27.js"></script> <script src="{{ base_url }}/assets/javascripts/application-3e4827aebb.js"></script>
<script>app.initialize({url:{base:"{{ base_url }}"}})</script> <script>app.initialize({url:{base:"{{ base_url }}"}})</script>
{% for path in extra_javascript %} {% for path in extra_javascript %}
<script src="{{ path }}"></script> <script src="{{ path }}"></script>

View File

@ -221,58 +221,94 @@ function initialize(config) { // eslint-disable-line func-style
})) }))
/* Listener: keyboard handlers */ /* Listener: keyboard handlers */
new Material.Event.Listener(window, "keyup", ev => { new Material.Event.Listener(window, "keydown", ev => {
switch (ev.key) { const toggle = document.querySelector("[data-md-toggle=search]")
if (!(toggle instanceof HTMLInputElement))
throw new ReferenceError
const query = document.querySelector("[data-md-component=query]")
if (!(query instanceof HTMLInputElement))
throw new ReferenceError
/* Escape: disable search */ /* Search is open */
case "Escape": { if (toggle.checked) {
/* Escape: close search */
if (ev.key === "Escape") {
toggle.checked = false
toggle.dispatchEvent(new CustomEvent("change"))
query.blur()
/* Horizontal arrows and backspace: focus input */
} else if ([
"ArrowLeft", "ArrowRight", "Backspace"
].indexOf(ev.key) !== -1) {
if (query !== document.activeElement)
query.focus()
/* Vertical arrows and tab: select previous or next search result */
} else if ([
"ArrowUp", "ArrowDown", "Tab"
].indexOf(ev.key) !== -1) {
const key = ev.key === "Tab"
? `Arrow${ev.shiftKey ? "Up" : "Down"}`
: ev.key
/* Retrieve all results */
const links = Array.prototype.slice.call(
document.querySelectorAll("[data-md-component=search] [href]"))
if (!links.length)
return
/* Retrieve current active/focused result */
const focus = links.find(link => {
if (!(link instanceof HTMLElement))
throw new ReferenceError
return link.dataset.mdState === "active"
})
if (focus)
focus.dataset.mdState = ""
/* Calculate index depending on direction, add length to form ring */
const index = Math.max(0, (
links.indexOf(focus) + links.length + (key === "ArrowUp" ? -1 : +1)
) % links.length)
/* Set active state and focus */
if (!(links[index] instanceof HTMLElement))
throw new ReferenceError
links[index].dataset.mdState = "active"
links[index].focus()
/* Prevent scrolling of page */
ev.preventDefault()
ev.stopPropagation()
/* Return false prevents the cursor position from changing */
return false
}
/* Search is closed */
} else {
/* S: Open search if not in input field */
if (ev.key === "s") {
query.focus()
ev.preventDefault()
}
}
}).listen()
/* Listener: focus query if in search is open and character is typed */
new Material.Event.Listener(window, "keypress", () => {
const toggle = document.querySelector("[data-md-toggle=search]") const toggle = document.querySelector("[data-md-toggle=search]")
if (!(toggle instanceof HTMLInputElement)) if (!(toggle instanceof HTMLInputElement))
throw new ReferenceError throw new ReferenceError
if (toggle.checked) { if (toggle.checked) {
toggle.checked = false
toggle.dispatchEvent(new CustomEvent("change"))
const query = document.querySelector("[data-md-component=query]") const query = document.querySelector("[data-md-component=query]")
if (!(query instanceof HTMLInputElement)) if (!(query instanceof HTMLInputElement))
throw new ReferenceError throw new ReferenceError
query.blur() if (query !== document.activeElement)
} query.focus()
break
}
/* Up arrow: select previous search result */
case "ArrowUp": {
const active = document.querySelector(
"[data-md-component=search] [href][data-md-state=active]")
const links = Array.prototype.slice.call(
document.querySelectorAll("[data-md-component=search] [href]"))
let index = active
? (links.indexOf(active) - 1) % links.length
: 0
if (index === -1)
index += links.length
if (active)
active.dataset.mdState = ""
links[index].dataset.mdState = "active"
links[index].focus()
break
}
/* Down arrow: select next search result */
case "ArrowDown": {
const active = document.querySelector(
"[data-md-component=search] [href][data-md-state=active]") // TODO: remove active on mouseover (debounce!)
const links = Array.prototype.slice.call(
document.querySelectorAll("[data-md-component=search] [href]"))
const index = active
? (links.indexOf(active) + 1) % links.length
: 0
if (active)
active.dataset.mdState = ""
links[index].dataset.mdState = "active"
links[index].focus()
break
}
} }
}).listen() }).listen()