Kereső működik, színezéssel, csoportkiválasztással
This commit is contained in:
parent
e1823c9aec
commit
fc5e4eb54e
@ -8,15 +8,16 @@
|
|||||||
<meta charset="UTF-8"/>
|
<meta charset="UTF-8"/>
|
||||||
<title>MKK Közivezető-választás</title>
|
<title>MKK Közivezető-választás</title>
|
||||||
<script src="js/req.js"></script>
|
<script src="js/req.js"></script>
|
||||||
|
<script src="js/o.js"></script>
|
||||||
<script src="js/mkkkvv.js"></script>
|
<script src="js/mkkkvv.js"></script>
|
||||||
<link rel="stylesheet" href="mkkkvv.css"/>
|
<link rel="stylesheet" href="mkkkvv.css"/>
|
||||||
</head>
|
</head>
|
||||||
<body>
|
<body>
|
||||||
<section id="mainbox">
|
<section id="mainbox">
|
||||||
<input oninput="search_in_names(this.value)" type="text" placeholder="Ki legyen a Közivezető? :)" id="nameinput">
|
<input oninput="search_in_names(this.value)"
|
||||||
<section id="hintzone">
|
type="text" placeholder="Ki legyen a Közivezető? :)" id="nameinput">
|
||||||
|
<section id="hintzone" shown="false">
|
||||||
<section id="hintbox">
|
<section id="hintbox">
|
||||||
|
|
||||||
</section>
|
</section>
|
||||||
</section>
|
</section>
|
||||||
</section>
|
</section>
|
||||||
|
@ -31,23 +31,35 @@ function read_electable_people(string $fname): array
|
|||||||
}
|
}
|
||||||
|
|
||||||
define("MINIMUM_NEEDLE_LENGTH", 3);
|
define("MINIMUM_NEEDLE_LENGTH", 3);
|
||||||
|
define("HIDE_GROUP_OF_NON_DUPLICATES", true);
|
||||||
|
|
||||||
// keresés a nevek között
|
// keresés a nevek között
|
||||||
function search_in_names(array $records, string $needle): array
|
function search_in_names(array $records, string $needle, string $group = ""): array
|
||||||
{
|
{
|
||||||
|
// keresés
|
||||||
$needle = trim($needle);
|
$needle = trim($needle);
|
||||||
|
|
||||||
if (strlen($needle) < MINIMUM_NEEDLE_LENGTH) {
|
if (strlen($needle) < MINIMUM_NEEDLE_LENGTH) {
|
||||||
return [];
|
return [];
|
||||||
}
|
}
|
||||||
|
|
||||||
|
$exact_match = [];
|
||||||
$hitpos_array = [];
|
$hitpos_array = [];
|
||||||
|
|
||||||
$filter = function(array $var) use (&$hitpos_array, $needle) : bool {
|
$filter = function (array $var) use (&$hitpos_array, &$exact_match, $needle, $group): bool {
|
||||||
|
// ha a csoporton belül keres
|
||||||
|
if ($group !== "" && $var["group"] !== $group) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
$hitpos = stripos($var["name"], $needle);
|
$hitpos = stripos($var["name"], $needle);
|
||||||
|
|
||||||
if ($hitpos != false) {
|
// ha van egyezés...
|
||||||
|
if ($hitpos !== false) {
|
||||||
$hitpos_array[] = $hitpos;
|
$hitpos_array[] = $hitpos;
|
||||||
|
|
||||||
|
// megvizsgálja, hogy exact egyezés van-e?
|
||||||
|
$exact_match[] = $var["name"] === $needle;
|
||||||
}
|
}
|
||||||
|
|
||||||
return $hitpos !== false;
|
return $hitpos !== false;
|
||||||
@ -58,9 +70,46 @@ function search_in_names(array $records, string $needle): array
|
|||||||
if (count($filter_res) > 0) {
|
if (count($filter_res) > 0) {
|
||||||
for ($i = 0; $i < count($filter_res); $i++) {
|
for ($i = 0; $i < count($filter_res); $i++) {
|
||||||
$filter_res[$i]["hitpos"] = $hitpos_array[$i];
|
$filter_res[$i]["hitpos"] = $hitpos_array[$i];
|
||||||
|
$filter_res[$i]["exact_match"] = $exact_match[$i];
|
||||||
|
$filter_res[$i]["duplicate"] = false;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (HIDE_GROUP_OF_NON_DUPLICATES) {
|
||||||
|
// nevek rendezése hossz szerint (substr gyorsítása n*(n-1)-ről (n-1)+(n-2)+(n-3)... vizsgálatra)
|
||||||
|
usort($filter_res, fn($a, $b) => strlen($a["name"]) - strlen($b["name"]));
|
||||||
|
|
||||||
|
// ha a név nem szerepel több, mint egyszer, akkor a csoportot törli (security reasons)
|
||||||
|
for ($i = 0; $i < count($filter_res); $i++) {
|
||||||
|
if ($filter_res[$i]["duplicate"]) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
$name_needle = $filter_res[$i]["name"]; // név, amit keresünk a többiben
|
||||||
|
$is_duplicate = false;
|
||||||
|
for ($j = $i + 1; $j < count($filter_res); $j++) {
|
||||||
|
// ha van találat, akkor kiugrunk a keresésből
|
||||||
|
if (stripos($filter_res[$j]["name"], $name_needle) !== false) {
|
||||||
|
$filter_res[$j]["duplicate"] = true;
|
||||||
|
$is_duplicate = true;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
$filter_res[$i]["duplicate"] = $is_duplicate;
|
||||||
|
}
|
||||||
|
|
||||||
|
// csoport törlése azokból a nevekből, amikből nem szerepel több
|
||||||
|
for ($i = 0; $i < count($filter_res); $i++) {
|
||||||
|
if (!$filter_res[$i]["duplicate"]) {
|
||||||
|
$filter_res[$i]["group"] = "";
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// rendezés abc-rendbe
|
||||||
|
usort($filter_res, fn($a, $b) => $a["name"] > $b["name"]);
|
||||||
|
|
||||||
return $filter_res;
|
return $filter_res;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -76,8 +125,9 @@ switch ($action) {
|
|||||||
case "search":
|
case "search":
|
||||||
{
|
{
|
||||||
$needle = json_decode($_POST["needle"]);
|
$needle = json_decode($_POST["needle"]);
|
||||||
|
$group = json_decode($_POST["group"]);
|
||||||
$p = read_electable_people(ELECTABLE_PEOPLE_DATABASE);
|
$p = read_electable_people(ELECTABLE_PEOPLE_DATABASE);
|
||||||
$hits = search_in_names($p, $needle);
|
$hits = search_in_names($p, $needle, $group);
|
||||||
$res = $hits;
|
$res = $hits;
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
|
110
js/mkkkvv.js
110
js/mkkkvv.js
@ -1,39 +1,54 @@
|
|||||||
const MINIMUM_NEEDLE_LENGTH = 3;
|
const MINIMUM_NEEDLE_LENGTH = 3;
|
||||||
const CANVAS = document.create
|
|
||||||
|
|
||||||
|
|
||||||
// keresés indítása a nevek között
|
// keresés indítása a nevek között
|
||||||
function search_in_names(needle) {
|
function search_in_names(needle) {
|
||||||
let hintbox = document.getElementById("hintbox");
|
let hintbox = document.getElementById("hintbox");
|
||||||
|
|
||||||
if (needle.length < 3) {
|
|
||||||
hintbox.innerHTML = "";
|
|
||||||
}
|
|
||||||
|
|
||||||
if (needle.trim().length < MINIMUM_NEEDLE_LENGTH) {
|
if (needle.trim().length < MINIMUM_NEEDLE_LENGTH) {
|
||||||
|
hintbox.innerHTML = "";
|
||||||
|
hide("hintzone");
|
||||||
|
o("nameinput").setAttribute("validity", "");
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
request({
|
let request_data = {
|
||||||
action: "search",
|
action: "search",
|
||||||
needle: needle
|
needle: "",
|
||||||
}).then(resp => {
|
group: ""
|
||||||
|
};
|
||||||
|
|
||||||
|
// csoport és név szétválasztása
|
||||||
|
let group_regex = /(\[[a-záéíóöúü]+\]$)/gi;
|
||||||
|
let group_extracted = needle.match(group_regex);
|
||||||
|
if (group_extracted != null) {
|
||||||
|
request_data["group"] = group_extracted[0].substring(1, group_extracted[0].length - 1);
|
||||||
|
request_data["needle"] = needle.substring(0, needle.length - group_extracted[0].length - 1).trim();
|
||||||
|
} else {
|
||||||
|
request_data["needle"] = needle;
|
||||||
|
}
|
||||||
|
|
||||||
|
request(request_data).then(resp => {
|
||||||
hintbox.innerHTML = "";
|
hintbox.innerHTML = "";
|
||||||
let hits = JSON.parse(resp);
|
let hits = JSON.parse(resp);
|
||||||
console.log(hits);
|
hits.forEach((val) => {
|
||||||
hits.forEach((key, val) => {
|
|
||||||
if (needle.length < 3) {
|
if (needle.length < 3) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
let hit = document.createElement("span");
|
let hit = document.createElement("span");
|
||||||
hit.classList.add("hit");
|
hit.classList.add("hit");
|
||||||
|
hit.addEventListener("click", () => {
|
||||||
|
let group_id = val["duplicate"] ? ` [${val["group"]}]` : "";
|
||||||
|
fill_name_input(`${val["name"]}${group_id}`);
|
||||||
|
hide("hintzone");
|
||||||
|
ninput.setAttribute("validity", "ok");
|
||||||
|
});
|
||||||
|
|
||||||
let name_node = document.createElement("span");
|
let name_node = document.createElement("span");
|
||||||
name_node.classList.add("name");
|
name_node.classList.add("name");
|
||||||
|
|
||||||
let hp = key["hitpos"];
|
let hp = val["hitpos"];
|
||||||
let name = key["name"];
|
let name = val["name"];
|
||||||
|
|
||||||
if (hp > 0) {
|
if (hp > 0) {
|
||||||
let name_begin = name.slice(0, hp);
|
let name_begin = name.slice(0, hp);
|
||||||
@ -52,12 +67,73 @@ function search_in_names(needle) {
|
|||||||
|
|
||||||
hit.appendChild(name_node);
|
hit.appendChild(name_node);
|
||||||
|
|
||||||
let group = document.createElement("span");
|
let group = val["group"];
|
||||||
group.innerText = `(${key["group"]})`;
|
if (group.length > 0) {
|
||||||
group.classList.add("group");
|
let group_node = document.createElement("span");
|
||||||
hit.appendChild(group);
|
group_node.innerHTML = ` ${print_from_group(group)}`;
|
||||||
|
group_node.classList.add("group");
|
||||||
|
hit.appendChild(group_node);
|
||||||
|
}
|
||||||
|
|
||||||
hintbox.appendChild(hit);
|
hintbox.appendChild(hit);
|
||||||
});
|
});
|
||||||
|
|
||||||
|
// doboz megjelenítése, ha szükséges
|
||||||
|
hits.length > 0 ? show("hintzone") : hide("hintzone");
|
||||||
|
|
||||||
|
// szövegmező színezése
|
||||||
|
let validity = "";
|
||||||
|
let ninput = document.getElementById("nameinput");
|
||||||
|
if (ninput.value.length > MINIMUM_NEEDLE_LENGTH) {
|
||||||
|
if (hits.length === 0) {
|
||||||
|
validity = "bad";
|
||||||
|
} else if (hits.length === 1 && hits[0]["exact_match"]) {
|
||||||
|
validity = "ok";
|
||||||
|
hide("hintzone");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
ninput.setAttribute("validity", validity);
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// csoport kiírása ("...az Azúrból" -- no reference of course :D), ha megkapja a szervertől
|
||||||
|
function print_from_group(group) {
|
||||||
|
group = group.trim();
|
||||||
|
if (group === "") {
|
||||||
|
return "";
|
||||||
|
}
|
||||||
|
|
||||||
|
let vowels = /[aáeéiíoóöőuúüű]/i; // magánhangzók regexe
|
||||||
|
let highpitched_vowels = /[eéiíöőüű]/i; // magas hangrendű maánhangzók regexe
|
||||||
|
|
||||||
|
// első betű megvizsgálása a névelő kiválasztásához
|
||||||
|
let b = group.charAt(0);
|
||||||
|
let article = (vowels.exec(b) != null) ? "az" : "a";
|
||||||
|
|
||||||
|
// hátulról az első magánhangzó keresése
|
||||||
|
let g_rev = group.split("").reverse().join("");
|
||||||
|
let last_vowel = g_rev.match(vowels)[0];
|
||||||
|
|
||||||
|
// megvizsgáljuk, hogy az utolsó betű volt-e a megtalált magánhangzó
|
||||||
|
let last_letter = g_rev.charAt(0).toLowerCase();
|
||||||
|
if (last_letter === last_vowel.charAt(0).toLowerCase()) {
|
||||||
|
if (last_letter === "a") {
|
||||||
|
last_letter = "á";
|
||||||
|
} else if (last_letter === "e") {
|
||||||
|
last_letter = "é";
|
||||||
|
}
|
||||||
|
|
||||||
|
// utolsó betű kicserélése
|
||||||
|
group = group.substring(0, group.length - 1) + last_letter;
|
||||||
|
}
|
||||||
|
|
||||||
|
// utolsó magánhangzó hangrendjének vizsgálata és rag kiválasztása
|
||||||
|
let suffix = highpitched_vowels.test(last_vowel) ? "ből" : "ból";
|
||||||
|
|
||||||
|
return `${article} <i>${group}${suffix}</i>`;
|
||||||
|
}
|
||||||
|
|
||||||
|
// szöveggel kitölti a nevet
|
||||||
|
function fill_name_input(str) {
|
||||||
|
document.getElementById("nameinput").value = str;
|
||||||
|
}
|
||||||
|
25
js/o.js
Normal file
25
js/o.js
Normal file
@ -0,0 +1,25 @@
|
|||||||
|
function o(input) {
|
||||||
|
var o;
|
||||||
|
if (typeof input === "string")
|
||||||
|
o = document.getElementById(input);
|
||||||
|
else if (typeof input === "object")
|
||||||
|
o = input;
|
||||||
|
return o;
|
||||||
|
}
|
||||||
|
|
||||||
|
// megjelenítés / eltüntetés
|
||||||
|
function show(obj) {
|
||||||
|
o(obj).setAttribute("shown", "true");
|
||||||
|
}
|
||||||
|
|
||||||
|
function hide(obj) {
|
||||||
|
o(obj).setAttribute("shown", "false");
|
||||||
|
}
|
||||||
|
|
||||||
|
function toggle_show(obj) {
|
||||||
|
o(obj).setAttribute("shown", o(obj).getAttribute("shown") === "false");
|
||||||
|
}
|
||||||
|
|
||||||
|
function scroll_enable(on) {
|
||||||
|
document.body.style.overflowY = on ? "scroll" : "hidden";
|
||||||
|
}
|
37
mkkkvv.css
37
mkkkvv.css
@ -4,10 +4,14 @@ body{
|
|||||||
--C_PRIMARY: #f89a17;
|
--C_PRIMARY: #f89a17;
|
||||||
--C_SEC: #44968e;
|
--C_SEC: #44968e;
|
||||||
--C_TER: #2a5999;
|
--C_TER: #2a5999;
|
||||||
|
--C_OK: #67b60a;
|
||||||
--C_TRIADIC1: #85ea11;
|
--C_TRIADIC1: #85ea11;
|
||||||
--C_TRIADIC2: #11ea76;
|
--C_TRIADIC2: #11ea76;
|
||||||
--C_BG1: #c0ccdf;
|
--C_BG1: #c0ccdf;
|
||||||
--C_BG2: #e3ecf3;
|
--C_BG2: #e3ecf3;
|
||||||
|
--C_BG3: #e9f3e3;
|
||||||
|
--C_UNKNOWN: #f84c17;
|
||||||
|
--C_TEXTINPUT_COLOR: #2f4c6e;
|
||||||
|
|
||||||
font-family: 'Faustina', serif;
|
font-family: 'Faustina', serif;
|
||||||
|
|
||||||
@ -27,6 +31,18 @@ input[type="text"]:focus {
|
|||||||
|
|
||||||
input#nameinput {
|
input#nameinput {
|
||||||
width: 100%;
|
width: 100%;
|
||||||
|
color: var(--C_TEXTINPUT_COLOR);
|
||||||
|
transition: color 0.3s ease;
|
||||||
|
}
|
||||||
|
|
||||||
|
input#nameinput[validity="ok"] {
|
||||||
|
color: var(--C_OK);
|
||||||
|
transition: color 0.3s ease;
|
||||||
|
}
|
||||||
|
|
||||||
|
input#nameinput[validity="bad"] {
|
||||||
|
color: var(--C_UNKNOWN);
|
||||||
|
transition: color 0.3s ease;
|
||||||
}
|
}
|
||||||
|
|
||||||
section#hintbox {
|
section#hintbox {
|
||||||
@ -41,10 +57,17 @@ span.hit {
|
|||||||
display: block;
|
display: block;
|
||||||
position: static;
|
position: static;
|
||||||
padding: 0.2em 0.5em;
|
padding: 0.2em 0.5em;
|
||||||
|
cursor: pointer;
|
||||||
|
}
|
||||||
|
|
||||||
|
span.hit:hover {
|
||||||
|
background-color: var(--C_BG3);
|
||||||
}
|
}
|
||||||
|
|
||||||
span.highlight {
|
span.highlight {
|
||||||
font-weight: bold;
|
font-weight: bold;
|
||||||
|
color: var(--C_SEC);
|
||||||
|
text-decoration: underline;
|
||||||
}
|
}
|
||||||
|
|
||||||
section#mainbox {
|
section#mainbox {
|
||||||
@ -52,3 +75,17 @@ section#mainbox {
|
|||||||
position: absolute;
|
position: absolute;
|
||||||
width: min(var(--MAINBOX_WIDTH), calc(100vw - 1em));
|
width: min(var(--MAINBOX_WIDTH), calc(100vw - 1em));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
*[shown="false"] {
|
||||||
|
visibility: hidden;
|
||||||
|
display: none;
|
||||||
|
opacity: 0;
|
||||||
|
transition: 0.3s ease;
|
||||||
|
width: 0;
|
||||||
|
height: 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
*[shown="true"] {
|
||||||
|
opacity: 1;
|
||||||
|
transition: 0.3s ease;
|
||||||
|
}
|
||||||
|
Loading…
x
Reference in New Issue
Block a user