(imported comment written by BenKus)
Hi abrice / jesseR,
How about this (I stole this from Jesse here at BigFix)… It is close to what you want:
<div><b>Last Updated: <?relevance now ?></b></div> <br> <table class=
"sortable" id=
"table1" border=1> <tbody> <th>Fixlet Name</th><th>Fixed</th><th>Needed</th><th>Not Needed</th> <?relevance concatenation of trs of ( td of link of it & (html tag (
"td", attr list of (
"class",
"sum"), it)) of ( it as string ) of number of results whose ( exists last became nonrelevant of it and not relevant flag of it ) of it & (html tag (
"td", attr list of (
"class",
"sum"), it)) of ( it as string ) of number of results whose ( relevant flag of it ) of it & (html tag (
"td", attr list of (
"class",
"sum"), it)) of ( it as string ) of (number of bes computers - number of computers of results of it) ) of fixlets whose ( fixlet flag of it) of bes site whose (name of it =
"Enterprise Security") ?> <tr class=sortbottom> <td><b>TOTALS</b></td> <td></td> <td></td> <td></td> </tr> </tbody> </table> <script type=
"text/javascript"> WriteSums();
//WriteCumulativePrecentages(); sortables_init(); function WriteSums()
{ var tables = document.getElementsByTagName(
'TABLE');
for (var i = 0; i < tables.length; i++)
{ var sums =
new Array(); var t = tables+; var rows = t.rows;
for (var j = 1; j < rows.length - 1; j++)
{ var cells = rows[j].cells;
for (var k = 0; k < cells.length; k++)
{
if (cells[k].className ==
"sum")
{
if (sums[k])
{ sums[k] += parseFloat(cells[k].innerText);
}
else
{ sums[k] = parseFloat(cells[k].innerText);
}
}
}
}
for (var a = 0; a < sums.length; a++)
{
if (sums[a])
{ t.rows[t.rows.length - 1].cells[a].innerText = sums[a];
}
}
}
} function WriteCumulativePrecentages()
{ lastCells = table1.rows[table1.rows.length - 1].cells; lastCells[4].innerText = (parseInt( lastCells[1].innerText , 10 ) / parseInt( lastCells[3].innerText , 10 ) * 100).toFixed(2) +
'%';
}
/** The MIT Licence, for code from kryogenix.org Code downloaded from the Browser Experiments section of kryogenix.org is licenced under the so-called MIT licence. The licence is below. Copyright (c) 1997-date Stuart Langridge Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. **/ var SORT_COLUMN_INDEX; function sortables_init()
{
// Find all tables with class sortable and make them sortable
if (!document.getElementsByTagName)
return; tbls = document.getElementsByTagName(
"table");
for (ti=0;ti<tbls.length;ti++)
{ thisTbl = tbls[ti];
if (((
' '+thisTbl.className+
' ').indexOf(
"sortable") != -1) && (thisTbl.id))
{
//initTable(thisTbl.id); ts_makeSortable(thisTbl);
}
}
} function ts_makeSortable(table)
{
if (table.rows && table.rows.length > 0)
{ var firstRow = table.rows[0];
}
if (!firstRow)
return;
// We have a first row: assume it's the header, and make its contents clickable links
// Skip cells with class 'notsortable' -- JWK 09/15/2006
for (var i=0;i<firstRow.cells.length;i++)
{ var cell = firstRow.cells+;
if (cell.className ==
'notsortable')
{
continue;
} var txt = ts_getInnerText(cell); cell.innerHTML =
'<a href="#" class="sortheader" '+
'onclick="ts_resortTable(this, '+i+
');return false;">' + txt+
'<span class="sortarrow"> </span></a>';
}
} function ts_getInnerText(el)
{
if (typeof el ==
"string")
return el;
if (typeof el ==
"undefined")
{
return el
};
if (el.innerText)
return el.innerText;
//Not needed but it is faster var str =
""; var cs = el.childNodes; var l = cs.length;
for (var i = 0; i < l; i++)
{
switch (cs+.nodeType)
{
case 1:
//ELEMENT_NODE str += ts_getInnerText(cs+);
break;
case 3:
//TEXT_NODE str += cs+.nodeValue;
break;
}
}
return str;
} function ts_resortTable(lnk,clid)
{
// get the span var span;
for (var ci=0;ci<lnk.childNodes.length;ci++)
{
if (lnk.childNodes[ci].tagName && lnk.childNodes[ci].tagName.toLowerCase() ==
'span') span = lnk.childNodes[ci];
} var spantext = ts_getInnerText(span); var td = lnk.parentNode; var column = clid || td.cellIndex; var table = getParent(td,
'TABLE');
// Work out a type for the column
if (table.rows.length <= 1)
return; var itm = ts_getInnerText(table.rows[1].cells[column]); sortfn = ts_sort_caseinsensitive;
if (itm.match(/^\d\d[\/-]\d\d[\/-]\d\d\d\d$/)) sortfn = ts_sort_date;
if (itm.match(/^\d\d[\/-]\d\d[\/-]\d\d$/)) sortfn = ts_sort_date;
if (itm.match(/^[£$]/)) sortfn = ts_sort_currency;
if (itm.match(/^[\d\.]+$/)) sortfn = ts_sort_numeric; SORT_COLUMN_INDEX = column; var firstRow =
new Array(); var newRows =
new Array();
for (i=0;i<table.rows[0].length;i++)
{ firstRow+ = table.rows[0]+;
}
for (j=1;j<table.rows.length;j++)
{ newRows[j-1] = table.rows[j];
} newRows.sort(sortfn);
if (span.getAttribute(
"sortdir") ==
'down')
{ ARROW =
' ↑'; newRows.reverse(); span.setAttribute(
'sortdir',
'up');
}
else
{ ARROW =
' ↓'; span.setAttribute(
'sortdir',
'down');
}
// We appendChild rows that already exist to the tbody, so it moves them rather than creating new ones
// don't do sortbottom rows
for (i=0;i<newRows.length;i++)
{
if (!newRows+.className || (newRows+.className && (newRows+.className.indexOf(
'sortbottom') == -1)))
{ table.tBodies[0].appendChild(newRows+);
if (i % 2 > 0) newRows+.className =
'wr_oddRow';
else newRows+.className =
'wr_evenRow';
}
}
// do sortbottom rows only
for (i=0;i<newRows.length;i++)
{
if (newRows+.className && (newRows+.className.indexOf(
'sortbottom') != -1)) table.tBodies[0].appendChild(newRows+);
}
// Delete any other arrows there may be showing var allspans = document.getElementsByTagName(
"span");
for (var ci=0;ci<allspans.length;ci++)
{
if (allspans[ci].className ==
'sortarrow')
{
if (getParent(allspans[ci],
"table") == getParent(lnk,
"table"))
{
// in the same table as us? allspans[ci].innerHTML =
' ';
}
}
} span.innerHTML = ARROW;
} function getParent(el, pTagName)
{
if (el ==
null)
return
null;
else
if (el.nodeType == 1 && el.tagName.toLowerCase() == pTagName.toLowerCase())
// Gecko bug, supposed to be uppercase
return el;
else
return getParent(el.parentNode, pTagName);
} function ts_sort_date_JWK(a,b)
{
// y2k notes: two digit years less than 50 are treated as 20XX, greater than 50 are treated as 19XX aa = ts_getInnerText(a.cells[SORT_COLUMN_INDEX]); bb = ts_getInnerText(b.cells[SORT_COLUMN_INDEX]);
if (aa.length == 10)
{ dt1 = aa.substr(6,4)+aa.substr(3,2)+aa.substr(0,2);
}
else
if (aa.length == 8 && parseInt(aa.substr(6,2)) && parseInt(aa.substr(3,2)) && parseInt(aa.substr(0,2)))
{ yr = aa.substr(6,2);
if (parseInt(yr) < 50)
{ yr =
'20'+yr;
}
else
{ yr =
'19'+yr;
} dt1 = yr+aa.substr(3,2)+aa.substr(0,2);
}
else
{
return ts_sort_default(aa,bb);
}
if (bb.length == 10)
{ dt2 = bb.substr(6,4)+bb.substr(3,2)+bb.substr(0,2);
}
else
if (bb.length == 8 && parseInt(bb.substr(6,2)) && parseInt(bb.substr(3,2)) && parseInt(bb.substr(0,2)))
{ yr = bb.substr(6,2);
if (parseInt(yr) < 50)
{ yr =
'20'+yr;
}
else
{ yr =
'19'+yr;
} dt2 = yr+bb.substr(3,2)+bb.substr(0,2);
}
else
{
return ts_sort_default(aa,bb);
}
if (dt1==dt2)
return 0;
if (dt1<dt2)
return -1;
return 1;
} function ts_sort_date(a,b)
{
// y2k notes: two digit years less than 50 are treated as 20XX, greater than 50 are treated as 19XX aa = ts_getInnerText(a.cells[SORT_COLUMN_INDEX]); bb = ts_getInnerText(b.cells[SORT_COLUMN_INDEX]);
if (aa.length == 10)
{ dt1 = aa.substr(6,4)+aa.substr(3,2)+aa.substr(0,2);
}
else
{ yr = aa.substr(6,2);
if (parseInt(yr) < 50)
{ yr =
'20'+yr;
}
else
{ yr =
'19'+yr;
} dt1 = yr+aa.substr(3,2)+aa.substr(0,2);
}
if (bb.length == 10)
{ dt2 = bb.substr(6,4)+bb.substr(3,2)+bb.substr(0,2);
}
else
{ yr = bb.substr(6,2);
if (parseInt(yr) < 50)
{ yr =
'20'+yr;
}
else
{ yr =
'19'+yr;
} dt2 = yr+bb.substr(3,2)+bb.substr(0,2);
}
if (dt1==dt2)
return 0;
if (dt1<dt2)
return -1;
return 1;
} function ts_sort_currency(a,b)
{ aa = ts_getInnerText(a.cells[SORT_COLUMN_INDEX]).replace(/[^0-9.]/g,
''); bb = ts_getInnerText(b.cells[SORT_COLUMN_INDEX]).replace(/[^0-9.]/g,
'');
return parseFloat(aa) - parseFloat(bb);
} function ts_sort_numeric(a,b)
{ aa = parseFloat(ts_getInnerText(a.cells[SORT_COLUMN_INDEX]));
if (isNaN(aa)) aa = 0; bb = parseFloat(ts_getInnerText(b.cells[SORT_COLUMN_INDEX]));
if (isNaN(bb)) bb = 0;
return aa-bb;
} function ts_sort_caseinsensitive(a,b)
{ aa = ts_getInnerText(a.cells[SORT_COLUMN_INDEX]).toLowerCase(); bb = ts_getInnerText(b.cells[SORT_COLUMN_INDEX]).toLowerCase();
if (aa==bb)
return 0;
if (aa<bb)
return -1;
return 1;
} function ts_sort_default(a,b)
{ aa = ts_getInnerText(a.cells[SORT_COLUMN_INDEX]); bb = ts_getInnerText(b.cells[SORT_COLUMN_INDEX]);
if (aa==bb)
return 0;
if (aa<bb)
return -1;
return 1;
} function addEvent(elm, evType, fn, useCapture)
// addEvent and removeEvent
// cross-browser event handling for IE5+, NS6 and Mozilla
// By Scott Andrew
{
if (elm.addEventListener)
{ elm.addEventListener(evType, fn, useCapture);
return
true;
}
else
if (elm.attachEvent)
{ var r = elm.attachEvent(
"on"+evType, fn);
return r;
}
else
{ alert(
"Handler could not be removed");
}
} </script>
You can filter it if you want… Let me know what you think…
Ben