Autocomplete (Werkt in FF, niet in IE)

Status
Niet open voor verdere reacties.

ErikBooy007

Terugkerende gebruiker
Lid geworden
24 mei 2007
Berichten
3.814
Ik heb de volgende code geschreven als onderdeel van een applicatie waar ik aan werk om de 'kaartenbak' van de bibliotheek te digitaliseren.

Daarbij hoort een invoerscherm waar een gebruiker / beheerder boeken kan toevoegen. Een van de opties die hij/zij kan selecteren is de auteurs die eraan hebben meegewerkt.

Daar voor heb ik het volgende bedacht. Ik maak 2 selects naast elkaar. 1 met de alle namen van de auteurs en 1 lege waar de namen van geselecteerde auteurs in komen. Dit werkt allemaal prima. Met 2 knoppen kan ik auteurs heen en weer schuiven tussen de lijsten.

Nu dacht ik dat het handig was om voor het geval de lijst vrij groot wordt een autocomplete functie toe te voegen. En dat heb ik gedaan. Althans voor FF, want het blijkt niet te werken in IE.

Dit is de volledige code:

HTML:
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html>
	<head>
		<title>Combinatie van lists met javascript</title>
		<style type="text/css">
			@import url(lists.css);
		</style>
		<script type="text/javascript">
		
			
			function addValue(elName, waarde, weergave){ // De functie die waarde gaat toevoegen aan één van de selects
				var elOptNew = document.createElement('option'); // creëer een javascript object die de '<option>' vasthoudt
  				elOptNew.text = weergave; // stel in dat de weergegeven tekst de naam van de auteur is
  				elOptNew.value = waarde; // stel in dat de value de ID van de auteur is
					try {
            elName.add(elOptNew, null); // standaard methode (IE doet hier moeilijk)
          }
          catch(ex) {
            elName.add(elOptNew); // aangepaste methode voor IE
          }
			}
			
			function removeValue(elName){ // De functie voor het verwijderen van een waarde uit de select
         var i; // creëer de variabele die we in de FOR-LOOP gaan gebruiken
         for (i = elName.length - 1; i>=0; i--) { // Loop door alle opties van de select
           if (elName.options[i].selected) { // als de waarde geselecteerd is,
             elName.remove(i); // verwijder hem dan
           }
         }
			}
			
			function transferValue(){ // de functie die wordt aangeroepen door de buttons en zelf de andere functies aanroept
        var q, i; // initialiseer de variabele 'q' en 'i'
        var obj2 = document.auteurs.compList.options; // creëer een referentie naar de complete lijst
        for(q = 0; q < obj2.length; q++){ // Loop door alle values in die lijst
        	if(obj2[q].selected == true){ // als ze geselecteerd zijn,
        		addValue(document.auteurs.smallList, obj2[q].value, obj2[q].text); // voeg ze dan toe aan de andere list
        	}
        }
        removeValue(document.auteurs.compList); // verwijder alle geselecteerde waarden uit compList
        var obj = document.auteurs.smallList.options; // creëer een referentie naar smallList
        var selAuteurs = new Array(); // maak een nieuwe (lege) array genaamd 'selAuteurs'
        for(i = 0; i < obj.length; i++){ // loop door de select
        	selAuteurs.push(obj[i].value); // voeg de waarde toe aan de selAuteurs array die we eerst leeg gemaakt hebben
        }
        document.auteurs.auteursSel.value = selAuteurs.join(); // maak van de waarde van het input veld (nu nog text, moet hidden worden) alle values in de array			
				return false; // stuur false terug, anders wordt het formulier verstuurd
			}
			
			function transferValueBack(){ // vrijwel hetzelfde als de functie hierboven maar dan andersom
				var q, i;
        var obj2 = document.auteurs.smallList.options;
        for(q = 0; q < obj2.length; q++){
        	if(obj2[q].selected == true){
        		addValue(document.auteurs.compList, obj2[q].value, obj2[q].text);
        	}
        }
        removeValue(document.auteurs.smallList);
        var obj = document.auteurs.smallList.options;
        var selAuteurs = new Array();
        for(i = 0; i < obj.length; i++){ // loop door de select
        	selAuteurs.push(obj[i].value); // voeg de waarde toe aan de selAuteurs array die we eerst leeg gemaakt hebben
        }
        document.auteurs.auteursSel.value = selAuteurs.join(); // maak van de waarde van het input veld (nu nog text, moet hidden worden) alle values in de array			
				return false;
			}
			
			function autoComplete(){ // Dit is de functie die aangeroepen wordt elke keer dat de cursor in het tekstvak staat en een toets losgelaten wordt.
				var zText = document.auteurs.AC.value.toLowerCase(); // sla de waarde van het tekstvak op in een variabele
				var obj = document.auteurs.compList.options; // creëer weer een referentie naar de select
				var i; // initializeer variabele 'i'
				for(i = 0; i < obj.length; i++){ // loop door alle elementen
					obj[i].style.display = 'none';
				}
				for(i = 0; i < obj.length; i++){
					var El = obj[i].text.toLowerCase(); // sla de waarde van de huidige option op in een variabele
					if(El.indexOf(zText) == 0){ // kijk of meteen aan het begin van die waarde onze ingetypte tekst staat, zo ja:
						obj[i].style.display = 'block';
					}
				}
			}
			
			function addA(){ // dit is de functie die auteurs aan de lijst kan toevoegen
				var autID = document.auteurs.NAID.value; // haal de ID uit het corresponderende veld
				var autName = document.auteurs.NANAME.value; //  haal de naam uit het corresponderende veld
				if(autID != '' && autName != ''){ // als in bij velden een waarde staat,
					var i; // initializeer variabele 'i'
					for(i = 0; i < document.auteurs.compList.options.length; i++){ // loop weer door alle options
						if(document.auteurs.compList.options[i].text == autName){ // als de tekst van de option gelijk is aan de ingetypte waarde,
							alert('Deze auteur komt al in de lijst voor.'); // geen een alert dat er iets mis gaat
							return false; // return false zorgt dat de functie gestopt wordt
						}
						if(document.auteurs.compList.options[i].value == autID){ // als de value van de option gelijk is aan de getype ID,
							alert('Deze ID komt al in de lijst voor.'); // geef een alert dat er iets misgaat
							return false; // stop de functie
						}
					}
						addValue(document.auteurs.compList, autID, autName); // voeg de waarde toe aan de lijst middels de eerder gedefinieerde functie
				} else { // als er niet in beide velden een waarde staat
					alert('De volgende velden moeten worden ingevuld bij het toevoegen van een auteur: \n\n- ID \n- Naam'); // geef een waarschuwing dat niet alle velden zijn ingevuld
					return false; // spreekt ondertussen voor zich
				}
				return false;
			}
		</script>		
	</head>
	<body>
		<form name="auteurs" action="" method="post" autocomplete="off">
			<div id="container">
			<input type="text" name="AC" id="AC" style="width: 225px;" onkeyup="autoComplete()" class="transferI" />

			<div style="float: left">	
				<select multiple size="5" style="width: 102px;" name="compList" class="transferS">
					<option value="12" style="display: block" >Beckman</option>
					<option value="18" style="display: block" >Bernlef</option>
					<option value="34" style="display: block" >Brown</option>
					<option value="39" style="display: block" >o'Neill</option>
					<option value="42" style="display: block" >Schmidt</option>

					<option value="49">Van Loon</option>
				</select>
			</div>
	
		<div style="float: left">
			<button onclick="transferValue(); autoComplete(); return false" class="transferB"> &raquo; </button><br />
			<button onclick="transferValueBack(); autoComplete(); return false" class="transferB"> &laquo; </button>

		</div>

			<div style="float: left">
				<select multiple size="5" style="width: 102px;" name="smallList" class="transferS">
					
				</select>
				

			</div>
			<div style="clear: both"></div>
			<input type="text" name="NAID" style="width: 22px;" value="ID" onfocus="this.value = (this.value == this.defaultValue) ? '' : this.value" class="transferI" /><input type="text" name="NANAME" style="width: 95px;" value="Naam" onfocus="this.value = (this.value == this.defaultValue) ? '' : this.value" class="transferI" /><input type="button" name="" value="Toevoegen" onclick="return addA()" class="transferB transfer" />

		</div>
					<input type="text" name="auteursSel" />

		</form>
	</body>
