diff --git a/soundboard.py b/soundboard.py index 4707577..0c1e08a 100644 --- a/soundboard.py +++ b/soundboard.py @@ -3,7 +3,7 @@ import sys import subprocess import sqlite3 -from flask import Flask, render_template, request, redirect, url_for, send_from_directory, g +from flask import Flask, render_template, request, redirect, url_for, send_from_directory, g, jsonify import config @@ -144,3 +144,25 @@ ON tag.id = checked.id""", (sound,)) @app.route("/sounds/") def sounds(name): return send_from_directory(config.path, name) + +@app.route("/tags/") +def tags(tags): + # Credits: https://stackoverflow.com/a/38955049/1532986 + query = """\ +SELECT button.file +FROM button +WHERE button.id IN ( + SELECT button_tags.fk_button + FROM button_tags + JOIN tag + ON tag.id = button_tags.fk_tag + GROUP BY button_tags.fk_button + HAVING +""" + tagFilter = "\t\tSUM(CASE WHEN tag.name = \"{}\" THEN 1 ELSE 0 END) > 0" + tagFilters = " AND \n".join([tagFilter.format(tag) for tag in tags.split(",")]) + query += tagFilters + "\n)" + + sounds = queryDB(query) + + return jsonify([sound["file"].split(".")[0] for sound in sounds]) diff --git a/static/main.css b/static/main.css index c24adad..f5f94c9 100644 --- a/static/main.css +++ b/static/main.css @@ -101,8 +101,13 @@ button:active { } .tags li a:hover { - background-color: #eee; - color: #333; + border-color: #eee; + color: #eee; +} + +.tagged { + background-color: #eee !important; + color: #333 !important; } label { diff --git a/static/main.js b/static/main.js index bedef1a..6a4d0b1 100644 --- a/static/main.js +++ b/static/main.js @@ -1,6 +1,7 @@ /* jshint esversion: 6 */ var localModeEnabled = false; +var selectedTags = []; // References to howler objects var howlerSounds = []; @@ -43,7 +44,6 @@ ready(function() { searchfield.focus(); searchFilter(searchfield, ".sound", "inline-block"); - searchFilter(searchfield, ".tag", "block"); var reset = document.querySelector("#reset"); var sounds_nav = document.querySelector("#sounds-nav"); @@ -74,6 +74,22 @@ function searchFilter(searchfield, itemSelector, unHideStyle) { } } +function tagFilter(sounds) { + var items = document.querySelectorAll(".sound"); + + items.forEach(function(item) { + item.style.display = "inline-block"; + }); + + items.forEach(function(item) { + var name = item.firstChild.innerHTML; + + if (sounds.length > 0 && sounds.indexOf(name.toLowerCase()) === -1) { + item.style.display = "none"; + } + }); +} + /* * Adds all necessary KeyListeners to document */ @@ -112,7 +128,42 @@ function addKeyListeners() { source.classList.remove("sound-pressed"); } }); - + }); + + var tags = document.querySelectorAll(".tags li"); + + tags.forEach(function(tag) { + tag.addEventListener("click", function(e) { + var className = "tagged"; + var el = this.firstChild; + + var classes = el.className.split(" "); + var existingIndex = classes.indexOf(className); + + if (existingIndex >= 0) + classes.splice(existingIndex, 1); + else + classes.push(className); + + el.className = classes.join(" "); + + var i = selectedTags.indexOf(el.innerHTML); + + if (i == -1) + selectedTags.push(el.innerHTML); + else + selectedTags.splice(i, 1); + + console.log(selectedTags); + + if (selectedTags.length > 0) { + ajaxRequest("/tags/" + selectedTags.join(), function() { + tagFilter(JSON.parse(this.responseText)); + }); + } else { + tagFilter([]); + } + }); }); } @@ -145,11 +196,15 @@ function hideSections() { }); } -function ajaxRequest(url) { +function ajaxRequest(url, callback) { var ajaxRequest; try { ajaxRequest = new XMLHttpRequest(); ajaxRequest.open("GET", url, true); + + if (typeof callback !== 'undefined') + ajaxRequest.onload = callback; + ajaxRequest.send(null); } catch (e) { alert("Unfortunately we were unable to handle your request. Please try again later and contact the server administrator if the problem persists.");