Hello Punk! In my daily boring...
I found something interesting that I will share with you, this is not too fancy or glam but still "fun-cy" for me, cz In my stupid knowledge this is really helpful and enough for me and myself.
HTML5 Input Datalist #
At least, this is what W3Schools said in their example:
What if I wrap inside PHP Function? #
When I work with HTMX I need isolated component that can be reusable a form. So I create a PHP Function that generate the Input Datalist.
1// Filename: helpers/Utils.php
2
3public static function selectSearch(string $inputId, array $options, int|string $selected = ''): string
4{
5 $inputHTML = '<div class="relative">';
6 $inputHTML .= '<input type="text" id="' . $inputId . '" list="" placeholder="Search..." autocomplete="off" class="transition-[0.2s] w-full input input-sm input-bordered focus:shadow-md" />';
7 $inputHTML .= '<datalist id="' . $inputId . '_list" class="box-border overflow-y-auto absolute top-full mt-1 max-h-40 bg-white border shadow-md">';
8
9 $selectedText = '';
10 $selectedValue = '';
11 foreach ($options as $option) {
12 $text = \explode('#', $option)[1];
13 $value = \explode('#', $option)[0];
14 if ($selected == $value) {
15 $selectedText = $text;
16 $selectedValue = $value;
17 }
18 $inputHTML .= '<option class="block p-1 mb-px cursor-pointer hover:bg-gray-200" value="' . $option . '">' . $text . '</option>';
19 }
20
21 $inputHTML .= '</datalist>';
22 $inputHTML .= '<input type="hidden" name="' . $inputId . '" id="target_' . $inputId . '" value="'.$selectedValue.'" />';
23 $inputHTML .= '</div>';
24 $inputHTML .= '<script type="text/javascript">';
25 $inputHTML .= 'fancyDropdown("' . $inputId . '");';
26 $inputHTML .= 'setTimeout(() => document.getElementById("' . $inputId . '").value = "'.$selectedText.'", 350);';
27 $inputHTML .= '</script>';
28
29 return $inputHTML;
30}
31
I create a static function inside Utils
class so I can use that function everywhere in my project.
Is that using TailwindCSS? Yes, it's too dirty. But fck it! It's work! (Don't blame on me, if you really programmer so read it)
You can see this script
:
1$inputHTML .= '<script type="text/javascript">';
2$inputHTML .= 'fancyDropdown("' . $inputId . '");';
3$inputHTML .= 'setTimeout(() => document.getElementById("' . $inputId . '").value = "' . $selectedText . '", 350);';
4$inputHTML .= '</script>';
Yes! Again I wrote JavaScript as a string in PHP, why not! And where is the fckin fancyDropdown
come from?!
Here is, I found a Question in StackOverflow that asked about
The Question: https://stackoverflow.com/q/13693482
Yes! Around 11 years ago, and the solution that match with my need is come around
The Solution: https://stackoverflow.com/a/76178626
The updated version of
Original Answer: https://stackoverflow.com/a/74786719
Here is this code:
1function fancyDropdown(inputId) {
2 const input = document.getElementById(inputId);
3 const target = document.getElementById('target_' + inputId);
4 const datalist = input.nextElementSibling;
5 let minWidth = datalist.offsetWidth;
6
7 function outputsize() {
8 if (input.offsetWidth < minWidth) {
9 datalist.style.minWidth = input.offsetWidth + 'px';
10 } else {
11 datalist.style.width = input.offsetWidth + 'px';
12 }
13 }
14
15 new ResizeObserver(outputsize).observe(input);
16
17 input.addEventListener("input", function(e) {
18 datalist.style.display = "block";
19 const text = input.value.toUpperCase();
20 let hide = 1;
21 for (let option of datalist.options) {
22 if (option.value.toUpperCase().indexOf(text) > -1) {
23 option.style.display = "block";
24 hide = 0;
25 } else {
26 option.style.display = "none";
27 }
28 }
29 if (hide) {
30 datalist.style.display = "none";
31 }
32 });
33
34 input.addEventListener("click", function(e) {
35 let hide = 1;
36 for (let option of datalist.options) {
37 if (window.getComputedStyle(option, null).display == "block") hide = 0;
38 }
39
40 if (datalist.style.display == "block" || hide == 1) {
41 datalist.style.display = "none";
42 } else {
43 datalist.style.display = "block";
44 }
45 });
46
47 document.addEventListener("click", function(e) {
48 if (e.target.tagName == "OPTION") {
49 let inputValue = e.target.value.split('#');
50 input.value = inputValue[1];
51 target.value = inputValue[0];
52 }
53 if (e.target.tagName !== "DATALIST" && e.target.tagName !== "INPUT") {
54 datalist.style.display = "none";
55 }
56 });
57
58 datalist.style.display = "none";
59}