Skip to content

Commit

Permalink
Add tag filtering to FAQ
Browse files Browse the repository at this point in the history
  • Loading branch information
Not-A-Normal-Robot authored Apr 29, 2024
1 parent 9e5fe84 commit 6662305
Show file tree
Hide file tree
Showing 3 changed files with 175 additions and 57 deletions.
96 changes: 92 additions & 4 deletions data/faq-template.html
Original file line number Diff line number Diff line change
Expand Up @@ -44,10 +44,92 @@ <h1>
<h1 class="center-text">
Frequently Asked Questions
</h1>
<h4 class="center-text">
Sourced from Techmino's official Discord server. <br>
Use your browser's "find in page" feature (Ctrl+F) to search for keywords.
<h4 class="center-text hide show-noscript">
Use your browser's "find in page" feature to filter questions. <br>
Tag filtering is only available with JavaScript enabled.
</h4>
<details class="tag-filter hide-noscript">
<summary>Filter tags</summary>
<ul>
<li>
<span class="tag techmino">Techmino</span>
<div class="filter-radio">
<input type="radio" name="techmino" id="tag-techmino-all" value="all" checked>
<label for="tag-techmino-all">All</label>
<input type="radio" name="techmino" id="tag-techmino-include" value="include">
<label for="tag-techmino-include">Include</label>
<input type="radio" name="techmino" id="tag-techmino-exclude" value="exclude">
<label for="tag-techmino-exclude">Exclude</label>
</div>
</li>
<li>
<span class="tag galaxy">Tech. Galaxy</span>
<div class="filter-radio">
<input type="radio" name="galaxy" id="tag-galaxy-all" value="all" checked>
<label for="tag-galaxy-all">All</label>
<input type="radio" name="galaxy" id="tag-galaxy-include" value="include">
<label for="tag-galaxy-include">Include</label>
<input type="radio" name="galaxy" id="tag-galaxy-exclude" value="exclude">
<label for="tag-galaxy-exclude">Exclude</label>
</div>
</li>
<li>
<span class="tag linux">Linux</span>
<div class="filter-radio">
<input type="radio" name="linux" id="tag-linux-all" value="all" checked>
<label for="tag-linux-all">All</label>
<input type="radio" name="linux" id="tag-linux-include" value="include">
<label for="tag-linux-include">Include</label>
<input type="radio" name="linux" id="tag-linux-exclude" value="exclude">
<label for="tag-linux-exclude">Exclude</label>
</div>
</li>
<li>
<span class="tag apple">Mac/iOS</span>
<div class="filter-radio">
<input type="radio" name="apple" id="tag-apple-all" value="all" checked>
<label for="tag-apple-all">All</label>
<input type="radio" name="apple" id="tag-apple-include" value="include">
<label for="tag-apple-include">Include</label>
<input type="radio" name="apple" id="tag-apple-exclude" value="exclude">
<label for="tag-apple-exclude">Exclude</label>
</div>
</li>
<li>
<span class="tag multiplayer">Multiplayer</span>
<div class="filter-radio">
<input type="radio" name="multiplayer" id="tag-multiplayer-all" value="all" checked>
<label for="tag-multiplayer-all">All</label>
<input type="radio" name="multiplayer" id="tag-multiplayer-include" value="include">
<label for="tag-multiplayer-include">Include</label>
<input type="radio" name="multiplayer" id="tag-multiplayer-exclude" value="exclude">
<label for="tag-multiplayer-exclude">Exclude</label>
</div>
</li>
<li>
<span class="tag error">Error</span>
<div class="filter-radio">
<input type="radio" name="error" id="tag-error-all" value="all" checked>
<label for="tag-error-all">All</label>
<input type="radio" name="error" id="tag-error-include" value="include">
<label for="tag-error-include">Include</label>
<input type="radio" name="error" id="tag-error-exclude" value="exclude">
<label for="tag-error-exclude">Exclude</label>
</div>
</li>
<li>
<span class="tag bot">ColdClear/9S</span>
<div class="filter-radio">
<input type="radio" name="bot" id="tag-bot-all" value="all" checked>
<label for="tag-bot-all">All</label>
<input type="radio" name="bot" id="tag-bot-include" value="include">
<label for="tag-bot-include">Include</label>
<input type="radio" name="bot" id="tag-bot-exclude" value="exclude">
<label for="tag-bot-exclude">Exclude</label>
</div>
</li>
</ul>
</details>
<h5 class="center-text" id="last-updated"></h5>
<br>

Expand All @@ -60,7 +142,7 @@ <h5 class="center-text" id="last-updated"></h5>
Question
<span class="tags">
<span class="tag techmino">Techmino</span>
<span class="tag galaxy">Galaxy</span>
<span class="tag galaxy">Tech. Galaxy</span>
<span class="tag linux">Linux</span>
<span class="tag apple">Mac/iOS</span>
<span class="tag multiplayer">Multiplayer</span>
Expand All @@ -75,6 +157,12 @@ <h5 class="center-text" id="last-updated"></h5>
</details>
-->
</section>

<br>
<small class="center-text">
The questions in this FAQ are originally sourced from Techmino's official Discord server, but slightly modified for easier finding. <br>
If you have any questions that are not answered here, feel free to ask in the <a href="https://discord.gg/f9pUvkh">Discord server</a>!
</small>
</section>
</div>

