Jump to content

Search Suggestions Menu with keyboard navigation


Fmdpa
 Share

Recommended Posts

see post #7 for the filesSome of you may recall when I was creating a search suggestions menu. It was quite basic, and now I'm extending its functionality. Mainly, I'm trying to allow the keyboard to control which <li> element is selected. So far, I've detected two problems:1. The hover event is not properly binding to the individual list elements in the for loop. When there should be a class applied to the element on hover, nothing happens. No errors, either. 2. When the "up" or "down" keyboard arrows are hit, the "active_li" class is only applied to the element as long as the event is active. i.e, if I use the keypress event, the classname is only applied to the element as long as the key is pressed. Why isn't the className sticking to the element until it is removed?Any other tips or notices would be appreciated.

$('#search_box').blur(function() {   $('ul#search_suggestions').fadeOut(300);});searchSuggestionsNav = function() {	currentIndex = 0;	input = $('#search_box');	input.suggestionsList = $('ul#search_suggestions');		input.active = 'active_li';	$('#search_box').keyup(function() {	   var query_val = $('#search_box').val();	   input.items = document.getElementById('search_suggestions').getElementsByTagName('li');	   $.post(			'/autocomplete.php', {				'query_val' : query_val			},			function(text) {				var search_suggestions = $('ul#search_suggestions');				if (!text) {					search_suggestions.fadeOut("normal");				}				else {				search_suggestions.html(text);				search_suggestions.fadeIn(500);				search_suggestions.click(function() {						txt = $(this).children('li').html();						$('input#search_box').val(txt);						$('#search_form').submit();					});				}			});			for ( j = 0; j < input.items.length; j++ ) {			 //problem #1...				$(input.items[j]).hover(function() {					currentIndex = j + 1;					$(input.items[j]).addClass(input.active);				}, function() {					$(input.items[j]).removeClass(input.active);				});			}		});		$('#search_box').keypress(function(e) {									   //problem #2...			switch(getEventCode(e)) {				case 13 : //prevent form submission through the enter button					$('#search_box').val($(input.items[currentIndex-1]).html());					$('#search_suggestions').fadeOut();					return false;					break;				case 38 :					go("up");					break;				case 40 :					go("down");					break;				case 27 :					$('ul#search_suggestions').fadeOut(300);					break;				default :					//go("nowhere")					break;			}	});	go = function(where) {		last = currentIndex;		currentIndex += (where == "down") ? 1 : -1;		if (currentIndex < 1) currentIndex = input.items.length;		if (currentIndex > input.items.length) currentIndex = 1;		selectItem(currentIndex, last);	}	selectItem = function(index, lastIndex) {		for ( i =1; i <= input.items.length; i++ ) {			if (i == index) {				thisElem = input.items[i-1];				$(thisElem).addClass(input.active);			}			if (i == lastIndex) {				thisElem = input.items[i-1];				$(thisElem).removeClass(input.active);			}		}	}	submitForm = function() {		value = input.items[currentIndex-1].html();		$('input#search_box').val(value);		//$('#search_form').submit();	}	reset = function() {		currentIndex = 0;	}}

Edited by Fmdpa
Link to comment
Share on other sites

when is this function running? after the document has loaded? Are you getting anything returned when this line runs?

input.items = document.getElementById('search_suggestions').getElementsByTagName('li');

Link to comment
Share on other sites

Thanks for showing me that. I'm not sure why I did that. Maybe it is because I originally was using pure Javascript.

selectItem = function(index, previousIndex) {		$(input.items[index-1]).addClass(input.active);		$(input.items[previousIndex-1]).removeClass(input.active);	}

However, it still does the same thing. The correct items are being selected (and the selection loops around the list if you hold on arrow down). I just can't figure out why the className is only applied to the element as long as the event is active.

Edited by Fmdpa
Link to comment
Share on other sites

It might be part of the magic of jQuery, I don't see anywhere where you're explicitly telling it to remove the class on key up. The only place you're telling it to remove the class is on key down, so I would add some debugging statements there to see if that function gets called again when you release the key.

Link to comment
Share on other sites

I think it was occurring when I was using pure JS (when I began the script).Here's a working example for you to try. Of course the real example has much more to the backend, but this should contain the relevant stuff. the html file (make sure to load jQuery)

<!DOCTYPE HTML><html>  <head>	<title></title>	<meta http-equiv="Content-Type" content="text/html; charset=UTF-8">	<style type="text/css">		.active_li { font-weight:bold; }	</style>  </head>  <body>	<form action="/search.php" action="get" id="search_form">		<input type="text" id="search_box" accesskey="4" name="query" autocomplete="off" />		<button type="submit" id="searchFormSubmit">Go!</button>		<ul id="search_suggestions"></ul>	</form>	<script src="/scripts/jquery.js"></script>	<script>		$('#search_box').blur(function() {		   $('ul#search_suggestions').fadeOut(300);		});		searchSuggestionsNav = function() {			currentIndex = 0;			input = $('#search_box');			input.suggestionsList = $('ul#search_suggestions');			input.active = 'active_li';			$('#search_box').keyup(function() {			   var query_val = $('#search_box').val();			   input.items = document.getElementById('search_suggestions').getElementsByTagName('li');			   $.post(					'/test_menu.php', {						'query_val' : query_val					},					function(text) {						var search_suggestions = $('ul#search_suggestions');						if (!text) {							search_suggestions.fadeOut("normal");						}						else {						search_suggestions.html(text);						search_suggestions.fadeIn(500);						search_suggestions.click(function() {								txt = $(this).children('li').html();								$('input#search_box').val(txt);								$('#search_form').submit();							});						}					});					for ( j = 0; j < input.items.length; j++ ) {						$(input.items[j]).hover(function() {							currentIndex = j + 1;							$(input.items[j]).addClass(input.active);						}, function() {							$(input.items[j]).removeClass(input.active);						});					}				});				$('#search_box').keypress(function(e) {					switch(getEventCode(e)) {						case 13 : //prevent form submission through the enter button							if ($('ul#search_suggestions').children('li').length <= 1) {								return true;							} else {								$('#search_box').val($(input.items[currentIndex-1]).html());								$('#search_suggestions').fadeOut();								return false;							}							break;						case 38 :							go("up");							break;						case 40 :							go("down");							break;						case 27 :							$('ul#search_suggestions').fadeOut(300);							break;						default :							//go("nowhere")							break;					}			});			go = function(where) {				previous = currentIndex;				currentIndex += (where == "down") ? 1 : -1;				if (currentIndex < 1) currentIndex = input.items.length;				if (currentIndex > input.items.length) currentIndex = 1;				selectItem(currentIndex, previous);			}			selectItem = function(index, previousIndex) {				$(input.items[index-1]).addClass(input.active);				$(input.items[previousIndex -1]).removeClass(input.active);			}			submitForm = function() {				value = input.items[currentIndex-1].html();				$('input#search_box').val(value);			}			reset = function() {				currentIndex = 0;			}		}		$(document).ready(searchSuggestionsNav);		getEventCode = function(evt) {		   code = null;		   if (!evt) evt = window.event;		   code = evt.keyCode;		   return code;		}	</script>  </body></html>

test_menu.php

<?php$suggestions = array('suggestion1', 'suggestion2', 'suggestion3');foreach ($suggestions as $val) {	echo '<li>' . $val . '</li>';}

Link to comment
Share on other sites

Create an account or sign in to comment

You need to be a member in order to leave a comment

Create an account

Sign up for a new account in our community. It's easy!

Register a new account

Sign in

Already have an account? Sign in here.

Sign In Now
 Share

×
×
  • Create New...