</html>

Dit is het deel waar het om gaat:

HTML:
function autoComplete(){ // Dit is de functie die aangeroepen wordt elke keer dat de cursor in het tekstvak staat en een toets losgelaten wordt.
				var zText = document.auteurs.AC.value.toLowerCase(); // sla de waarde van het tekstvak op in een variabele
				var obj = document.auteurs.compList.options; // creëer weer een referentie naar de select
				var i; // initializeer variabele 'i'
				for(i = 0; i < obj.length; i++){ // loop door alle elementen
					obj[i].style.display = 'none';
				}
				for(i = 0; i < obj.length; i++){
					var El = obj[i].text.toLowerCase(); // sla de waarde van de huidige option op in een variabele
					if(El.indexOf(zText) == 0){ // kijk of meteen aan het begin van die waarde onze ingetypte tekst staat, zo ja:
						obj[i].style.display = 'block';
					}
				}
			}

Het lijkt erop dat:

HTML:
obj[i].style.display = 'none' / 'block';

Niet werkt in IE. Volgens mij is dit een geldige manier om elementen te verbergen, maar IE denkt daar dus anders over.

De hele 'bende' staat online op http://www.specialwebservice.nl/lists.htm

Overigens gaan de loops en dergelijke wel goed in IE, ook worden de waarden voor display schijbaar wel toegekend, aangezien als ik daarna een alert(obj.style.display) doe, ik netjes de waarde 'none' krijg.
 
