diff --git a/build/assets/js/modules/quick-key-manager.js b/build/assets/js/modules/quick-key-manager.js
new file mode 100644
index 00000000..858b2ba5
--- /dev/null
+++ b/build/assets/js/modules/quick-key-manager.js
@@ -0,0 +1,62 @@
+/**
+ * @class
+ * Class to manage quick keys in the current application.
+ */
+"use strict";
+
+import { QuickKey } from "./quick-key.js";
+
+export class QuickKeyManager {
+
+ quickKeys = new Map();
+
+ /**
+ * @constructor
+ * @param {Object} quickKeyData - Set of key/value pairs mapping keyboard characters to CSS selectors.
+ * @param {Node} rootNode - Root node to use for finding quick key matches.
+ * @returns {QuickKeyManager} - A new instance of the QuickKeyManager class.
+ */
+ constructor(quickKeyData, rootNode) {
+ // Create a new QuickKey object for each key/selector pair.
+ for (const key in quickKeyData) {
+ if (Object.hasOwnProperty.call(quickKeyData, key)) {
+ const selector = quickKeyData[key];
+ const qk = new QuickKey(key, selector, rootNode);
+ if (qk.nodes.length > 0) {
+ this.quickKeys.set(key, new QuickKey(key, selector, rootNode));
+ }
+ }
+ }
+ }
+
+ /**
+ * Binds the specified function to the node returned
+ * by the pressed quick key. The lowercase quick key yields
+ * the next matching node, and the uppercase quick key yields
+ * the previous matching node.
+ *
+ * The specified function must take two parameters:
+ * - The node returned by the quick key.
+ * - The event processed by the "keydown" listener.
+ * @method
+ * @param {func} - The function to call on the node returned by pressing the quick key.
+ */
+ bindQuickKeysToFunction(func) {
+ document.addEventListener( 'keydown', function (e) {
+ // If the lowercase quick key is pressed...
+ // use the next matching node.
+ var node = null;
+ if (this.quickKeys.has(e.key)) {
+ node = this.quickKeys.get(e.key).nextNode();
+ }
+ // If the uppercase quick key is pressed,
+ // use the previous matching node.
+ else if (e.key === e.key.toUpperCase() && this.quickKeys.has(e.key.toLowerCase)) {
+ node = this.quickKeys.get(e.key.toLowerCase()).previousNode();
+ }
+ if (node) {
+ func(node, e);
+ }
+ });
+ }
+}
\ No newline at end of file
diff --git a/build/assets/js/modules/quick-key.js b/build/assets/js/modules/quick-key.js
new file mode 100644
index 00000000..43ead3b1
--- /dev/null
+++ b/build/assets/js/modules/quick-key.js
@@ -0,0 +1,120 @@
+/**
+ * @class
+ * Class to represent a screen reader quick key to iterate through a set of
+ * tags in the DOM when a certain key is pressed.
+ */
+
+ "use strict";
+
+ export class QuickKey {
+
+ // Key to press to advance to the next node.
+ key = null;
+
+ // CSS selector for DOM nodes matched by this quick key.
+ selector = '';
+
+ // List of nodes that that match this quick key.
+ nodes = [];
+
+ // Index of current node in list of nodes.
+ currentNodeIndex = -1;
+
+ /**
+ * @constructor
+ *
+ * @param {String} key - Key to press to advance to the next node.
+ * @param {String} selector - CSS selector for DOM nodes matched by this quick key
+ * @param {Node} rootNode - Root node against which selector is run (optional).
+ * @returns {QuickKey} - A new instance of the QuickKey class.
+ */
+ constructor(key, selector, rootNode = null) {
+ this.key = key;
+ this.selector = selector;
+ if (rootNode) {
+ this.nodes = this.findNodes(rootNode);
+ }
+ }
+
+ /**
+ * Finds and returns a list of nodes which matches the object's selector property.
+ * @method
+ * @param {NodeListOf} rootNode - Root node against which selector is run.
+ * @returns {Array[Node]} - List of nodes matching the object's selector.
+ */
+ findNodes(rootNode) {
+ var nodes = [];
+ if (rootNode) {
+ nodes = rootNode.querySelectorAll(this.selector);
+ }
+ return nodes;
+ }
+
+ /**
+ * Returns the current node matched by this quick key.
+ * @method
+ * @returns {Node} - The current matching node or undefined if there are none
+ * or the list of nodes has not been traversed yet.
+ */
+ currentNode() {
+ if (!this.nodes.length || this.currentNodeIndex < 0) {
+ return;
+ }
+ return this.nodes[this.currentNodeIndex];
+ }
+
+ /**
+ * Returns the next node in the DOM matched by this quick key.
+ * @method
+ * @returns {Node} - The next matching node (which could be the first one
+ * if we are at the end of the list), or undefined if there are no matching nodes.
+ */
+ nextNode() {
+ // Make sure there are matching nodes for this quick key.
+ if (!this.nodes.length) {
+ return;
+ }
+
+ // Return this node if it's the only one in the list.
+ if (this.nodes.length == 1) {
+ this.currentNodeIndex = 0;
+ }
+ // Get the next node in the list.
+ else if (this.currentNodeIndex < this.nodes.length - 1) {
+ this.currentNodeIndex += 1;
+ }
+ // Or loop around to to the start of the list if we are at the end.
+ else {
+ this.currentNodeIndex = 0;
+ }
+
+ return this.nodes[this.currentNodeIndex];
+ }
+
+ /**
+ * Returns the previous node in the DOM matched by this quick key.
+ * @method
+ * @returns {Node} - The previous matching node (which could be the last one
+ * if we are at the start of the list), or null if there are no matching nodes.
+ */
+ previousNode() {
+ // Make sure there are matching nodes for this quick key.
+ if (!this.nodes.length) {
+ return;
+ }
+
+ // Return this node if it's the only one in the list.
+ if (this.nodes.length == 1) {
+ this.currentNodeIndex = 0;
+ }
+ // Get the previous node in the list.
+ else if (this.currentNodeIndex > 0) {
+ this.currentNodeIndex -= 1;
+ }
+ // Or loop around to to the start of the list if we are at the end.
+ else {
+ this.currentNodeIndex = this.nodes.length - 1;
+ }
+ return this.nodes[this.currentNodeIndex];
+ }
+ }
\ No newline at end of file
diff --git a/build/assets/js/quick-key-setup.js b/build/assets/js/quick-key-setup.js
new file mode 100644
index 00000000..e877e540
--- /dev/null
+++ b/build/assets/js/quick-key-setup.js
@@ -0,0 +1,41 @@
+"use strict";
+
+import { QuickKeyManager } from './modules/quick-key-manager.js';
+
+// Keys/values for quick keys and the CSS selectors they match.
+let keyData = {
+ // Press h/H to move forward/backward through headings.
+ 'h': 'h1, h2, h3, h4, h5, h6',
+ // Press k/K to move forward/backward through links.
+ 'k': 'a, [role="link"]',
+ // Press r/R to move forward/backward through page regions and landmarks.
+ 'r': ' header, nav, main, footer, [role="region"], [role="banner"], [role="navigation"], [role="main"], [role="contentinfo"], [role="search"]',
+ // Press f/F to move forward/backward through form controls.
+ 'f': 'input, select, button, [role="form"], [role="textbox"], [role="checkbox"], [role="button"]',
+ // Press b/B to move forward/backward through buttons.
+ 'b': 'button, input[type="button"], input[type="submit"], input[type="reset"], [role="button"]',
+ // Press l/L to move forward/backward through lists.
+ 'l': 'ul, ol, dl, [role="list"]'
+};
+
+let qkm = new QuickKeyManager(keyData, document.getElementById('content'));
+
+// Check if the pressed key is a quick key.
+document.addEventListener( 'keydown', function (e) {
+ // If the pressed key is the lowercase version of a quick key,
+ // target the next matching node.
+ var node = null;
+ if (qkm.quickKeys.has(e.key)) {
+ node = qkm.quickKeys.get(e.key).nextNode();
+ }
+ // If the pressed key is the uppercase version of a quick key,
+ // target the next matching node.
+ else if (e.key === e.key.toUpperCase() && qkm.quickKeys.has(e.key.toLowerCase())) {
+ node = qkm.quickKeys.get(e.key.toLowerCase()).previousNode();
+ }
+ // Move keyboard focus to the matching node (if any).
+ if (node) {
+ // alert( e.key + " ==> " + node.nodeName + ": " + node.textContent );
+ node.focus();
+ }
+});
diff --git a/build/index.html b/build/index.html
index 55566311..2a774a92 100644
--- a/build/index.html
+++ b/build/index.html
@@ -1,4 +1,4 @@
-
Inclusiville Arts Festival 2021
Inclusiville Arts Festival 2021
A festival to celebrate the local creative talent held at Inclusiville Showgrounds this year.
This is a great space to write long text about your company and your services. You can use this space to go into a little more detail about your company. Talk about your team and what services you provide. Tell your visitors the story of how you came up with the idea for your business and what makes you different from your competitors. Make your company stand out and show.
Celebrating local talent
Event Schedule
The Digital Navigator: an interpretive dance — 12pm
Headbanging Keyboards – 1pm
The Empaths – 2pm
Wucag Tang Clan — 3pm
Closing event: Fireworks on the hills — 6pm
FAQ
All events are general admission, meaning that you are able to choose where to sit when you arrive. This works on a first come, first served basis.
IAF is an alcohol free, family friendly event held during the day. We welcome attendees of all ages, however, children under the age of 16 must be accompanied by a guardian.
Inclusiville Arts Festival allows guide dogs. If you find that you need assitance after you arrive at the showgrounds, there will be event staff available to assist you. Please indicate to the ticketing staff as you enter the grounds.
If you find that you need assitance after you arrive at the showgrounds, there will be event staff available to assist you. Please indicate to the ticketing staff as you enter the grounds.
You heard your colleagues mention a local arts and music festival to you in the break room. You barely caught the name of it as you rushed off to the next meeting, and you think you have the correct website on the screen in front of you now.
You love people, and you love music; It would be great if you could take your guide dog. You want to get a feel of what kind of event this is so you can plan ahead.
Blind people don't use computers the same way sighted people do; Often, they use the keyboard to navigate as a sighted user would do with a mouse. The keyboard sends messages to the installed screen reader application, which reads out information about the screen they are looking at to the person, piece by piece.
Keeping this in mind, try navigating this website using only the keyboard to find the information you need.
Press Tab to start navigating. What screen readers see will show as text here.
Nice work! How did that feel?
Did you find yourself doing any of the following?
Memorising the steps when you weren't able to get to the button you wanted to with the keyboard ... not so successfully
Needing to go back constantly to remind yourself what the screen reader "said".
The digital landscape can be a hostile, lonely place when you're not a sighted person. Accessible web applications can be an ally by ensuring that screen readers can talk to it.
You can make a difference today by:
Go to your favourite website and do an accessibility check.