Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Hide feature metadata barplot controls if no feature metadata is available; add first barplot panel tests; abstract Empress initialization code for JS testing #320

Merged
merged 6 commits into from
Aug 13, 2020
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
105 changes: 61 additions & 44 deletions empress/support_files/js/barplot-layer.js
Original file line number Diff line number Diff line change
Expand Up @@ -33,9 +33,14 @@ define(["jquery", "underscore", "spectrum", "Colorer", "util"], function (
this.layerContainer = layerContainer;
this.num = num;

this.fmAvailable = this.fmCols.length > 0;

// This should be "fm" if the barplot is for feature metadata; "sm" if
// the barplot is for sample metadata
this.barplotType = "fm";
// the barplot is for sample metadata. (The default is to use feature
// metadata barplots, but if no feature metadata was passed to Empress
// then we have no choice but to just draw sample metadata barplots for
// everything.)
this.barplotType = this.fmAvailable ? "fm" : "sm";

// Various properties of the barplot layer state for feature metadata
this.initialDefaultColorHex = Colorer.getQIIMEColor(this.num - 1);
Expand Down Expand Up @@ -81,47 +86,55 @@ define(["jquery", "underscore", "spectrum", "Colorer", "util"], function (
this.updateHeader();

// Add UI elements for switching between feature and sample metadata
// barplots for this layer
var metadataChoiceP = this.layerDiv.appendChild(
document.createElement("p")
);
var fmBtn = metadataChoiceP.appendChild(
document.createElement("button")
);
var smBtn = metadataChoiceP.appendChild(
document.createElement("button")
);
fmBtn.innerText = "Feature Metadata";
smBtn.innerText = "Sample Metadata";
// Center the feature and sample metadata buttons
fmBtn.setAttribute("style", "margin: 0 auto;");
smBtn.setAttribute("style", "margin: 0 auto;");
// Since we default to feature metadata barplot layers, we mark the
// feature metadata button as "selected" (a.k.a. we darken it a bit)
fmBtn.classList.add("selected-metadata-choice");

this.initFMDiv();
this.initSMDiv();

fmBtn.onclick = function () {
if (scope.barplotType !== "fm") {
scope.smDiv.classList.add("hidden");
scope.fmDiv.classList.remove("hidden");
fmBtn.classList.add("selected-metadata-choice");
smBtn.classList.remove("selected-metadata-choice");
scope.barplotType = "fm";
}
};
smBtn.onclick = function () {
if (scope.barplotType !== "sm") {
scope.fmDiv.classList.add("hidden");
scope.smDiv.classList.remove("hidden");
smBtn.classList.add("selected-metadata-choice");
fmBtn.classList.remove("selected-metadata-choice");
scope.barplotType = "sm";
}
};
// barplots for this layer (only if feature metadata is available;
// otherwise, things will just default to sample metadata barplots.)
if (this.fmAvailable) {
var metadataChoiceP = this.layerDiv.appendChild(
document.createElement("p")
);
var fmBtn = metadataChoiceP.appendChild(
document.createElement("button")
);
var smBtn = metadataChoiceP.appendChild(
document.createElement("button")
);
fmBtn.innerText = "Feature Metadata";
smBtn.innerText = "Sample Metadata";
// Center the feature and sample metadata buttons
fmBtn.setAttribute("style", "margin: 0 auto;");
smBtn.setAttribute("style", "margin: 0 auto;");
// Since we default to feature metadata barplot layers, we mark the
// feature metadata button as "selected" (a.k.a. we darken it a bit)
fmBtn.classList.add("selected-metadata-choice");

// We delay calling initFMDiv() (and initSMDiv(), although that
// isn't in this block because it doesn't depend on feature
// metadata being available) until after we create the
// "type switching" choice buttons above. This is so that the
// buttons are placed above the FM / SM divs in the page layout.
this.initFMDiv();

fmBtn.onclick = function () {
if (scope.barplotType !== "fm") {
scope.smDiv.classList.add("hidden");
scope.fmDiv.classList.remove("hidden");
fmBtn.classList.add("selected-metadata-choice");
smBtn.classList.remove("selected-metadata-choice");
scope.barplotType = "fm";
}
};
smBtn.onclick = function () {
if (scope.barplotType !== "sm") {
scope.fmDiv.classList.add("hidden");
scope.smDiv.classList.remove("hidden");
smBtn.classList.add("selected-metadata-choice");
fmBtn.classList.remove("selected-metadata-choice");
scope.barplotType = "sm";
}
};
}

this.initSMDiv();
// Add a row of UI elements that supports removing this layer
var rmP = this.layerDiv.appendChild(document.createElement("p"));
var rmLbl = rmP.appendChild(document.createElement("label"));
Expand All @@ -144,6 +157,9 @@ define(["jquery", "underscore", "spectrum", "Colorer", "util"], function (
BarplotLayer.prototype.initFMDiv = function () {
var scope = this;
this.fmDiv = this.layerDiv.appendChild(document.createElement("div"));
if (this.barplotType !== "fm") {
this.fmDiv.classList.add("hidden");
}

// Add default color stuff
var dfltColorP = document.createElement("p");
Expand Down Expand Up @@ -416,8 +432,9 @@ define(["jquery", "underscore", "spectrum", "Colorer", "util"], function (
BarplotLayer.prototype.initSMDiv = function () {
var scope = this;
this.smDiv = this.layerDiv.appendChild(document.createElement("div"));
// Hide this div by default
this.smDiv.classList.add("hidden");
if (this.barplotType !== "sm") {
this.smDiv.classList.add("hidden");
}

var chgFieldP = this.smDiv.appendChild(document.createElement("p"));
// Add a label
Expand Down
36 changes: 33 additions & 3 deletions tests/index.html
Original file line number Diff line number Diff line change
Expand Up @@ -57,6 +57,28 @@
</div>
</div>

<!-- Various side panel / selected-node-menu tags that are needed in order to
create an instance of CanvasEvents in Empress without crashing things.
Ideally, these should be loaded dynamically from what's in the empress
template HTML files, rather than inserted here willy-nilly.
-->
<div style="display: none;">
<input type="text" id="quick-search" placeholder="Search by node name..."
style="flex-grow: 1;" class="empress-input">
<button id="side-header-search-btn" style="flex-grow: 1;">Search</button>
<div id="menu-sm-table"></div>
<div id="menu-sm-section"></div>
<div id="menu-box"></div>
<div id="menu-select"></div>
<div id="menu-add-btn"></div>
<div id="menu-box-node-id"></div>
<div id="menu-box-notes"></div>
<div id="menu-box-warning"></div>
<div id="menu-fm-table"></div>
<div id="menu-fm-header"></div>
<div id="menu-sm-header"></div>
</div>

<script>
QUnit.config.autostart = false;

Expand Down Expand Up @@ -92,6 +114,9 @@
'CanvasEvents' : './support_files/js/canvas-events',
'SelectedNodeMenu' : './support_files/js/select-node-menu',

/* test utility code */
'UtilitiesForTesting' : './../tests/utilities-for-testing',

/* test paths */
'testBPTree' : './../tests/test-bp-tree',
'testByteTree' : './../tests/test-byte-array',
Expand All @@ -103,7 +128,8 @@
'testVectorOps' : './../tests/test-vector-ops',
'testEmpress' : './../tests/test-empress',
'testExport': './../tests/test-export',
'testAnimationHandler': './../tests/test-animation-panel-handler'
'testAnimationHandler': './../tests/test-animation-panel-handler',
'testBarplotPanelHandler': './../tests/test-barplot-panel-handler'
}
});

Expand All @@ -125,6 +151,7 @@
'util',
'Empress',
'Legend',
'UtilitiesForTesting',
'testBPTree',
'testByteTree',
'testBIOMTable',
Expand All @@ -134,8 +161,9 @@
'testCircularLayoutComputation',
'testVectorOps',
'testEmpress',
'testExport',
'testAnimationHandler',
'testExport'
'testBarplotPanelHandler',
],

// start tests
Expand All @@ -157,6 +185,7 @@
util,
Empress,
Legend,
UtilitiesForTesting,
testBPTree,
testByteTree,
testCamera,
Expand All @@ -165,8 +194,9 @@
testCircularLayoutComputation,
testVectorOps,
testEmpress,
testExport,
testAnimationHandler,
testExport
testBarplotPanelHandler
) {
$(document).ready(function() {
QUnit.start();
Expand Down
121 changes: 121 additions & 0 deletions tests/test-barplot-panel-handler.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,121 @@
require(["jquery", "Empress", "UtilitiesForTesting"], function (
$,
Empress,
UtilitiesForTesting
) {
module("Barplot Panel Handler", {
setup: function () {
this.testData = UtilitiesForTesting.getTestData();
},
});

test("Layout availability toggling: initialization", function () {
// The default layout should influence whether the barplot panel's
// "available" or "unavailable" content is shown. First, let's try the
// unrooted layout, which doesn't support barplots.
var empress = new Empress(
this.testData.tree,
this.testData.treeData,
this.testData.tdToInd,
this.testData.nameToKeys,
this.testData.layoutToCoordSuffix,
"Unrooted",
this.testData.yrscf,
this.testData.biom,
this.testData.fmCols,
this.testData.tm,
this.testData.im,
this.testData.canvas
);
ok(empress._barplotPanel.availContent.classList.contains("hidden"));
notOk(
empress._barplotPanel.unavailContent.classList.contains("hidden")
);

// And now let's try starting out in the rectangular layout, which
// *does* support barplots.
var empress2 = new Empress(
this.testData.tree,
this.testData.treeData,
this.testData.tdToInd,
this.testData.nameToKeys,
this.testData.layoutToCoordSuffix,
"Rectangular",
this.testData.yrscf,
this.testData.biom,
this.testData.fmCols,
this.testData.tm,
this.testData.im,
this.testData.canvas
);
notOk(empress2._barplotPanel.availContent.classList.contains("hidden"));
ok(empress2._barplotPanel.unavailContent.classList.contains("hidden"));
});
test("Layout availability toggling post-initialization", function () {
var empress = new Empress(
this.testData.tree,
this.testData.treeData,
this.testData.tdToInd,
this.testData.nameToKeys,
this.testData.layoutToCoordSuffix,
"Unrooted",
this.testData.yrscf,
this.testData.biom,
this.testData.fmCols,
this.testData.tm,
this.testData.im,
this.testData.canvas
);
// We need to call this in order to make updateLayout() work.
// Otherwise, things start breaking -- see
// https://github.com/biocore/empress/pull/320 for context.
empress.initialize();

// After updating the layout to something that supports barplots, the
// barplot "available content" should now be shown.
empress.updateLayout("Rectangular");
notOk(empress._barplotPanel.availContent.classList.contains("hidden"));
ok(empress._barplotPanel.unavailContent.classList.contains("hidden"));

// ... And going back to a not-compatible-with-barplots layout should
// switch back to the unavailable content.
empress.updateLayout("Unrooted");
ok(empress._barplotPanel.availContent.classList.contains("hidden"));
notOk(
empress._barplotPanel.unavailContent.classList.contains("hidden")
);
});
test("Barplot layers default to feature metadata layers, but only if feature metadata is available", function () {
var empressWithFM = new Empress(
this.testData.tree,
this.testData.treeData,
this.testData.tdToInd,
this.testData.nameToKeys,
this.testData.layoutToCoordSuffix,
"Unrooted",
this.testData.yrscf,
this.testData.biom,
this.testData.fmCols,
this.testData.tm,
this.testData.im,
this.testData.canvas
);
equal(empressWithFM._barplotPanel.layers[0].barplotType, "fm");

var empressWithNoFM = new Empress(
this.testData.tree,
this.testData.treeData,
this.testData.tdToInd,
this.testData.nameToKeys,
this.testData.layoutToCoordSuffix,
"Unrooted",
this.testData.yrscf,
this.testData.biom,
[],
{},
{},
this.testData.canvas
);
equal(empressWithNoFM._barplotPanel.layers[0].barplotType, "sm");
});
});
Loading