Skip to content

Commit

Permalink
1c2b8525f8b36c5161993c9c564f77aa5cf7b165 Dev fix: Full and start/end …
Browse files Browse the repository at this point in the history
…rows couldn't have their own id/class set - they were mixed. This has resulted in rewrite of how the `layout` object is parsed.

Tests: Adding tests for rowId, rowClass, id and className for layout

Sync to source repo @1c2b8525f8b36c5161993c9c564f77aa5cf7b165
  • Loading branch information
dtbuild committed Jul 11, 2024
1 parent d5fd526 commit dae8243
Show file tree
Hide file tree
Showing 5 changed files with 239 additions and 213 deletions.
2 changes: 1 addition & 1 deletion datatables.json
Original file line number Diff line number Diff line change
Expand Up @@ -11,5 +11,5 @@
],
"src-repo": "http://github.com/DataTables/DataTablesSrc",
"last-tag": "2.0.8",
"last-sync": "f1ef76c7cea1f30eacc5e01daf7729b9c69c8f78"
"last-sync": "1c2b8525f8b36c5161993c9c564f77aa5cf7b165"
}
223 changes: 118 additions & 105 deletions js/dataTables.js
Original file line number Diff line number Diff line change
Expand Up @@ -3574,140 +3574,153 @@


/**
* Convert a `layout` object given by a user to the object structure needed
* for the renderer. This is done twice, once for above and once for below
* the table. Ordering must also be considered.
*
* @param {*} settings DataTables settings object
* @param {*} layout Layout object to convert
* @param {string} side `top` or `bottom`
* @returns Converted array structure - one item for each row.
* Expand the layout items into an object for the rendering function
*/
function _layoutArray ( settings, layout, side )
{
var groups = {};

// Combine into like groups (e.g. `top`, `top2`, etc)
$.each( layout, function ( pos, val ) {
if (val === null) {
return;
function _layoutItems (row, align, items) {
if ( Array.isArray(items)) {
for (var i=0 ; i<items.length ; i++) {
_layoutItems(row, align, items[i]);
}

var splitPos = pos.replace(/([A-Z])/g, ' $1').split(' ');

if ( ! groups[ splitPos[0] ] ) {
groups[ splitPos[0] ] = {};
}
return;
}

var align = splitPos.length === 1 ?
'full' :
splitPos[1].toLowerCase();
var group = groups[ splitPos[0] ];
var groupRun = function (group, align, innerVal) {
// Allow for an array or just a single object
if ( Array.isArray(innerVal)) {
for (var i=0 ; i<innerVal.length ; i++) {
groupRun(group, align, innerVal[i]);
}
var rowCell = row[align];

return;
// If it is an object, then there can be multiple features contained in it
if ( $.isPlainObject( items ) ) {
// A feature plugin cannot be named "features" due to this check
if (items.features) {
if (items.rowId) {
row.id = items.rowId;
}
if (items.rowClass) {
row.className = items.rowClass;
}

var groupCell = group[align];
rowCell.id = items.id;
rowCell.className = items.className;

// If it is an object, then there can be multiple features contained in it
if ( $.isPlainObject( innerVal ) ) {
// A feature plugin cannot be named "features" due to this check
if (innerVal.features) {
if (innerVal.rowId) {
group.id = innerVal.rowId;
}
if (innerVal.rowClass) {
group.className = innerVal.rowClass;
}
_layoutItems(row, align, items.features);
}
else {
Object.keys(items).map(function (key) {
rowCell.contents.push( {
feature: key,
opts: items[key]
});
});
}
}
else {
rowCell.contents.push(items);
}
}

groupCell.id = innerVal.id;
groupCell.className = innerVal.className;
/**
* Find, or create a layout row
*/
function _layoutGetRow(rows, rowNum, align) {
var row;

groupRun(group, align, innerVal.features);
}
else {
Object.keys(innerVal).map(function (key) {
groupCell.contents.push( {
feature: key,
opts: innerVal[key]
});
});
// Find existing rows
for (var i=0; i<rows.length; i++) {
row = rows[i];

if (row.rowNum === rowNum) {
// full is on its own, but start and end share a row
if (
(align === 'full' && row.full) ||
((align === 'start' || align === 'end') && (row.start || row.end))
) {
if (! row[align]) {
row[align] = {
contents: []
};
}
}
else {
groupCell.contents.push(innerVal);

return row;
}
}
}

// Transform to an object with a contents property
if (! group[align] || ! group[align].contents) {
group[align] = { contents: [] };
}
// If we get this far, then there was no match, create a new row
row = {
rowNum: rowNum
};

groupRun(group, align, val);
row[align] = {
contents: []
};

// And make contents an array
if ( ! Array.isArray( group[ align ].contents ) ) {
group[ align ].contents = [ group[ align ].contents ];
}
} );
rows.push(row);

var filtered = Object.keys(groups)
.map( function ( pos ) {
// Filter to only the side we need
if ( pos.indexOf(side) !== 0 ) {
return null;
}
return row;
}

return {
name: pos,
val: groups[pos]
};
} )
.filter( function (item) {
return item !== null;
});
/**
* Convert a `layout` object given by a user to the object structure needed
* for the renderer. This is done twice, once for above and once for below
* the table. Ordering must also be considered.
*
* @param {*} settings DataTables settings object
* @param {*} layout Layout object to convert
* @param {string} side `top` or `bottom`
* @returns Converted array structure - one item for each row.
*/
function _layoutArray ( settings, layout, side ) {
var rows = [];

// Split out into an array
$.each( layout, function ( pos, items ) {
if (items === null) {
return;
}

// Order by item identifier
filtered.sort( function ( a, b ) {
var order1 = a.name.replace(/[^0-9]/g, '') * 1;
var order2 = b.name.replace(/[^0-9]/g, '') * 1;
var parts = pos.match(/^([a-z]+)([0-9]*)([A-Za-z]*)$/);
var rowNum = parts[2]
? parts[2] * 1
: 0;
var align = parts[3]
? parts[3].toLowerCase()
: 'full';

return order2 - order1;
} );

if ( side === 'bottom' ) {
filtered.reverse();
}
// Filter out the side we aren't interested in
if (parts[1] !== side) {
return;
}

// Split into rows
var rows = [];
// Get or create the row we should attach to
var row = _layoutGetRow(rows, rowNum, align);

for (var i=0, ien=filtered.length; i<ien; i++) {
var val = filtered[i].val;
_layoutItems(row, align, items);
});

if ( val.full ) {
rows.push({
className: val.className,
id: val.id,
full: val.full
});
// Order by item identifier
rows.sort( function ( a, b ) {
var order1 = a.rowNum;
var order2 = b.rowNum;

delete val.full;
}
// If both in the same row, then the row with `full` comes first
if (order1 === order2) {
var ret = a.full && ! b.full ? -1 : 1;

if (val.start || val.end) {
rows.push(val);
return side === 'bottom'
? ret * -1
: ret;
}

return order2 - order1;
} );

// Invert for below the table
if ( side === 'bottom' ) {
rows.reverse();
}

for (var row = 0; row<rows.length; row++) {
delete rows[row].rowNum;

_layoutResolve(settings, rows[row]);
}

Expand Down
2 changes: 1 addition & 1 deletion js/dataTables.min.js

Large diffs are not rendered by default.

2 changes: 1 addition & 1 deletion js/dataTables.min.mjs

Large diffs are not rendered by default.

Loading

0 comments on commit dae8243

Please sign in to comment.