• Das Erstellen neuer Accounts wurde ausgesetzt. Bei berechtigtem Interesse bitte Kontaktaufnahme über die üblichen Wege. Beste Grüße der Admin

[FRAGE] Input-Dropdown Script optimieren

du-doch-nicht

New member
Guten Abend,

vorweg erläutere ich euch, was das Script machen soll.

Ich möchte ein Formular erstellen in dem mehrere Eingabefelder sind. Beim anklicken eines Eingabefeldes soll unterhalb eine DropDown-Liste mit alternativen Eingabemöglichkeiten erscheinen die der Benutzer anklicken kann und im Eingabefeld übernommen wird (DropDown schließt sich beim anklicken einer Auswahlmöglichkeit). Der Benutzer hat aber auch die Freiheit etwas anderes ins Eingabefeld zu schreiben. Beim verlassen des Eingabefeldes schließt die DropDown-Liste.

Vorab für die, die gleich an "datalist" denken... Nein, diese Lösung kann ich nicht verwenden, da etwas entscheidendes nicht funktioniert. Wenn eine Eingabe im Feld exisitiert und ich mich doch für eine andere Eingabe aus der alternativen DropDown-Liste entscheide, erscheint keine DropDown-Liste um alle Auswahlmöglichkeiten zu sehen. Erst nachdem ich die Eingabe aus dem Feld lösche erscheint die DropDown-Liste und kann etwas auswählen.

Es ist eine provisorische Lösung und bedarf einer Optimierung, da ich mich mit Javascript noch nicht zu 100% auskenne.

Ich hoffe Ihr versteht was ich meine.


Hier mein Quellcode:

HTML:
<!doctype html>
<html>
<head>
<meta charset="utf-8">
<title>Unbenanntes Dokument</title>
<style>
input[type=text] { position: relative; z-index: 2; }
.datalist { border: 1px solid #CCC; width: 200px; box-shadow: 0 0 5px #DDD; position: relative; z-index: 1; margin-top: -17px; }
</style>
</head>
<body>

<p>
	<strong>Bearbeiter :</strong><br />
	<input type="text" id="ipt2" name="bearbeiter" value="" onClick="OpenList('2');return false" onBlur="CloseList('2');return false" />
</p>

<ul id="dl2" style="display:none" class="datalist">
    <li><a href="#" onClick="InputVal('2','Max Mustermann');return false">Max Mustermann</a></li>
    <li><a href="#" onClick="InputVal('2','Axel Springer');return false">Axel Springer</a></li>
    <li><a href="#" onClick="InputVal('2','John Doe');return false">John Doe</a></li>
</ul>

<script>

function OpenList(_id_) { return document.getElementById("dl"+_id_).style.display="block"; }

function GetClose(_id_) { return document.getElementById("dl"+_id_).style.display="none"; }

function CloseList(_id_) { setTimeout('GetClose('+_id_+')', 200); }

function InputVal(_id_,_val_) { document.getElementById("ipt"+_id_).value=_val_; CloseList(_id_); }

</script>

</body>
</html>
 
Deinen zweiten Absatz mit der datalist hab ich nicht ganz verstanden.

Es gibt ein HTML5 Tag namens "datalist" das man mit einem Inputfeld verknüpfen kann. Funktioniert genauso wie dein JQuery Autocomplete, nur eben für mich nicht nutzbar wie ich es mir vorstelle.
Hast du mal mein Quellcode ausprobiert und gesehen was ich meine?

Meine DropDown-Liste soll nicht nach dem "Autocomplete-Prinzip" funktionieren. Die Liste soll immer bereit stehen wenn ich das Inputfeld anklicke.

Im Prinzip einfach mein Quellcode kopieren und mir sagen was man an meinem Javascriptcode verbessern kann, da es irgendwie eine Notlösung darstellt.
Das "setTimeout" stört mich und müsste irgendwie durch ein EventHandler ersetzt werden, nur wie?
 
Ich benutze "onClick" damit sich die Liste beim anklicken des Inputfeldes öffnet.
Beim verlassen des Inputfeldes nutze ich "onBlur", damit die Liste geschlossen wird.

- Soweit auch alles ok, jetzt kommt das knifflige an der Sache. -

Das "setTimeout" soll die onBlur-Aktion verzögern, da meine Liste ausserhalb des Inputfeldes liegt und ich sonst keine Auswahl anklicken kann, weil die Liste sofort verschwindet da ich ja das Inputfeld verlasse. Das setTimeout gibt mir eine gewisse Zeit dennoch eine Auswahl anzuklicken und diese im Inputfeld übernommen wird, bevor die Liste geschlossen wird.
 
- Soweit auch alles ok, jetzt kommt das knifflige an der Sache. -
Und was ist jetzt deine Frage?
Nein, ich habe deinen Code nicht ausprobiert. Sieht auch ein wenig aus wie Kraut und Rüben.
Es heißt onclick und onblur.
<a href="#"> ist nicht dein Ernst!? Du kannst den Eventhandler auch direkt an das <li/>-Element binden.
 
Und was ist jetzt deine Frage? Nein, ich habe deinen Code nicht ausprobiert. Sieht auch ein wenig aus wie Kraut und Rüben.

Wie im ersten Beitrag schon beschrieben, sollte der Javascriptcode optimiert werden und es nur eine Notlösung darstellt, da meine Kenntnisse nicht ausreichen.
Anstatt mir nochmal zu sagen das es wie "Kraut und Rüben" ausschaut und ich es schon erwähnt hatte das es eine Notlösung ist, wäre ich für eine konstruktive Lösung im Detail sehr dankbar ;-)

