onkeydown not working properly for form inputs - behavior

I have an html page with a form text input that has a onkeydown attribute, like so:
<DOCTYPE !html>
<html>
<head>
<title>Lookup User</title>
</head>
<body>
<form method="POST">
<strong>Last Name: </strong><input type="text" id="lname" onkeydown="lookup_user(this.value)" />
</form>
<span id="test"></span>
<script type="text/javascript" src="lookup_user.js"></script>
</body>
</html>
The page makes asynchronous requests to a server to searchup the user as the keys are being downed. The javascript file is
function lookup_user (lname) {
var xmlhttp;
if (lname=='') {
document.getElementById('lname').innerHTML = '';
return;
}
if (window.XMLHttpRequest) {
xmlhttp = new XMLHttpRequest();
}
else {
xmlhttp=new ActiveXObject("Microsoft.XMLHTTP");
}
// generally preferred to place onreadystatechange before open so that it detects readyState 0-4 instead of 1-4
xmlhttp.onreadystatechange = function () {
if (xmlhttp.readyState==4 && xmlhttp.status==200) {
document.getElementById("test").innerHTML = xmlhttp.responseText;
}
}
xmlhttp.open('POST', 'lookup_user.php', true);
xmlhttp.setRequestHeader("Content-type","application/x-www-form-urlencoded");
xmlhttp.send('lname='+lname);
}
This works almost fine, except for the fact that it doesn't detect the first keydown.
For example, if in the input form, I type in 'D', it doesn't search up the user. When I type in the second character, it searches up the characters before the second character, not including the second character. If I want to look up "Daisy", and type in "Daisy" into the input box, it searches up "Dais". Only when I down another key does it lookup "Daisy".
Why is this?

The onkeydown event is working properly.
When a key is pressed, the events are fired in the following sequence; keydown, keypress, keyup.
The onkeydown event is fired after the key press but before the character is put into the DOM.
Since the character has not been put into the DOM when the event is fired your form text input will not have that character inside of it.
For example: the onkeydown event can be used to restrict characters from being inputted into your form.
On the other hand: the onkeyup event is fired after the user has released the key and after the DOM has been modified.
Perhaps the onkeyup event is better suited for your application.

Related

How to correctly set the request header in an ajax containing non-alphanumeric characters?

My HTML file contains a form with just a textarea whose contents are sent to a java servlet (called "Compiler"). The textarea text will always be java code, so it might include characters like +, %, =, etc.
I'm using ajax to get and display the response from the servlet.
But using ajax breaks the whole data being sent by the form, because it strips out part of the text or completely ignores the characters I mentioned above.
This is my html file:
<html>
<head>
<script type="text/javascript">
function objetoAjax(){
http_request= false;
if (window.XMLHttpRequest) { // Mozilla, Safari,...
http_request = new XMLHttpRequest();
if (http_request.overrideMimeType) {
http_request.overrideMimeType('text/xml');
}
} else if (window.ActiveXObject) { // IE
try {
http_request = new ActiveXObject("Msxml2.XMLHTTP");
} catch (e) {
try {
http_request = new ActiveXObject("Microsoft.XMLHTTP");
} catch (e) {}
}
}
return http_request;
}
function devolver_resultado(){
var llamadaAjax = objetoAjax();
var codigo = document.getElementById('codigo').value;
llamadaAjax.open("POST",'Compiler',true);
llamadaAjax.onreadystatechange = function() {
if(llamadaAjax.readyState == 4){
document.getElementById("resultado").innerHTML = llamadaAjax.responseText;
}
};
llamadaAjax.setRequestHeader("Content-Type","application/x-www-form-urlencoded");
llamadaAjax.send('codigo='+codigo);
}
</script>
</head>
<body>
<form action="Compiler" method="post">
<textarea rows="18" cols="70" id="codigo" name="codigo"></textarea>
<input type="submit" value="Compile" onclick="devolver_resultado(); return false;">
</form>
<div id="resultado">
</div>
</body>
</html>
I've debugged the javascript to see if the problem was where I assign the textarea value to the "codigo" variable:
var codigo = document.getElementById('codigo').value;
(screenshot)
But this variable is being correctly set, so I suspect the request is being incorrectly encoded (screenshot).
I'm new to ajax, but I assume this is controlled by llamadaAjax.setRequestHeader("Content-Type","application/x-www-form-urlencoded");
From this page I get that I should encode the form as multipart/form-data. I tried adding the encoding type to the form: but this didn't help.
So, two questions here:
1) Is actually this line the faulty one? llamadaAjax.setRequestHeader("Content-Type","application/x-www-form-urlencoded")
If so, how do I fix it?
2) If that's not where the bug is, what else could be happening? (remember that removing all the ajax and leaving a plain form that calls my "Compiler" servlet works as expected, so the servlet is not buggy).
Thanks!
SOLVED.
All I needed was to encode the text before sending it:
llamadaAjax.send('codigo='+encodeURIComponent(codigo));

