javascriptgoogle-chromeeventsonpaste

onpaste / paste event not firing for table on first few attempts


Google Chrome specific - this is an internal-use app that does not require cross-browser compatibility

See http://jsfiddle.net/spetnik/vpcyt4yv/

I have a table into which I am attempting to allow pasting of data. I made the individual cells selectable as such:

<td tabindex="0">

I originally tried adding the onpaste event to the TD elements themselves, but this did not work at all. So instead, I added the event to the table element and just check to make sure that the focused element is a TD and then paste the data to that element:

document.getElementById("tblData").onpaste = function(evt){
    if(document.querySelector(":focus").tagName.toLowerCase() != "td"){
        return;
    }

    document.querySelector(":focus").innerText = evt.clipboardData.getData("text/plain");
};

While this does essentially work, the event usually does not fire on the first attempt. It seems that I need to either a) click around in the table a random number of times (each time is different) or b) change focus to another window and then back again before the event fires. In the jsFiddle I have added a console.log() call to the very beginning of the event so that I can see exactly when the event fires in the debug pane.

See the above jsFiddle or just the result at https://jsfiddle.net/spetnik/vpcyt4yv/embedded/result/


Solution

  • Wow. The culprit seems to be the -webkit-user-select/user-select CSS! I discovered this when I noticed that pasting would be allowed only after initially clicking and dragging the mouse over a cell (which explains the random clicking - only after I clicked until my mouse moved mid-click did it work). I removed this CSS and now it works. Of course, now I need to find a workaround to prevent selecting, but at least I'm no longer stumped.

    Edit: It seems that on a normal element (e.g. a DIV with the onpaste set to the element itself) onpaste does not work at all when -webkit-user-select is set to none. I submitted a bug report here

    EDIT 2: I have managed to find the following workaround: If I programmatically select the contents of the cell before Ctrl-V is pressed, then it will work, even with -webkit-user-select set to none. I accomplished this by adding the following event handler (jQuery shown here) to the TD (this still does not work in a standalone DIV with -webkit-user-select set to none):

    $(elem).click(function(evt){
        var selection = window.getSelection();            
        var range = document.createRange();
        range.selectNodeContents(this);
        selection.removeAllRanges();
        selection.addRange(range);
    })