Search code examples
javascriptjqueryfunctionkeykeypress

JQuery function not firing on enter keypress


I have the following jQuery/js controlling a trello style input field. So when you click on the span element, it switches to an input field. Then after you finish editing the element and take focus away from it(blur), it switches back to the span element with the new text. I also having it submitting to an ajax script to submit the new text to my database.

Now this all works flawlessly and I have no problems with what is described above. The problem came when I tried to make the "switch back to the span element" work on "enter" key press.

I have tested the code with an alert so I know the enter key is being detected but I can not get the "editableTextBlurred" function to fire from within the keypress function. Which means that it will not switch back to the span element on enter press.

function divClicked(div) {
    div = "#"+div;
    var divHtml = $(div).text();
    var editableText = $('<input type="text" id="firstname" name="firstname" placeholder="First Name" onChange="profileUpdate(this)">');
    editableText.val(divHtml);
    $(div).replaceWith(editableText);
    editableText.focus();
    console.log(editableText);
    // setup the blur event for this new textarea
    editableText.blur(editableTextBlurred);

    $(":input").keypress(function(event) {
        if (event.which == '13') {
            event.preventDefault();
            editableTextBlurred();
        }
    });
}

function editableTextBlurred() {
    var html = $(this).val();
    var viewableText = $("<span id='firtname_text' onClick='divClicked(this.id)'></span>");
    viewableText.html(html);
    $(this).replaceWith(viewableText);
}

<span id='firtname_text' onClick='divClicked(this.id)'>
    ".ucfirst($fname)."
</span>

Any insight on what I missing or doing wrong will be greatly appreciated, Thanks!


Solution

  • I suspect it's successfully calling editableTextBlurred, but then that function isn't working. And the reason it's not working is that it expects this to refer to the input element, but the way you're calling it, this will be the global object (in loose mode) or undefined (in strict mode).

    To make the this in editableTextBlurred the same as the this in the keypress handler, use .call:

    editableTextBlurred.call(this);
    

    Alternately, just pass the element as an argument:

    editableTextBlurred(this);
    

    ...and then

    function editableTextBlurred(input) { var html = $(input).val(); var viewableText = $(""); viewableText.html(html); $(input).replaceWith(viewableText); }


    Separately, there's a problem with that onClick code, it will end up with this.id (the actual text) in the onClick attribute. You probably wanted:

    var viewableText = $("<span id='firtname_text' onClick='divClicked(\"'" + input.id + "'\")'></span>");
    

    ...though I wouldn't use onClick for this at all; use jQuery.


    Rather than adding/removing event handlers, this is the kind of situation that cries out for event delegation:

    // Delegated handler for converting to inputs
    $("#container").on("click", ".click-to-edit", function(e) {
      var $div = $(this),
          $input = $("<input type=text>");
      $div.toggleClass("click-to-edit editing");
      $input.val($div.text());
      $div.empty().append($input);
      setTimeout(function() { // Some browsers want this delay
        $input.focus();
      }, 50);
    });
    
    // Delegated handler for converting back
    $("#container").on("keypress", ".editing input", function(event) {
      var $input = $(this), $div;
      if (event.which == 13) {
        event.preventDefault();
        $div = $input.closest(".editing");
        $div.toggleClass("click-to-edit editing");
        $div.empty().text($input.val());
      }
    });
    <div id="container">
      <div class="click-to-edit">Testing 1 2 3</div>
      <div class="click-to-edit">Testing 4 5 6</div>
      <div class="click-to-edit">Testing 7 8 9</div>
    </div>
    <script src="https://ajax.googleapis.com/ajax/libs/jquery/1.11.1/jquery.min.js"></script>