Project

General

Profile

Feature #6571 ยป redmine_totals.user.js

Greasemonkey/Scritish user script to totalise numeric columns in Redmine issue lists - James Robertson, 2011-09-14 07:15

 
1
// ==UserScript==
2
// @id             redmine_totals
3
// @name           Redmine Totals
4
// @version        0.1
5
// @namespace      http://jamesarobertson.co.nz/
6
// @author         James Robertson
7
// @description    Redmine issue list totals
8
// @run-at         document-end
9
// ==/UserScript==
10

    
11
function isDate(str) {
12
	return !isNaN(Date.parse(str));
13
}
14

    
15
function isNumber(n) {
16
	return !isNaN(parseFloat(n)) && isFinite(n);
17
}
18

    
19
function addRowValuesToTotals(row, totals) {
20
	var cell_content;
21
	var cell_value;
22
	var cells = row.getElementsByTagName('td');
23
	for (var col_num=2; col_num<cells.length; col_num++) {
24
		cell_content = cells[col_num].innerHTML;
25
		if (!isDate(cell_content)) {
26
			cell_value = parseFloat(cell_content);
27
			if (isNumber(cell_value)){
28
				if(!totals[col_num].total) {
29
					totals[col_num].total = 0;
30
					totals[col_num].group_total = 0;
31
				}
32
				totals[col_num].total += cell_value;
33
				totals[col_num].group_total += cell_value;
34
			}
35
		}
36
	}
37
	return totals;
38
}
39

    
40
function insertTotalsRow(table_body, totals, is_group_total, before_row) {
41
	if(is_group_total==null) is_group_total = false;
42

    
43
	var totals_row = document.createElement('tr');
44

    
45
	totals_row.style.textAlign = 'center';
46
	if (!is_group_total){
47
		totals_row.style.borderTop = "1px solid #CCCCCC";
48
		totals_row.style.fontWeight = 'bold';
49
	}
50

    
51
	var cell;
52
	for (var col_num=1; col_num<totals.length; col_num++){
53
		cell = document.createElement('td');
54
		if (col_num == 1) {
55
			cell.colSpan = 2;
56
			if (is_group_total) {
57
				cell.innerHTML = '&nbsp;';
58
			} else {
59
				cell.innerHTML = 'Total';
60
			}
61
		} else {
62
			if (totals[col_num].total){
63
				if(is_group_total) {
64
					cell.innerHTML = totals[col_num].group_total;
65
					cell.style.borderTop = "1px solid #CCCCCC";
66
				} else {
67
					cell.innerHTML = totals[col_num].total;
68
				}
69
			} else {
70
				cell.innerHTML = '&nbsp;';
71
			}
72
		}
73
		totals_row.appendChild(cell);
74
	}
75
	if(before_row != null){
76
		table_body.insertBefore(totals_row, before_row);
77
	} else {
78
		table_body.appendChild(totals_row);
79
	}
80
}
81

    
82
function main() {
83
	var issues_table = document.getElementsByClassName('list issues')[0];
84
	if(!issues_table) return;
85

    
86
	var head_cells = issues_table.getElementsByTagName('th');
87
	var table_body = issues_table.getElementsByTagName('tbody')[0];
88
	var table_rows = table_body.getElementsByTagName('tr');
89

    
90
	var totals = new Array();
91
	var has_groups = false;
92
	var has_multiple_groups = false;
93

    
94
	for (var col_num=0; col_num<head_cells.length; col_num++) {
95
		totals[col_num] = new Object();
96
	}
97

    
98
	for (var row_num=0; row_num<table_rows.length; row_num++) {
99
		if(table_rows[row_num].className.indexOf('group') >= 0){
100
			if (!has_groups) {
101
				has_groups = true;
102
			} else {
103
				has_multiple_groups = true;
104
				insertTotalsRow(table_body, totals, true, table_rows[row_num]);
105
				for (var col_num=0; col_num<totals.length; col_num++){
106
					if (totals[col_num].total){
107
						totals[col_num].group_total = 0;
108
					}
109
				}
110
				row_num++;
111
			}
112
		} else {
113
			totals = addRowValuesToTotals(table_rows[row_num], totals);
114
		}
115
	}
116

    
117
	if (has_multiple_groups) {
118
		insertTotalsRow(table_body, totals, true);
119
	}
120
	insertTotalsRow(table_body, totals);
121
}
122

    
123
main();
    (1-1/1)