//region Datatables.net import 'datatables.net'; import 'datatables.net-dt/css/dataTables.dataTables.min.css'; //endregion //region Bootstrap 5 styling for Datatables.net import 'datatables.net-bs5'; import 'datatables.net-bs5/css/dataTables.bootstrap5.min.css'; //endregion //region Custom style for Datatables.net import './styles/datatables2.scss'; //endregion import 'jqueryLocal'; import Utils from 'utils'; /** * Chargement automatique des éléments : tableaux, {@link https://datatables.net/ DataTables (v2)} * * Valide seulement si le JS "DataTable" est bien présent\ * S'instancie automatiquement sur les <table class="table-datatable2"> * * Options : * * table : * * data-sort-paging : boolean\ *     Pagination gérée ?\ *     Défaut : faux * * data-sort-per-page : integer\ *     Nombre d'éléments par défaut par page\ *     Défaut : 50 * * data-sort-layout : string (JSON)\ *     Le JSON du modèle du tableau (https://datatables.net/reference/option/layout)\ *     Défaut : pagination (si active) en bas à droite * * data-sort-ajax : string|false\ *     Faux si pas de requête AJAX géré\ *     Sinon l'URL AJAX appelée\ *         Bien penser à définir les "data-sort-name" sur les <th>\ *     Défaut : false * * data-sort-ajax-type : string\ *     Le type de la requête AJAX (GET, POST, etc.)\ *     Défaut : POST * * data-sort-ajax-cache : boolean\ *     Mise en cache du résultat des requêtes AJAX ?\ *     Défaut : faux * * data-sort-lang : string (JSON)\ *     Le JSON des traductions * * data-sort-lang-url : string (url)\ *     L'URL renvoyant le JSON des traductions\ *     Ignore si "data-sort-lang" renseigné * * data-sort-lang-code : string\ *     Code langue (plugin, voir https://datatables.net/plug-ins/i18n/French.html#Browser-loading-/-CDN)\ *         Exemple avec "fr-FR" : chargera "//cdn.datatables.net/plug-ins/2.2.2/i18n/fr-FR.json"\ *     Ignoré si "data-sort-lang" ou "data-sort-lang-url" est renseigné * * data-sort-child : string (HTML)|false\ *     Faux si pas de lignes enfants gérées\ *     Sinon le contenu HTML de la ligne enfant\ *     Ignoré si supplanté par la version sur les <tr>\ *     Défaut : false * * data-sort-child-ajax : string (url)|false\ *     Faux si pas de lignes enfants gérées\ *     L'URL des requêtes AJAX pour les lignes enfants\ *     Ignoré si "data-sort-child" est renseigné ou supplanté par la version sur les <tr>\ *     Défaut : false * * data-sort-child-ajax-type : string\ *     Le type de la requête AJAX pour les lignes enfants (GET, POST, etc.)\ *     Ignoré si supplanté par la version sur les <tr>\ *     Défaut : POST * * data-sort-child-ajax-cache : boolean\ *     Mise en cache du résultat des requêtes AJAX pour les lignes enfants ?\ *     Ignoré si supplanté par la version sur les <tr>\ *     Défaut : faux * * thead th : * * data-sort-onLoad : integer\ *     Ordre de tri de la colonne pour le tri initial/au chargement * * data-sort-order : string ("asc", "desc")\ *     Sens du tri de la colonne lors du 1er clic (et lors du tri initial/au chargement si "data-sort-onLoad" également renseigné) * * data-sort : boolean\ *     Activer le tri sur la colonne ?\ *     Défaut : vrai * * data-sort-name : string\ *     Le nom de la colonne dans la source de données (AJAX : cf. data-sort-ajax) * * data-sort-name-value : boolean\ *     La colonne à une valeur de tri différente de son affichage ?\ *     Si vrai attends une paire display/sort dans le JSON (exemple : https://datatables.net/examples/ajax/orthogonal-data.html)\ *         Cf. SolulogSAS\BaseSite\Web\DataTables2_ColumnWithSortValue\ *     Défaut : faux * * data-sort-child : string (HTML)|false\ *     Faux si pas de lignes enfants gérées\ *     Sinon le contenu HTML de la ligne enfant\ *     Défaut : false * * data-sort-child-ajax : string (url)|false\ *     Faux si pas de lignes enfants gérées\ *     L'URL des requêtes AJAX pour les lignes enfants\ *     Ignoré si "data-sort-child" est renseigné\ *     Défaut : false * * data-sort-child-ajax-id : any\ *     L'ID ajax de la ligne enfant (transmis dans "ajaxId")\ *     Défaut : {néant} * * data-sort-child-ajax-type : string\ *     Le type de la requête AJAX pour les lignes enfants (GET, POST, etc.)\ *     Défaut : POST * * data-sort-child-ajax-cache : boolean\ *     Mise en cache du résultat des requêtes AJAX pour les lignes enfants ?\ *     Défaut : faux * * tbody td : * * data-order : any\ *     La valeur utilisée pour le tri * * data-filter : any\ *     La valeur utilisée pour le filtrage * * @param {Document|jQuery} page */ function datatables2 (page) { $('table.table-datatable2', page).each(function () { const self = $(this); //region Options du datatable let options = { paging: self.dataDefault('sortPaging', false), pageLength: self.dataDefault('sortPerPage', 50), processing: true, layout: self.dataDefault('sortLayout', { topStart: null, topEnd: null, bottomStart: null, bottomEnd: 'paging', }, ), }; //endregion //region Gestion traduction let lang = self.dataDefault('sortLang', undefined); if (Utils.isUndefined(lang)) { let langUrl = self.dataDefault('sortLangUrl', undefined); if (Utils.isUndefined(langUrl)) { const langCode = self.dataDefault('sortLangCode', undefined); if (!Utils.isUndefined(langCode)) { langUrl = '//cdn.datatables.net/plug-ins/2.2.2/i18n/' + langCode + '.json'; } } if (!Utils.isUndefined(langUrl)) { lang = {url: langUrl}; } } if (!Utils.isUndefined(lang)) { options.language = lang; } //endregion //region Gestion tri initial let initialSort = []; $('> thead > tr > th[data-sort-onLoad]', self).each(function () { let self = $(this); initialSort.push( { index: self.index(), priority: self.dataDefault('sortOnload', 0), direction: self.dataDefault('sortOrder', 'asc').toLowerCase(), }, ); }); initialSort.sort(function (sort1, sort2) { if (sort1.priority === sort2.priority) { return sort1.index - sort2.index; } return sort1.priority - sort2.priority; }); if (initialSort.length > 0) { options.order = []; initialSort.forEach(function (sortOrder) { options.order.push([sortOrder.index, sortOrder.direction]); }); } //endregion //region Gestion sens de tri (1er clic ou initial si concerné) let descSort = []; $('> thead > tr > th[data-sort-order]', self).each(function () { const self = $(this); if (self.dataDefault('sortOrder', 'asc').toLowerCase() === 'desc') { descSort.push(self.index()); } }); if (descSort.length > 0) { if (!options.hasOwnProperty('columnDefs')) { options.columnDefs = []; } options.columnDefs.push( { targets: descSort, orderSequence: ['desc', 'asc'], }, ); } //endregion //region Gestion désactivation tri let disabledSort = []; $('> thead > tr > th[data-sort]', self).each(function () { const self = $(this); if (!self.dataDefault('sort', true)) { disabledSort.push(self.index()); } }); if (disabledSort.length > 0) { if (!options.hasOwnProperty('columnDefs')) { options.columnDefs = []; } options.columnDefs.push( { targets: disabledSort, orderable: false, }, ); } //endregion //region Gestion nom des colonnes const columnsName = $('> thead > tr > th[data-sort-name]', self); if (columnsName.length > 0) { if (!options.hasOwnProperty('columnDefs')) { options.columnDefs = []; } columnsName.each(function () { const self = $(this); const name = self.dataDefault('sortName', ''); if (name !== '') { options.columnDefs.push( { targets: self.index(), name: name, }, ); } }); } //endregion //region Gestion de AJAX const ajaxUrl = self.dataDefault('sortAjax', false); if (ajaxUrl !== false) { options.serverSide = true; options.ajax = { url: ajaxUrl, type: self.dataDefault('sortAjaxType', 'POST'), cache: self.dataDefault('sortAjaxCache', false), }; options.columns = []; columnsName.each(function () { const self = $(this); const name = self.dataDefault('sortName', ''); const nameValue = self.dataDefault('sortNameValue', false); if (name !== '') { options.columns[self.index()] = { data: nameValue ? {_: name + '.display', sort: name + '.sort'} : name, }; } }); } //endregion const datatable = self.DataTable(options); //region Gestion lignes enfants const child = self.dataDefault('sortChild', false); const childAjaxUrl = self.dataDefault('sortChildAjax', false); const childAjaxType = self.dataDefault('sortChildAjaxType', 'POST'); const childAjaxCache = self.dataDefault('sortChildAjaxCache', false); if (child === true || childAjaxUrl !== false) { const showData = function (dtRow, childData) { const parentHtml = '
'; const childJquery = $(parentHtml).append(childData); datatables2(childJquery); //noinspection JSUnresolvedReference dtRow.child(childJquery).show(); }; self.on('click', '> tbody > tr:not([data-dt-row!=""][data-dt-row]) > td', function () { //region Obtention ligne const row = $(this).parents('tr').first(); const dtRow = datatable.row(row); //endregion //region Lignes enfants déjà affichées ? Les masques //noinspection JSUnresolvedReference if (dtRow.child.isShown()) { //noinspection JSUnresolvedReference dtRow.child.hide(); return; } //endregion //region Données enfants directement spécifiées const childData = row.dataDefault('sortChild', false); if (childData !== false) { showData(dtRow, childData); return; } //endregion //region Données enfants via AJAX const rowChildAjaxUrl = row.dataDefault('sortChildAjax', childAjaxUrl); if (Utils.isUndefined(rowChildAjaxUrl) || rowChildAjaxUrl === false) { return; } $.ajax( { type: row.dataDefault('sortChildAjaxType', childAjaxType), url: rowChildAjaxUrl, data: { ajaxId: row.dataDefault('sortChildAjaxId', undefined), }, cache: row.dataDefault('sortChildAjaxCache', childAjaxCache), }, ) .done(childData => { showData(dtRow, childData); }); //endregion }); } //endregion }); } $(function () { datatables2(document); });