1

Following are scenarios I m implementing using JQuery in HTML

  • When a user double click on table cell it should a new input inside the Double Clicked Cell [Done]
  • When a user KeyPress [Tab] and it should move to next Cell [Done]

In Case of 2 Scenario, I need to trigger the dblclick() event on the next Cell which creates the Input Element Inside it, but it is not able to the Focus inside Input Element.

I have tried to debug that scenario not able to understand why it is happening.

I have created a button and written click function which trigger dblclick() , then focus was set inside the Input Element.

I m not able to understand when user click using the mouse / click() then why focus is set on the created input element but why same is not happening when I m triggering double click when from the code using dblclick()

Following are code For the Same:


//Global Variables
var TabEdit_sourceInput = null;
var TabEdit_currentTd = null;
var TabEdit_DOMtocheck = null;
var TabEdit_previousHour = null;
var gridRefreshFlag = false;

//Init Double Click Event on the Table TD
$('.custom-table-td').dblclick(function(event){
    var tableId = $(this).attr('id');
    var inputId = 'input-'+tableId;
    $(this).html('<input id="input-'+tableId+'" placeholder="Type Message" class="form-control" onkeydown="return initCheckKeypress();" tabindex="1"/>');
    
    //Focusing on Generated Event
    $('#'+inputId).focus();

    //Binding the Focus Out Event to
    $('#'+inputId).focusout(function(){
        debugger;
        $('.header').html($(this).val());
     });
     
});

//Click Event to trigger dblclick on td with id = 'tableData1'
$('.btn-trigger-dbclick').click(function(){
    $('#tableData1').dblclick();
});

//Function to check Tab is Press or not
function initCheckKeypress(evt) {
    "use strict";
    var e = event || evt; // for trans-browser compatibility
    var charCode = e.which || e.keyCode;
    if (charCode === 9) {
        gridRefreshFlag = true;
        TabEdit_sourceInput = $(e.target);
        TabEdit_currentTd = TabEdit_sourceInput.parent();
        TabEdit_DOMtocheck = TabEdit_currentTd.next('td');
        movetoNextTD();
    }
}


//Code to Click on Next Cell
function movetoNextTD() {
    if (gridRefreshFlag && TabEdit_DOMtocheck !== null) {
        TabEdit_currentTd.html("");
        TabEdit_DOMtocheck.dblclick();
        resetmovetoNextVariable();
    }
}

//Reset Global Variable
function resetmovetoNextVariable(){
    TabEdit_sourceInput = null;
    TabEdit_currentTd = null;
    TabEdit_DOMtocheck = null;
    TabEdit_previousHour = null;
    gridRefreshFlag = false;
}
<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>Focus Issue</title>
    <link rel="stylesheet" href="https://stackpath.bootstrapcdn.com/bootstrap/4.4.1/css/bootstrap.min.css" >
</head>
<body>
    <div class="container">
        <div class="row">
            <div class="col-lg-6">
                <div class="header"></div>
                <table class="table table-bordered">
                    <tbody>
                        <tr id="tableRow1">
                            <th id="tableHeader1" class="custom-table-th">TH 1</th>
                            <th id="tableHeader2" class="custom-table-th">TH 2</th>
                            <th id="tableHeader3" class="custom-table-th">TH 3</th>
                        </tr>
                        <tr id="tableRow2">
                            <td id="tableData1" class="custom-table-td"></td>
                            <td id="tableData2" class="custom-table-td"></td>
                            <td id="tableData3" class="custom-table-td"></td>
                        </tr>
                    </tbody>
                </table>
                <button class="btn btn-primary btn-trigger-dbclick">Trigger</button>
            </div>
        </div>
    </div>
    <script src="https://code.jquery.com/jquery-3.4.1.slim.min.js"></script>
<script src="https://cdn.jsdelivr.net/npm/popper.js@1.16.0/dist/umd/popper.min.js"></script>
<script src="https://stackpath.bootstrapcdn.com/bootstrap/4.4.1/js/bootstrap.min.js"></script>
</body>
</html>

2 Answers2

0

What's happening is this:

  • double click - generates first input and sets focus, fine
  • user presses tab - the code that checks for tab kicks in before the system event handler and creates the 2nd input and sets focus - the system then continues with the default tab action and tabs off the 2nd input

The fix is to cancel the system default event after creating the 2nd input:

e.preventDefault();

Updated snippet:

//Global Variables
var TabEdit_sourceInput = null;
var TabEdit_currentTd = null;
var TabEdit_DOMtocheck = null;
var TabEdit_previousHour = null;
var gridRefreshFlag = false;

//Init Double Click Event on the Table TD
$('.custom-table-td').dblclick(function(event){
    var tableId = $(this).attr('id');
    var inputId = 'input-'+tableId;
    $(this).html('<input id="input-'+tableId+'" placeholder="Type Message" class="form-control" onkeydown="return initCheckKeypress();" tabindex="1"/>');
    
    //Focusing on Generated Event
    $('#'+inputId).focus();

    //Binding the Focus Out Event to
    $('#'+inputId).focusout(function(){
        debugger;
        $('.header').html($(this).val());
     });
     
});

//Click Event to trigger dblclick on td with id = 'tableData1'
$('.btn-trigger-dbclick').click(function(){
    $('#tableData1').dblclick();
});