Deswegen habe ich auch mein Quellcode gepostet, damit jeder weiß und ausprobieren kann was das Script bewirken soll.

Wie setz ich den Eventhandler im Detail ein?
 
Anstatt mir nochmal zu sagen das es wie "Kraut und Rüben" ausschaut und ich es schon erwähnt hatte das es eine Notlösung ist, wäre ich für eine konstruktive Lösung im Detail sehr dankbar ;-)
Auch die Formatierung hatte ich damit gemeint.
Wie setz ich den Eventhandler im Detail ein?
Ungefähr so:
Code:
<!DOCTYPE html>
<html>
<head>
<title>Unbenanntes Dokument</title>
<meta charset="utf-8">
<style>
	input[type=text] {
		position: relative; z-index: 2;
	}

	ul.datalist {
		border: 1px solid #CCC;
		width: 200px;
		box-shadow: 0 0 5px #DDD;
		position: relative;
		z-index: 1;
		margin-top: -17px;
		padding: 0;
		display: none;
	}
	ul.datalist li {
		display: block;
		margin: 0;
		list-style-type: none;
	}
	ul.datalist li:hover {
		background-color: silver;
		cursor: pointer;
	}
</style>
<script>
	function openList(id) {
		document.getElementById("dl" + id).style.display = "block";
	}

	function closeList(id) {
		setTimeout(function () {
			document.getElementById("dl" + id).style.display = "none";
		}, 200);
	}

	function inputVal(id, val) {
		document.getElementById("ipt" + id).value = val;
	}
</script>
</head>

<body>
	<p>
		<strong>Bearbeiter:</strong>
		<br />
		<input type="text" id="ipt2" name="bearbeiter" value="" onclick="openList('2');" onblur="closeList('2');" />
	</p>

	<ul id="dl2" class="datalist">
		<li onclick="inputVal('2', 'Max Mustermann');">Max Mustermann</li>
		<li onclick="inputVal('2', 'Axel Springer');">Axel Springer</li>
		<li onclick="inputVal('2', 'John Doe');">John Doe</li>
	</ul>
</body>
</html>
 
Gibt es für "setTimeOut" eine alternative?
Ich habe gemerkt, wenn man langsam den Link in de Liste klickt, wird die Auswahl nicht ins Textfeld übernommen.
Langsam in dem Fall, wenn man die Auswahl mit der Maus anklickt, aber in den 200ms die Maustaste nicht loslässt, wird die Auswahl nicht aktiviert.
 
