pdfdatatables-1.10

DataTables image (or at least image title) export to PDF


Using DataTables and Buttons (NOT TableTools, which is retired) extension. Some cells have progressbars and small icons. Is there a way to export these images (or at least their titles) to PDF? Found some possible hacks on this page, but all of them were for retired TableTools.

Checked https://datatables.net/reference/button/pdf and https://datatables.net/reference/api/buttons.exportData%28%29 but couldn't find any method to achieve this goal. Tested by adding this code:

stripHtml: false

but whole HTML code (like img src=...) was included in PDF file instead of images.

If exporting images isn't possible, is there a way to export at least alt or title attribute of each image? That would be enough.


Solution

  • I assume you are using pdfHtml5. dataTables is using pdfmake in order to export pdf files. When pdfmake is used from within a browser it needs images to be defined as base64 encoded dataurls.

    Example : You have rendered a <img src="myglyph.png"> in the first column of some of the rows - those glyphs should be included in the PDF. First create an Image reference to the glyph :

    var myGlyph = new Image();
    myGlyph.src = 'myglyph.png';
    

    In your customize function you must now

    1) build a dictionary with all images that should be included in the PDF
    2) replace text nodes with image nodes to reference images

    buttons : [
        { 
        extend : 'pdfHtml5',
        customize: function(doc) {
    
            //ensure doc.images exists
            doc.images = doc.images || {};
    
            //build dictionary
            doc.images['myGlyph'] = getBase64Image(myGlyph);
            //..add more images[xyz]=anotherDataUrl here
    
            //when the content is <img src="myglyph.png">
            //remove the text node and insert an image node
            for (var i=1;i<doc.content[1].table.body.length;i++) {
                if (doc.content[1].table.body[i][0].text == '<img src="myglyph.png">') {
                    delete doc.content[1].table.body[i][0].text;
                    doc.content[1].table.body[i][0].image = 'myGlyph';
                }
            }
        },
        exportOptions : {
            stripHtml: false
        }
    }
    

    Here is a an example of a getBase64Image function

    function getBase64Image(img) {
        var canvas = document.createElement("canvas");
        canvas.width = img.width;
        canvas.height = img.height;
        var ctx = canvas.getContext("2d");
        ctx.drawImage(img, 0, 0);
        return canvas.toDataURL("image/png");
    }
    

    If you just want to show the title of images in the PDF - or in any other way want to manipulate the text content of the PDF - then it is a little bit easier. The content of each column in each row can be formatted through the exportOptions.format.body callback :

    buttons : [
        { 
        extend : 'pdfHtml5',
        exportOptions : {
            stripHtml: false
            format: {
                body: function(data, col, row) {
                    var isImg = ~data.toLowerCase().indexOf('img') ? $(data).is('img') : false;
                    if (isImg) {
                        return $(data).attr('title');
                    }
                    return data;
                }
            }
        }
    ]
    

    The reason format.body cannot be used along with images is that is only let us pass data back to the text node part of the PDF document.

    See also