Create data reports using javascript function
Assume you have a sporting event or competition. Most likely the results will be stored in a database and have to be listed on a website. You can use the Fetch API to fetch the data from the backend. This will not be explained in this document. I assume the data has already been retrieved and is an array of records. This array of records has to be in the correct order, but the source function can filter and sort the array on the fly within the report engine.
This document decribes how to define headers and footers very easily and how to arrange record grouping by compare function as well.
Each header function returns html based on static text and parameters currentRecord, objWork and splitPosition. Each footer function returns html based on static text and parameters previousRecord, objWork and splitPosition.
It is very flexible, but you have to make the html yourself! Don't expect a WYSIWYG editor.
General structure of a report
- Report has a report header and footer. Can be text or just html or both.
- Report has one or more section levels. Section level N starts with header level N and ends with footer level N.
- Section level N contains one or more times section level N 1, except the highest section level.
- Highest section level contains the data created based on the records in the array. In most cases highest section level is just a html table or html flex item.
Example of report structure

Structure of report definition object called reportDefinition
const reportDefinition = {};
reportDefinition.headers = [report_header, header_level_1, header_level_2, header_level_3, ...]; // default = []
reportDefinition.footers = [report_footer, footer_level_1, footer_level_2, footer_level_3, ...]; // default = []
reportDefinition.compare = (previousRecord, currentRecord, objWork) => {
// default = () => -1
// code that returns an integer (report level break number)
};
reportDefinition.display = (currentRecord, objWork) => {
// code that returns a string, for example
return `${currentRecord.team} - ${currentRecord.player}`;
};
// source array can be preprocessed, for example filter or sort
reportDefinition.source = (arr, objWork) => preProcessFuncCode(arr); // optional function to preprocess data array
// example to add extra field for HOME and AWAY and sort afterwards
reportDefinition.source = (arr, objWork) => arr.flatMap(val => [{ team: val.team1, ...val }, { team: val.team2, ...val }])
.sort((a, b) => a.team.localeCompare(b.team));
// optional method 'init' which should be a function. It will be called with argument objWork
// can be used to initialize some things.
reportDefinition.init = objWork => { ... };
Examples of headers and footers array elements
reportDefinition.headers = [];
// currentRecord=current record, objWork is extra object,
// splitPosition=0 if this is the first header shown at this place, otherwise it is 1, 2, 3 ...
reportDefinition.headers[0] = (currentRecord, objWork, splitPosition) => {
// code that returns a string
};
reportDefinition.headers[1] = '<div>Some string</div>'; // string instead of function is allowed;
reportDefinition.footers = [];
// previousRecord=previous record, objWork is extra object,
// splitPosition=0 if this is the last footer shown at this place, otherwise it is 1, 2, 3 ...
reportDefinition.footers[0] = (previousRecord, objWork, splitPosition) => {
// code that returns a string
};
reportDefinition.footers[1] = '<div>Some string</div>'; // string instead of function is allowed;
Example of compare function
// previousRecord=previous record, currentRecord=current record, objWork is extra object,
reportDefinition.compare = (previousRecord, currentRecord, objWork) => {
// please never return 0! headers[0] will be displayed automagically on top of report
// group by date return 1 (lowest number first)
if (previousRecord.date !== currentRecord.date) return 1;
// group by team return 2
if (previousRecord.team !== currentRecord.team) return 2;
// assume this function returns X (except -1) then:
// footer X upto and include LAST footer will be displayed (in reverse order). In case of footer function the argument is previous record
// header X upto and include LAST header will be displayed. In case of header function the argument is current record
// current record will be displayed
//
// if both records belong to same group return -1
return -1;
};
Running counter
In case you want to implement a running counter, you have to initialize/reset it in the right place. It can be achieved by putting some code in the relevant header:
reportDefinition.headers[2] = (currentRecord, objWork, splitPosition) => {
// this is a new level 2 group. Reset objWork.runningCounter to 0
objWork.runningCounter = 0;
// put extra code here
return `<div>This is header number 2: ${currentRecord.team}</div>`;
};
If you only want to initialize objWork.runningCounter at the beginning of the report you can achieve that by putting the right code in reportDefinition.headers[0]. I call it property runningCounter, but you can give it any name you want.
You have to increase the running counter somewhere in your code because... otherwise it is not running ;-) for example:
const reportDefinition = {};
reportDefinition.headers = [report_header, header_level_1, header_level_2, header_level_3, ...]; // default = []
reportDefinition.footers = [report_footer, footer_level_1, footer_level_2, footer_level_3, ...]; // default = []
reportDefinition.compare = (previousRecord, currentRecord, objWork) => {
// default = () => -1
// code that returns an integer (report level break number)
};
reportDefinition.display = (currentRecord, objWork) => {
// code that returns a string, for example
return `${currentRecord.team} - ${currentRecord.player}`;
};
// source array can be preprocessed, for example filter or sort
reportDefinition.source = (arr, objWork) => preProcessFuncCode(arr); // optional function to preprocess data array
// example to add extra field for HOME and AWAY and sort afterwards
reportDefinition.source = (arr, objWork) => arr.flatMap(val => [{ team: val.team1, ...val }, { team: val.team2, ...val }])
.sort((a, b) => a.team.localeCompare(b.team));
// optional method 'init' which should be a function. It will be called with argument objWork
// can be used to initialize some things.
reportDefinition.init = objWork => { ... };
How to create totals for multiple section levels, a running total and even a numbered header
reportDefinition.headers = [];
// currentRecord=current record, objWork is extra object,
// splitPosition=0 if this is the first header shown at this place, otherwise it is 1, 2, 3 ...
reportDefinition.headers[0] = (currentRecord, objWork, splitPosition) => {
// code that returns a string
};
reportDefinition.headers[1] = '<div>Some string</div>'; // string instead of function is allowed;
reportDefinition.footers = [];
// previousRecord=previous record, objWork is extra object,
// splitPosition=0 if this is the last footer shown at this place, otherwise it is 1, 2, 3 ...
reportDefinition.footers[0] = (previousRecord, objWork, splitPosition) => {
// code that returns a string
};
reportDefinition.footers[1] = '<div>Some string</div>'; // string instead of function is allowed;
How to preprocess the source array on the fly (for example in click event)
// previousRecord=previous record, currentRecord=current record, objWork is extra object,
reportDefinition.compare = (previousRecord, currentRecord, objWork) => {
// please never return 0! headers[0] will be displayed automagically on top of report
// group by date return 1 (lowest number first)
if (previousRecord.date !== currentRecord.date) return 1;
// group by team return 2
if (previousRecord.team !== currentRecord.team) return 2;
// assume this function returns X (except -1) then:
// footer X upto and include LAST footer will be displayed (in reverse order). In case of footer function the argument is previous record
// header X upto and include LAST header will be displayed. In case of header function the argument is current record
// current record will be displayed
//
// if both records belong to same group return -1
return -1;
};
How to generate the report
reportDefinition.headers[2] = (currentRecord, objWork, splitPosition) => {
// this is a new level 2 group. Reset objWork.runningCounter to 0
objWork.runningCounter = 0;
// put extra code here
return `<div>This is header number 2: ${currentRecord.team}</div>`;
};
Source code
Below source code I created to make this all work. It is kind of wrapper function for all headers and footers. Feel free to copy paste it and use it in your own module.
reportDefinition.display = (currentRecord, objWork) => {
objWork.runningCounter++;
// put extra code here
return `<div>This is record number ${objWork.runningCounter}: ${currentRecord.team} - ${currentRecord.player}</div>`;
};
What is objWork
objWork is a javascript object that is passed as the second argument to createOutput function (optional argument, default {}). It is passed on as shallow copy to headers functions, footers functions, compare function, init function, source function and display function. All these functions share this object. You can use it for example for configuration information or color theme. objWork is automagically extended with { rawData: thisData }. For example createOutput(reportDefinition, { font: 'Arial', font_color: 'blue' }).
Examples
The examples listed below are written in Dutch.
Reports for billiard club
Reports for billiard scores
More reports for carom billiards
Reports for petanque
and many more....
The above is the detailed content of Create data reports using javascript function. For more information, please follow other related articles on the PHP Chinese website!
Hot AI Tools
Undresser.AI Undress
AI-powered app for creating realistic nude photos
AI Clothes Remover
Online AI tool for removing clothes from photos.
Undress AI Tool
Undress images for free
Clothoff.io
AI clothes remover
AI Hentai Generator
Generate AI Hentai for free.
Hot Article
Hot Tools
Notepad++7.3.1
Easy-to-use and free code editor
SublimeText3 Chinese version
Chinese version, very easy to use
Zend Studio 13.0.1
Powerful PHP integrated development environment
Dreamweaver CS6
Visual web development tools
SublimeText3 Mac version
God-level code editing software (SublimeText3)
Hot Topics
1379
52
How do I create and publish my own JavaScript libraries?
Mar 18, 2025 pm 03:12 PM
Article discusses creating, publishing, and maintaining JavaScript libraries, focusing on planning, development, testing, documentation, and promotion strategies.
How do I optimize JavaScript code for performance in the browser?
Mar 18, 2025 pm 03:14 PM
The article discusses strategies for optimizing JavaScript performance in browsers, focusing on reducing execution time and minimizing impact on page load speed.
What should I do if I encounter garbled code printing for front-end thermal paper receipts?
Apr 04, 2025 pm 02:42 PM
Frequently Asked Questions and Solutions for Front-end Thermal Paper Ticket Printing In Front-end Development, Ticket Printing is a common requirement. However, many developers are implementing...
How do I debug JavaScript code effectively using browser developer tools?
Mar 18, 2025 pm 03:16 PM
The article discusses effective JavaScript debugging using browser developer tools, focusing on setting breakpoints, using the console, and analyzing performance.
Who gets paid more Python or JavaScript?
Apr 04, 2025 am 12:09 AM
There is no absolute salary for Python and JavaScript developers, depending on skills and industry needs. 1. Python may be paid more in data science and machine learning. 2. JavaScript has great demand in front-end and full-stack development, and its salary is also considerable. 3. Influencing factors include experience, geographical location, company size and specific skills.
How do I use source maps to debug minified JavaScript code?
Mar 18, 2025 pm 03:17 PM
The article explains how to use source maps to debug minified JavaScript by mapping it back to the original code. It discusses enabling source maps, setting breakpoints, and using tools like Chrome DevTools and Webpack.
The difference in console.log output result: Why are the two calls different?
Apr 04, 2025 pm 05:12 PM
In-depth discussion of the root causes of the difference in console.log output. This article will analyze the differences in the output results of console.log function in a piece of code and explain the reasons behind it. �...
How to merge array elements with the same ID into one object using JavaScript?
Apr 04, 2025 pm 05:09 PM
How to merge array elements with the same ID into one object in JavaScript? When processing data, we often encounter the need to have the same ID...