Das window.setTimeout() ist komplett überflüssig, wenn man die richtigen Events verwendet:
Code:
<!DOCTYPE html>
<html>
<head>
<title>Unbenanntes Dokument</title>
<meta charset="utf-8">
<style>
	input[type=text] {
		position: relative; z-index: 2;
	}

	ul.datalist {
		border: 1px solid #CCC;
		width: 200px;
		box-shadow: 0 0 5px #DDD;
		position: relative;
		z-index: 1;
		margin-top: -17px;
		padding: 0;
		display: none;
	}
	ul.datalist li {
		display: block;
		margin: 0;
		list-style-type: none;
	}
	ul.datalist li:hover {
		background-color: silver;
		cursor: pointer;
	}
</style>
<script>
	function openList(id) {
		document.getElementById("dl" + id).style.display = "block";
	}

	function closeList(id) {
		document.getElementById("dl" + id).style.display = "none";
	}

	function inputVal(id, val) {
		document.getElementById("ipt" + id).value = val;
	}
</script>
</head>

<body>
	<p>
		<strong>Bearbeiter:</strong>
		<br />
		<input type="text" id="ipt2" name="bearbeiter" value="" onfocus="openList('2');" onblur="closeList('2');" />
	</p>

	<ul id="dl2" class="datalist" onmousedown="return false">
		<li onmouseup="inputVal('2', 'Max Mustermann');">Max Mustermann</li>
		<li onmouseup="inputVal('2', 'Axel Springer');">Axel Springer</li>
		<li onmouseup="inputVal('2', 'John Doe');">John Doe</li>
	</ul>
</body>
</html>
- aber eigentlich sind inline-Eventlistener nicht wirklich schön:
Code:
<!DOCTYPE html>

<html>
<head>
<meta http-equiv="content-type" content="text/html; charset=UTF-8">
<title>Fenstertitel</title>
<link rel="stylesheet" type="text/css" href="/kkjs/modules/css/autocomplete.css">
<style type="text/css"></style>
</head>
<body>
test
<input id="input">
<script type="text/javascript" src="//kkjs.kkapsner.de/modules/kkjs.load.js?modules=NodeRepresenatator,autocomplete"></script>
<script type="text/javascript">
kkjs.autocomplete.set(kkjs.$("input"), ["hallo", "test", "jdlskdj", "was", "auch", "immer"], {openOnFocus: true, closeOnMark: false});
</script>
</body>
</html>
 
Zuletzt bearbeitet:
Klar kann man andere Events verwenden und ebenso sind inline-Eventlistener nicht schön. Bei deinem Beispiel wird aber das Dropdown nach einer Auswahl nicht geschlossen bzw. bei erneutem Klick in das input-Feld nicht wieder geöffnet. Daher noch mal mein Beispiel abgeändert:
Code:
<!DOCTYPE html>
<html>
<head>
<title>Unbenanntes Dokument</title>
<meta charset="utf-8">
<style>
	input[type=text] {
		position: relative; z-index: 2;
	}

	ul.datalist {
		border: 1px solid #CCC;
		width: 200px;
		box-shadow: 0 0 5px #DDD;
		position: relative;
		z-index: 1;
		margin-top: -17px;
		padding: 0;
		display: none;
	}
	ul.datalist li {
		display: block;
		margin: 0;
		list-style-type: none;
	}
	ul.datalist li:hover {
		background-color: silver;
		cursor: pointer;
	}
