Fmdpa Posted December 31, 2010 Share Posted December 31, 2010 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; }} Link to comment Share on other sites More sharing options...
thescientist Posted December 31, 2010 Share Posted December 31, 2010 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 More sharing options...
Fmdpa Posted December 31, 2010 Author Share Posted December 31, 2010 Oops, forgot to include the part that triggers the function. Yes, it runs when the document is loaded. The line you questioned returns an [Object nodeList]. Link to comment Share on other sites More sharing options...
justsomeguy Posted January 3, 2011 Share Posted January 3, 2011 Why are you looping over all elements in selectItem? Why not just access input.items[index] and input.items[lastIndex] directly? You may want to print those values to make sure that it's getting called with the correct arguments. Link to comment Share on other sites More sharing options...
Fmdpa Posted January 5, 2011 Author Share Posted January 5, 2011 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. Link to comment Share on other sites More sharing options...
justsomeguy Posted January 6, 2011 Share Posted January 6, 2011 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 More sharing options...
Fmdpa Posted January 7, 2011 Author Share Posted January 7, 2011 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 More sharing options...
Fmdpa Posted January 10, 2011 Author Share Posted January 10, 2011 Did anyone try it yet to see the errors I'm encountering? Link to comment Share on other sites More sharing options...
Recommended Posts
Archived
This topic is now archived and is closed to further replies.