Laatst bewerkt:
Ik heb ook nog even gezocht, het blijkt dat dat wanproduct 'display:none' niet ondersteunt voor <option>'s. Ook 'visibility: hidden' werkt niet (ook niet handig voor mijn geval). Overigens geldt dat ook voor Opera, Safari en Chrome. De enige browser die er niet moeilijk over doet is FireFox :love:

Wat ik nu heb gedaan is zorgen dat de eerste optie die aan de zoekterm voldoet geselecteerd wordt.

Thanks anyway!
 
Ik weet niet meer precies waarom, maar toen ik een autocomplete script maakte heb ik ervan afgezien om de standaard <select> te gebruiken om de opties te weergeven. Ik heb in plaats daarvan een LISTBOX class gemaakt met Javascript die werkt op een div met div'jes erin. Volgens mij waren er problemen met de zIndex en layering. Een <select> is een windowed control geloof ik. Hoe dan ook, in IE ging er iets mis met de positionering voor/achter andere elementen.
 
Ja, maar dat gaat in dit geval niet echt werken, ten eerste omdat ik alle functionaliteit van de select gewoon nodig heb en ten tweede omdat ik javascript functies gebruik om opties aan de select toe te voegen, values te achterhalen etc.
 
dat snap ik, maar alle functionaliteit van een select is simpel te kopieren met javascript. Maarja, je moet natuurlijk gewoon doen wat je zelf wilt he:rolleyes:
 
Nog even een laatste update,

HET WERKT!

Uiteindelijk is het dan toch gelukt. Door de select bij elke keypress helemaal leeg te maken en de nieuwe data met ajax op te halen, wil het!

Nu is het ook zo, dat als je een gebruiker toevoegt aan de lijst, deze ook direct in de database verschijnt.

Een werkend voorbeeld staat op:

http://www.specialwebservice.nl/lists/lists.php
 
Status
Niet open voor verdere reacties.

Nieuwste berichten

Terug
Bovenaan Onderaan