</style>
<script>
	function addEvent(obj, type, fn) {
		'use strict';
		if (obj.addEventListener) {
			obj.addEventListener(type, fn, false);
		} else if (obj.attachEvent) {
			obj["e" + type + fn] = fn;
			obj[type + fn] = function () {
				obj["e" + type + fn](window.event);
			};
			obj.attachEvent('on' + type, obj[type + fn]);
		}
	}

	function inputSelect(input, select) {
		'use strict';
		var i,
			liste,
			listeLength;

		function registerListItem(index) {
			addEvent(liste[index], 'mousedown', function () {
				input.value = this.dataset.value;
			});
		}

		liste = select.getElementsByTagName('li');
		listeLength = liste.length;
		if (listeLength > 0) {
			for (i = 0; i < listeLength; i += 1) {
				registerListItem(i);
			}

			addEvent(input, 'click', function () {
				select.style.display = 'block';
			});

			addEvent(input, 'blur', function () {
				select.style.display = 'none';
			});
		}
	}

	function init() {
		'use strict';
		inputSelect(document.getElementById('ipt2'), document.getElementById('dl2'));
	}

	window.onload = init;
</script>
</head>

<body>
	<p>
		<strong>Bearbeiter:</strong>
		<br />
		<input type="text" id="ipt2" name="bearbeiter" value="" />
	</p>

	<ul id="dl2" class="datalist">
		<li data-value="Max Mustermann">Max Mustermann</li>
		<li data-value="Axel Springer">Axel Springer</li>
		<li data-value="John Doe">John Doe</li>
	</ul>
</body>
</html>
 
Zuletzt bearbeitet:
du registrierst die events in inputSelect n-fach
Code:
<html>
  <head>
    <title></title>
    <style>
      input[type=text] {
        position: relative; z-index: 2;
      }
    
      ul.datalist {
        border: 1px solid #CCC;
        width: 200px;
        box-shadow: 0 0 5px #DDD;
        position: relative;
        z-index: 1;
        margin-top: -17px;
        padding: 0;
        display: none;
      }
      ul.datalist li {
        display: block;
        margin: 0;
        list-style-type: none;
      }
      ul.datalist li:hover {
        background-color: silver;
        cursor: pointer;
      }
    </style>
    <script src="jquery.js"></script>
    <script>
      $(document).ready(function()
      {
        $('#ipt2').on('focus', function()
        {
          $('#dl2').show();
        }).on('blur', function()
        {
          $('#dl2').hide();
        });
        $('#dl2 li').on('mousedown', function()
        {
          $('#ipt2').val(this.dataset.value);
        });
      });
    </script>
  </head>
  <body>
    <p>
      <strong>Bearbeiter:</strong>
      <br />
      <input type="text" id="ipt2" name="bearbeiter" value="" />
    </p>
    <ul id="dl2" class="datalist">
      <li data-value="Max Mustermann">Max Mustermann</li>
      <li data-value="Axel Springer">Axel Springer</li>
      <li data-value="John Doe">John Doe</li>
    </ul>
  </body>
</html>
 
@hesst: an deiner Lösung gefällt mir nicht, dass man sich nicht mit gedrückter Maustaste umentscheiden kann und dass nach dem Auwählen das <input> keinen Fokus mehr hat.
 
Ich muss mich erstmeinmal bedanken :)

den EventHandler "onmouseup" hatte ich auch gefunden und eingesetzt. Hat sehr gut funktioniert.
Aber wie Ihr schon sagt, das Inline-EventHandler sehr unübersichtlich mit der Zeit werden.
Die Lösung von "miniA4kuser" ist echt super, hätte ich so nie hinbekommen. Erfüllt genau das was ich auch schon versucht habe umzusetzen, was wirklich nur als Notlösung diente.


@ miniA4kuser
Wenn ich mehrere Textfelder mit einer Liste ausstatten möchte, dann muss ich nur in der Funktion "init" erweitern, sprich die Dokumenten-ID hinschreiben?

HTML:
function init() {
	'use strict';
	inputSelect(document.getElementById('ipt2'), document.getElementById('dl2'));
	inputSelect(document.getElementById('ipt3'), document.getElementById('dl3'));
	inputSelect(document.getElementById('ipt4'), document.getElementById('dl4'));
}



Danke an alle.
 
Zurück
Oben