views:

74

answers:

3

I'm currently making a web-based chat system but I've run into a problem. I have set up a function in javascript to check if the user presses enter in the textarea and send the message if this has happened. The problem is every time that function is used the textarea is left with a single carriage return in it as if the value of the textarea was "\n" when it should be just "". Here's the code:

function checkEnter(e) {
 var charCode;
 if (e && e.which) {
  charCode = e.which;
 } else {
  charCode = e.keyCode;
 }
 if (charCode == 13) {
  say();
  document.getElementById('chatfieldbox').value = "";
  return false;
 } else {
  return true;
 }
}
function say() {
 updateStats();
 text = document.getElementById('chatfieldbox').value;
 xhr=new XMLHttpRequest();
 xhr.open("POST", "say", false);
 xhr.setRequestHeader("Content-type", "application/x-www-form-urlencoded");
 xhr.setRequestHeader("Content-length", text.length);
 xhr.setRequestHeader("Connection", "close");
 xhr.send("text=" + text);
 document.getElementById('chatfieldbox').value = "";
 update();
}
function updateStats() {
 var text = document.getElementById('chatfieldbox').value;
 var num = text.length;
 var lines = 1;
 for (var i = 0; i < num; i++) {
  if (text.charAt(i) == '\n') {
   lines++;
  }
 }
 document.getElementById('characters').innerHTML = num;
 document.getElementById('lines').innerHTML = lines;
}

say(); does some ajax stuff to send the message. updateStats(); is just a character and line counter for the user's benefit. say(); sends the message to the server then calls to update to see if there are messages from anyone else to display (irrelevant). The HTML:

<textarea id="chatfieldbox" onKeyPress="checkEnter(event)"></textarea>

Any suggestions?

+4  A: 

In your code the position of return false; makes sure that document.getElementById('chatfieldbox').value = ""; never gets called. Switch the positions of the two lines and it should work.

Marek Karbarz
Ok i fixed that and the problem persists. That was a duplicate of the same line at the end of say(); anyway.
puddingfox
is your `<textarea>` and `</textarea>` all on a single line (like you have it pasted here) or are they on their separate lines?
Marek Karbarz
They are on the same line.
puddingfox
+2  A: 

why don't you just clear out the textbox before you send the ajax request.

edit: also cancel event bubbling.

function say() {
    text = document.getElementById('chatfieldbox').value;
    document.getElementById('chatfieldbox').value = "";
    xhr=new XMLHttpRequest();
    xhr.open("POST", "say", false);
    xhr.setRequestHeader("Content-type", "application/x-www-form-urlencoded");
    xhr.setRequestHeader("Content-length", text.length);
    xhr.setRequestHeader("Connection", "close");
    xhr.send("text=" + text);
    update();
}

function checkEnter(e) {
    var charCode;
    if (e && e.which) {
        charCode = e.which;
    } else {
        charCode = e.keyCode;
    }
    if (charCode == 13) {
        say();
        if (e.stopPropagation) {
            e.stopPropagation();
        } else {
            window.event.cancelBubble=true;
        }
        return false;
    } else {
        return true;
    }
}
ithcy
This does simplify the code but didn't fix the problem.
puddingfox
I see what the problem is. You clear out the TA but the 'enter' keypress event is still sent afterwards. Return false is not enough, you need to add e.stopPropagation() or e.cancelEvent() before you return from checkEnter().
ithcy
I tried that and neither of those functions worked. Actually the Firefox error console told me cancelEvent() wasn't a function.
puddingfox
That's why i changed the code in my answer. It's e.stopPropagation() for firefox and window.event.cancelBubble=true for IE. cancelEvent was a typo but I can't edit my comment.
ithcy
+1  A: 

A couple of things I guess would help:

Use the keyDown event(if not already):

textarea.onkeyDown = checkEnter;

In checkEnter you should pass the textarea reference to the say function:

if (charCode == 13) {
    elm = e.target || e.srcElement;
    say(elm);
    return false;
} else {
    return true;
}

And in the say function, clear the value when you get a positive response from the server.

function say(elm){
    var txt = elm.value;
    //make the ajax call and when done, call the 2nd param function
    call('say', function(resp){
        if(resp.ok){
            elm.value = '';
            doSomethingWith(txt);
        }else{
            //show error
        }
    });
}
Mic
I ended up fixing it myself by using a setTimeout("clearTextarea()", 10); to wait 10 milliseconds after enter is pressed to clear the textarea. But I guess your answer would achieve the same thing so I marked as answer.
puddingfox
You shouldn't use setTimeout in this way. First hoping that 10 ms will be enough for all your audience everytime, who knows what can happen, and then you shouldn't use string in setTimeout, but a closure setTimeout(function(){...your code...}, msecs). Thanks for the flag.
Mic