AJAX update for Spring <form:select> element

I'm using Spring MVC for a project. In it, on a particular page, I'm using the Spring form tags to display an ArrayList added to the model in the controller as below:
<form:select path="myList">
<form:options items="${listElements}"/>
</form:select>
Now, listElements may be edited from another page (a child window), so I want myList to be auto updated every 2 sec or so. As of now I am refreshing the parent window when an element is added; the form in the parent page however has other fields in which the user simply keys in data, so a full refresh resets that data as it has not yet been posted. As such, I want to use AJAX to update just my form:select element every 2 seconds.
How can I do this?
Note: I am an AJAX noob. I went through a few similar posts on SO and elsewhere, but sadly I was not able to figure it out. Any help would be extremely appreciated!
1.Add Id attribute in select element.
2.Add ajax method handler in mvc controller which returns arrayList (I would prefer return json object).
3.Fire ajax call in jquery/javascript
JSP code:
<head>
<link href="<c:url value="/resources/form.css" />" rel="stylesheet" type="text/css" />
<script type="text/javascript" src="<c:url value="/resources/jquery/1.6/jquery.js" />"></script>
<script type="text/javascript">
var interval =2000;
setInterval("getServerData()",interval);
function getServerData(){
$.getJSON("/MyApp/data/jsonList", function(response){
$("#selectBox option").remove();
var options = '';
$.each(response, function(index, item) {
options += '<option value="' + item + '">' + item + '</option>';
$("#selectBox").html(options);
});
});
}
</script>
</head>
<body>
<form:form id="form" method="post">
<select id="selectBox">
<select>
</form:form>
</body>
Controller Code:
#RequestMapping(value="/data/jsonList", method=RequestMethod.GET)
public #ResponseBody List<String> getDataList() {
List<String> myList = new ArrayList<String>();
myList.add("option1");
myList.add("option2");
myList.add("option3");
myList.add("option4");
return myList;
}
if you plan to user jquery check
Updating select box options via jQuery AJAX?
Good read: Spring ajax 3.0 page.
I found what I was looking for! :)
In case someone else finds it useful in the future, what I did is as follows:
Gave an id to my <form:select>:
Created reloadlist.html, a page with only a copy of the relevant <form:select>.
Added the following script:
<script type="text/javascript">
function Ajax(){
var xmlHttp;
try{
xmlHttp=new XMLHttpRequest();// Firefox, Opera 8.0+, Safari
}catch (e){
try{
xmlHttp=new ActiveXObject("Msxml2.XMLHTTP"); // Internet Explorer
}catch (e){
try{
xmlHttp=new ActiveXObject("Microsoft.XMLHTTP");
}catch (e){
alert("No AJAX!?");
return false;
}
}
}
xmlHttp.onreadystatechange=function(){
document.getElementById('ReloadList').innerHTML=xmlHttp.responseText;
setTimeout('Ajax()',10000);
}
xmlHttp.open("GET","reloadlist.html",true);
xmlHttp.send(null);
}
window.onload=function(){
setTimeout('Ajax()',10000);
}
</script>
This probably isn't a very good way to get this done, but it worked. Better answers will be greatly appreciated!

Strange issue with ajax POST

