diff --git a/webapp/config/licenser/known_exceptions.txt b/webapp/config/licenser/known_exceptions.txt
index 21f3d8522..594711031 100644
--- a/webapp/config/licenser/known_exceptions.txt
+++ b/webapp/config/licenser/known_exceptions.txt
@@ -159,5 +159,8 @@ webapp/web/js/selectivizr.js
# PROBLEM: Can't find any info on licensing.
webapp/web/js/jquery_plugins/supersleight.js
+# See /doc/3rd-party-licenses.txt for LICENSE file
+webapp/web/js/raphael/*
+
# See /doc/3rd-party-licenses.txt for LICENSE file
webapp/web/js/sparql/prototype.js
diff --git a/webapp/web/css/browseClassGroups.css b/webapp/web/css/browseClassGroups.css
new file mode 100644
index 000000000..33bef6bbb
--- /dev/null
+++ b/webapp/web/css/browseClassGroups.css
@@ -0,0 +1,123 @@
+/* $This file is distributed under the terms of the license in /doc/license.txt$ */
+
+/* Styles used for class group browse (browse-classgroups.ftl) */
+
+#browse {
+ clear: both;
+ width: 920px;
+ margin: 0 auto;
+ border: 1px solid #dfe6e6;
+ background: #f7f9f9;
+ overflow: hidden;
+ padding-bottom: 30px;
+}
+#browse h4 {
+ width: 13%;
+ height: 30px;
+ margin-bottom: 27px;
+ padding-left: 15px;
+ font-weight: normal;
+ line-height: 38px;
+ color: #fff;
+ background: #5e6363;
+ font-size: 20px;
+}
+/* BROWSE CLASS GROUPS ------> */
+ul#browse-classgroups {
+ float: left;
+ width: 200px;
+ border: 1px solid #dde4e3;
+ border-right: none;
+ background: #f1f2ee;
+ margin-left: 34px;
+ padding: 0 20px 23px 20px;
+ margin-top: 10px;
+ padding-top: 10px;
+}
+ul#browse-classgroups li {
+ display: block;
+ border-bottom: 1px solid #dde4e3;
+ font-size: 18px;
+ width: 200px;
+ height: 35px;
+ line-height: 35px;
+}
+ul#browse-classgroups li:last-child {
+ border-bottom: none
+}
+ul#browse-classgroups a {
+ display: block;
+ padding-left: 15px;
+ width: 200px;
+ height: 35px;
+ color: #5e6363;
+ text-decoration: none;
+}
+ul#browse-classgroups .count-classes {
+ font-size: 14px
+}
+/* BROWSE CLASSES IN CLASS GROUP ------> */
+#browse-classes {
+ float: left;
+ width: 610px;
+ border: 1px solid #dde6e5;
+ background: #fff;
+ min-height: 230px;
+}
+ul#classgroup-list {
+ float: left;
+ width: 90%;
+ padding: 0 10px 15px 22px;
+ margin-top: 20px;
+ margin-bottom: 10px;
+}
+ul#classgroup-list.vis {
+ width: 44%;
+ border-right: 1px solid #DDE5E4;
+}
+ul#classgroup-list li {
+ display: block;
+ float: left;
+ width: 100%;
+ border-bottom: 1px solid #dde4e3;
+ font-size: 14px;
+ height: 35px;
+ line-height: 35px;
+}
+ul#classgroup-list li:last-child {
+ border-bottom: none
+}
+ul#classgroup-list a {
+ display: block;
+ padding-left: 15px;
+ height: 35px;
+ color: #5e6363;
+ text-decoration: none;
+}
+ul#classgroup-list .count-individuals {
+ font-size: 12px;
+}
+/* VISUALIZATION ------> */
+#visual-graph {
+ float: left;
+ width: 308px;
+}
+#visual-graph h5 {
+ padding: 20px 0 12px 12px;
+ width: auto;
+ font-size: 18px;
+ font-weight: normal;
+}
+#pieViz {
+ width: 308px;
+ height: 308px;
+}
+svg text {
+ font-family: inherit !important;
+ font-size: 12px !important;
+ color: #5E6363 !important;
+/* display: none;*/
+}
+svg rect {
+ cursor: pointer;
+}
\ No newline at end of file
diff --git a/webapp/web/js/browseClassGroups.js b/webapp/web/js/browseClassGroups.js
new file mode 100644
index 000000000..6858d608e
--- /dev/null
+++ b/webapp/web/js/browseClassGroups.js
@@ -0,0 +1,141 @@
+/* $This file is distributed under the terms of the license in /doc/license.txt$ */
+
+var browseClassGroups = {
+ // Initial page setup
+ onLoad: function() {
+ this.mergeFromTemplate();
+ this.initObjects();
+ // this.bindEventListeners();
+ },
+
+ // Add variables from menupage template
+ mergeFromTemplate: function() {
+ $.extend(this, browseData);
+ },
+
+ // Create references to frequently used elements for convenience
+ initObjects: function() {
+ this.vClassesInClassGroup = $('ul#classgroup-list');
+ this.browseClassGroupLinks = $('#browse-classgroups li a');
+ },
+
+ // Event listeners. Called on page load
+ bindEventListeners: function() {
+ // Listener for classGroup switching
+ this.browseClassGroupLinks.click(function() {
+ uri = $(this).attr("data-uri");
+ browseClassGroups.getVClasses(uri);
+ return false;
+ })
+ },
+
+ // Load classes and chart for default class group as defined by template
+ defaultClassGroup: function() {
+ if ( this.defaultBrowseClassGroupURI != "false" ) {
+ this.getVClasses(this.defaultBrowseClassGroupUri);
+ }
+ },
+
+ getVClasses: function(classgroupUri, alpha) {
+ url = this.dataServiceUrl + encodeURIComponent(classgroupUri);
+ if ( alpha && alpha != "all") {
+ url = url + '&alpha=' + alpha;
+ }
+
+ // First wipe currently displayed classes
+ this.vClassesInClassGroup.empty();
+
+ $.getJSON(url, function(results) {
+ $.each(results.vClasses, function(i, item) {
+ name = results.vClasses[i].name;
+ uri = results.vClasses[i].URI;
+ indivCount = results.vClasses[i].individualCount;
+ indexUrl = browseClassGroups.baseUrl + '/individuallist?vclassId=' + encodeURIComponent(uri);
+ // Build the content of each list item, piecing together each component
+ listItem = '
';
+ listItem += ''+ name +'';
+ // Include the moniker only if it's not empty and not equal to the VClass name
+ listItem += ' (${indivCount})'
+ listItem += '
';
+ browseClassGroups.vClassesInClassGroup.append(listItem);
+ })
+ // set selected class group
+ browseClassGroups.selectedClassGroup(results.vclassGroup.URI);
+ });
+ },
+
+ selectedClassGroup: function(vclassUri) {
+ // Remove active class on all vClasses
+ $('#browse-childClasses li a.selected').removeClass('selected');
+ // Can't figure out why using this.selectedBrowseVClass doesn't work here
+ // this.selectedBrowseVClass.removeClass('selected');
+
+ // Add active class for requested vClass
+ $('#browse-childClasses li a[data-uri="'+ vclassUri +'"]').addClass('selected');
+ }
+};
+
+var graphClassGroups = {
+
+ barchart: function() {
+ var values = [],
+ labels = [];
+ uris = [];
+ $("tr").each(function() {
+ values.push(parseInt($("td", this).text(), 10));
+ labels.push($("th", this).text());
+ uris.push($("th", this).attr("data-uri"));
+ });
+ var height = values.length * 37;
+
+ // Create the canvas
+ var r = Raphael("pieViz", 300, height + 10);
+
+ // Hide the table containing the data to be graphed
+ $('table.graph-data').addClass('hidden');
+ var chart = r.g.hbarchart(0, 16, 300, height, [values], {type:"soft", singleColor:"#999"});
+
+ // Add the class names as labels and then hide them
+ chart.label(labels, true);
+ // getting a JS error in the console when trying to add the class
+ // "setting a property that has only a getter"
+ // $('svg text').addClass('hidden');
+ // so using .hide() instead
+ $('svg text').hide();
+
+ // Was unable to append within