HDFS-6407. Add sorting and pagination in the datanode tab of the NN Web UI. Contributed by Haohui Mai.
Project: http://git-wip-us.apache.org/repos/asf/hadoop/repo Commit: http://git-wip-us.apache.org/repos/asf/hadoop/commit/456e901a Tree: http://git-wip-us.apache.org/repos/asf/hadoop/tree/456e901a Diff: http://git-wip-us.apache.org/repos/asf/hadoop/diff/456e901a Branch: refs/heads/HDFS-7285 Commit: 456e901a4c5c639267ee87b8e5f1319f256d20c2 Parents: 2e7b7e2 Author: Haohui Mai <whe...@apache.org> Authored: Mon Aug 17 11:04:00 2015 -0700 Committer: Haohui Mai <whe...@apache.org> Committed: Mon Aug 17 11:04:00 2015 -0700 ---------------------------------------------------------------------- hadoop-hdfs-project/hadoop-hdfs/CHANGES.txt | 3 + hadoop-hdfs-project/hadoop-hdfs/pom.xml | 3 + .../src/main/webapps/hdfs/dfshealth.html | 20 +- .../src/main/webapps/hdfs/dfshealth.js | 17 + .../webapps/static/dataTables.bootstrap.css | 371 +++++++++++++++++++ .../main/webapps/static/dataTables.bootstrap.js | 205 ++++++++++ .../webapps/static/jquery.dataTables.min.js | 160 ++++++++ 7 files changed, 771 insertions(+), 8 deletions(-) ---------------------------------------------------------------------- http://git-wip-us.apache.org/repos/asf/hadoop/blob/456e901a/hadoop-hdfs-project/hadoop-hdfs/CHANGES.txt ---------------------------------------------------------------------- diff --git a/hadoop-hdfs-project/hadoop-hdfs/CHANGES.txt b/hadoop-hdfs-project/hadoop-hdfs/CHANGES.txt index bfd95f7..c12e678 100644 --- a/hadoop-hdfs-project/hadoop-hdfs/CHANGES.txt +++ b/hadoop-hdfs-project/hadoop-hdfs/CHANGES.txt @@ -793,6 +793,9 @@ Release 2.8.0 - UNRELEASED HDFS-8713. Convert DatanodeDescriptor to use SLF4J logging. (wang) + HDFS-6407. Add sorting and pagination in the datanode tab of the NN Web UI. + (wheat9) + OPTIMIZATIONS HDFS-8026. Trace FSOutputSummer#writeChecksumChunks rather than http://git-wip-us.apache.org/repos/asf/hadoop/blob/456e901a/hadoop-hdfs-project/hadoop-hdfs/pom.xml ---------------------------------------------------------------------- diff --git a/hadoop-hdfs-project/hadoop-hdfs/pom.xml b/hadoop-hdfs-project/hadoop-hdfs/pom.xml index 145a8cd..1a29ad3 100644 --- a/hadoop-hdfs-project/hadoop-hdfs/pom.xml +++ b/hadoop-hdfs-project/hadoop-hdfs/pom.xml @@ -390,6 +390,9 @@ http://maven.apache.org/xsd/maven-4.0.0.xsd"> <exclude>src/main/webapps/static/dust-full-2.0.0.min.js</exclude> <exclude>src/main/webapps/static/dust-helpers-1.1.1.min.js</exclude> <exclude>src/main/webapps/static/jquery-1.10.2.min.js</exclude> + <exclude>src/main/webapps/static/jquery.dataTables.min.js</exclude> + <exclude>src/main/webapps/static/dataTables.bootstrap.css</exclude> + <exclude>src/main/webapps/static/dataTables.bootstrap.js</exclude> </excludes> </configuration> </plugin> http://git-wip-us.apache.org/repos/asf/hadoop/blob/456e901a/hadoop-hdfs-project/hadoop-hdfs/src/main/webapps/hdfs/dfshealth.html ---------------------------------------------------------------------- diff --git a/hadoop-hdfs-project/hadoop-hdfs/src/main/webapps/hdfs/dfshealth.html b/hadoop-hdfs-project/hadoop-hdfs/src/main/webapps/hdfs/dfshealth.html index 7e7604a..38808ca 100644 --- a/hadoop-hdfs-project/hadoop-hdfs/src/main/webapps/hdfs/dfshealth.html +++ b/hadoop-hdfs-project/hadoop-hdfs/src/main/webapps/hdfs/dfshealth.html @@ -20,6 +20,7 @@ <head> <meta http-equiv="X-UA-Compatible" content="IE=9" /> <link rel="stylesheet" type="text/css" href="/static/bootstrap-3.0.2/css/bootstrap.min.css" /> +<link rel="stylesheet" type="text/css" href="/static/dataTables.bootstrap.css" /> <link rel="stylesheet" type="text/css" href="/static/hadoop.css" /> <title>Namenode information</title> </head> @@ -290,7 +291,7 @@ </div> <div class="page-header"><h1><small>In operation</small></h1></div> <small> -<table class="table"> +<table class="table" id="table-datanodes"> <thead> <tr> <th>Node</th> @@ -303,7 +304,7 @@ </thead> {#LiveNodes} <tr> - <td class="dfshealth-node-icon dfshealth-node-{state}">{name} ({xferaddr})</td> + <td ng-value="{state}-{name}" class="dfshealth-node-icon dfshealth-node-{state}">{name} ({xferaddr})</td> <td ng-value="{lastContact}">{#helper_relative_time value="{lastContact}"/}</td> <td ng-value="{usedPercentage}"> <div> @@ -315,18 +316,18 @@ </div> </td> <td>{numBlocks}</td> - <td>{blockPoolUsed|fmt_bytes} ({blockPoolUsedPercent|fmt_percentage})</td> + <td ng-value="{blockPoolUsedPercent}">{blockPoolUsed|fmt_bytes} ({blockPoolUsedPercent|fmt_percentage})</td> <td>{version}</td> </tr> {/LiveNodes} {#DeadNodes} <tr class="danger"> - <td class="dfshealth-node-icon dfshealth-node-{state}">{name} ({xferaddr})</td> + <td ng-value="{state}-{name}" class="dfshealth-node-icon dfshealth-node-{state}">{name} ({xferaddr})</td> <td>{#helper_relative_time value="{lastContact}"/}</td> - <td>-</td> - <td>-</td> - <td>-</td> - <td>-</td> + <td></td> + <td></td> + <td></td> + <td></td> </tr> {/DeadNodes} </table> @@ -418,7 +419,10 @@ There are no reported volume failures. </script> <script type="text/javascript" src="/static/jquery-1.10.2.min.js"> +</script><script type="text/javascript" src="/static/jquery.dataTables.min.js"> </script><script type="text/javascript" src="/static/bootstrap-3.0.2/js/bootstrap.min.js"> +</script><script type="text/javascript" src="/static/dataTables.bootstrap.js"> +</script><script type="text/javascript" src="/static/moment.min.js"> </script><script type="text/javascript" src="/static/moment.min.js"> </script><script type="text/javascript" src="/static/dust-full-2.0.0.min.js"> </script><script type="text/javascript" src="/static/dust-helpers-1.1.1.min.js"> http://git-wip-us.apache.org/repos/asf/hadoop/blob/456e901a/hadoop-hdfs-project/hadoop-hdfs/src/main/webapps/hdfs/dfshealth.js ---------------------------------------------------------------------- diff --git a/hadoop-hdfs-project/hadoop-hdfs/src/main/webapps/hdfs/dfshealth.js b/hadoop-hdfs-project/hadoop-hdfs/src/main/webapps/hdfs/dfshealth.js index de93854..03b27fe 100644 --- a/hadoop-hdfs-project/hadoop-hdfs/src/main/webapps/hdfs/dfshealth.js +++ b/hadoop-hdfs-project/hadoop-hdfs/src/main/webapps/hdfs/dfshealth.js @@ -24,6 +24,13 @@ dust.loadSource(dust.compile($('#tmpl-datanode-volume-failures').html(), 'datanode-volume-failures')); dust.loadSource(dust.compile($('#tmpl-snapshot').html(), 'snapshot-info')); + $.fn.dataTable.ext.order['ng-value'] = function (settings, col) + { + return this.api().column(col, {order:'index'} ).nodes().map(function (td, i) { + return $(td).attr('ng-value'); + }); + }; + function load_overview() { var BEANS = [ {"name": "nn", "url": "/jmx?qry=Hadoop:service=NameNode,name=NameNodeInfo"}, @@ -235,6 +242,16 @@ var base = dust.makeBase(HELPERS); dust.render('datanode-info', base.push(data), function(err, out) { $('#tab-datanode').html(out); + $('#table-datanodes').dataTable( { + 'lengthMenu': [ [25, 50, 100, -1], [25, 50, 100, "All"] ], + 'columns': [ + { 'orderDataType': 'ng-value', 'searchable': true }, + { 'orderDataType': 'ng-value', 'type': 'numeric' }, + { 'orderDataType': 'ng-value', 'type': 'numeric' }, + { 'orderData': 3, 'type': 'numeric' }, + { 'orderDataType': 'ng-value', 'type': 'numeric'}, + { 'orderData': 5 } + ]}); $('#ui-tabs a[href="#tab-datanode"]').tab('show'); }); })).error(ajax_error_handler); http://git-wip-us.apache.org/repos/asf/hadoop/blob/456e901a/hadoop-hdfs-project/hadoop-hdfs/src/main/webapps/static/dataTables.bootstrap.css ---------------------------------------------------------------------- diff --git a/hadoop-hdfs-project/hadoop-hdfs/src/main/webapps/static/dataTables.bootstrap.css b/hadoop-hdfs-project/hadoop-hdfs/src/main/webapps/static/dataTables.bootstrap.css new file mode 100644 index 0000000..033c652 --- /dev/null +++ b/hadoop-hdfs-project/hadoop-hdfs/src/main/webapps/static/dataTables.bootstrap.css @@ -0,0 +1,371 @@ +div.dataTables_length label { + font-weight: normal; + text-align: left; + white-space: nowrap; +} + +div.dataTables_length select { + width: 75px; + display: inline-block; +} + +div.dataTables_filter { + text-align: right; +} + +div.dataTables_filter label { + font-weight: normal; + white-space: nowrap; + text-align: left; +} + +div.dataTables_filter input { + margin-left: 0.5em; + display: inline-block; + width: auto; +} + +div.dataTables_info { + padding-top: 8px; + white-space: nowrap; +} + +div.dataTables_paginate { + margin: 0; + white-space: nowrap; + text-align: right; +} + +div.dataTables_paginate ul.pagination { + margin: 2px 0; + white-space: nowrap; +} + +@media screen and (max-width: 767px) { + div.dataTables_wrapper > div.row > div, + div.dataTables_length, + div.dataTables_filter, + div.dataTables_info, + div.dataTables_paginate { + text-align: center; + } + + div.DTTT { + margin-bottom: 0.5em; + } +} + + +table.dataTable td, +table.dataTable th { + -webkit-box-sizing: content-box; + -moz-box-sizing: content-box; + box-sizing: content-box; +} + + +table.dataTable { + clear: both; + margin-top: 6px !important; + margin-bottom: 6px !important; + max-width: none !important; +} + +table.dataTable thead .sorting, +table.dataTable thead .sorting_asc, +table.dataTable thead .sorting_desc, +table.dataTable thead .sorting_asc_disabled, +table.dataTable thead .sorting_desc_disabled { + cursor: pointer; + position: relative; +} + +table.dataTable thead .sorting:after, +table.dataTable thead .sorting_asc:after, +table.dataTable thead .sorting_desc:after { + position: absolute; + top: 8px; + right: 8px; + display: block; + font-family: 'Glyphicons Halflings'; + opacity: 0.5; +} +table.dataTable thead .sorting:after { + opacity: 0.2; + content: "\e150"; /* sort */ +} +table.dataTable thead .sorting_asc:after { + content: "\e155"; /* sort-by-attributes */ +} +table.dataTable thead .sorting_desc:after { + content: "\e156"; /* sort-by-attributes-alt */ +} +div.dataTables_scrollBody table.dataTable thead .sorting:after, +div.dataTables_scrollBody table.dataTable thead .sorting_asc:after, +div.dataTables_scrollBody table.dataTable thead .sorting_desc:after { + display: none; +} + +table.dataTable thead .sorting_asc_disabled:after, +table.dataTable thead .sorting_desc_disabled:after { + color: #eee; +} + +table.dataTable thead > tr > th { + padding-right: 30px; +} + +table.dataTable th:active { + outline: none; +} + + +/* Condensed */ +table.dataTable.table-condensed thead > tr > th { + padding-right: 20px; +} + +table.dataTable.table-condensed thead .sorting:after, +table.dataTable.table-condensed thead .sorting_asc:after, +table.dataTable.table-condensed thead .sorting_desc:after { + top: 6px; + right: 6px; +} + +/* Scrolling */ +div.dataTables_scrollHead table { + margin-bottom: 0 !important; + border-bottom-left-radius: 0; + border-bottom-right-radius: 0; +} + +div.dataTables_scrollHead table thead tr:last-child th:first-child, +div.dataTables_scrollHead table thead tr:last-child td:first-child { + border-bottom-left-radius: 0 !important; + border-bottom-right-radius: 0 !important; +} + +div.dataTables_scrollBody table { + border-top: none; + margin-top: 0 !important; + margin-bottom: 0 !important; +} + +div.dataTables_scrollBody tbody tr:first-child th, +div.dataTables_scrollBody tbody tr:first-child td { + border-top: none; +} + +div.dataTables_scrollFoot table { + margin-top: 0 !important; + border-top: none; +} + +/* Frustratingly the border-collapse:collapse used by Bootstrap makes the column + width calculations when using scrolling impossible to align columns. We have + to use separate + */ +table.table-bordered.dataTable { + border-collapse: separate !important; +} +table.table-bordered thead th, +table.table-bordered thead td { + border-left-width: 0; + border-top-width: 0; +} +table.table-bordered tbody th, +table.table-bordered tbody td { + border-left-width: 0; + border-bottom-width: 0; +} +table.table-bordered tfoot th, +table.table-bordered tfoot td { + border-left-width: 0; + border-bottom-width: 0; +} +table.table-bordered th:last-child, +table.table-bordered td:last-child { + border-right-width: 0; +} +div.dataTables_scrollHead table.table-bordered { + border-bottom-width: 0; +} + + + + +/* + * TableTools styles + */ +.table.dataTable tbody tr.active td, +.table.dataTable tbody tr.active th { + background-color: #08C; + color: white; +} + +.table.dataTable tbody tr.active:hover td, +.table.dataTable tbody tr.active:hover th { + background-color: #0075b0 !important; +} + +.table.dataTable tbody tr.active th > a, +.table.dataTable tbody tr.active td > a { + color: white; +} + +.table-striped.dataTable tbody tr.active:nth-child(odd) td, +.table-striped.dataTable tbody tr.active:nth-child(odd) th { + background-color: #017ebc; +} + +table.DTTT_selectable tbody tr { + cursor: pointer; +} + +div.DTTT .btn:hover { + text-decoration: none !important; +} + +ul.DTTT_dropdown.dropdown-menu { + z-index: 2003; +} + +ul.DTTT_dropdown.dropdown-menu a { + color: #333 !important; /* needed only when demo_page.css is included */ +} + +ul.DTTT_dropdown.dropdown-menu li { + position: relative; +} + +ul.DTTT_dropdown.dropdown-menu li:hover a { + background-color: #0088cc; + color: white !important; +} + +div.DTTT_collection_background { + z-index: 2002; +} + +/* TableTools information display */ +div.DTTT_print_info { + position: fixed; + top: 50%; + left: 50%; + width: 400px; + height: 150px; + margin-left: -200px; + margin-top: -75px; + text-align: center; + color: #333; + padding: 10px 30px; + opacity: 0.95; + + background-color: white; + border: 1px solid rgba(0, 0, 0, 0.2); + border-radius: 6px; + + -webkit-box-shadow: 0 3px 7px rgba(0, 0, 0, 0.5); + box-shadow: 0 3px 7px rgba(0, 0, 0, 0.5); +} + +div.DTTT_print_info h6 { + font-weight: normal; + font-size: 28px; + line-height: 28px; + margin: 1em; +} + +div.DTTT_print_info p { + font-size: 14px; + line-height: 20px; +} + +div.dataTables_processing { + position: absolute; + top: 50%; + left: 50%; + width: 100%; + height: 60px; + margin-left: -50%; + margin-top: -25px; + padding-top: 20px; + padding-bottom: 20px; + text-align: center; + font-size: 1.2em; + background-color: white; + background: -webkit-gradient(linear, left top, right top, color-stop(0%, rgba(255,255,255,0)), color-stop(25%, rgba(255,255,255,0.9)), color-stop(75%, rgba(255,255,255,0.9)), color-stop(100%, rgba(255,255,255,0))); + background: -webkit-linear-gradient(left, rgba(255,255,255,0) 0%, rgba(255,255,255,0.9) 25%, rgba(255,255,255,0.9) 75%, rgba(255,255,255,0) 100%); + background: -moz-linear-gradient(left, rgba(255,255,255,0) 0%, rgba(255,255,255,0.9) 25%, rgba(255,255,255,0.9) 75%, rgba(255,255,255,0) 100%); + background: -ms-linear-gradient(left, rgba(255,255,255,0) 0%, rgba(255,255,255,0.9) 25%, rgba(255,255,255,0.9) 75%, rgba(255,255,255,0) 100%); + background: -o-linear-gradient(left, rgba(255,255,255,0) 0%, rgba(255,255,255,0.9) 25%, rgba(255,255,255,0.9) 75%, rgba(255,255,255,0) 100%); + background: linear-gradient(to right, rgba(255,255,255,0) 0%, rgba(255,255,255,0.9) 25%, rgba(255,255,255,0.9) 75%, rgba(255,255,255,0) 100%); +} + + + +/* + * FixedColumns styles + */ +div.DTFC_LeftHeadWrapper table, +div.DTFC_LeftFootWrapper table, +div.DTFC_RightHeadWrapper table, +div.DTFC_RightFootWrapper table, +table.DTFC_Cloned tr.even { + background-color: white; + margin-bottom: 0; +} + +div.DTFC_RightHeadWrapper table , +div.DTFC_LeftHeadWrapper table { + border-bottom: none !important; + margin-bottom: 0 !important; + border-top-right-radius: 0 !important; + border-bottom-left-radius: 0 !important; + border-bottom-right-radius: 0 !important; +} + +div.DTFC_RightHeadWrapper table thead tr:last-child th:first-child, +div.DTFC_RightHeadWrapper table thead tr:last-child td:first-child, +div.DTFC_LeftHeadWrapper table thead tr:last-child th:first-child, +div.DTFC_LeftHeadWrapper table thead tr:last-child td:first-child { + border-bottom-left-radius: 0 !important; + border-bottom-right-radius: 0 !important; +} + +div.DTFC_RightBodyWrapper table, +div.DTFC_LeftBodyWrapper table { + border-top: none; + margin: 0 !important; +} + +div.DTFC_RightBodyWrapper tbody tr:first-child th, +div.DTFC_RightBodyWrapper tbody tr:first-child td, +div.DTFC_LeftBodyWrapper tbody tr:first-child th, +div.DTFC_LeftBodyWrapper tbody tr:first-child td { + border-top: none; +} + +div.DTFC_RightFootWrapper table, +div.DTFC_LeftFootWrapper table { + border-top: none; + margin-top: 0 !important; +} + + +div.DTFC_LeftBodyWrapper table.dataTable thead .sorting:after, +div.DTFC_LeftBodyWrapper table.dataTable thead .sorting_asc:after, +div.DTFC_LeftBodyWrapper table.dataTable thead .sorting_desc:after, +div.DTFC_RightBodyWrapper table.dataTable thead .sorting:after, +div.DTFC_RightBodyWrapper table.dataTable thead .sorting_asc:after, +div.DTFC_RightBodyWrapper table.dataTable thead .sorting_desc:after { + display: none; +} + + +/* + * FixedHeader styles + */ +div.FixedHeader_Cloned table { + margin: 0 !important +} http://git-wip-us.apache.org/repos/asf/hadoop/blob/456e901a/hadoop-hdfs-project/hadoop-hdfs/src/main/webapps/static/dataTables.bootstrap.js ---------------------------------------------------------------------- diff --git a/hadoop-hdfs-project/hadoop-hdfs/src/main/webapps/static/dataTables.bootstrap.js b/hadoop-hdfs-project/hadoop-hdfs/src/main/webapps/static/dataTables.bootstrap.js new file mode 100644 index 0000000..115bf84 --- /dev/null +++ b/hadoop-hdfs-project/hadoop-hdfs/src/main/webapps/static/dataTables.bootstrap.js @@ -0,0 +1,205 @@ +/*! DataTables Bootstrap 3 integration + * ©2011-2014 SpryMedia Ltd - datatables.net/license + */ + +/** + * DataTables integration for Bootstrap 3. This requires Bootstrap 3 and + * DataTables 1.10 or newer. + * + * This file sets the defaults and adds options to DataTables to style its + * controls using Bootstrap. See http://datatables.net/manual/styling/bootstrap + * for further information. + */ +(function(window, document, undefined){ + +var factory = function( $, DataTable ) { +"use strict"; + + +/* Set the defaults for DataTables initialisation */ +$.extend( true, DataTable.defaults, { + dom: + "<'row'<'col-sm-6'l><'col-sm-6'f>>" + + "<'row'<'col-sm-12'tr>>" + + "<'row'<'col-sm-5'i><'col-sm-7'p>>", + renderer: 'bootstrap' +} ); + + +/* Default class modification */ +$.extend( DataTable.ext.classes, { + sWrapper: "dataTables_wrapper form-inline dt-bootstrap", + sFilterInput: "form-control input-sm", + sLengthSelect: "form-control input-sm" +} ); + + +/* Bootstrap paging button renderer */ +DataTable.ext.renderer.pageButton.bootstrap = function ( settings, host, idx, buttons, page, pages ) { + var api = new DataTable.Api( settings ); + var classes = settings.oClasses; + var lang = settings.oLanguage.oPaginate; + var btnDisplay, btnClass, counter=0; + + var attach = function( container, buttons ) { + var i, ien, node, button; + var clickHandler = function ( e ) { + e.preventDefault(); + if ( !$(e.currentTarget).hasClass('disabled') ) { + api.page( e.data.action ).draw( false ); + } + }; + + for ( i=0, ien=buttons.length ; i<ien ; i++ ) { + button = buttons[i]; + + if ( $.isArray( button ) ) { + attach( container, button ); + } + else { + btnDisplay = ''; + btnClass = ''; + + switch ( button ) { + case 'ellipsis': + btnDisplay = '…'; + btnClass = 'disabled'; + break; + + case 'first': + btnDisplay = lang.sFirst; + btnClass = button + (page > 0 ? + '' : ' disabled'); + break; + + case 'previous': + btnDisplay = lang.sPrevious; + btnClass = button + (page > 0 ? + '' : ' disabled'); + break; + + case 'next': + btnDisplay = lang.sNext; + btnClass = button + (page < pages-1 ? + '' : ' disabled'); + break; + + case 'last': + btnDisplay = lang.sLast; + btnClass = button + (page < pages-1 ? + '' : ' disabled'); + break; + + default: + btnDisplay = button + 1; + btnClass = page === button ? + 'active' : ''; + break; + } + + if ( btnDisplay ) { + node = $('<li>', { + 'class': classes.sPageButton+' '+btnClass, + 'id': idx === 0 && typeof button === 'string' ? + settings.sTableId +'_'+ button : + null + } ) + .append( $('<a>', { + 'href': '#', + 'aria-controls': settings.sTableId, + 'data-dt-idx': counter, + 'tabindex': settings.iTabIndex + } ) + .html( btnDisplay ) + ) + .appendTo( container ); + + settings.oApi._fnBindAction( + node, {action: button}, clickHandler + ); + + counter++; + } + } + } + }; + + // IE9 throws an 'unknown error' if document.activeElement is used + // inside an iframe or frame. + var activeEl; + + try { + // Because this approach is destroying and recreating the paging + // elements, focus is lost on the select button which is bad for + // accessibility. So we want to restore focus once the draw has + // completed + activeEl = $(document.activeElement).data('dt-idx'); + } + catch (e) {} + + attach( + $(host).empty().html('<ul class="pagination"/>').children('ul'), + buttons + ); + + if ( activeEl ) { + $(host).find( '[data-dt-idx='+activeEl+']' ).focus(); + } +}; + + +/* + * TableTools Bootstrap compatibility + * Required TableTools 2.1+ + */ +if ( DataTable.TableTools ) { + // Set the classes that TableTools uses to something suitable for Bootstrap + $.extend( true, DataTable.TableTools.classes, { + "container": "DTTT btn-group", + "buttons": { + "normal": "btn btn-default", + "disabled": "disabled" + }, + "collection": { + "container": "DTTT_dropdown dropdown-menu", + "buttons": { + "normal": "", + "disabled": "disabled" + } + }, + "print": { + "info": "DTTT_print_info" + }, + "select": { + "row": "active" + } + } ); + + // Have the collection use a bootstrap compatible drop down + $.extend( true, DataTable.TableTools.DEFAULTS.oTags, { + "collection": { + "container": "ul", + "button": "li", + "liner": "a" + } + } ); +} + +}; // /factory + + +// Define as an AMD module if possible +if ( typeof define === 'function' && define.amd ) { + define( ['jquery', 'datatables'], factory ); +} +else if ( typeof exports === 'object' ) { + // Node/CommonJS + factory( require('jquery'), require('datatables') ); +} +else if ( jQuery ) { + // Otherwise simply initialise as normal, stopping multiple evaluation + factory( jQuery, jQuery.fn.dataTable ); +} + + +})(window, document);