initializeDataTables = (target) ->
$(target || document).find('table.effective-datatable:not(.initialized)').each ->
datatable = $(this)
options = datatable.data('options') || {}
buttons_export_columns = options['buttons_export_columns'] || ':not(.col-actions)'
reorder = datatable.data('reorder')
if options['buttons'] == false
options['buttons'] = []
init_options =
ajax: { url: datatable.data('source'), type: 'POST' }
autoWidth: false
buttons: [
{
extend: 'colvis',
postfixButtons: [
{ extend: 'colvisGroup', text: 'Show all', show: ':hidden', className: 'buttons-colvisGroup-first'},
{ extend: 'colvisGroup', text: 'Show none', hide: ':visible' },
{ extend: 'colvisGroup', text: 'Show default', hide: ':not(.colvis-default)', show: '.colvis-default' }
]
},
{
extend: 'copy',
exportOptions:
format:
header: (str) -> $("
#{str}
").children('span').first().text()
columns: buttons_export_columns
},
{
extend: 'csv',
exportOptions:
format:
header: (str) -> $("#{str}
").children('span').first().text()
columns: buttons_export_columns
},
{
extend: 'print',
footer: true,
exportOptions:
format:
header: (str) -> $("#{str}
").children('span').first().text()
columns: ':visible:not(.col-actions)'
},
]
columns: datatable.data('columns')
deferLoading: [datatable.data('display-records'), datatable.data('total-records')]
deferRender: true
displayStart: datatable.data('display-start')
iDisplayLength: datatable.data('display-length')
language: datatable.data('language')
lengthMenu: [[5, 10, 25, 50, 100, 250, 500, 9999999], ['5', '10', '25', '50', '100', '250', '500', 'All']]
order: datatable.data('display-order')
processing: true
responsive: true
serverParams: (params) ->
api = this.api()
api.columns().flatten().each (index) => params['columns'][index]['visible'] = api.column(index).visible()
$table = $(api.table().node())
$form = $(".effective-datatables-filters[aria-controls='#{$table.attr('id')}']").first()
params['attributes'] = $table.data('attributes')
params['authenticity_token'] = $table.data('authenticity-token')
if $form.length > 0
params['scope'] = $form.find("input[name='filters[scope]']:checked").val() || ''
params['filter'] = {}
$form.find("select,textarea,input:not([type=submit])").each ->
$input = $(this)
if ['utf8', 'authenticity_token', 'filters[scope]'].includes($input.attr('name'))
# Skipped
else if $input.attr('type') == 'radio'
name = $input.attr('name')
filter_name = name.replace('filters[', '').substring(0, name.length-9)
params['filter'][filter_name] = $form.find("input[name='#{name}']:checked").val()
else if $input.attr('id')
filter_name = $input.attr('id').replace('filters_', '')
params['filter'][filter_name] = $input.val()
serverSide: true
scrollCollapse: true
pagingType: 'simple_numbers'
initComplete: (settings) ->
initializeButtons(this.api())
initializeSearch(this.api())
drawCallback: (settings) ->
$table = $(this.api().table().node())
if settings['json']
if settings['json']['effective_datatables_error']
alert("DataTable error: #{settings['json']['effective_datatables_error']}\n\nPlease refresh the page and try again")
return
if settings['json']['aggregates']
drawAggregates($table, settings['json']['aggregates'])
if settings['json']['charts']
drawCharts($table, settings['json']['charts'])
$table.children('tbody').trigger('effective-bootstrap:initialize')
# Copies the bulk actions html, stored in a data attribute on the table, into the buttons area
initializeButtons = (api) ->
$table = $(api.table().node())
$buttons = $table.closest('.dataTables_wrapper').children().first().find('.dt-buttons')
if $table.data('reset')
$buttons.prepend($table.data('reset'))
if $table.data('reorder')
$buttons.prepend($table.data('reorder'))
if $table.data('bulk-actions')
$buttons.prepend($table.data('bulk-actions'))
drawAggregates = ($table, aggregates) ->
$tfoot = $table.find('tfoot').first()
$.each aggregates, (row, values) =>
$row = $tfoot.children().eq(row)
if $row
$.each values, (col, value) => $row.children().eq(col).html(value)
drawCharts = ($table, charts) ->
if typeof(google) != 'undefined' && typeof(google.visualization) != 'undefined'
$.each charts, (name, data) =>
$(".effective-datatables-chart[data-name='#{name}']").each (_, obj) =>
chart = new google.visualization[data['type']](obj)
chart.draw(google.visualization.arrayToDataTable(data['data']), data['options'])
# Appends the search html, stored in the column definitions, into each column header
initializeSearch = (api) ->
api.columns().flatten().each (index) =>
$th = $(api.column(index).header())
settings = api.settings()[0].aoColumns[index] # column specific settings
if settings.search != null # Assign preselected values
api.settings()[0].aoPreSearchCols[index].sSearch = settings.search
if settings.searchHtml # Append the search html and initialize input events
$th.append(settings.searchHtml)
initializeSearchEvents($th)
# Sets up the proper events for each input
initializeSearchEvents = ($th) ->
$th.find('input,select').each (_, input) ->
$input = $(input)
return true if $input.attr('type') == 'hidden' || $input.attr('type') == 'checkbox'
$input.parent().on 'click', (event) -> false # Dont order columns when you click inside the input
$input.parent().on 'mousedown', (event) -> event.stopPropagation() # Dont order columns when you click inside the input
if $input.is('select')
$input.on 'change', (event) -> dataTableSearch($(event.currentTarget))
else if $input.is('input')
$input.delayedChange ($input) -> dataTableSearch($input)
$input.on('paste', -> dataTableSearch($input))
# Do the actual search
dataTableSearch = ($input) -> # This is the function called by a select or input to run the search
return if $input.is(':invalid')
table = $input.closest('table.dataTable')
table.DataTable().column("#{$input.data('column-name')}:name").search($input.val()).draw()
if reorder
init_options['rowReorder'] = { selector: 'td.col-_reorder', snapX: true, dataSrc: datatable.data('reorder-index') }
# Let's actually initialize the table now
table = datatable.dataTable(jQuery.extend(init_options, options))
# Fix a tabindex issue
table.children('tbody').children('tr').children('td[tabindex]').removeAttr('tabindex')
# Apply EffectiveFormInputs to the Show x per page dropdown
try table.closest('.dataTables_wrapper').find('.dataTables_length select').removeAttr('name').select2(minimumResultsForSearch: 100)
if reorder
table.DataTable().on('row-reorder', (event, diff, edit) -> $(event.target).DataTable().reorder(event, diff, edit))
table.addClass('initialized')
table.children('thead').trigger('effective-bootstrap:initialize')
true
destroyDataTables = ->
$('.effective-datatables-inline-expanded').removeClass('effective-datatables-inline-expanded')
$('table.effective-datatable').each -> try $(this).removeClass('initialized').DataTable().destroy()
$ -> initializeDataTables()
$(document).on 'effective-datatables:initialize', (event) -> initializeDataTables(event.currentTarget)
$(document).on 'page:change', -> initializeDataTables()
$(document).on 'turbolinks:load', -> initializeDataTables()
$(document).on 'turbolinks:render', -> initializeDataTables()
$(document).on 'turbolinks:before-cache', -> destroyDataTables()