And the “finished” product … I’m not a javascript expert and I tried to give credit to the original poster but the link I had wasn’t valid.
Also … the resultant data is only as good as the analysis and I’ve found that the “pre-canned” analysis “Installed Applications - Windows” is not returning certain application installations. I’m still working on it but used the original analysis in this code as it is most commonly used.
Please feel free to update/change just post any important/major changes so we can all get up to speed!
Enjoy!
<!--
Dynamic Installed Application Search from Analysis
Analysis: Installed Applications - Windows
Analysis Source: Application Information (Windows)
Anaysis Site: Site BES Inventory and License
Code Crediting:
Original Post: http://forum.bigfix.com/viewtopic.php?pid=22938 <-- page not found -- link format changed at some point
Reposted code found at: https://forum.bigfix.com/t/bigfix-web-report-no-longer-working-fixlet-fixdate-by-computergroup-w-date-search/36822
Code updated and repurposed for Dynamic Application Search by Idiopathic - 04/28/2025
Updated code posted to: https://forum.bigfix.com/t/report-of-computers-with-installed-applications-by-application-name/51596/6
-->
<style type="text/css">
body {
background-color: #B5D3F4;
}
a {
text-decoration: none;
}
a.hover {
color: #FF8000;
font-weight: bold;
text-decoration: none;
}
table {
width: 100%;
border: 1px solid black;
}
table.sortable {
margin: 0;
border-collapse: collapse;
color: #222;
font: 10pt verdana, geneva, lucida, 'lucida grande', arial, helvetica, sans-serif;
}
th.res {
font: 10pt verdana, geneva, lucida, 'lucida grande', arial, helvetica, sans-serif;
color: navy;
font-weight: bold;
background-color: #F2F2F2;
border: 1px solid #cccccc;
margin: 0;
padding: 4px 10px 4px 5px;
text-align: left;
}
td.res {
color: #222;
font: 8pt verdana, geneva, lucida, 'lucida grande', arial, helvetica, sans-serif;
border-bottom: 1px solid #cccccc;
margin: 0;
/* padding: 6px 20px 1px 0; */
padding: 8px 20px 5px 5px;
}
td.userinput {
color: #222;
font: 10pt verdana, geneva, lucida, 'lucida grande', arial, helvetica, sans-serif;
font-weight: bold;
border-bottom: 0px;
margin: 0;
padding: 6px 20px 1px 0;
}
td.errormsg {
color: red;
font: 10pt verdana, geneva, lucida, 'lucida grande', arial, helvetica, sans-serif;
font-weight: bold;
border-bottom: 0px;
margin: 0;
padding: 6px 20px 1px 0;
}
td.msg {
color: #747170;
font: 10pt verdana, geneva, lucida, 'lucida grande', arial, helvetica, sans-serif;
font-weight: bold;
border-bottom: 0px;
margin: 0;
padding: 6px 20px 1px 0;
}
h3 {
font: 10pt verdana, geneva, lucida, 'lucida grande', arial, helvetica, sans-serif;
background-color: #747170;
padding: 4px 4px 4px 4px;
color: white;
width: 100%;
}
</style>
<table>
<tr>
<td class="userinput">
Enter any part of the Application Name:
</td>
<td colspan=2 class="userinput">
<input type="text" id="userQuery" name="userQuery" style="wisdth:100%">
</td>
<td class="userinput">
<input type='button' onclick='search()' value='Filter'/>
</td>
<td class="userinput">
-- OR --
</td>
<td class="userinput">
<input type='button' onclick='showAll()' value='Show All Installed Applications'/>
</td>
</tr>
</table>
<hr />
<div id="resultsDiv">
</div>
<script type="text/javascript">
addEvent(window, "load", init_load);
var divRes = document.getElementById('resultsDiv');
var computerFilter;
var res_count;
function search() {
if (document.getElementById('userQuery').value == '')
{
divRes.style.display = 'block';
divRes.innerHTML = 'Please provide a search parameter';
return;
}
divRes.style.display = 'block';
divRes.innerHTML = 'Processing...';
var relevance = '(html "<table id=%22resultsTable%22 class=%22sortable%22><tr class=%22res%22><th class=%22res%22>Computer</th><th class=%22res%22>Application</th><th class=%22res%22>Version</th></tr>" & it & html "</table>") of concatenation of trs "class=%22res%22" of (item 0 of it & item 0 of item 1 of it & item 1 of item 1 of it) of ((tds "class=%22res%22" of names of it, (tds "class=%22res%22" of preceding texts of firsts " |" of it, tds "class=%22res%22" of following texts of firsts "| " of it) of values of results from (bes properties whose (name of it is "Installed Applications - Windows")) of it) of (bes computers)) whose (item - of item 1 of it as string as lowercase contains ("' + document.getElementById('userQuery').value + '" as lowercase))';
strResponse = EvaluateRelevance(relevance);
divRes.innerHTML = strResponse;
sortables_init();
stripe('resultsTable', '#fff', '#E6E3E8');
}
function showAll() {
divRes.style.display = 'block';
divRes.innerHTML = 'Processing...';
var relevance = '(html "<table id=%22resultsTable%22 class=%22sortable%22><tr class=%22res%22><th class=%22res%22>Computer</th><th class=%22res%22>Application</th><th class=%22res%22>Version</th></tr>" & it & html "</table>") of concatenation of trs "class=%22res%22" of (item 0 of it & item 0 of item 1 of it & item 1 of item 1 of it) of ((tds "class=%22res%22" of names of it, (tds "class=%22res%22" of preceding texts of firsts " |" of it, tds "class=%22res%22" of following texts of firsts "| " of it) of values of results from (bes properties whose (name of it is "Installed Applications - Windows")) of it) of (bes computers))';
strResponse = EvaluateRelevance(relevance);
divRes.innerHTML = strResponse;
sortables_init();
stripe('resultsTable', '#fff', '#E6E3E8');
}
function init_load() {
}
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
for (var i = 0; i < firstRow.cells.length; i++) {
var cell = firstRow.cells[i];
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[i].nodeType) {
case 1: // ELEMENT_NODE
str += ts_getInnerText(cs[i]);
break;
case 3: // TEXT_NODE
str += cs[i].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\.]+$/))
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[i] = table.rows[0][i];
}
for (j = 1; j < table.rows.length; j++) {
newRows[j - 1] = table.rows[j];
}
newRows.sort(sortfn);
if (span.getAttribute("sortdir") == 'down') {
ARROW = ' <img src="/images/besreports/ENU/maximizebutton1.gif" border="0" height="12" width="15" alt="">';
newRows.reverse();
span.setAttribute('sortdir', 'up');
}
else {
ARROW = ' <img src="/images/besreports/ENU/minimizebutton1.gif" border="0" height="12" width="15" alt="">';
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[i].className || (newRows[i].className && (newRows[i].className.indexOf('sortbottom') == -1))) {
table.tBodies[0].appendChild(newRows[i]);
if (i % 2 > 0)
newRows[i].className = 'wr_oddRow';
else
newRows[i].className = 'wr_evenRow';
}
}
// do sortbottom rows only
for (i = 0; i < newRows.length; i++) {
if (newRows[i].className && (newRows[i].className.indexOf('sortbottom') != -1))
table.tBodies[0].appendChild(newRows[i]);
}
// Delete any other arrows that 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 = ' ';
}
}
}
// adds up/down arrow to the column header
span.innerHTML = ARROW;
// Make zebra stripes in table
stripe('resultsTable', '#fff', '#E6E3E8');
}
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_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");
}
}
// this function is needed to work around
// a bug in IE related to element attributes
function hasClass(obj) {
var result = false;
if (obj.getAttributeNode("class") != null) {
result = obj.getAttributeNode("class").value;
}
return result;
}
function stripe(id) {
// the flag we'll use to keep track of
// whether the current row is odd or even
var even = false;
// if arguments are provided to specify the colors
// of the even & odd rows, then use them;
// otherwise use the following defaults:
var evenColor = arguments[1] ? arguments[1] : "#fff";
var oddColor = arguments[2] ? arguments[2] : "#eee";
// obtain a reference to the desired table
// if no such table exists, abort
var table = document.getElementById(id);
if (!table) { return; }
// by definition, tables can have more than one tbody
// element, so we'll have to get the list of child
// <tbody>s
var tbodies = table.getElementsByTagName("tbody");
// and iterate through them ...
for (var h = 0; h < tbodies.length; h++) {
// find all the <tr> elements ...
var trs = tbodies[h].getElementsByTagName("tr");
// and iterate through them ...
for (var i = 0; i < trs.length; i++) {
// get all the cells in this row ...
var tds = trs[i].getElementsByTagName("td");
// and iterate through them ...
for (var j = 0; j < tds.length; j++) {
var mytd = tds[j];
mytd.style.backgroundColor = even ? evenColor : oddColor;
}
// flip from odd to even, or vice-versa
even = ! even;
}
}
}
</script>