I have this html page with the form
<form method="post" id="form1" name="form1" action="/status_comment/save">
//Some text inputs
<input type="text" name="new_comment" id="new_comment" onkeydown="post_comment(event,'13')" >
</form>
And this is my javascript function to do the POST call
function post_comment(event,item_id)
{
var keyCode = ('which' in event) ? event.which : event.keyCode;
if(parseInt(keyCode)==13 && event.shiftKey!=1)
{
var str = $('#form1').serialize(); // Gets all the filled details
$.post('/status_comment/save',
str,
function(data){
alert(data);
});
}}
Backend is done using Django and this is the return statement
data=simplejson.dumps(data)
return HttpResponse(data, mimetype='application/json')
The referral url is say "/xyz".
The thing is, after the form gets submitted, it is being automatically redirect to the "/status_comment/save" page instead of remaining on the same page.
I tried the get method and it works fine but not the POST method.
I tried debugging it, so changed the url in post call to the referral url, then it refreshs the page instead of doing nothing.
Also the alert() command inside the function above doesnt work, so its probably not being entered into.
Interesting thing I have noticed, when looking at the web developer console, the Initiator for the POST call in this page is being displayed as "Other" while the initiator for GET call and POST call (in other pages, where its working) is "jquery-1.8.0.min.js:2"
Any thoughts? Thanks...
First you really shouldn't try to capture the enter if you can avoid it. Use the submit binding. It makes everything more obvious and easier for your fellow developers (I bet I am not the only one who thought "What the heck is KeyCode 13?").
I'm wondering if perhaps being more explicit might help. Have you tried calling preventDefault and stopImmediatePropagation?
$('#form1').submit(function(evt) {
evt.preventDefault();
evt.stopImmediatePropagation();
// serialize and be AJAXy yada yada yada
If that doesn't work, or for some reason you prefer to handle capturing enter on your own, then you might want to have the above code in addition to your keydown handler. So it would be:
<input type="text" name="new_comment" id="new_comment" onkeydown="post_comment(event,'13')" >
...
$('#form1').submit(function(event) {
event.preventDefault();
event.stopImmediatePropagation();
}
function post_comment(event,item_id)
{
event.preventDefault();
event.stopImmediatePropagation();
var keyCode = ('which' in event) ? event.which : event.keyCode;
if(parseInt(keyCode)==13 && event.shiftKey!=1)
{
var str = $('#form1').serialize(); // Gets all the filled details
$.post('/status_comment/save',
str,
function(data){
alert(data);
});
}
}
Start by getting rid of the onkeydown attribute from the input:
<form method="post" id="form1" name="form1" action="/status_comment/save">
//Some text inputs
<input type="text" name="new_comment" id="new_comment" />
</form>
And then simply subscribe to the .submit() event of this form using jquery and perform the AJAX request in there. Don't forget to return false from it to ensure that the default action is canceled and the browser stays on the same page:
$('#form1').submit(function() {
var str = $(this).serialize(); // Gets all the filled details
$.post(this.action, str, function(data) {
alert(data);
});
return false; // <!-- that's the important part
});

How can I return an id value from a div already populated through ajax

I am having some difficulty passing a correct id function back to AJAX.
I'm creating a product bulletin generator that lets items to be added by their SKU code (which works fine). My problem is that when a bulletin is clicked on, a preview of that bulletin is loaded into a div and shows all products associated with that bulletin.
From inside those results, I am trying to add the ability to delete a product from the bulletin. The problem is that the value being passed back to AJAX belongs to the first product only. It won't send the value belonging to the particular item if it is any other item than the first one.
This is the code (belonging to main.php) that gets loaded via AJAX into a div and is looped with each product associated with a selected bulletin
echo "<form name='myDelForm'>
$news_gen_id<br>
<input type='hidden' id='delccode' value='".$news_gen_id."'>
<input type='hidden' id='deledit' value='".$edit."'>
<input type='button' onclick='ajaxDelCcode()' value='Delete' /><br></form>
</td>";
The AJAX code (on index.php, where the div that calls in main.php is also located) is this
function ajaxDelCcode(){
var ajaxRequest; // The variable that makes Ajax possible!
try{
// Opera 8.0+, Firefox, Safari
ajaxRequest = new XMLHttpRequest();
} catch (e){
// Internet Explorer Browsers
try{
ajaxRequest = new ActiveXObject("Msxml2.XMLHTTP");
} catch (e) {
try{
ajaxRequest = new
ActiveXObject("Microsoft.XMLHTTP");
} catch (e){
// Something went wrong
alert("Your browser broke!");
return false;
}
}
}
// Create a function that will receive data sent from the server
ajaxRequest.onreadystatechange = function(){
if(ajaxRequest.readyState == 4){
var ajaxDisplay = document.getElementById("ajaxMain2");
ajaxDisplay.innerHTML = ajaxRequest.responseText;
}
}
var deledit = document.getElementById("deledit").value;
var delccode = document.getElementById("delccode").value;
var queryString = "?delccode=" + delccode + "&deledit=" + deledit;
ajaxRequest.open("GET", "main.php" + queryString, true);
ajaxRequest.send(null);
}
//-->
</script>
Currently, using those two pieces of code, I can successfully delete only the first product. The delccode variables do not seem to change when the products are looped (although when I echo the variables during the loop, it is definitely changing to the appropriate value...it's just not passing it correctly back to AJAX.)
I tried taking the AJAX code, putting it inside the main.php product loop, and change the function name during each loop (so ajaxDelCcode$news_gen_id() for example) and also to the button itself so that it is calling the AJAX specific to it. And it works if you are visiting main.php directly...but not from index.php after main.php has been called into the div.
I can't figure out how to pass the correct looped value from main.php within the div, back to the AJAX code on index.php
Can anyone help me with this?
Thanks,
Dustin
Instead of storing the id in the input, just pass it as an argument to the function:
function ajaxDelCcode(delccode) { ...
<input type='button' onclick='ajaxDelCcode(\"".$news_gen_id."\")' value='Delete' />
Also, I'd swap the quotes if I were you. Or better yet, instead of using echo, break the PHP code and just write HTML:
<? ... ?><input type="button" onclick="ajaxDelCcode('<?= $news_gen_id ?>')" value="Delete" /><? ... ?>
What does the code you use to delete look like? Is it in the same php file as the form you posted above? If so, is the form getting submitted to itself accidentally? Like perhaps when a user presses enter while on an input type=text control? I understand that you want to do this by ajax but I am suspecting that the form is your problem.
Seconding the jQuery comment.
Here try this
1) add jquery to your document.
<script type="text/javascript" src="//ajax.googleapis.com/ajax/libs/jquery/1.7.1/jquery.min.js"></script>
2) give your inputs name attributes
<input type='hidden' name='delcode' id='delccode' value='".$news_gen_id."'>
<input type='hidden' name='deledit' id='deledit' value='".$edit."'>
3) Use a function something like this instead of all that code above
function ajaxDelCcode() {
$.ajax({
url: "main.php",
type: "GET",
dataType: "text",
data: $("#myDelForm").serialize(),
success: function(rText) {
$("#ajaxMain2").text(rText);
}
});
}

Upload onload don't work on firefox iframe

I am having a problem in Firefox with a file uploading into an iframe. An anchor should call the function dosubf() that posts the form to the iFrame to upload a XML file that will be parsed later with Ajax and displayed in another form on the same page.
The iframe is generated dynamically into a div tag. When it loads the first time, works fine, but, in Firefox, when reloading the content into the div, result on an error 'var ret is null'! caught by the firebug extension. I have also noticed that another error occurs on a xmlhttp.open("POST", var, var.length) call that is made in order to generate one select html object into a table cell. Again the error shows that some var is null but in this case the function that dropping the program is out of the scope! Both functions are working fine in IE9.
For the first issue I think that it could be something related to the onload event. For the second I really don't know what's happening.
Below is the code that load an html form with method Ajax into the div for the initial input of the XML file.
<form id='file_upload_form' method='post'
enctype='multipart/form-data' target='upload_targetf'
action='include/php/util/handle/handlexml.php'>
<input name="file" id="file" type="file" />
IMPORT
<iframe id='upload_target' name='upload_targetf' onload='lerxml()' ></iframe>
</form>
The javascript for the event onclick of the button that submits the form.
function dosubf(){
if (document.getElementById('file').value==''){
alert ("Por favor seleccione um arquivo");
return
}
document.getElementById('file_upload_form').submit();
}
And the function for the event onload that is firing well when it's the first load into the div of the HTML shown before, but fails when I refresh with Ajax that content on the div and try fire the onload. It fails in the second time on the fire empty onload iFrame and of course on button action submit onload.
function lerxml(){
var ret = window.frames['upload_targetf'].document;
//Here the code breaks with a ret is null error on firebug!
var novostring='';
var d=ret.body.innerHTML;
var mess='';
if (d!=''){
d=eval("("+d+")");
//This for getting the JSON response to evaluate the file
if (d.tipo){
mess+=(d.tipo);
}
if (d.tamanho){
mess+=(d.tamanho);
}
var ok='';
if (d.sucesso){
//The filepath of the uploaded file to use Ajax for parse it later
novostring="arquivo/xml/"+d.sucesso;
}else{
novostring="";
alert (mess);
return
}
}
The PHP that evaluate the file upload to the iFrame
<?
$erro = $config = array();
$arquivo = isset($_FILES["file"]) ? $_FILES["file"] : FALSE;
$config["tamanho"] = 500000;
if($arquivo){
if(!preg_match("/^text\/xml$/",$arquivo["type"])) {
$erro['tipo'] = "Não é um arquivo XML! Por favor seleccione outro arquivo";
} else {
if($arquivo["size"] > $config["tamanho"]) {
$erro['tamanho'] = "Arquivo em tamanho muito grande!";
}
}
if(sizeof($erro)) {
foreach($erro as $err) {
$err=htmlentities($err);
}
echo json_encode($erro);
die;
}else {
$imagem_nome = md5(uniqid(time())) . ".xml";
$imagem_dir ['sucesso'] = "arquivo/xml/" . $imagem_nome;
move_uploaded_file($arquivo["tmp_name"],"../../../../".$imagem_dir ['sucesso']);
echo json_encode(htmlentities($imagem_dir));
}
}
?>
Well I hope 'twas clearly enough to reach some help from you.
Thank you in advance for any comments.
I bet you're running into https://bugzilla.mozilla.org/show_bug.cgi?id=170799
Try replacing window.frames['upload_targetf'].document with document.getElementById("upload_target").contentDocument, which won't have the same issue.

Resources