diff --git a/webapp/web/images/menupage/arrow-carousel-people.jpg b/webapp/web/images/menupage/arrow-carousel-people.jpg deleted file mode 100644 index 88d09a876..000000000 Binary files a/webapp/web/images/menupage/arrow-carousel-people.jpg and /dev/null differ diff --git a/webapp/web/images/menupage/arrow-green.gif b/webapp/web/images/menupage/arrow-green.gif deleted file mode 100644 index b3a75c25d..000000000 Binary files a/webapp/web/images/menupage/arrow-green.gif and /dev/null differ diff --git a/webapp/web/images/menupage/arrow.gif b/webapp/web/images/menupage/arrow.gif deleted file mode 100644 index 8d9199e7a..000000000 Binary files a/webapp/web/images/menupage/arrow.gif and /dev/null differ diff --git a/webapp/web/images/menupage/visual-graph-generic-class.jpg b/webapp/web/images/menupage/visual-graph-generic-class.jpg deleted file mode 100644 index 8749a5a75..000000000 Binary files a/webapp/web/images/menupage/visual-graph-generic-class.jpg and /dev/null differ diff --git a/webapp/web/images/menupage/visual-graph.jpg b/webapp/web/images/menupage/visual-graph.jpg deleted file mode 100644 index 2b9634b20..000000000 Binary files a/webapp/web/images/menupage/visual-graph.jpg and /dev/null differ diff --git a/webapp/web/js/browseClassGroupsPie.js b/webapp/web/js/browseClassGroupsPie.js new file mode 100644 index 000000000..d28a4cbf1 --- /dev/null +++ b/webapp/web/js/browseClassGroupsPie.js @@ -0,0 +1,95 @@ +/* $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(); + }, + + // Add variables from browse template + mergeFromTemplate: function() { + $.extend(this, browseData); + }, + + // Create references to frequently used elements for convenience + initObjects: function() { + this.browseClassLinks = $('#vgraph-classes li a'); + }, + + // Retrieve classes + graphSetup: function() { + var values = [], + labels = [], + uris = []; + this.browseClassLinks.each(function() { + var count = $(this).children('span').text(); + var count = parseInt(count.slice(1, -1), 10); + var percentage = parseInt(Math.round((count / browseClassGroups.classGroupIndividualCount) * 100), 10); + var name = $(this).text(); + var countStart = name.lastIndexOf(' ('); + var name = name.substring(0, countStart); + // alert(name +' | ' + count +' | '+ percentage); + if ( percentage > 0) { + values.push(percentage); + var name = name +' ('+ percentage +'%)'; + labels.push(name); + uris.push($(this).attr("data-uri")); + } + }); + + // Send the parameters to build the pie chart + graphClasses.piechart(values, labels, uris); + } +}; + +var graphClasses = { + // Build the pie chart using gRaphael + piechart: function(values, labels, uris) { + // Clear the existing pie chart + $('#menupage-graph').empty(); + + // Create the canvas + var r = Raphael("menupage-graph", 500, 300); + + // Setup the colors for the slices + // colors = ['#192933', '#26404E', '#294656', '#194c68', '#487A96', '#63A8CE', '#67AED6','#758A96', '#9DB9C9' ]; + colors = ['#143D52', '#1F5C7A', '#297AA3', '#3399CC', '#5CADD6', '#85C2E0', '#ADD6EB', '#ADCBDD', '#D6EBF5', '#E9F1F5' ]; + // Reverse colors to see how it looks with larger slices in lighter hues: + // colors = colors.reverse(); + + // Now draw the pie chart + var pie = r.g.piechart(150, 142, 100, values, {legend: labels, legendmark: "square", legendpos: "east", colors: colors}); + pie.hover(function () { + this.sector.stop(); + this.sector.scale(1.1, 1.1, this.cx, this.cy); + if (this.label) { + this.label[0].stop(); + this.label[0].scale(1.5); + this.label[1].attr({"font-weight": 800}); + } + }, function () { + this.sector.animate({scale: [1, 1, this.cx, this.cy]}, 500, "bounce"); + if (this.label) { + this.label[0].animate({scale: 1}, 500, "bounce"); + this.label[1].attr({"font-weight": 400}); + } + }); + + // Can't reliably link the slices at the moment. Will come up with a solution if we end up sticking with the pie charts + // $('path').click(function() { + // var index = $('path').index(this); + // var uri = uris[index]; + // // var link = browseClassGroups.baseUrl + '/individuallist?vclassId=' + encodeURIComponent(uri); + // window.location = "#browse-by"; + // browseByVClass.getIndividuals(uri); + // return false; + // }); + } +}; + +$(document).ready(function() { + browseClassGroups.onLoad(); + browseClassGroups.graphSetup(); + // graphClasses.piechart(); +}); \ No newline at end of file diff --git a/webapp/web/js/menupage/browseByVClass.js b/webapp/web/js/menupage/browseByVClass.js index 10c1c469f..7bd7ac95f 100644 --- a/webapp/web/js/menupage/browseByVClass.js +++ b/webapp/web/js/menupage/browseByVClass.js @@ -19,10 +19,8 @@ var browseByVClass = { this.vgraphVClassLinks = $('#vgraph-classes li a'); this.browseVClasses = $('#browse-classes'); this.browseVClassLinks = $('#browse-classes li a'); - this.selectedBrowseVClass = $('#browse-classes li a.selected'); this.alphaIndex = $('#alpha-browse-individuals'); this.alphaIndexLinks = $('#alpha-browse-individuals li a'); - this.selectedAlphaIndex = $('#alpha-browse-individuals li a.selected'); this.paginationNav = $('nav.pagination'); this.paginationLinks = $('nav.pagination li a'); this.individualsInVClass = $('#individuals-in-class ul'); @@ -56,9 +54,8 @@ var browseByVClass = { this.paginationListener(); }, + // Listener for page switching -- separate from the rest because it needs to be callable paginationListener: function() { - // Listener for page switching - // separate from the rest because it needs to be callable $('nav.pagination li a').click(function() { uri = $('#browse-classes li a.selected').attr('data-uri'); alpha = $('#alpha-browse-individuals li a.selected').attr('data-alpha'); @@ -75,6 +72,7 @@ var browseByVClass = { } }, + // Where all the magic happens -- gonna fetch me some individuals getIndividuals: function(vclassUri, alpha, page) { url = this.dataServiceUrl + encodeURIComponent(vclassUri); if ( alpha && alpha != "all") { @@ -149,22 +147,22 @@ var browseByVClass = { browseByVClass.individualsInVClass.append(listItem); }) - // set selected class, alpha and page + // Set selected class, alpha and page browseByVClass.selectedVClass(results.vclass.URI); browseByVClass.selectedAlpha(alpha); }); }, + // Toggle the active class so it's clear which is selected selectedVClass: function(vclassUri) { // Remove active class on all vClasses $('#browse-classes 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-classes li a[data-uri="'+ vclassUri +'"]').addClass('selected'); }, + // Toggle the active letter so it's clear which is selected selectedAlpha: function(alpha) { // if no alpha argument sent, assume all if ( alpha == null ) { diff --git a/webapp/web/js/raphael/g.pie.js b/webapp/web/js/raphael/g.pie.js new file mode 100644 index 000000000..e9c937207 --- /dev/null +++ b/webapp/web/js/raphael/g.pie.js @@ -0,0 +1,205 @@ +/* + * g.Raphael 0.4.1 - Charting library, based on Raphaƫl + * + * Copyright (c) 2009 Dmitry Baranovskiy (http://g.raphaeljs.com) + * Licensed under the MIT (http://www.opensource.org/licenses/mit-license.php) license. + */ +Raphael.fn.g.piechart = function (cx, cy, r, values, opts) { + opts = opts || {}; + var paper = this, + sectors = [], + covers = this.set(), + chart = this.set(), + series = this.set(), + order = [], + len = values.length, + angle = 0, + total = 0, + others = 0, + cut = 9, + defcut = true; + chart.covers = covers; + if (len == 1) { + series.push(this.circle(cx, cy, r).attr({fill: this.g.colors[0], stroke: opts.stroke || "#fff", "stroke-width": opts.strokewidth == null ? 1 : opts.strokewidth})); + covers.push(this.circle(cx, cy, r).attr(this.g.shim)); + total = values[0]; + values[0] = {value: values[0], order: 0, valueOf: function () { return this.value; }}; + series[0].middle = {x: cx, y: cy}; + series[0].mangle = 180; + } else { + function sector(cx, cy, r, startAngle, endAngle, fill) { + var rad = Math.PI / 180, + x1 = cx + r * Math.cos(-startAngle * rad), + x2 = cx + r * Math.cos(-endAngle * rad), + xm = cx + r / 2 * Math.cos(-(startAngle + (endAngle - startAngle) / 2) * rad), + y1 = cy + r * Math.sin(-startAngle * rad), + y2 = cy + r * Math.sin(-endAngle * rad), + ym = cy + r / 2 * Math.sin(-(startAngle + (endAngle - startAngle) / 2) * rad), + res = ["M", cx, cy, "L", x1, y1, "A", r, r, 0, +(Math.abs(endAngle - startAngle) > 180), 1, x2, y2, "z"]; + res.middle = {x: xm, y: ym}; + return res; + } + for (var i = 0; i < len; i++) { + total += values[i]; + values[i] = {value: values[i], order: i, valueOf: function () { return this.value; }}; + } + values.sort(function (a, b) { + return b.value - a.value; + }); + for (i = 0; i < len; i++) { + if (defcut && values[i] * 360 / total <= 1.5) { + cut = i; + defcut = false; + } + if (i > cut) { + defcut = false; + values[cut].value += values[i]; + values[cut].others = true; + others = values[cut].value; + } + } + len = Math.min(cut + 1, values.length); + others && values.splice(len) && (values[cut].others = true); + for (i = 0; i < len; i++) { + var mangle = angle - 360 * values[i] / total / 2; + if (!i) { + angle = 90 - mangle; + mangle = angle - 360 * values[i] / total / 2; + } + if (opts.init) { + var ipath = sector(cx, cy, 1, angle, angle - 360 * values[i] / total).join(","); + } + var path = sector(cx, cy, r, angle, angle -= 360 * values[i] / total); + var p = this.path(opts.init ? ipath : path).attr({fill: opts.colors && opts.colors[i] || Raphael.getColor("#194c68") || "#666", stroke: opts.stroke || "#fff", "stroke-width": (opts.strokewidth == null ? 1 : opts.strokewidth), "stroke-linejoin": "round"}); + p.value = values[i]; + p.middle = path.middle; + p.mangle = mangle; + sectors.push(p); + series.push(p); + opts.init && p.animate({path: path.join(",")}, (+opts.init - 1) || 1000, ">"); + } + for (i = 0; i < len; i++) { + p = paper.path(sectors[i].attr("path")).attr(this.g.shim); + opts.href && opts.href[i] && p.attr({href: opts.href[i]}); + p.attr = function () {}; + covers.push(p); + series.push(p); + } + } + + chart.hover = function (fin, fout) { + fout = fout || function () {}; + var that = this; + for (var i = 0; i < len; i++) { + (function (sector, cover, j) { + var o = { + sector: sector, + cover: cover, + cx: cx, + cy: cy, + mx: sector.middle.x, + my: sector.middle.y, + mangle: sector.mangle, + r: r, + value: values[j], + total: total, + label: that.labels && that.labels[j] + }; + cover.mouseover(function () { + fin.call(o); + }).mouseout(function () { + fout.call(o); + }); + })(series[i], covers[i], i); + } + return this; + }; + // x: where label could be put + // y: where label could be put + // value: value to show + // total: total number to count % + chart.each = function (f) { + var that = this; + for (var i = 0; i < len; i++) { + (function (sector, cover, j) { + var o = { + sector: sector, + cover: cover, + cx: cx, + cy: cy, + x: sector.middle.x, + y: sector.middle.y, + mangle: sector.mangle, + r: r, + value: values[j], + total: total, + label: that.labels && that.labels[j] + }; + f.call(o); + })(series[i], covers[i], i); + } + return this; + }; + chart.click = function (f) { + var that = this; + for (var i = 0; i < len; i++) { + (function (sector, cover, j) { + var o = { + sector: sector, + cover: cover, + cx: cx, + cy: cy, + mx: sector.middle.x, + my: sector.middle.y, + mangle: sector.mangle, + r: r, + value: values[j], + total: total, + label: that.labels && that.labels[j] + }; + cover.click(function () { f.call(o); }); + })(series[i], covers[i], i); + } + return this; + }; + chart.inject = function (element) { + element.insertBefore(covers[0]); + }; + var legend = function (labels, otherslabel, mark, dir) { + var x = cx + r + r / 5, + y = cy, + h = y + 10; + labels = labels || []; + dir = (dir && dir.toLowerCase && dir.toLowerCase()) || "east"; + mark = paper.g.markers[mark && mark.toLowerCase()] || "disc"; + chart.labels = paper.set(); + for (var i = 0; i < len; i++) { + var clr = series[i].attr("fill"), + j = values[i].order, + txt; + values[i].others && (labels[j] = otherslabel || "Others"); + labels[j] = paper.g.labelise(labels[j], values[i], total); + chart.labels.push(paper.set()); + chart.labels[i].push(paper.g[mark](x + 5, h, 5).attr({fill: clr, stroke: "none"})); + chart.labels[i].push(txt = paper.text(x + 20, h, labels[j] || values[j]).attr(paper.g.txtattr).attr({fill: opts.legendcolor || "#000", "text-anchor": "start"})); + covers[i].label = chart.labels[i]; + h += txt.getBBox().height * 1.2; + } + var bb = chart.labels.getBBox(), + tr = { + east: [0, -bb.height / 2], + west: [-bb.width - 2 * r - 20, -bb.height / 2], + north: [-r - bb.width / 2, -r - bb.height - 10], + south: [-r - bb.width / 2, r + 10] + }[dir]; + chart.labels.translate.apply(chart.labels, tr); + chart.push(chart.labels); + }; + if (opts.legend) { + legend(opts.legend, opts.legendothers, opts.legendmark, opts.legendpos); + } + chart.push(series, covers); + chart.series = series; + chart.covers = covers; + return chart; +}; \ No newline at end of file diff --git a/webapp/web/templates/freemarker/body/partials/menupage/menupage-scripts.ftl b/webapp/web/templates/freemarker/body/partials/menupage/menupage-scripts.ftl index 16cf88b29..035b3845b 100644 --- a/webapp/web/templates/freemarker/body/partials/menupage/menupage-scripts.ftl +++ b/webapp/web/templates/freemarker/body/partials/menupage/menupage-scripts.ftl @@ -21,12 +21,22 @@ template variable with the domain name for an AJAX request with visualizations. +<#-- classGroupIndividualCount is assigned in menupage-vClassesInClassGroup.ftl --> -${scripts.add("/js/menupage/browseByVClass.js")} \ No newline at end of file +<#-- Script to enable browsing individuals within a class --> +${scripts.add("/js/menupage/browseByVClass.js")} + +<#-- Scripts required to create the visual graphs --> +${scripts.add("/js/raphael/raphael.js", "/js/raphael/g.raphael.js", "/js/raphael/g.pie.js", "/js/browseClassGroupsPie.js")} \ No newline at end of file diff --git a/webapp/web/templates/freemarker/body/partials/menupage/menupage-vClassesInClassgroup.ftl b/webapp/web/templates/freemarker/body/partials/menupage/menupage-vClassesInClassgroup.ftl index 3a2661717..f4f1db777 100644 --- a/webapp/web/templates/freemarker/body/partials/menupage/menupage-vClassesInClassgroup.ftl +++ b/webapp/web/templates/freemarker/body/partials/menupage/menupage-vClassesInClassgroup.ftl @@ -7,6 +7,12 @@ <#list vClassGroup as vClass> <#-- Only display vClasses with individuals --> <#if (vClass.entityCount > 0)> + <#-- Calculate the individual count for the group since it's not currently provided to menu page templates --> + <#if !classGroupIndividualCount??> + <#assign classGroupIndividualCount = vClass.entityCount /> + <#else> + <#assign classGroupIndividualCount = classGroupIndividualCount + vClass.entityCount /> +
  • ${vClass.name} (${vClass.entityCount})