shutat Posted November 13, 2008 Share Posted November 13, 2008 I have four select boxes that I'm switching using the arrow keys (key down event). I'd like to be able to select an item, then cancel and move onto another select, but whenever I try it, the onchange event is triggered in the select that I blurred. I have a common handler for all four selects during the onchange event. The onfocus handler was an attempt to set the selectedIndex property to 0, but it didn't matter whether I tried it within that function or inside of the keyboard handler... neither seemed to help. <select id="c_cmd" size="1" onfocus="setIdx(this.id);" onchange="doCmd(this.id);">...</select> ... <select id="c_itm" size="1" onfocus="setIdx(this.id);" onchange="doCmd(this.id);">...</select> switch(evt.keyCode) { case 37: switch(activeSel) { case 1: docu...("c_cmd").selectedIndex = 0; docu...("c_itm").focus(); activeSel = 4; break; ... case 4: docu...("c_itm").selectedIndex = 0; docu...("c_cmd").focus(); activeSel = 1; break; } break; case 39: ... } I tried the above and thought it was working, but if I had selected an item in the list and then decided to choose another select box, the onchange for the prior select box fires. Is there a way to ensure that the select boxes that aren't desired won't fire the onchange event? onblur doesn't seem to work either. TIA Quote Link to comment Share on other sites More sharing options...
Psycho Posted November 15, 2008 Share Posted November 15, 2008 I've read your post a few times now and am still perplexed by what you arereally doing - I suspect there is probably a better way to accomplish what you are doing by changing the functionality in your "working" functions. Posting the code for a working page would be helpful to see the problem first hand. I tried building a test page to replicate what I think your problem is, but I couldn't create the problem. I have an onchange event for the select lists and I also have an onkeydown event. The onkeydown event changes the value of the select field and then changes focus to the other select list. When that happens the onchange event does not fire - it only fires when the user changes the value, not when the functins hnage the value. Here is the test page which includes code that I could have used to suppress the onchange event if it was fired from changing the vlaue in code (commented out) <html> <head> <script type="text/javascript"> // var runOnChange = true; function s_onchange() { // if (runOnChange) // { alert('Run on change code'); // } // else // { // runOnChange = true; // } } function s_onkeydown(sObj) { sObj.value = (sObj.selectedIndex==1) ? 'one' : 'two'; sObj.blur(); if (sObj.name=='test1') { document.forms[0].test2.focus(); } else { document.forms[0].test1.focus(); } // runOnChange = false; } </script> </head> <body> <form action=""> <select name="test1" onchange="s_onchange();" onkeydown="s_onkeydown(this);"> <option value='one'>one</option> <option value='two'>two</option> </select> <br> <select name="test2" onchange="s_onchange();" onkeydown="s_onkeydown(this);"> <option>one</option> <option>two</option> </select> </form> </body> </html> Quote Link to comment Share on other sites More sharing options...
shutat Posted November 20, 2008 Author Share Posted November 20, 2008 I've read your post a few times now and am still perplexed by what you arereally doing lol; you aren't the only one - I'm at a loss myself. Thank you for the response. I tried to create a page from what I could remember, but I don't have access to the original code at the moment. I've copied and pasted your code as well and will play around with it once I log off. <html> <head> <style type="text/css"> select { width: 100px } </style> <script language="javascript"> var idx = 1; function processSel(id) { var docs = document.getElementById(id); var r_id = document.getElementById("res"); switch(docs.id) { case "sel_1": switch(docs.options[docs.selectedIndex].value) { case "cmd 1": r_id.innerHTML = "ID: " + docs.id + " VALUE: " + docs.options[docs.selectedIndex].value; break; case "cmd 2": r_id.innerHTML = "ID: " + docs.id + " VALUE: " + docs.options[docs.selectedIndex].value; break; case "cmd 3": r_id.innerHTML = "ID: " + docs.id + " VALUE: " + docs.options[docs.selectedIndex].value; break; } break; case "sel_2": //alert(docs.options[docs.selectedIndex].value); break; case "sel_3": //alert(docs.options[docs.selectedIndex].value); break; case "sel_4": //alert(docs.options[docs.selectedIndex].value); break; } } function keyB(evt) { try { switch(evt.keyCode) { case 37: switch(idx) { case 1: idx = 4; document.getElementById("sel_4").focus(); break; case 2: idx = 1; document.getElementById("sel_1").focus(); break; case 3: idx = 2; document.getElementById("sel_2").focus(); break; case 4: idx = 3; document.getElementById("sel_3").focus(); break; } break; case 39: switch(idx) { case 1: idx = 2; document.getElementById("sel_2").focus(); break; case 2: idx = 3; document.getElementById("sel_3").focus(); break; case 3: idx = 4; document.getElementById("sel_4").focus(); break; case 4: idx = 1; document.getElementById("sel_1").focus(); break; } break; } } catch(e) { alert("oops"); } } </script> </head> <body onkeydown="keyB(event)"> <div id="res">.</div> <form name="f"> <select id="sel_1" size="1" onchange="processSel(this.id);" onblur="this.selectedIndex=0;"> <option value="-- sel1">-- sel1</option> <option value="cmd 1">cmd 1</option> <option value="cmd 2">cmd 2</option> <option value="cmd 3">cmd 3</option> </select> <select id="sel_2" size="1" onchange="processSel(this.id);" onblur="this.selectedIndex=0;"> <option value="-- sel2">-- sel2</option> <option value="cmd 1">cmd 1</option> </select> <select id="sel_3" size="1" onchange="processSel(this.id);" onblur="this.selectedIndex=0;"> <option value="-- sel3">-- sel3</option> </select> <select id="sel_4" size="1" onchange="processSel(this.id);" onblur="this.selectedIndex=0;"> <option value="-- sel4">-- sel4</option> </select> </form> </body> </html> The above is similar to what I was doing, but I changed a few things to try and replicate what the problem was. Select an item, other than index 0 in the first select, and then use the left and right arrow keys alone. IE6, at least, doesn't seem to be affected, but in Firefox 3 and Opera 9.6, if you use the left and right arrow keys, the value above the select *should* change. I want to be able to cycle through any of the four selects, choose an item in any of the selects, yet be able to "cancel" any choice by moving to another select. A "choice" should be made only if the mouse onclick event is triggered or the enter key is pressed, or at least that's what I'm trying to make it do. Any ideas? TIA Quote Link to comment Share on other sites More sharing options...
Psycho Posted November 20, 2008 Share Posted November 20, 2008 OK, I think I am starting to understand. I ran the code above and see the same results in IE7 and FF3. Don't have access to IE at the moment. I see the same results in IE6 and FF3. If I select a value in the first field text is displayed above it. But, when I use left/right arrow keys the field is reset to the 0 index and the text remains. It would really help if you list the steps you would take and the resulting action you want to occur. But, I think I'm starting to understand. Should only 1 select field have a value and no others? I think adding the keydown event to the body and using a global variable to track the current field will run into problems as well. Try this: <html> <head> <style type="text/css"> select { width: 100px } </style> <script language="javascript"> function processSel(fieldObj) { if(fieldObj.selectedIndex==0) { var resultHTML = '.'; } else { var resultHTML = 'ID: ' + fieldObj.id + ' VALUE: ' + fieldObj.options[fieldObj.selectedIndex].value; } divID = 'res' + fieldObj.id.substr(4); document.getElementById(divID).innerHTML = resultHTML; return; } function blurThis(fieldObj) { fieldObj.selectedIndex = 0; processSel(fieldObj); return; } function keyB(evt, fieldObj) { try { if (evt.keyCode==37 || evt.keyCode==39) { var index = parseInt(fieldObj.id.substr(4)); index = (evt.keyCode==37) ? (index-1) : (index+1) ; if (index==0) { index = 4; } if (index==5) { index = 1; } document.getElementById('sel_'+index).focus(); } } catch(e) { alert("oops"); } return; } </script> </head> <body> <div id="res1">.</div> <div id="res2">.</div> <div id="res3">.</div> <div id="res4">.</div> <form name="f" id="f"> <select id="sel_1" size="1" onchange="processSel(this);" onblur="blurThis(this);" onkeydown="keyB(event, this);"> <option value="-- sel1">-- sel1</option> <option value="cmd 1">cmd 1</option> <option value="cmd 2">cmd 2</option> <option value="cmd 3">cmd 3</option> </select> <select id="sel_2" size="1" onchange="processSel(this);" onblur="blurThis(this);" onkeydown="keyB(event, this);"> <option value="-- sel2">-- sel2</option> <option value="cmd 1">cmd 1</option> <option value="cmd 2">cmd 2</option> <option value="cmd 3">cmd 3</option> </select> <select id="sel_3" size="1" onchange="processSel(this);" onblur="blurThis(this);" onkeydown="keyB(event, this);"> <option value="-- sel3">-- sel3</option> <option value="cmd 1">cmd 1</option> <option value="cmd 2">cmd 2</option> <option value="cmd 3">cmd 3</option> </select> <select id="sel_4" size="1" onchange="processSel(this);" onblur="blurThis(this);" onkeydown="keyB(event, this);"> <option value="-- sel4">-- sel4</option> <option value="cmd 1">cmd 1</option> <option value="cmd 2">cmd 2</option> <option value="cmd 3">cmd 3</option> </select> </form> </body> </html> Quote Link to comment Share on other sites More sharing options...
shutat Posted November 22, 2008 Author Share Posted November 22, 2008 It would really help if you list the steps you would take and the resulting action you want to occur. But, I think I'm starting to understand. Should only 1 select field have a value and no others? I think adding the keydown event to the body and using a global variable to track the current field will run into problems as well. I'm working a game actually, where each of the selects will represent commands the player can take. The first select is static, but the others will be filled once conditions are met. The first item in each select is just a moniker of sorts to show what each of the commands are, so element 0 wouldn't ever be acted upon. Thanks a lot for the great tips; I was looking for a way to compact my version of the switch that you did within your version of the keyB function, and your method is nice and clean. I think your select handler is going to help out a lot too. I'm going to go ahead and marked this as solved; I really appreciate your help! Thank you. Quote Link to comment Share on other sites More sharing options...
Recommended Posts
Join the conversation
You can post now and register later. If you have an account, sign in now to post with your account.