1. Completed the feature for ability to select organizations/people in temporal vis see http://issues.library.cornell.edu/browse/NIHVIVO-2022

2. Refactored legacy front-end code to remove unneceesary repetitive computations for activity count.
3. Fixed the overlay when parameter switch happens (earlier it used to go in the center of  the screen).
This commit is contained in:
cdtank 2011-04-15 18:36:20 +00:00
parent 680f9ec2d4
commit 3c1afb45a0
4 changed files with 263 additions and 122 deletions

View file

@ -21,10 +21,35 @@
display: none; display: none;
} }
/*
This is for the overlay that happens when you change the parameter. Somehow the top
for the message is getting set to 50%, hence we need to override it here.
*/
.blockElement {
top: 10px !important;
}
.easy-deselect-label a.temporal-vis-url { .easy-deselect-label a.temporal-vis-url {
float: right; float: right;
} }
#people-organizations-filter {
margin-bottom: 9px;
display: none;
}
.filter-option {
color: #2485AE;
cursor: pointer;
/*padding-right: 5px;*/
text-decoration: underline;
}
.active-filter {
color: #595B5B;
text-decoration: none;
}
.current-year-bar, .current-year-bar,
.known-bar { .known-bar {
display: inline-block; display: inline-block;

View file

@ -17,8 +17,6 @@ $(document).ready(function() {
graphContainer = $("#graphContainer"); graphContainer = $("#graphContainer");
tableDiv = $('#paginatedTable'); tableDiv = $('#paginatedTable');
//temporalGraphProcessor.initiateTemporalGraphRenderProcess(graphContainer, jsonString);
/* /*
* When the intra-entity parameters are clicked, * When the intra-entity parameters are clicked,
* update the status accordingly. * update the status accordingly.
@ -82,13 +80,16 @@ $(document).ready(function() {
options.errorContainer.show(); options.errorContainer.show();
options.responseContainer.unblock(); options.responseContainer.unblock();
} else { } else {
options.bodyContainer.show(); options.bodyContainer.show();
options.errorContainer.hide(); options.errorContainer.hide();
temporalGraphProcessor.redoTemporalGraphRenderProcess(graphContainer, data); temporalGraphProcessor.redoTemporalGraphRenderProcess(graphContainer, data);
options.responseContainer.unblock(); options.responseContainer.unblock();
} }
} }
}); });
}); });
}); });
@ -153,6 +154,27 @@ $("#copy-vis-viewlink-icon").live('click', function() {
}); });
$(".filter-option").live('click', function() {
if (!$(this).hasClass('active-filter')) {
if ($(this).attr('id') === 'people-filter') {
$("#organizations-filter").removeClass('active-filter');
temporalGraphProcessor.currentSelectedFilter = "PEOPLE";
} else if ($(this).attr('id') === 'organizations-filter') {
$("#people-filter").removeClass('active-filter');
temporalGraphProcessor.currentSelectedFilter = "ORGANIZATIONS";
}
$(this).addClass('active-filter');
temporalGraphProcessor.dataTable.fnDraw();
}
});
function getCurrentParameterVisViewLink() { function getCurrentParameterVisViewLink() {
return location.protocol + "//" + location.host + COMPARISON_PARAMETERS_INFO[currentParameter].viewLink; return location.protocol + "//" + location.host + COMPARISON_PARAMETERS_INFO[currentParameter].viewLink;
} }
@ -201,7 +223,52 @@ var processJSONData = {
isParentEntityAvailable: false, isParentEntityAvailable: false,
currentEntityLevel: "Organizations",
/**
* This is used to find out the sum of all the counts of a particular entity. This is
* especially useful to render the bars below the line graph where it doesnt matter if
* a count has any associated year to it or not.
* @returns sum{values}.
*/
aggregateActivityCounts: function(allActivities) {
var known = 0;
var unknown = 0;
var currentYear = 0;
$.each(allActivities, function(index, data){
if (this[0] === -1) {
unknown += this[1];
} else {
known += this[1];
if (this[0] === globalDateObject.getFullYear()) {
currentYear += this[1];
}
}
});
sum = {
knownYearCount: known,
unknownYearCount: unknown,
currentYearCount: currentYear
};
return sum;
},
setupGlobals: function(jsonContent) { setupGlobals: function(jsonContent) {
var entityLevels = new Array();
var entityActivityCount = {
PERSON: 0,
ORGANIZATION: 0
};
$.each(jsonContent, function (index, val) { $.each(jsonContent, function (index, val) {
/* /*
@ -215,6 +282,29 @@ var processJSONData = {
if (val.lastCachedAtDateTime) { if (val.lastCachedAtDateTime) {
lastCachedAtDateTimes[lastCachedAtDateTimes.length] = val.lastCachedAtDateTime; lastCachedAtDateTimes[lastCachedAtDateTimes.length] = val.lastCachedAtDateTime;
} }
/*
* Setup value to be used to determine whether to show people or organizations filter,
* by default.
* */
var activityCountInfoForEntity = processJSONData.aggregateActivityCounts(val.data);
URIToEntityRecord[val.entityURI].activityCount = activityCountInfoForEntity;
entityActivityCount[val.visMode] +=
activityCountInfoForEntity.knownYearCount
+ activityCountInfoForEntity.unknownYearCount;
/*
* Setup the entity level
* */
if (val.visMode === "PERSON"){
entityLevels.push("People");
} else if (val.visMode === "ORGANIZATION"){
entityLevels.push("Organizations");
}
} else if (val.subjectEntityLabel) { } else if (val.subjectEntityLabel) {
/* /*
@ -230,13 +320,48 @@ var processJSONData = {
processJSONData.isParentEntityAvailable = true; processJSONData.isParentEntityAvailable = true;
}); });
} }
}); });
if (entityActivityCount.ORGANIZATION >= entityActivityCount.PERSON) {
temporalGraphProcessor.currentSelectedFilter = "ORGANIZATIONS";
$("#organizations-filter").addClass("active-filter");
$("#people-filter").removeClass("active-filter");
} else {
temporalGraphProcessor.currentSelectedFilter = "PEOPLE";
$("#people-filter").addClass("active-filter");
$("#organizations-filter").removeClass("active-filter");
}
if (processJSONData.isParentEntityAvailable) { if (processJSONData.isParentEntityAvailable) {
$("#subject-parent-entity").show(); $("#subject-parent-entity").show();
} else { } else {
$("#subject-parent-entity").hide(); $("#subject-parent-entity").hide();
} }
var uniqueEntityLevels = $.unique(entityLevels);
/*
* This case is when organizations & people are mixed because both are directly attached
* to the parent organization.
* */
if (uniqueEntityLevels.length > 1) {
processJSONData.currentEntityLevel = "Organizations & People";
$("#people-organizations-filter").show();
} else if (uniqueEntityLevels.length === 1) {
processJSONData.currentEntityLevel = uniqueEntityLevels[0];
$("#people-organizations-filter").hide();
} else {
/* To provide graceful degradation set entity level to a default error message.*/
processJSONData.currentEntityLevel = "ENTITY LEVEL UNDEFINED ERROR";
}
}, },
/* /*
@ -248,8 +373,9 @@ var processJSONData = {
processJSONData.setupGlobals(jsonData); processJSONData.setupGlobals(jsonData);
prepareTableForDataTablePagination(jsonData, dataTableParams); temporalGraphProcessor.dataTable = prepareTableForDataTablePagination(jsonData, dataTableParams);
setEntityLevel(getEntityVisMode(jsonData));
setEntityLevel(processJSONData.currentEntityLevel);
entityCheckboxOperatedOnEventListener(); entityCheckboxOperatedOnEventListener();
}, },
@ -263,8 +389,9 @@ var processJSONData = {
processJSONData.setupGlobals(jsonData); processJSONData.setupGlobals(jsonData);
reloadDataTablePagination(preselectedEntityURIs, jsonData); temporalGraphProcessor.dataTable = reloadDataTablePagination(preselectedEntityURIs, jsonData);
setEntityLevel(getEntityVisMode(jsonData));
setEntityLevel(processJSONData.currentEntityLevel);
$("a#csv").attr("href", csvDownloadURL); $("a#csv").attr("href", csvDownloadURL);
} }
@ -300,6 +427,8 @@ function renderTemporalGraphVisualization(parameters) {
setupLoadingScreen(parameters.responseContainer); setupLoadingScreen(parameters.responseContainer);
//return;
getTemporalGraphData(parameters.dataURL, getTemporalGraphData(parameters.dataURL,
parameters.bodyContainer, parameters.bodyContainer,
parameters.errorContainer, parameters.errorContainer,
@ -319,7 +448,7 @@ function setupLoadingScreen(visContainerDIV) {
$.blockUI.defaults.css.width = '500px'; $.blockUI.defaults.css.width = '500px';
$.blockUI.defaults.css.border = '0px'; $.blockUI.defaults.css.border = '0px';
$.blockUI.defaults.css.top = '1%'; $.blockUI.defaults.css.top = '10px';
visContainerDIV.block({ visContainerDIV.block({
message: '<div id="loading-data-container"><h3><img id="data-loading-icon" src="' + loadingImageLink message: '<div id="loading-data-container"><h3><img id="data-loading-icon" src="' + loadingImageLink
@ -366,10 +495,12 @@ function getTemporalGraphData(temporalGraphDataURL,
errorBodyDIV.show(); errorBodyDIV.show();
visContainerDIV.unblock(); visContainerDIV.unblock();
} else { } else {
graphBodyDIV.show(); graphBodyDIV.show();
errorBodyDIV.hide(); errorBodyDIV.hide();
temporalGraphProcessor.initiateTemporalGraphRenderProcess(graphContainer, data); temporalGraphProcessor.initiateTemporalGraphRenderProcess(graphContainer, data);
visContainerDIV.unblock(); visContainerDIV.unblock();
} }
}, },
complete: function() { complete: function() {
@ -432,6 +563,10 @@ temporalGraphProcessor = {
loadingScreenTimeout: '', loadingScreenTimeout: '',
currentSelectedFilter: 'ORGANIZATIONS',
dataTable: '',
initiateTemporalGraphRenderProcess: function(givenGraphContainer, jsonData) { initiateTemporalGraphRenderProcess: function(givenGraphContainer, jsonData) {
this.dataTableParams = { this.dataTableParams = {
@ -520,6 +655,12 @@ temporalGraphProcessor = {
}); });
} }
/*
* Table has to be redrawn now & not later to avoid checkboxes not being selected, which is
* caused if they are not visible at that point of time.
* */
temporalGraphProcessor.dataTable.fnDraw();
if ($("#incomplete-data-disclaimer").length > 0 && lastCachedAtDateTimes.length > 0) { if ($("#incomplete-data-disclaimer").length > 0 && lastCachedAtDateTimes.length > 0) {
var disclaimerText = "This information is based solely on " var disclaimerText = "This information is based solely on "

View file

@ -208,6 +208,35 @@
})(jQuery); })(jQuery);
var DatatableCustomFilters = {
peopleOrOrganizations: function(oSettings, aData, iDataIndex) {
/*
* We know for a fact that the unique identifier for each row is the value for the checkbox,
* that is found in the first column for each row.
* */
var row_data = aData[0];
var entityURI = $(row_data).filter("input[type=checkbox]").val();
var currentEntityVisMode = URIToEntityRecord[entityURI].visMode;
if (currentEntityVisMode === "ORGANIZATION"
&& temporalGraphProcessor.currentSelectedFilter === "ORGANIZATIONS") {
return true;
} else if (currentEntityVisMode === "PERSON"
&& temporalGraphProcessor.currentSelectedFilter === "PEOPLE") {
return true;
} else {
// console.log(entityURI);
return false;
}
return true;
}
};
/** /**
* init sets some initial options for the default graph. i.e for when the page * init sets some initial options for the default graph. i.e for when the page
@ -224,10 +253,9 @@ function init(graphContainer) {
$("#comparisonParameter").text("Total Number of " + optionSelected); $("#comparisonParameter").text("Total Number of " + optionSelected);
$('#yaxislabel').html("Number of " + optionSelected).mbFlipText(false); $('#yaxislabel').html("Number of " + optionSelected).mbFlipText(false);
$('#comparisonHeader').html(optionSelected).css('font-weight', 'bold'); $('#comparisonHeader').html(optionSelected).css('font-weight', 'bold');
$('#legend-unknown-bar-text').text(COMPARISON_PARAMETERS_INFO[currentParameter].name + " with unknown year");
$('#legend-known-bar-text').text(COMPARISON_PARAMETERS_INFO[currentParameter].name + " with known year"); $('#legend-known-bar-text').text(COMPARISON_PARAMETERS_INFO[currentParameter].name + " with known year");
$('#legend-current-year-bar-text').text(COMPARISON_PARAMETERS_INFO[currentParameter].name + " from current incomplete year"); $('#legend-current-year-bar-text').text(COMPARISON_PARAMETERS_INFO[currentParameter].name + " from current incomplete year");
$('#legend-unknown-bar-text').text(COMPARISON_PARAMETERS_INFO[currentParameter].name + " with unknown year");
var defaultFlotOptions = { var defaultFlotOptions = {
xaxis : { xaxis : {
@ -373,12 +401,8 @@ function stuffZerosIntoLineGraphs(jsonObject, year) {
function(key, val) { function(key, val) {
var position = normalizedYearRange.normalizedMinYear, i = 0; var position = normalizedYearRange.normalizedMinYear, i = 0;
//console.log(key, val, position, (arrayOfMinAndMaxYears[1] - arrayOfMinAndMaxYears[0]) + 1);
for (i = 0; i < normalizedYearRange.normalizedRange + 1; i++) { for (i = 0; i < normalizedYearRange.normalizedRange + 1; i++) {
//console.log("val.data[i]", val.data[i]);
if (val.data[i]) { if (val.data[i]) {
if (val.data[i][0] != position if (val.data[i][0] != position
@ -386,15 +410,12 @@ function stuffZerosIntoLineGraphs(jsonObject, year) {
val.data.splice(i, 0, [ position, 0 ]); val.data.splice(i, 0, [ position, 0 ]);
} }
} }
else { else {
val.data.push( [ position, 0 ]); val.data.push( [ position, 0 ]);
} }
position++; position++;
} }
}); });
//console.log("after stuffing", jsonObject);
} }
/** /**
* During runtime, when the user checks/unchecks a checkbox, the zeroes have to * During runtime, when the user checks/unchecks a checkbox, the zeroes have to
@ -473,7 +494,9 @@ function calcMaxOfComparisonParameter(allEntities) {
var validCountsInData = new Array(); var validCountsInData = new Array();
$.each(allEntities, function(key, currentEntity) { $.each(allEntities, function(key, currentEntity) {
combinedCount = calcSumOfComparisonParameter(currentEntity);
combinedCount = currentEntity.activityCount;
validCountsInData.push(combinedCount.knownYearCount + combinedCount.unknownYearCount); validCountsInData.push(combinedCount.knownYearCount + combinedCount.unknownYearCount);
}); });
@ -503,41 +526,6 @@ function calcMaxWithinComparisonParameter(jsonObject){
return Math.max.apply(Math, validCountsInData); return Math.max.apply(Math, validCountsInData);
} }
/**
* This is used to find out the sum of all the counts of a particular entity. This is
* especially useful to render the bars below the line graph where it doesnt matter if
* a count has any associated year to it or not.
* @returns sum{values}.
*/
function calcSumOfComparisonParameter(entity) {
var known = 0;
var unknown = 0;
var currentYear = 0;
$.each(entity.data, function(index, data){
if (this[0] === -1) {
unknown += this[1];
} else {
known += this[1];
if (this[0] === globalDateObject.getFullYear()) {
currentYear += this[1];
}
}
});
sum = {
knownYearCount: known,
unknownYearCount: unknown,
currentYearCount: currentYear
};
return sum;
}
/** /**
* A simple function to see if the passed * A simple function to see if the passed
* *
@ -710,7 +698,7 @@ function createLegendRow(entity, bottomDiv) {
function renderBarAndLabel(entity, divBar, divLabel, spanElement) { function renderBarAndLabel(entity, divBar, divLabel, spanElement) {
var combinedCount = calcSumOfComparisonParameter(entity); var combinedCount = entity.activityCount;
var sum = combinedCount.knownYearCount + combinedCount.unknownYearCount; var sum = combinedCount.knownYearCount + combinedCount.unknownYearCount;
@ -1040,6 +1028,13 @@ function removeCheckBoxFromGlobalSet(checkbox){
*/ */
function prepareTableForDataTablePagination(jsonData, dataTableParams){ function prepareTableForDataTablePagination(jsonData, dataTableParams){
// console.log(processJSONData.currentEntityLevel);
if (processJSONData.currentEntityLevel.toUpperCase() === "ORGANIZATIONS & PEOPLE") {
$.fn.dataTableExt.afnFiltering.push(DatatableCustomFilters.peopleOrOrganizations);
}
var table = $('<table>'); var table = $('<table>');
table.attr('cellpadding', '0'); table.attr('cellpadding', '0');
table.attr('cellspacing', '0'); table.attr('cellspacing', '0');
@ -1095,7 +1090,7 @@ function prepareTableForDataTablePagination(jsonData, dataTableParams){
var publicationCountTD = $('<td>'); var publicationCountTD = $('<td>');
var combinedCount = calcSumOfComparisonParameter(val); var combinedCount = val.activityCount;
publicationCountTD.html(combinedCount.knownYearCount + combinedCount.unknownYearCount); publicationCountTD.html(combinedCount.knownYearCount + combinedCount.unknownYearCount);
@ -1148,11 +1143,7 @@ function prepareTableForDataTablePagination(jsonData, dataTableParams){
entityListTable.fnFilter(""); entityListTable.fnFilter("");
}); });
/* return entityListTable;
var filterInfo = $(".filterInfo").detach();
$("#infoContainer").append(filterInfo);
*/
} }
@ -1163,11 +1154,22 @@ function prepareTableForDataTablePagination(jsonData, dataTableParams){
*/ */
function reloadDataTablePagination(preselectedEntityURIs, jsonData){ function reloadDataTablePagination(preselectedEntityURIs, jsonData){
if (processJSONData.currentEntityLevel.toUpperCase() === "ORGANIZATIONS & PEOPLE") {
/* /*
* In case no entities are selected, we want that redraw should happen so that top entities are * This will make sure that duplicate filters are not added.
* pre-selected.
* */ * */
var shouldRedraw = preselectedEntityURIs.length ? false : true; if($.inArray(DatatableCustomFilters.peopleOrOrganizations, $.fn.dataTableExt.afnFiltering) < 0) {
$.fn.dataTableExt.afnFiltering.push(DatatableCustomFilters.peopleOrOrganizations);
}
} else {
var indexOfPeopleOrOrganizationFilter = $.inArray(DatatableCustomFilters.peopleOrOrganizations, $.fn.dataTableExt.afnFiltering);
if (indexOfPeopleOrOrganizationFilter >= 0) {
$.fn.dataTableExt.afnFiltering.splice(indexOfPeopleOrOrganizationFilter, 1);
}
}
var currentDataTable = $('#datatable').dataTable(); var currentDataTable = $('#datatable').dataTable();
@ -1188,7 +1190,8 @@ function reloadDataTablePagination(preselectedEntityURIs, jsonData){
var labelTD = entity.label; var labelTD = entity.label;
var combinedCount = calcSumOfComparisonParameter(entity); var combinedCount = entity.activityCount;
var publicationCountTD = combinedCount.knownYearCount + combinedCount.unknownYearCount; var publicationCountTD = combinedCount.knownYearCount + combinedCount.unknownYearCount;
var entityTypeTD = removeStopWords(entity); var entityTypeTD = removeStopWords(entity);
@ -1201,13 +1204,7 @@ function reloadDataTablePagination(preselectedEntityURIs, jsonData){
/* /*
* Dont redraw the table, so no sorting, no filtering. * Dont redraw the table, so no sorting, no filtering.
* */ * */
currentDataTable.fnAddData(newRow, shouldRedraw); currentDataTable.fnAddData(newRow, false);
/*
* Dont redraw the table, so no sorting, no filtering.
* */
currentDataTable.fnDraw(shouldRedraw);
} }
/* /*
@ -1236,6 +1233,9 @@ function reloadDataTablePagination(preselectedEntityURIs, jsonData){
* We should change to the first page so that checkboxes are selectable. * We should change to the first page so that checkboxes are selectable.
* */ * */
currentDataTable.fnPageChange('first'); currentDataTable.fnPageChange('first');
return currentDataTable;
} }
function updateRowHighlighter(linkedCheckBox){ function updateRowHighlighter(linkedCheckBox){
@ -1258,36 +1258,6 @@ function setEntityLevel(entityLevel){
$('#headerText').css("color", "#2485ae"); $('#headerText').css("color", "#2485ae");
} }
function getEntityVisMode(jsonData){
var entityLevels = new Array();
$.each(jsonData, function(index, val) {
if (val.visMode == "PERSON"){
entityLevels.push("People");
} else {
entityLevels.push("Organizations");
}
});
var uniqueEntityLevels = $.unique(entityLevels);
/*
* This case is when organizations & people are mixed because both are directly attached
* to the parent organization.
* */
if (uniqueEntityLevels.length > 1) {
entityLevel = "Organizations & People";
} else if (uniqueEntityLevels.length === 1) {
entityLevel = uniqueEntityLevels[0];
} else {
/* To provide graceful degradation set entity level to a default error message.*/
entitylevel = "ENTITY LEVEL UNDEFINED ERROR";
}
return entityLevel;
}
function toCamelCase(string){ function toCamelCase(string){
return string ? (string.substr(0,1).toUpperCase() + string.substr(1, string.length-1).toLowerCase()) : ""; return string ? (string.substr(0,1).toUpperCase() + string.substr(1, string.length-1).toLowerCase()) : "";
} }

View file

@ -61,7 +61,12 @@
</div> </div>
</div> </div>
<h3>Who do you want to compare?</h3> <h3>What do you want to compare?</h3>
<div id="people-organizations-filter">
<span id="organizations-filter" class="filter-option active-filter">Organizations</span>
<span id="people-filter" class="filter-option">People</span>
</div>
<div id="paginatedTable"></div> <div id="paginatedTable"></div>
<div id="paginated-table-footer"> <div id="paginated-table-footer">
<a id="csv" href="${temporalGraphDownloadFileLink}" class="temporalGraphLinks">Save All as CSV</a> <a id="csv" href="${temporalGraphDownloadFileLink}" class="temporalGraphLinks">Save All as CSV</a>
@ -97,8 +102,8 @@
</div> </div>
<p class="displayCounter">Legend</p> <p class="displayCounter">Legend</p>
<span class="legend-bar unknown-legend-bar"><span style="width: 25px; margin-bottom:3px;" class="unknown-inner-bar">&nbsp;</span></span> <span id="legend-unknown-bar-text">${currentParameterObject.name} with unknown year</span><br />
<span style="background-color: #A8A8A8; width: 25px;" class="known-bar legend-bar">&nbsp;</span> <span id="legend-known-bar-text">${currentParameterObject.name} with known year</span><br /> <span style="background-color: #A8A8A8; width: 25px;" class="known-bar legend-bar">&nbsp;</span> <span id="legend-known-bar-text">${currentParameterObject.name} with known year</span><br />
<span style="background-color: #CDCDCD; width: 25px;" class="current-year-legend-bar legend-bar">&nbsp;</span> <span id="legend-current-year-bar-text">${currentParameterObject.name} from current incomplete year</span><br /> <span style="background-color: #CDCDCD; width: 25px;" class="current-year-legend-bar legend-bar">&nbsp;</span> <span id="legend-current-year-bar-text">${currentParameterObject.name} from current incomplete year</span>
<span class="legend-bar unknown-legend-bar"><span style="width: 25px;" class="unknown-inner-bar">&nbsp;</span></span> <span id="legend-unknown-bar-text">${currentParameterObject.name} with unknown year</span>
</div> </div>
</div> </div>