Finished commenting stackviewer.html

This commit is contained in:
Kaelin Hooper
2016-08-17 18:39:41 -07:00
parent c3c02c4f35
commit 557438033e
@@ -338,6 +338,9 @@
} }
}); });
/* CONTEXT MENU EVENT LISTENERS */
// This is attaching the BasicContext menu to the context event listern of all the objects listed in querySelectorAll()
// Essentially, this is what enables right clicks on the specified elements
var nodeList = document.querySelectorAll('#by-name-list tbody, #call-treeTree tbody, #callersTree tbody, #calleesTree tbody') var nodeList = document.querySelectorAll('#by-name-list tbody, #call-treeTree tbody, #callersTree tbody, #calleesTree tbody')
for (var i = 0; i < nodeList.length; ++i) { for (var i = 0; i < nodeList.length; ++i) {
var node = nodeList[i]; var node = nodeList[i];
@@ -356,21 +359,29 @@
}); });
} }
/* CONTEXT MENU FUNCTIONS */
// Set First (id=first-filter) and Last (id=last-filter) filters to the time range of the row that was rigt clicked on
function setTimeRange(e) { function setTimeRange(e) {
// Get the first and last metrics from this row
var first = $(e.target.parentNode).find(".firstTimeRelativeMSec").text(); var first = $(e.target.parentNode).find(".firstTimeRelativeMSec").text();
var last = $(e.target.parentNode).find(".lastTimeRelativeMSec").text(); var last = $(e.target.parentNode).find(".lastTimeRelativeMSec").text();
// Place them in first-filter and last-filter, respectively
$("#start-filter").val(first); $("#start-filter").val(first);
$("#end-filter").val(last); $("#end-filter").val(last);
// TODO: Maybe override onSubmit() for #filtersForm so that a submit() can be used instead of a simulated enter (13) keypress // This triggers the keypress by simulating an 'Enter' key press in one of the filter inputs,
// which in turn triggers a request to the server.
var press = jQuery.Event("keypress"); var press = jQuery.Event("keypress");
press.ctrlKey = false; press.ctrlKey = false;
press.which = 13; press.which = 13; // 13 == 'Enter' key
$("#start-filter").trigger(press); $("#start-filter").trigger(press);
} }
// Add this item to IncPats Filter (id=incpats-filter)
function includeItem(e) { function includeItem(e) {
// See setTimeRange(e) function for details on the following similar logic
var name = $(e.target.parentNode).find(".name-col").text(); var name = $(e.target.parentNode).find(".name-col").text();
if (name == "ROOT") { name = '^' + name; } if (name == "ROOT") { name = '^' + name; }
@@ -383,7 +394,9 @@
$("#incpats-filter").trigger(press); $("#incpats-filter").trigger(press);
} }
// Add this item to ExcPats Filter (id=excpats-filter)
function excludeItem(e) { function excludeItem(e) {
// See setTimeRange(e) function for details on the following similar logic
var name = $(e.target.parentNode).find(".name-col").text(); var name = $(e.target.parentNode).find(".name-col").text();
var excpatsFilter = $("#excpats-filter"); var excpatsFilter = $("#excpats-filter");
@@ -395,7 +408,9 @@
$("#excpats-filter").trigger(press); $("#excpats-filter").trigger(press);
} }
// Adds this item to FoldPats (id=foldpats-filter)
function foldItem(e) { function foldItem(e) {
// See setTimeRange(e) function for details on the following similar logic
var name = $(e.target.parentNode).find(".name-col").text(); var name = $(e.target.parentNode).find(".name-col").text();
var foldpatsFilter = $("#foldpats-filter"); var foldpatsFilter = $("#foldpats-filter");
@@ -407,7 +422,9 @@
$("#foldpats-filter").trigger(press); $("#foldpats-filter").trigger(press);
} }
// Clears fold-related filters
function removeAllFolding() { function removeAllFolding() {
// See setTimeRange(e) function for details on the following similar logic
$("#foldpercent-filter").val(""); $("#foldpercent-filter").val("");
$("#foldpats-filter").val(""); $("#foldpats-filter").val("");
@@ -417,7 +434,9 @@
$("#foldpats-filter").trigger(press); $("#foldpats-filter").trigger(press);
} }
// Clears all the filters
function clearFilters() { function clearFilters() {
// See setTimeRange(e) function for details on the following similar logic
$("#start-filter").val(""); $("#start-filter").val("");
$("#end-filter").val(""); $("#end-filter").val("");
$("#grouppats-filter").val(""); $("#grouppats-filter").val("");
@@ -435,23 +454,27 @@
/*_____________________________________*/ /*_____________________________________*/
/*_______ Tab Updater Function ________*/ /*______ TABLE UPDATER FUNCTION _______*/
/*_____________________________________*/ /*_____________________________________*/
/* OPTIONS: /*
"forceParentNodeId" : "id" This function iterates through the stack data and generates html table row for each node.
It takes the following paremeters:
updateTreeTableHtml(String, jQuery TreeTable Node, Deserialized Stack JSON)
*/ */
function updateTreeTableHtml(treeTableId, parentNode, stackData, options={}) { function updateTreeTableHtml(treeTableId, parentNode, stackData) {
// Iterate through each row var rowsToAppend = ""; // The string that we'll use to build up the html table
var rowsToAppend = ""; var dataIncludesSearchResults = false; // This will flip to true if any of the nodes contain a flag indicating they were the result of a search
var dataIncludesSearchResults = false;
for (var i = 0; i < stackData.length; ++i) { for (var i = 0; i < stackData.length; ++i) {
// Evaluate if node was the result of a search; if it was, as "data-find-flag=#" as an attribute on the row.
// This allows the finder to navigate to nodes that were the result of a search.
var findFlag = (stackData[i].findFlag != "" && treeTableId == "#" + $(".tabs-panel.is-active table").attr("id") ? "\" data-find-flag=\"" + stackData[i].findFlag : ""); var findFlag = (stackData[i].findFlag != "" && treeTableId == "#" + $(".tabs-panel.is-active table").attr("id") ? "\" data-find-flag=\"" + stackData[i].findFlag : "");
dataIncludesSearchResults = dataIncludesSearchResults || findFlag.length; dataIncludesSearchResults = dataIncludesSearchResults || findFlag.length;
// Some required attributes so the jQuery TreeTable works
rowsToAppend = rowsToAppend + "<tr data-tt-id=\"" + stackData[i].contextId rowsToAppend = rowsToAppend + "<tr data-tt-id=\"" + stackData[i].contextId
+ "\" data-tt-parent-id=\"" + stackData[i].parentContextId + "\" data-tt-parent-id=\"" + stackData[i].parentContextId
+ "\" data-tt-branch=\"" + stackData[i].hasChildren + "\" data-tt-branch=\"" + stackData[i].hasChildren // essentially, will it have a dropdown arrow
+ findFlag + findFlag
+ "\">"; + "\">";
@@ -465,9 +488,10 @@
<td class=\"lastTimeRelativeMSec selectable\" relevant-filter-id=\"#end-filter\">" + stackData[i].lastTimeRelativeMSec.toFixed(3) + "</td>\ <td class=\"lastTimeRelativeMSec selectable\" relevant-filter-id=\"#end-filter\">" + stackData[i].lastTimeRelativeMSec.toFixed(3) + "</td>\
</tr>"; </tr>";
} }
// Load all these html rows into the correct table
$(treeTableId).treetable("loadBranch", parentNode, rowsToAppend); // treetable treats a null node parameter as meaning root $(treeTableId).treetable("loadBranch", parentNode, rowsToAppend); // treetable treats a null node parameter as meaning root
// Open all the paths to nodes found from a search
if (dataIncludesSearchResults) { if (dataIncludesSearchResults) {
$(treeTableId + " tbody tr").each(function(index) { $(treeTableId + " tbody tr").each(function(index) {
var hasChildren = $(treeTableId).treetable("node", $(this).attr("data-tt-id")).children.length > 0; var hasChildren = $(treeTableId).treetable("node", $(this).attr("data-tt-id")).children.length > 0;
@@ -478,42 +502,51 @@
/*_____________________________________*/ /*_____________________________________*/
/*__________ Event Listeners __________*/ /*_______ TABLE EVENT LISTENERS _______*/
/*_____________________________________*/ /*_____________________________________*/
/* by-name-list click event */ /*
by-name-list click event
Sets the new focus node to be the clicked node and reloads the stack data, given the new context
*/
$(document).on("dblclick", "#by-name-list tbody tr td:first-child", function (row) { $(document).on("dblclick", "#by-name-list tbody tr td:first-child", function (row) {
//var focusNode = row.currentTarget.innerText.trim(); // Get the name of the clicked node // Get the row as a jQuery TreeTable node; need to get its data-tt-id to do that
var clickedNodeId = row.currentTarget.parentElement.getAttribute("data-tt-id"); var clickedNodeId = row.currentTarget.parentElement.getAttribute("data-tt-id");
var newFocusNode = $("#by-name-list").treetable("node", clickedNodeId); var node = $("#by-name-list").treetable("node", clickedNodeId);
switchExclusiveAndInclusiveMetricsElements(newFocusNode);
// TODO: Need to create a CLONE of the clicked node and switch its Exc%, Exc, Inc%, and Inc
// Somehow, the below code is NOT performing a deep copy, which needs to happen.
var newFocusNode = jQuery.extend(true, {}, node);
//switchExclusiveAndInclusiveMetricsElements(newFocusNode);
stackDelegate.setFocusNode(newFocusNode); stackDelegate.setFocusNode(newFocusNode); // Sets the focus node to the click node
$('#tabs').foundation('selectTab', $("#callers")); // Switch to Callers tab $('#tabs').foundation('selectTab', $("#callers")); // Switch to Callers tab
loadAndDisplayData(["callersTree", "calleesTree"], false); loadAndDisplayData(["callersTree", "calleesTree"], false);
stackDelegate.clearSelectedCell(); stackDelegate.clearSelectedCell();
}); });
function switchExclusiveAndInclusiveMetricsElements(node) { //function switchExclusiveAndInclusiveMetricsElements(node) {
// TODO: Use id's of td elements instead of indexing // // TODO: Use id's of td elements instead of indexing
var exclusiveMetricPercent = $(node.row[0].children[1]).text(); // var exclusiveMetricPercent = $(node.row[0].children[1]).text();
var exclusiveMetric = $(node.row[0].children[2]).text(); // var exclusiveMetric = $(node.row[0].children[2]).text();
var inclusiveMetricPercent = $(node.row[0].children[3]).text(); // var inclusiveMetricPercent = $(node.row[0].children[3]).text();
var inclusiveMetric = $(node.row[0].children[4]).text(); // var inclusiveMetric = $(node.row[0].children[4]).text();
$(node.row[0].children[1]).text(inclusiveMetricPercent); // $(node.row[0].children[1]).text(inclusiveMetricPercent);
$(node.row[0].children[2]).text(inclusiveMetric); // $(node.row[0].children[2]).text(inclusiveMetric);
$(node.row[0].children[3]).text(exclusiveMetricPercent); // $(node.row[0].children[3]).text(exclusiveMetricPercent);
$(node.row[0].children[4]).text(exclusiveMetric); // $(node.row[0].children[4]).text(exclusiveMetric);
} //}
/* callersTree click event */ /*
callersTree click event
Sets the new focus node to be the clicked node and reloads the stack data, given the new context
*/
$(document).on("dblclick", "#callersTree tbody tr td:first-child", function (row) { $(document).on("dblclick", "#callersTree tbody tr td:first-child", function (row) {
if (row.target !== this) { return; } if (row.target !== this) { return; }
//var focusNode = row.currentTarget.innerText.trim(); // Get the name of the clicked node // Get the row as a jQuery TreeTable node; need to get its data-tt-id to do that
var clickedNodeId = row.currentTarget.parentElement.getAttribute("data-tt-id"); var clickedNodeId = row.currentTarget.parentElement.getAttribute("data-tt-id");
//var clickedNodeId = row.currentTarget.innerText.trim();
var newFocusNode = $("#callersTree").treetable("node", clickedNodeId); var newFocusNode = $("#callersTree").treetable("node", clickedNodeId);
stackDelegate.setFocusNode(newFocusNode); stackDelegate.setFocusNode(newFocusNode);
@@ -523,13 +556,14 @@
}); });
/* calleesTree click event */ /*
calleesTree click event
Sets the new focus node to be the clicked node and reloads the stack data, given the new context
*/
$(document).on("dblclick", "#calleesTree tbody tr td:first-child", function (row) { $(document).on("dblclick", "#calleesTree tbody tr td:first-child", function (row) {
if (row.target !== this) { return; } if (row.target !== this) { return; }
//var focusNode = row.currentTarget.innerText.trim(); // Get the name of the clicked node
var clickedNodeId = row.currentTarget.parentElement.getAttribute("data-tt-id"); var clickedNodeId = row.currentTarget.parentElement.getAttribute("data-tt-id");
//var clickedNodeId = row.currentTarget.innerText.trim();
var newFocusNode = $("#calleesTree").treetable("node", clickedNodeId); var newFocusNode = $("#calleesTree").treetable("node", clickedNodeId);
stackDelegate.setFocusNode(newFocusNode); stackDelegate.setFocusNode(newFocusNode);
@@ -538,33 +572,48 @@
stackDelegate.clearSelectedCell(); stackDelegate.clearSelectedCell();
}); });
// Handles highlighting a table cell when its clicked
$(document).on("click", ".is-active table tbody tr td", function(cell) { $(document).on("click", ".is-active table tbody tr td", function(cell) {
if ($(cell.target).is(".selectable")) { if ($(cell.target).is(".selectable")) {
stackDelegate.setSelectedCell(cell.target); stackDelegate.setSelectedCell(cell.target);
} }
}); });
// Places the data in a cell into its respective filter, if it has a relevant-filter-id data attribute
// Right now, only cells in columns 'First' and 'Last' have relevant-filter-ids
$(document).on("dblclick", ".is-active table tbody tr td", function (cell) { $(document).on("dblclick", ".is-active table tbody tr td", function (cell) {
var filterId = $(cell.target).attr("relevant-filter-id"); var filterId = $(cell.target).attr("relevant-filter-id");
$(filterId).val($(cell.target).text()); $(filterId).val($(cell.target).text());
}); });
/*_______________________________________________*/
/*_______ LOAD STACKS AND POPULATE TABLES _______*/
/*_______________________________________________*/
/*
This function has the following signature:
loadAndDisplayData(String[], Boolean)
*/
function loadAndDisplayData(treesToUpdate, includeSearch=true) { function loadAndDisplayData(treesToUpdate, includeSearch=true) {
// DISPLAY BY-NAME DATA // DISPLAY BY-NAME DATA
if (treesToUpdate == null || treesToUpdate.includes("by-name-list")) { if (treesToUpdate == null || treesToUpdate.includes("by-name-list")) {
var options = { "includeSearch" : includeSearch }; var options = { "includeSearch" : includeSearch };
// stackDelegate handles the AJAX request
stackDelegate.getSummaryData(function (summaryStackData) { stackDelegate.getSummaryData(function (summaryStackData) {
$("#by-name-list tbody").empty(); // TODO: Maybe unload branch, instead // Empty out any old data
$("#by-name-list tbody").empty();
// Load the new data into the by-name-list TreeTable
updateTreeTableHtml("#by-name-list", null, stackDelegate.summaryStackData); updateTreeTableHtml("#by-name-list", null, stackDelegate.summaryStackData);
// TODO: This might be redundant
if (stackDelegate.focusNode != null) { if (stackDelegate.focusNode != null) {
var newFocusNode = $("#by-name-list").treetable("node", stackDelegate.focusNode.id); var newFocusNode = $("#by-name-list").treetable("node", stackDelegate.focusNode.id);
stackDelegate.setFocusNode(newFocusNode); stackDelegate.setFocusNode(newFocusNode);
} }
// If a search was performed, navigate to the first found element
// This can easily be done by simulating a click on 'next'
if (includeSearch) { if (includeSearch) {
displayFindNavigation("#by-name-list", "#by-name"); displayFindNavigation("#by-name-list", "#by-name");
$("#by-name .searchNavButtons .next").click(); $("#by-name .searchNavButtons .next").click();
@@ -577,10 +626,11 @@
stackDelegate.getNode("ROOT", function(nodeData){ stackDelegate.getNode("ROOT", function(nodeData){
$("#call-treeTree tbody").empty(); $("#call-treeTree tbody").empty();
// Place root node in tree // Place root node into tree
updateTreeTableHtml("#call-treeTree", null, [nodeData]); updateTreeTableHtml("#call-treeTree", null, [nodeData]);
var options = {"overrideFocusNode" : "ROOT", var options = {
"overrideFocusNode" : "ROOT",
"includeSearch" : includeSearch, "includeSearch" : includeSearch,
"call-treeTree" : true "call-treeTree" : true
}; };
@@ -589,10 +639,12 @@
// elicits all the ROOT node metrics (same as ROOT node row data). // elicits all the ROOT node metrics (same as ROOT node row data).
$("#top-status-bar").html("Totals Metric: " + nodeData.inclusiveMetric + ", Count: " + nodeData.inclusiveMetric + ", First: " + nodeData.firstTimeRelativeMSec.toFixed(3) + ", Last: " + nodeData.lastTimeRelativeMSec.toFixed(3) + ", Last-First: " + (nodeData.lastTimeRelativeMSec - nodeData.firstTimeRelativeMSec).toFixed(3) + ", TotalProcs: " + callTreeStackData.length); $("#top-status-bar").html("Totals Metric: " + nodeData.inclusiveMetric + ", Count: " + nodeData.inclusiveMetric + ", First: " + nodeData.firstTimeRelativeMSec.toFixed(3) + ", Last: " + nodeData.lastTimeRelativeMSec.toFixed(3) + ", Last-First: " + (nodeData.lastTimeRelativeMSec - nodeData.firstTimeRelativeMSec).toFixed(3) + ", TotalProcs: " + callTreeStackData.length);
// Place data in CallTree tab // Place data into the call-treeTree TreeTable
var parentNode = $("#call-treeTree").treetable("node", "ROOT"); var parentNode = $("#call-treeTree").treetable("node", "ROOT");
updateTreeTableHtml("#call-treeTree", parentNode, callTreeStackData); updateTreeTableHtml("#call-treeTree", parentNode, callTreeStackData);
// If a search was performed, navigate to the first found element
// This can easily be done by simulating a click on 'next'
if (includeSearch) { if (includeSearch) {
displayFindNavigation("#call-treeTree", "#call-tree"); displayFindNavigation("#call-treeTree", "#call-tree");
$("#call-tree .searchNavButtons .next").click(); $("#call-tree .searchNavButtons .next").click();
@@ -612,13 +664,15 @@
" + stackDelegate.focusNode.row[0].innerHTML + "\ " + stackDelegate.focusNode.row[0].innerHTML + "\
" + "</tr>"; " + "</tr>";
// Need to add stackDelegate.focusNode as parent node for this tree table // Must use stackDelegate.focusNode as parent node for this tree table
$("#callersTree").treetable("loadBranch", null, focusNodeHtml); $("#callersTree").treetable("loadBranch", null, focusNodeHtml);
var parentNode = $("#callersTree").treetable("node", stackDelegate.focusNode.id); var parentNode = $("#callersTree").treetable("node", stackDelegate.focusNode.id);
// Place data in Callers tab // Place data in callersTree TreeTable
updateTreeTableHtml("#callersTree", parentNode, callersStackData); updateTreeTableHtml("#callersTree", parentNode, callersStackData);
// If a search was performed, navigate to the first found element
// This can easily be done by simulating a click on 'next'
if (includeSearch) { if (includeSearch) {
displayFindNavigation("#callersTree", "#callers"); displayFindNavigation("#callersTree", "#callers");
$("#callers .searchNavButtons .next").click(); $("#callers .searchNavButtons .next").click();
@@ -637,13 +691,15 @@
" + stackDelegate.focusNode.row[0].innerHTML + "\ " + stackDelegate.focusNode.row[0].innerHTML + "\
" + "</tr>"; " + "</tr>";
// Need to add stackDelegate.focusNode as parent node for this tree table // Must use stackDelegate.focusNode as parent node for this tree table
$("#calleesTree").treetable("loadBranch", null, focusNodeHtml); $("#calleesTree").treetable("loadBranch", null, focusNodeHtml);
var parentNode = $("#calleesTree").treetable("node", stackDelegate.focusNode.id); var parentNode = $("#calleesTree").treetable("node", stackDelegate.focusNode.id);
// Place data in Callees tab // Place data in calleesTree TreeTable
updateTreeTableHtml("#calleesTree", parentNode, calleesStackData); updateTreeTableHtml("#calleesTree", parentNode, calleesStackData);
// If a search was performed, navigate to the first found element
// This can easily be done by simulating a click on 'next'
if (includeSearch) { if (includeSearch) {
displayFindNavigation("#calleesTree", "#callees"); displayFindNavigation("#calleesTree", "#callees");
$("#callees .searchNavButtons .next").click(); $("#callees .searchNavButtons .next").click();
@@ -659,6 +715,7 @@
var options = {"overrideFocusNode" : node.id }; var options = {"overrideFocusNode" : node.id };
/* Get the child nodes of the node that was expanded */
if (treeName == "#callersTree") { if (treeName == "#callersTree") {
stackDelegate.getCallersData(function (callersStackData, status) { stackDelegate.getCallersData(function (callersStackData, status) {
if (status == "success") { if (status == "success") {
@@ -693,6 +750,7 @@
function onTreeNodeCollapse(node, treeName) { function onTreeNodeCollapse(node, treeName) {
if (node.children.length <= 0) { return; } if (node.children.length <= 0) { return; }
// Collapse this node as well any children of it that are expanded
for (var i = 0; i < node.children.length; ++i) { for (var i = 0; i < node.children.length; ++i) {
var child = node.children[i]; var child = node.children[i];
$(treeName).treetable("collapseNode", child.id); $(treeName).treetable("collapseNode", child.id);
@@ -700,8 +758,9 @@
} }
} }
/* Display the find bar in the top right of the screen */
function displayFindNavigation(treeId, tabId) { function displayFindNavigation(treeId, tabId) {
// Search for all the nodes that have a data-find-flag attribute on them
var targetNodesFound = 0; var targetNodesFound = 0;
$(treeId + " tbody tr").each(function(index) { $(treeId + " tbody tr").each(function(index) {
var findFlag = $(this).attr("data-find-flag"); var findFlag = $(this).attr("data-find-flag");
@@ -711,14 +770,19 @@
} }
}); });
// Set the number for the find bar (e.g. 0/14)
$(tabId + " .searchNavButtons span").text("0/" + targetNodesFound); $(tabId + " .searchNavButtons span").text("0/" + targetNodesFound);
// Display the find bar
$(tabId + " .searchNavButtons").show(); $(tabId + " .searchNavButtons").show();
} }
// Find next click event listener
$(".next").click(function (e) { $(".next").click(function (e) {
changeFindCounter(e, 1); changeFindCounter(e, 1);
}); });
// Find previous click event listener
$(".prev").click(function (e) { $(".prev").click(function (e) {
changeFindCounter(e, -1); changeFindCounter(e, -1);
}); });
@@ -726,17 +790,21 @@
$("body").keydown(function(e) { $("body").keydown(function(e) {
if (e.ctrlKey) { if (e.ctrlKey) {
if (e.which == 39 || e.which == 40) { if (e.which == 39 || e.which == 40) {
// Ctrl + right arrow OR Ctrl + down arrow
$(".is-active .searchNavButtons .next").click(); $(".is-active .searchNavButtons .next").click();
} else if (e.which == 37 || e.which == 38) { } else if (e.which == 37 || e.which == 38) {
// Ctrl + left arrow OR Ctrl + up arrow
$(".is-active .searchNavButtons .prev").click(); $(".is-active .searchNavButtons .prev").click();
} }
} else if (e.which == 27) { } else if (e.which == 27) {
// Esc (escape) key
$(".is-active .searchNavButtons").hide(); $(".is-active .searchNavButtons").hide();
$(".is-active .findContainer").hide(); $(".is-active .findContainer").hide();
$(".is-active .findContainer input").val(""); $(".is-active .findContainer input").val("");
stackDelegate.clearSelectedCell(); stackDelegate.clearSelectedCell();
// TODO: This "each" method of deleting data-find-flags could take a while on larger data sets // TODO: This "each" method of deleting data-find-flags could take a while on larger data sets
// Instead, maybe keep a list of pointers (in the stackDelegate) to all the found nodes
$(".is-active table tbody tr").each(function(index) { $(".is-active table tbody tr").each(function(index) {
var findFlag = $(this).attr("data-find-flag"); var findFlag = $(this).attr("data-find-flag");
@@ -747,12 +815,13 @@
} }
}); });
// Find 'next' or 'prev' handler
function changeFindCounter(e, i) { function changeFindCounter(e, i) {
var itemIndicator = $(e.target.parentNode).find('span'); var itemIndicator = $(e.target.parentNode).find('span'); // e.g. 2/14
var numbersFromIndicator = itemIndicator.text().split('/'); var numbersFromIndicator = itemIndicator.text().split('/'); // e.g. ('2', '14')
var current = parseInt(numbersFromIndicator[0]); var current = parseInt(numbersFromIndicator[0]); // e.g. 2
var total = parseInt(numbersFromIndicator[1]); var total = parseInt(numbersFromIndicator[1]); // e.g. 14
if (total <= 0) { return; } if (total <= 0) { return; }
@@ -761,13 +830,8 @@
current = current == 0 ? total : current; current = current == 0 ? total : current;
var targetNode = $(".is-active").find("[data-find-flag='" + current + "']"); var targetNode = $(".is-active").find("[data-find-flag='" + current + "']");
/* // Open path to this node.
Open path to this node. // This can be accomplished by opening all of this node's parents.
This can be accomplished by opening all of this node's parents.
TODO: Only open the path to this node if it was collapsed after having been searched for,
otherwise we're iterating over all of its parent nodes for nothing (e.g. the path is already open)
*/
var nodeId = $(".is-active .treetable").treetable("node", targetNode.attr("data-tt-id")).parentId; var nodeId = $(".is-active .treetable").treetable("node", targetNode.attr("data-tt-id")).parentId;
while (nodeId !== undefined && nodeId != null && nodeId != "") { while (nodeId !== undefined && nodeId != null && nodeId != "") {
var node = $(".is-active .treetable").treetable("node", nodeId); var node = $(".is-active .treetable").treetable("node", nodeId);
@@ -775,16 +839,18 @@
nodeId = node.parentId; nodeId = node.parentId;
} }
// Navigate the page to that node
$('html, body').animate({ $('html, body').animate({
scrollTop: targetNode.offset().top - 400 scrollTop: targetNode.offset().top - 400
}, 100); }, 100);
stackDelegate.setSelectedCell(targetNode); stackDelegate.setSelectedCell(targetNode);
// Update itemIndicator // Update itemIndicator with new current number
itemIndicator.text(current + '/' + total); itemIndicator.text(current + '/' + total);
} }
// Find bar (Ctrl-F) listener
$(window).keydown(function(e){ $(window).keydown(function(e){
if ((e.ctrlKey || e.metaKey) && e.keyCode === 70) { if ((e.ctrlKey || e.metaKey) && e.keyCode === 70) {
e.preventDefault(); e.preventDefault();
@@ -793,6 +859,7 @@
} }
}); });
// Find bar 'Enter' key listener
$(".filter, .find").keypress(function (e) { $(".filter, .find").keypress(function (e) {
// If the user pressed enter in a filter textfield // If the user pressed enter in a filter textfield
if (e.which == 13) { if (e.which == 13) {