Expand Down
107 changes: 54 additions & 53 deletions js/faq.js
Original file line number Diff line number Diff line change
@@ -1,64 +1,65 @@
addButtonListeners();
{
const faqLastUpdatedElement = document.getElementById('last-updated');
if(faqLastUpdatedElement !== undefined) {
// fetch github api to get date of last edit of FAQ
fetch('https://api.github.com/repos/techmino-hub/techmino-hub.github.io/commits?path=faq.html')
.then(response => response.json())
.then(json => {
const lastUpdated = new Date(json[0].commit.committer.date);
const currentDate = new Date();
const timeDifference = currentDate - lastUpdated;
let formattedDate;

const faqLastUpdatedElement = document.getElementById('last-updated');
if(faqLastUpdatedElement !== undefined) {
// fetch github api to get date of last edit of FAQ
fetch('https://api.github.com/repos/techmino-hub/techmino-hub.github.io/commits?path=faq.html')
.then(response => response.json())
.then(json => {
const lastUpdated = new Date(json[0].commit.committer.date);
const currentDate = new Date();
const timeDifference = currentDate - lastUpdated;
let formattedDate;
if (timeDifference < 60 * 60 * 1000) {
const minutes = Math.floor(timeDifference / (60 * 1000));
formattedDate = `${minutes} minutes ago`;
} else if (timeDifference < 24 * 60 * 60 * 1000) {
const hours = Math.floor(timeDifference / (60 * 60 * 1000));
formattedDate = `${hours} hours ago`;
} else {
formattedDate = lastUpdated.toLocaleDateString('en-US', {
year: "numeric",
month: "long",
day: "numeric"
})
}

if (timeDifference < 60 * 60 * 1000) {
const minutes = Math.floor(timeDifference / (60 * 1000));
formattedDate = `${minutes} minutes ago`;
} else if (timeDifference < 24 * 60 * 60 * 1000) {
const hours = Math.floor(timeDifference / (60 * 60 * 1000));
formattedDate = `${hours} hours ago`;
} else {
formattedDate = lastUpdated.toLocaleDateString('en-US', {
year: "numeric",
month: "long",
day: "numeric"
})
}

faqLastUpdatedElement.innerText = "Last updated: " + formattedDate;
});
}

function addFAQEntries(faqObject) {
faqObject.forEach(entry => {
faqSection.innerHTML += faqHTML(entry);
});

addButtonListeners();
}
faqLastUpdatedElement.innerText = "Last updated: " + formattedDate;
});
}

function addButtonListeners() {
// Add button listeners
const questionHeaders = document.getElementsByClassName('question-header');
for(let i = 0; i < questionHeaders.length; i++) {
questionHeaders[i].addEventListener('click', () => {
questionHeaders[i].parentElement.classList.toggle('expanded');
});
}
}

function faqHTML(entry) {
return `<div class="question">
<button class="question-header">
<div class="question-icon-container">
<svg class="question-icon" viewBox="0 0 24 24">
<path fill="currentColor" d="M7 14l5-5 5 5z"></path>
</svg>
</div>
<h2 class="question-title">${entry.question}</h2>
</button>
<div class="answer">
${entry.answerHTML}
<div class="answer-source">— ${entry.author}</div>
</div>
</div>`;
// Add radio listeners
for(const radioElement of document.getElementsByClassName('tag-filter')[0].getElementsByTagName('input')) {
radioElement.addEventListener('change', () => {
handleFilterUpdate(radioElement.name, radioElement.value);
});
}

function handleFilterUpdate(tag, mode) {
tag = tag.trim().toLowerCase();
mode = mode.trim().toLowerCase();

const faqElement = document.getElementsByClassName('faq')[0];

if(mode === "all") {
faqElement.classList.remove(`show-${tag}`);
faqElement.classList.remove(`hide-${tag}`);
} else if(mode === "include") {
faqElement.classList.remove(`hide-${tag}`);
faqElement.classList.add(`show-${tag}`);
} else if(mode === "exclude") {
faqElement.classList.remove(`show-${tag}`);
faqElement.classList.add(`hide-${tag}`);
} else {
console.error(`Invalid filter mode: ${mode}`);
}
}
}
29 changes: 29 additions & 0 deletions style.css
Original file line number Diff line number Diff line change
Expand Up @@ -199,6 +199,35 @@ details.question > summary::marker {
--tag-logo: "󰂖"; /* console icon */
}
/* #endregion */
/* #region Tag filter UI */
details.tag-filter {
border: 1px solid lime;
border-radius: 0.4rem;
padding: 0.5rem 1rem;
}
details.tag-filter ul {
display: flex;
flex-direction: column;
padding-left: 0;
gap: 0.5rem;
list-style-type: none;
}
details.tag-filter li {
display: flex;
flex-direction: row;
justify-content: space-between;
}
@media (max-width: 400px) {
details.tag-filter li {
flex-direction: column;
}
details.tag-filter li:not(:last-child) {
border-bottom: 1px solid grey;
padding-bottom: 0.5rem;
margin-bottom: 0.5rem;
}
}
/* #endregion */
/* #region Question tag filters */
.faq.show-techmino details.question:not(.techmino),
.faq.show-galaxy details.question:not(.galaxy),
Expand Down

0 comments on commit 6662305

Please sign in to comment.