//Function to check Tab is Press or not
function initCheckKeypress(evt) {
    "use strict";
    var e = event || evt; // for trans-browser compatibility
    var charCode = e.which || e.keyCode;
    if (charCode === 9) {
        gridRefreshFlag = true;
        TabEdit_sourceInput = $(e.target);
        TabEdit_currentTd = TabEdit_sourceInput.parent();
        TabEdit_DOMtocheck = TabEdit_currentTd.next('td');
        movetoNextTD();
        e.preventDefault();
    }
}


//Code to Click on Next Cell
function movetoNextTD() {
    if (gridRefreshFlag && TabEdit_DOMtocheck !== null) {
        TabEdit_DOMtocheck.dblclick();
        TabEdit_currentTd.html("");
        resetmovetoNextVariable();
    }
}

//Reset Global Variable
function resetmovetoNextVariable(){
    TabEdit_sourceInput = null;
    TabEdit_currentTd = null;
    TabEdit_DOMtocheck = null;
    TabEdit_previousHour = null;
    gridRefreshFlag = false;
}
<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>Focus Issue</title>
    <link rel="stylesheet" href="https://stackpath.bootstrapcdn.com/bootstrap/4.4.1/css/bootstrap.min.css" >
</head>
<body>
    <div class="container">
        <div class="row">
            <div class="col-lg-6">
                <div class="header"></div>
                <table class="table table-bordered">
                    <tbody>
                        <tr id="tableRow1">
                            <th id="tableHeader1" class="custom-table-th">TH 1</th>
                            <th id="tableHeader2" class="custom-table-th">TH 2</th>
                            <th id="tableHeader3" class="custom-table-th">TH 3</th>
                        </tr>
                        <tr id="tableRow2">
                            <td id="tableData1" class="custom-table-td"></td>
                            <td id="tableData2" class="custom-table-td"></td>
                            <td id="tableData3" class="custom-table-td"></td>
                        </tr>
                    </tbody>
                </table>
                <button class="btn btn-primary btn-trigger-dbclick">Trigger</button>
            </div>
        </div>
    </div>
    <script src="https://code.jquery.com/jquery-3.4.1.slim.min.js"></script>
<script src="https://cdn.jsdelivr.net/npm/popper.js@1.16.0/dist/umd/popper.min.js"></script>
<script src="https://stackpath.bootstrapcdn.com/bootstrap/4.4.1/js/bootstrap.min.js"></script>
</body>
</html>
freedomn-m
  • 27,664
  • 8
  • 35
  • 57
  • It's not helped as you've mixed jquery events with html events and your html event is on key *down* but your js method is key *press* (`onkeydown="return initCheckKeypress();"`) - key press event works differently from key down. – freedomn-m Apr 20 '20 at 15:15
  • Using `setTimeout` can be a quick and easy fix, but it's not ideal and better to know why it's not working. – freedomn-m Apr 20 '20 at 15:20
  • Thanks. It helps a lot but it will not let me trigger my function which is written on the focus out event. But For That, I can trigger it manually using $('#'+inputid).focusout(); – Amit Prajapati Apr 20 '20 at 15:55
  • That's a similar issue - it's not that it's not firing the blur - it's that you're removing the 1st input before removing its focus. i.e press tab, delete 1st input, create 2nd input, focus to 2nd input, send blur to current input...oh current input doesn't exist anymore, so no blur event. – freedomn-m Apr 20 '20 at 15:59
  • You can fix this by creating new input+set focus before removing the old input - ie swap these two lines: `TabEdit_DOMtocheck.dblclick(); TabEdit_currentTd.html("");` - I've updated the snippet. – freedomn-m Apr 20 '20 at 16:00
  • focusout vs blur: https://stackoverflow.com/questions/8973532/blur-vs-focusout-any-real-differences (you're really using blur as it's on the input, but the end result is the same) – freedomn-m Apr 20 '20 at 16:03
0

Changing you initCheckKeyPress functions implementation would help. I fixed this by preventing the default behaviour of the triggered event by adding :

e.preventDefault();

This works because the default behaviour of the "tab" key press event is to focus on the next key item. This happens before the input is created (as rightly highlighted by freedomn-m). So preventing that would make this work.

Your final code would look like this:

Before

function initCheckKeypress(evt) {
"use strict";
var e = event || evt; // for trans-browser compatibility
var charCode = e.which || e.keyCode;
if (charCode === 9) {
    gridRefreshFlag = true;
    TabEdit_sourceInput = $(e.target);
    TabEdit_currentTd = TabEdit_sourceInput.parent();
    TabEdit_DOMtocheck = TabEdit_currentTd.next('td');
    movetoNextTD();
}}

After:

function initCheckKeypress(evt) {
"use strict";
var e = event || evt; 
e.preventDefault();// for trans-browser compatibility
var charCode = e.which || e.keyCode;
if (charCode === 9) {
    gridRefreshFlag = true;
    TabEdit_sourceInput = $(e.target);
    TabEdit_currentTd = TabEdit_sourceInput.parent();
    TabEdit_DOMtocheck = TabEdit_currentTd.next('td');
    movetoNextTD();

}}
  • *This happens before the input is created* - apologies, this information was incorrect. There are some other SO questions with similar code (add an input, then focus it) and these do not have this problem. The problem was that the default tab handler was occurring *after* the input had focus (so thus un-focusing it) as OPs code was on key down (not on key up (not sure if this is relevant though)). Sample question with fiddle links: https://stackoverflow.com/questions/12052322/jquery-create-input-field-and-set-focus – freedomn-m Apr 20 '20 at 16:08