diff --git a/features/slidingChild/datatables.slidingChild.js b/features/slidingChild/datatables.slidingChild.js new file mode 100644 index 0000000..10951ad --- /dev/null +++ b/features/slidingChild/datatables.slidingChild.js @@ -0,0 +1,245 @@ +/** + * @summary SlidingChild + * @description Show / Hide row child plugin + * @version 2.0.1 + * @file dataTables.slidingChild.js + * @author Nick Adkinson (https://github.com/data-handler) + * @copyright Copyright 2018 Nick Adkinson + * + * License MIT - http://datatables.net/license/mit + * + * 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); + * } + * } + * }); + * + */ +(function( factory ){ + if ( typeof define === 'function' && define.amd ) { + // AMD + define( ['jquery', 'datatables.net'], function ( $ ) { + return factory( $, window, document ); + } ); + } + else if ( typeof exports === 'object' ) { + // CommonJS + module.exports = function (root, $) { + if ( ! root ) { + root = window; + } + + if ( ! $ || ! $.fn.dataTable ) { + $ = require('datatables.net')(root, $).$; + } + + return factory( $, root, root.document ); + }; + } + else { + // Browser + factory( jQuery, document ); + } +}(function( $, document ) { +'use strict'; + +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); + }); + }, + _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); + } + } + }, + _showChildCallback: function(dtRow) { + return function( dtRow ) { + this._showChild(dtRow); + }.bind( this, dtRow ); + }, + _showChild: function(dtRow) { + this.s.source( $(dtRow.node() ), this._response(dtRow) ); + }, + _response: function(dtRow) { + return function( dtRow, childData ) { + this.__showChild( dtRow, childData ); + }.bind( this, dtRow ); + }, + __showChild: function(dtRow, data) { + var settings = this.s; + var slider = settings.slider; + + slider.append(data); + dtRow.child(slider, settings.childClass).show(); + + $(dtRow.node()).toggleClass('shown'); + this._updateFadedRows(); + + if (settings.animateShow) { + this._showChildWithAnimation(dtRow); + } else { + this._showChildWithoutAnimation(dtRow); + } + }, + _showChildWithAnimation: function(dtRow) { + var settings = this.s; + $(settings.slider, dtRow.child()).slideDown(settings.animationSpeed, function () { + settings.onShown(dtRow); + }); + }, + _showChildWithoutAnimation: function(dtRow) { + var settings = this.s; + $(settings.slider, dtRow.child()).show(); + settings.onShown(dtRow); + }, + _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); + } + }, + _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(); + }); + }, + _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(); + }, + _updateFadedRows: function() { + if (this.s.fadeNonShowingRows) { + this._fadeNonShowingRows(); + this._removeFadeFromShowingRows(); + } else { + this._removeFadeFromRows(); + } + }, + _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(); + } + }, + _removeFadeFromShowingRows: function() { + this.s.dt.rows('.shown.faded:visible') + .nodes() + .to$() + .css('opacity', 1) + .removeClass('faded'); + }, + _removeFadeFromRows: function() { + this.s.dt.rows('.faded') + .nodes() + .to$() + .css('opacity', 1) + .removeClass('faded'); + } +}; + +SlidingChild.defaults = { + selector: "tr", + childClass: 'child', + source: function() {}, + toggle: true, + animateShow: true, + animateHide: true, + fadeNonShowingRows: false, + fadeOpacity: 0.4, + animationSpeed: 200, + onShown: function() {}, + onHidden: function() {} +}; + + +$.fn.dataTable.SlidingChild = SlidingChild; +$.fn.DataTable.SlidingChild = SlidingChild; + +// Automatic initialisation listener +$(document).on( 'init.dt', function ( e, settings ) { + if ( e.namespace !== 'dt' ) { + return; + } + + var api = new $.fn.dataTable.Api( settings ); + + if ( $( api.table().node() ).hasClass( 'slidingChild' ) || + settings.oInit.slidingChild || + $.fn.dataTable.defaults.slidingChild ) + { + new SlidingChild( api, settings.oInit.slidingChild ); + } +} ); + + +})); diff --git a/features/slidingChild/datatables.slidingChild.min.js b/features/slidingChild/datatables.slidingChild.min.js new file mode 100644 index 0000000..9056677 --- /dev/null +++ b/features/slidingChild/datatables.slidingChild.min.js @@ -0,0 +1,4 @@ +/* + Copyright 2017 datahandler. +*/ +!function(n){"function"==typeof define&&define.amd?define(["jquery","datatables.net"],function(i){return n(i,window,document)}):"object"==typeof exports?module.exports=function(i,t){return i||(i=window),t&&t.fn.dataTable||(t=require("datatables.net")(i,t).$),n(t,i,i.document)}:n(jQuery,document)}(function(s,d){"use strict";var h=function(i,t){var n=this;i.on("draw",function(){n._updateFadedRows()});var o=i.table(),e=d.createElement("div");e.className="slider",this.s=s.extend({},{dt:i,table:s(o.node()),slider:s(e)},h.defaults,t),this._bind()};h.prototype={_bind:function(){var o=this,e=o.s;s(e.table,"> tbody").on("click",e.selector,function(){var i=s(this),t=i.is("tr")?i:i.closest("tr");if(t.is("tr")){var n=e.dt.row(t);o._toggleChild(n)}})},_toggleChild:function(i){var t=this.s;if(i.child.isShown())this._hideChild(i,function(){});else{var n=t.dt.row(".shown");n.length&&t.toggle?this._hideChild(n,this._showChildCallback(i)):this._showChild(i)}},_showChildCallback:function(i){return function(i){this._showChild(i)}.bind(this,i)},_showChild:function(i){this.s.source(s(i.node()),this._response(i))},_response:function(i){return function(i,t){this.__showChild(i,t)}.bind(this,i)},__showChild:function(i,t){var n=this.s,o=n.slider;o.append(t),i.child(o,n.childClass).show(),s(i.node()).toggleClass("shown"),this._updateFadedRows(),n.animateShow?this._showChildWithAnimation(i):this._showChildWithoutAnimation(i)},_showChildWithAnimation:function(i){var t=this.s;s(t.slider,i.child()).slideDown(t.animationSpeed,function(){t.onShown(i)})},_showChildWithoutAnimation:function(i){var t=this.s;s(t.slider,i.child()).show(),t.onShown(i)},_hideChild:function(i,t){var n=this.s;s(i.node()).toggleClass("shown"),this._updateFadedRows(),n.animateHide?this._hideChildWithAnimation(i,t):this._hideChildWithoutAnimation(i,t)},_hideChildWithAnimation:function(i,t){var n=this.s,o=n.slider;s(o,i.child()).slideUp(n.animationSpeed,function(){i.child.remove(),o.empty(),n.onHidden(i),t()})},_hideChildWithoutAnimation:function(i,t){var n=this.s,o=n.slider;s(o,i.child()).hide(),i.child.remove(),o.empty(),n.onHidden(i),t()},_updateFadedRows:function(){this.s.fadeNonShowingRows?(this._fadeNonShowingRows(),this._removeFadeFromShowingRows()):this._removeFadeFromRows()},_fadeNonShowingRows:function(){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"):this._removeFadeFromRows()},_removeFadeFromShowingRows:function(){this.s.dt.rows(".shown.faded:visible").nodes().to$().css("opacity",1).removeClass("faded")},_removeFadeFromRows:function(){this.s.dt.rows(".faded").nodes().to$().css("opacity",1).removeClass("faded")}},h.defaults={selector:"tr",childClass:"child",source:function(){},toggle:!0,animateShow:!0,animateHide:!0,fadeNonShowingRows:!1,fadeOpacity:.4,animationSpeed:200,onShown:function(){},onHidden:function(){}},s.fn.dataTable.SlidingChild=h,s.fn.DataTable.SlidingChild=h,s(d).on("init.dt",function(i,t){if("dt"===i.namespace){var n=new s.fn.dataTable.Api(t);(s(n.table().node()).hasClass("slidingChild")||t.oInit.slidingChild||s.fn.dataTable.defaults.slidingChild)&&new h(n,t.oInit.slidingChild)}})}); diff --git a/features/slidingChild/js/sliding-child.js b/features/slidingChild/js/sliding-child.js deleted file mode 100644 index 237815a..0000000 --- a/features/slidingChild/js/sliding-child.js +++ /dev/null @@ -1,128 +0,0 @@ -/** - * @summary SlidingChild - * @description Plug-in to show/hide row child data - * @version 1.0.0 - * @file slidingchild.js - * @author datahandler (www.datahandler.uk) - * @copyright Copyright datahandler (www.datahandler.uk) - * - * License MIT - http://datatables.net/license/mit - */ - -/** - * Example usage - * @example - * var table = $('#table_id').DataTable(); - * slidingChild = - * new $.fn.dataTable.SlidingChild(table, { - * ajax: { - * requestType: 'POST', - * requestUrl: '/Home/GetChildData', - * dataType: 'HTML', - * requestDataCallback: myRequestDataCallback - * } - * }); - */ -(function ($) { - var SlidingChild = function (dt, options) { - var opts = $.extend({}, SlidingChild.defaults, options); - - // bind to selector click - $(opts.selector).on('click', function () { - var $this = $(this); - var dtRow = $this.is('tr') ? $this : $this.closest('tr'); - - if (!dtRow.is('tr')) { return; } // throw error? - // check row belongs to this table? - - dtRow = dt.row(dtRow); - toggleChild(dtRow); - }); - - var toggleChild = function (dtRow) { - // if child already showing, close it. - if (dtRow.child.isShown()) { - closeChild(dtRow); - } - else { - // closes existing showing child, if any - if (opts.toggleChild) closeChild(dt.row('.shown')); - - showChildData(dtRow); - } - }; - // code borrowed from the resource at: https://datatables.net/blog/2014-10-02 - var closeChild = function (dtRow) { - if (dtRow) { - var showingRow = $(dtRow.node()); - $(opts.sliderSelector, dtRow.child()).slideUp(function () { - dtRow.child.remove(); - showingRow.removeClass('shown'); - $(dt.table().node()).trigger('childClosed', [dtRow]); - }); - } - }; - - var showChildData = function (dtRow) { - if (opts.useRowData) { - showChildDataFromRow(dtRow); - } - else { - $.ajax({ - type: opts.ajax.requestType, - url: opts.ajax.requestUrl, - beforeSend: function(xhr, settings) { - if (opts.ajax.requestDataCallback) { - this.data = opts.ajax.requestDataCallback(dtRow); - } - }, - contentType: opts.ajax.contentType, - dataType: opts.ajax.dataType, - success: function (response) { - var data = response; - if (opts.dataFormatCallback) { - data = opts.dataFormatCallback(response); - } - showChild(dtRow, data); - }, - error: function (response) { showChild(dtRow, response); } - }); - } - }; - - var showChildDataFromRow = function(dtRow) { - if (!opts.dataFormatCallback) { return; } // throw error? - var data = opts.dataFormatCallback(dtRow.data()); - showChild(dtRow, data); - } - - var showChild = function(dtRow, data) { - var selectedRow = $(dtRow.node()); - dtRow.child(data).show(); - - $(opts.sliderSelector, dtRow.child()).slideDown(function () { - selectedRow.addClass('shown'); - - $(dt.table().node()).trigger('childShown', [dtRow]); - }); - }; - }; - - SlidingChild.defaults = { - selector: "tr", - toggleChild: false, - useRowData: false, - ajax: { - requestType: "GET", - requestDataCallback: null, - requestUrl: null, - contentType: "application/json; charset=utf-8", - dataType: "json" - }, - dataFormatCallback: null, - sliderSelector: 'div.slider' - }; - - $.fn.dataTable.SlidingChild = SlidingChild; - $.fn.DataTable.SlidingChild = SlidingChild; -}(jQuery));