You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
Plugins/features/slidingChild/dataTables.slidingChild.mjs

225 lines
7.0 KiB
JavaScript

/*! © Nick Adkinson, SpryMedia Ltd - datatables.net/license */
import jQuery from 'jquery';
import DataTable from 'datatables.net';
// Allow reassignment of the $ variable
let $ = jQuery;
/**
* @summary SlidingChild
* @description Show / Hide row child plugin
* @version 2.1.0
* @author [Nick Adkinson](https://github.com/data-handler)
* @copyright Copyright 2018 Nick Adkinson
*
* This feature plug-in provides functionality for showing and hiding row child
* information in DataTables. This can be particularly useful for displaying
* hierarchical data as a drill-down, or where you wish to convey more information
* about a row than there is space for in the host table.
*
* @example
* $('#myTable').DataTable({
* slidingChild: {
* source: function(parent, response) {
* $.get('/Child/GetByParentId/' + parent.data('id'), response);
* }
* }
* });
*
*/
var SlidingChild = function (dt, options) {
var that = this;
dt.on('draw', function () {
that._updateFadedRows();
});
var table = dt.table();
var sliderElement = document.createElement('div');
sliderElement.className = 'slider';
this.s = $.extend({}, {
dt: dt,
table: $(table.node()),
slider: $(sliderElement),
}, SlidingChild.defaults, options);
this._bind();
};
SlidingChild.prototype._bind = function () {
var that = this;
var settings = that.s;
$(settings.table, '> tbody').on('click', settings.selector, function () {
var $this = $(this);
var tr = $this.is('tr') ? $this : $this.closest('tr');
if (!tr.is('tr')) {
return;
} // throw error?
var dtRow = settings.dt.row(tr);
that._toggleChild(dtRow);
});
};
SlidingChild.prototype._toggleChild = function (dtRow) {
var settings = this.s;
if (dtRow.child.isShown()) {
this._hideChild(dtRow, function () { });
}
else {
var existingShownDtRow = settings.dt.row('.shown');
if (existingShownDtRow.length && settings.toggle) {
this._hideChild(existingShownDtRow, this._showChildCallback(dtRow));
}
else {
this._showChild(dtRow);
}
}
};
SlidingChild.prototype._showChildCallback = function (dtRow) {
return function (dtRow) {
this._showChild(dtRow);
}.bind(this, dtRow);
};
SlidingChild.prototype._showChild = function (dtRow) {
var $tr = $(dtRow.node());
if (this.s.displayLoadingIndicator) {
this._addLoadingIndicator($tr);
}
this.s.source($tr, this._response(dtRow));
};
SlidingChild.prototype._response = function (dtRow) {
return function (dtRow, childData) {
this.__showChild(dtRow, childData);
}.bind(this, dtRow);
};
SlidingChild.prototype.__showChild = function (dtRow, data) {
var settings = this.s;
var slider = settings.slider;
var $tr = $(dtRow.node());
if (settings.displayLoadingIndicator) {
$('.' + this.s.loadingIndicatorClass).remove();
}
slider.append(data);
dtRow.child(slider, settings.childClass).show();
$tr.toggleClass('shown');
this._updateFadedRows();
if (settings.animateShow) {
this._showChildWithAnimation(dtRow);
}
else {
this._showChildWithoutAnimation(dtRow);
}
};
SlidingChild.prototype._showChildWithAnimation = function (dtRow) {
var settings = this.s;
$(settings.slider, dtRow.child()).slideDown(settings.animationSpeed, function () {
settings.onShown(dtRow);
});
};
SlidingChild.prototype._showChildWithoutAnimation = function (dtRow) {
var settings = this.s;
$(settings.slider, dtRow.child()).show();
settings.onShown(dtRow);
};
SlidingChild.prototype._hideChild = function (dtRow, callback) {
var settings = this.s;
$(dtRow.node()).toggleClass('shown');
this._updateFadedRows();
if (settings.animateHide) {
this._hideChildWithAnimation(dtRow, callback);
}
else {
this._hideChildWithoutAnimation(dtRow, callback);
}
};
SlidingChild.prototype._hideChildWithAnimation = function (dtRow, callback) {
var settings = this.s;
var slider = settings.slider;
$(slider, dtRow.child()).slideUp(settings.animationSpeed, function () {
dtRow.child.remove();
slider.empty();
settings.onHidden(dtRow);
callback();
});
};
SlidingChild.prototype._hideChildWithoutAnimation = function (dtRow, callback) {
var settings = this.s;
var slider = settings.slider;
$(slider, dtRow.child()).hide();
dtRow.child.remove();
slider.empty();
settings.onHidden(dtRow);
callback();
};
SlidingChild.prototype._updateFadedRows = function () {
if (this.s.fadeNonShowingRows) {
this._fadeNonShowingRows();
this._removeFadeFromShowingRows();
}
else {
this._removeFadeFromRows();
}
};
SlidingChild.prototype._fadeNonShowingRows = function () {
if (this.s.dt.rows('.shown:visible').count()) {
this.s.dt
.rows(':visible:not(.shown):not(.faded)')
.nodes()
.to$()
.css('opacity', this.s.fadeOpacity)
.addClass('faded');
}
else {
this._removeFadeFromRows();
}
};
SlidingChild.prototype._removeFadeFromShowingRows = function () {
this.s.dt
.rows('.shown.faded:visible')
.nodes()
.to$()
.css('opacity', 1)
.removeClass('faded');
};
SlidingChild.prototype._removeFadeFromRows = function () {
this.s.dt.rows('.faded').nodes().to$().css('opacity', 1).removeClass('faded');
};
SlidingChild.prototype._addLoadingIndicator = function ($tr) {
var position = $tr.position();
var indicator = $(this.s.loadingIndicatorContent);
indicator.addClass(this.s.loadingIndicatorClass);
indicator.css('top', position.top);
indicator.css('left', position.left);
indicator.css('height', $tr.height());
$tr.append(indicator);
};
const options = {
selector: 'tr',
childClass: 'child',
source: function () { },
toggle: true,
animateShow: true,
animateHide: true,
fadeNonShowingRows: false,
fadeOpacity: 0.4,
animationSpeed: 200,
onShown: function () { },
onHidden: function () { },
displayLoadingIndicator: false,
loadingIndicatorClass: 'loading-indicator',
loadingIndicatorContent: '<div style="background: black; color: white; display: flex; align-items: center; justify-content: center; opacity: 0.5; position: absolute; width: 100%; z-index: 100;">Loading...</div>',
};
SlidingChild.defaults = options;
DataTable.SlidingChild = SlidingChild;
// Automatic initialisation listener
$(document).on('init.dt', function (e, settings) {
if (e.namespace !== 'dt') {
return;
}
var api = new DataTable.Api(settings);
if ($(api.table().node()).hasClass('slidingChild') ||
settings.oInit.slidingChild ||
DataTable.defaults.slidingChild) {
new SlidingChild(api, settings.oInit.slidingChild);
}
});
export default DataTable;