DataTables 'Copy to Clipboard' (HTML5) button not working with jQuery UI Dialog widget

3.9k Views Asked by At

I'm using:

  • jQuery v1.11.3
  • jQuery UI for Dialog widget, v1.11.4
  • Via CDN, v1.10.9 and v1.0.3, respectively, of DataTables and the DataTables Button extension.

On the page, I have a jQuery UI Dialog widget, which is launched manually by the user. Inside the Dialog is where the DataTables Table and Buttons are placed. The user clicks the 'Copy' button, which creates modal/modal-like window that tells the user to press Ctrl-C to copy the table to the clipboard.

DataTables has two versions of the 'Copy' button, one for Flash, and the other for HTML5. Flash works fine, but is designed primarily as a fallback for legacy browsers. HTML5 is the one that is the problem here.

Reading through their code which executes the HTML5 button..what it essentially does is creates a textarea element, copies the table data into the textarea, and then it focuses on the textarea and selects it such that the user can copy via Ctrl-C.

The problem is the textarea does not get focused and cannot even be forced to get focused, due to some conflict with the Dialog widget. Without using the Dialog widget, the 'Copy to Clipboard' feature works fine.

In Google Chrome, document.activeElement is on the body. In IE11, document.activeElement is on the 'Copy' button. I've tried a number of things to force it to focus on textarea but nothing works including $(document.activeElement).blur() and then $("textarea")[0].focus().

Here is the code:

<link rel="stylesheet" type="text/css" href="https://cdn.datatables.net/1.10.9/css/jquery.dataTables.css"/>
<link rel="stylesheet" type="text/css" href="https://cdn.datatables.net/buttons/1.0.3/css/buttons.dataTables.css"/>

<script type="text/javascript" src="https://cdn.datatables.net/1.10.9/js/jquery.dataTables.js"></script>
<script type="text/javascript" src="https://cdn.datatables.net/buttons/1.0.3/js/dataTables.buttons.js"></script>
<script type="text/javascript" src="https://cdn.datatables.net/buttons/1.0.3/js/buttons.flash.js"></script>
<script type="text/javascript" src="https://cdn.datatables.net/buttons/1.0.3/js/buttons.html5.js"></script> 

<script type="text/javascript">
    $(document).ready(function() {
        $("#launchdialog").on("click", function( event ) {
            var dialog = $("#dialogModal")
                .dialog(
                {
                    height: $(window).height()*.40,
                    width: $(window).width()*.30,
                    modal: true,
                    autoOpen: true,
                    title: "test",
                    close: function(ev, ui) {
                        $(this).dialog( "destroy" ).empty();
                    }
                }
            )

            // Display table as DataTable
            var $table = $('#exampleDataTables').DataTable( {
                buttons: [
                    {
                        extend: "copyHtml5",
                        title: "copy"
                    }
                ]

            });

            // Place Buttons in existing Div tag
            $table.buttons().container()
                .appendTo( "#button-div-dialog" );          
        });
    });
</script>

<style>
    // Display 'Copy to Clipboard' modal above document and Dialog
    // z-index is to set to 21 by DataTables code and, therefore, is behind div overlay and Dialog widget 
    div.dt-button-info {
        z-index: 1000;
    }

    // Reveal 'Copy to Clipboard' textarea content for troubleshooting
    div.dt-button-info span div {
        height: 200px !important;
        width: 200px !important;
        overflow: scroll !important;
    }

    // Reveal 'Copy to Clipboard' textarea content for troubleshooting
    textarea {
        height: 200px;
        width: 200px;
    }
</style>

For troubleshooting purposes, I observed in Google Chrome if I open the Dialog, then delete the div overlay (which is created with the Dialog widget so the user can't click anywhere behind the Dialog), with the Developer toolbar, and then click the 'Copy' button, the textarea content is selected. In IE11, I was unable to reproduce this same effect with the same steps.

The only thing that worked, and it's kind-of a crude solution, is the following:

// User clicks on the 'Copy' button. Any event here always fires before
// the DataTables code does its thing. Thus, I use setInterval as a trick
// to have the code I want to execute fire after the DataTables code
// execution is done.
$("#dialogModal").on("click", "div span.ui-button-text", function( event ) {    
    var intervalID = setInterval(function() {
        if ( $("textarea").length !== 0) {
            // Since textarea exists, that means DataTables code has finished executing.

            // Hide Dialog trick (for IE) (Google Chrome works fine)
            $("div.ui-dialog").hide();

            // Since focus is no longer being hijacked by Dialog
            // due to some unknown conflict, I can now finally set focus to
            // the textarea element.
            $("textarea")[0].focus();

            // Display Dialog once more and select textarea contents
            $("div.ui-dialog").show();
            $("textarea")[0].select();      
            clearInterval(intervalID);
        } 
    }, 10); 
});

I don't know of any way to have an event fire after the DataTables event code is done executing, without modifying the DataTables code itself. So, I use setInterval to check if textarea exists. When it does, that means the DataTables event code has finished. I can select it now with Google Chrome. For IE11, focus is being hijacked by the Dialog widget. The only way around it that I could figure out was briefly hide the Dialog widget, focus on the textarea, and then show the Dialog widget once more.

For IE11, I can't force it to focus on textarea. I tried so many things, so many ways to unset and set focus to the textarea, in Developer Toolbar and nothing worked. The only thing that did work was hiding the Dialog widget.

For all I know, this Dialog/DataTables conflict may be in other IE versions. I only tested Chrome and IE11, thus far. I am strongly persuaded to believe this is a bug with the Dialog widget and/or IE.

Other than the workaround I'm using above, is there anything else that can get around this Dialog/DataTables conflict?

Thank you very much.

1

There are 1 best solutions below

5
Triforcey On

I have created a pure JavaScript easy to use alternative to copy to the clipboard with a command as simple as clip(text); (github.com/Triforcey/clip-j).

Here is the source code:

function clip(text) {
    var copyElement = document.createElement('input');
    copyElement.setAttribute('type', 'text');
    copyElement.setAttribute('value', text);
    copyElement = document.body.appendChild(copyElement);
    copyElement.select();
    document.execCommand('copy');
    copyElement.remove();
}