Live html/js code https://jsfiddle.net/larrycai/9e8rg76f/2/ (data is sample, not real)
I have lots of 3pps for scanned container images, see column 3pp lists
, normally it could have 100+ 3pps.
In order to have better UX, I want
...
) in end inside the cellI tried to use render()
function, bit it seems if I filtered, then Datatable search can't cover all original 3pp list
var table = $('#dataTable').DataTable({ "data": jsonData, "columns": [{ "data": "name" }, { "data": "image", "render": function(data, type, row, meta) { return "" + data + ""; } }, { "data": "3pp", "render": function(data, type, row, meta) { /* 1. if nothing in search (initial), show first SHOW_NUM keywords + ... 2. if value in search, show matched 3pps, if it is bigger than 20, show first 20 keywords + ... */ return data.slice(0, SHOW_NUM) + " ..." }
I've never understood why render
replaces the data. Instead, use callback after the row has been rendered to amend the rendered cell using the data attribute. I've used rowCallback and jQuery data cell click callback, which passes the referenced row and data to a small prettify3pp
function that quote renders
unquote the cell with updated content.
Add a little few bootstrap badges and voila.
var jsonData = [{
"name": "ubuntu",
"image": "ubuntu:focal",
"3pp": ['acl:2.3.1-1', 'adduser:3.118ubuntu5', 'apt:2.4.8', 'attr:2.5.1-1build1', 'audit:3.0.7-1build1', 'base-files:12ubuntu4.2', 'base-passwd:3.5.52build1', 'bash:5.1-6ubuntu1', 'berkeleydb:5.3.28+dfsg1-0.8ubuntu3', 'bzip2:1.0.8-5build1', 'cdebconf:0.261ubuntu1', 'coreutils:8.32-4.1ubuntu1', 'dash:0.5.11+git20210903+057cd650a4ed-3build1', 'debconf:1.5.79ubuntu1', 'debianutils:5.5-1ubuntu2', 'diffutils:3.8-0ubuntu2', 'dpkg:1.21.1ubuntu2.1', 'e2fsprogs:1.46.5-2ubuntu1.1', 'findutils:4.8.0-1ubuntu3', 'gcc-12:12.1.0-2ubuntu1~22.04', 'glibc:2.35-0ubuntu3.1', 'gmp:6.2.1+dfsg-3ubuntu1', 'gnupg:2.2.27-3ubuntu2.1', 'gnutls:3.7.3-4ubuntu1.1', 'grep:3.7-1build1', 'gzip:1.10-4ubuntu4.1', 'hostname:3.23ubuntu2', 'iconv:2.35', 'init-system-helpers:1.62', 'kerberos:', 'keyutils:1.6.1-2ubuntu3', 'krb5:1.19.2-2', 'libcap:', 'libcap:2.44-1build3', 'libcap-ng:0.7.9-2.2build3', 'libffi:3.4.2-4', 'libgcrypt:1.9.4-3ubuntu3', 'libgpg-error:1.43-3', 'libidn2:2.3.2-2build1', 'libnsl:', 'libnsl:1.3.0-2build2', 'libseccomp:2.5.3-2ubuntu2', 'libsemanage:3.3-1build2', 'libsepol:3.3-1build1', 'libtasn1:4.18.0-4build1', 'libtasn1-6:4.18.0-4build1', 'libtirpc:1.3.2-2ubuntu0.1', 'libunistring:1.0-1', 'libxcrypt:4.4.27-1', 'linux-pam:1.4.0-11ubuntu2', 'lsb:11.1.0ubuntu4', 'lz4:1.9.3-2build2', 'mawk:1.3.4.20200120-3', 'ncurses:6.3-2', 'nettle:3.7.3-1build2', 'openssl:3.0.2-0ubuntu1.6', 'p11-kit:0.24.0-6build1', 'pcre:8.39-13ubuntu0.22.04.1', 'pcre2:10.39-3ubuntu0.1', 'perl:5.34.0-3ubuntu1.1', 'procps:3.3.17-6ubuntu2', 'readline:', 'sed:4.8-1ubuntu2', 'selinux:3.3-1build2', 'sensible-utils:0.0.17', 'shadow:4.8.1-2ubuntu2', 'systemd:249.11-0ubuntu3.6', 'sysvinit:3.01-1ubuntu1', 'tar:1.34+dfsg-1build3', 'tdb:1.46.5', 'ubuntu-keyring:2021.03.26', 'usrmerge:25ubuntu2', 'util-linux:2.37.2-4ubuntu3', 'xxhash:0.8.1-1', 'xz:5.2.5-2ubuntu1', 'zlib:1.2.11.dfsg-2ubuntu9.2', 'zstd:1.4.8+dfsg-3build1'],
"report": "report-581-20221104-154434.pdf"
}, {
"name": "toolkit",
"image": "ubuntu-tookit:jammy",
"3pp": ['jfrog-jfrog-cli:', 'jfrog-jfrog-cli-core:v2.20.3', 'jfrog-jfrog-client-go:v1.21.0', 'jq:1.6-3.3.1', 'json-c:0.13-3.3.1', 'jszwec-csvutil:v1.7.1', 'jwalterweatherman:v1.1.0', 'kerberos:', 'kerberos:1.19', 'kevinburke-ssh_config:v0.0.0-20201106050909-4977a11b4351', 'keyutils:1.6.3-5.6.1', 'klauspost-compress:v1.13.5', 'kmod:29-4.15.1', 'less:530-3.3.2', 'libassuan:2.5.1-2.14', 'libatomic1:', 'libcap:', 'libcap:2.26-4.6.1', 'libcap-ng:0.7.9-4.37', 'libdevmapper:1.03.01', 'libedit:3.1.snap20150325-2.12', 'libfdisk:2.36.2', 'libffi:3.2.1.git259-10.8', 'libgcrypt:1.8.2-8.42.1', 'libgpg-error:1.29-1.8', 'libidn2:2.2.0-3.6.1', 'libksba:1.3.5-2.14', 'libmnl:1.0.4-1.25', 'libmpc3:1.1.0-1.47', 'libnsl:', 'libnsl:1.2.0-2.44', 'libproxy:0.4.15-12.41', 'libqrencode:4.0.0-1.17', 'libsanitizer:', 'libseccomp:', 'libsemanage:3.0-1.27', 'libsepol:3.0-1.31', 'libsolv:0.7.22', 'libssh:0.8.7-10.12.1', 'libtasn1:4.13-4.5.1', 'libtirpc:1.2.6-150300.3.3.1', 'libunistring:0.9.10-1.1', 'libusb:1.0.21-3.3.1', 'libxml2:2.9.7', 'linux-pam:', 'lua:5.3.6-3.6.1', 'lz4:1.9.2-3.3.1', 'make:4.2.1-7.3.2', 'manifoldco-promptui:v0.9.0', 'mergo:v0.3.12', 'minio-sha256-simd:v1.0.1-0.20210617151322-99e45fae3395', 'mitchellh-mapstructure:v1.5.0', 'mpfr:4.0.2-3.3.1', 'ncurses:6.1-5.9.1', 'nghttp2:1.40.0-6.1', 'npth:1.5-2.11', 'olekukonko-ts:v0.0.0-20171002115256-78ecb04241c0', 'oniguruma:6.7.0-1.19', 'openldap:', 'openslp:2.0.0-6.15.1', 'openssl:1.1.1d', 'owenrumney-go-sarif:v2.1.2', 'p11-kit:0.23.2-4.13.1', 'packaging:16.8', 'packaging:19.2', 'packaging:20.1', 'patch:2.7.6-3.5', 'pcre:8.45-20.10.1', 'pcre2:10.31-3.3.1', 'pep517:0.7.0', 'perl:5.26.1-150300.17.3.1', 'pgzip:v1.2.5', 'pierrec-lz4:v4.1.2', 'pinentry:1.1.0-4.3.1', 'pip:20.0.2', 'pkg-browser:v0.0.0-20210911075715-681adbf594b8', 'pkg-config:0.29.2-1.436', 'pkg-term:v1.1.0', 'popt:1.16-3.22', 'procps:3.3.15-7.22.1', 'properties:v1.8.6', 'protobuf:3.9.2-4.12.1', 'python:3.6.15-150300.10.21.1', 'rardecode:v1.1.0', 'readline:7.0', 'requests:2.22.0', 'rfkill:', 'rivo-uniseg:v0.2.0', 'rpm:4.14.3-150300.46.1', 'rsync:3.1.3-4.10.1', 'rubyist-tracerx:v0.0.0-20170927163412-787959303086', 'safestring:', 'sed:4.4-11.6', 'selinux:3.0-1.31', 'sergi-go-diff:v1.1.0', 'setuptools:44.1.1', 'shadow:', 'spew:v1.1.1', 'spf13-pflag:v1.0.3', 'spf13-pflag:v1.0.5', 'sqlite3:3.36.0-3.12.1', 'ssgelm-cookiejarparser:v1.0.1', 'sysfsutils:2.1.0-3.3.1', 'systemd:246.16-150300.7.45.1', 'tar:1.34-150000.3.12.1', 'testify:v1.5.1', 'testify:v1.8.0', 'ulikunitz-xz:v0.5.9', 'urfave-cli:v1.22.9', 'urllib3:1.25.7', 'util-linux:', 'util-linux:2.36.2', 'vbauerster-mpb:v7.4.2', 'vim:8.0.1568-5.17.1', 'viper:v1.12.0', 'visual_studio_runtime:', 'webencodings:0.5.1', 'wget:1.20.3-3.12.1', 'x-crypto:v0.0.0-20190426145343-a29dc8fdc734', 'x-crypto:v0.0.0-20220622213112-05595931fe9d', 'x-mod:v0.5.1', 'x-net:v0.0.0-20200301022130-244492dfa37a', 'x-net:v0.0.0-20220520000938-2e3eb7b945c2', 'x-sync:v0.0.0-20190911185100-cd5d95a43a6e', 'x-sys:v0.0.0-20200302150141-5c8b2ff67527', 'x-sys:v0.0.0-20220520151302-bc2c85ada10a', 'x-term:v0.0.0-20220526004731-065cf7ba2467', 'x-text:v0.3.0', 'x-text:v0.3.7', 'x-xerrors:v0.0.0-20220517211312-f3a8303e98df', 'xanzy-ssh-agent:v0.3.1', 'xi2-xz:v0.0.0-20171230120015-48954b6210f8', 'xo-terminfo:v0.0.0-20210125001918-ca9a967f8778', 'xxhash:', 'xz:5.2.3-150000.4.7.1', 'zlib:1.2.11-150000.3.30.1', 'zlib:1.2.3', 'zlib:1.2.5', 'zlib:1.2.8', 'zstd:1.4.4-1.6.1'],
"report": "report-584-20221104-154434.pdf"
}];
var SHOW_NUM = 20
$(document).ready(function() {
const prettify3pp = (row, data, searchTerm, showAll) => {
let deps
if (searchTerm === '') {
deps = data['3pp'].map(dep => `<span class="badge bg-secondary">${dep}</span>`)
} else {
deps = data['3pp'].filter(dep => dep.toLowerCase().includes(searchTerm)).map(dep => `<span class="badge bg-primary">${dep}</span>`)
}
if (deps.length > SHOW_NUM && !showAll) {
const totalLength = deps.length
deps = deps.slice(0, SHOW_NUM)
deps.push(`<span class="badge bg-info show-all">Showing ${deps.length} of ${totalLength} - Show all</span>`)
}
row.querySelector('td.shorten').innerHTML = deps.join('<span hidden>,</span> ')
}
const table = $('#dataTable').DataTable({
"data": jsonData,
"columns": [{
"data": "name"
},
{
"data": "image",
"render": function(data, type, row, meta) {
return "<a href='https://hub.docker.com/_/" + data + "'>" + data + "</a>";
}
},
{
"data": "3pp",
className: 'shorten',
},
{
"data": "report",
"render": function(data, type, row, meta) {
return "<a href='" + data + "'>" + data + "</a>"
}
}
],
"rowCallback": function(row, data) {
const searchTerm = this.api().search().toLowerCase()
//console.log('rowCallback', row, data, searchTerm)
prettify3pp(row, data, searchTerm)
}
})
$('#dataTable tbody').on('click', 'td.shorten .show-all', function() {
const row = $(this).closest('tr')[0]
const data = table.row(row).data()
const searchTerm = table.search().toLowerCase()
//console.log('clicked row', row, data, searchTerm)
prettify3pp(row, data, searchTerm, true)
});
});
.show-all {
cursor: pointer;
}
<script src="https://code.jquery.com/jquery-3.5.1.js"></script>
<script src="https://cdn.datatables.net/1.12.1/js/jquery.dataTables.min.js"></script>
<link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/twitter-bootstrap/5.2.0/css/bootstrap.min.css">
<link rel="stylesheet" href="https://cdn.datatables.net/1.12.1/css/dataTables.bootstrap5.min.css">
<div class="container-fluid">
<h2>Filter the 3pps: </h2>
<table id="dataTable" class="datatables-table table table-striped table-hover table-bordered" style="width:100%">
<thead>
<tr>
<th>Group</th>
<th>container image</th>
<th>3pp lists</th>
<th>PDF</th>
</tr>
</thead>
<tbody>
</tbody>
</table>
</div>