diff --git a/CHANGELOG b/CHANGELOG index 0d6a22f1f..a95208bc4 100644 --- a/CHANGELOG +++ b/CHANGELOG @@ -15,6 +15,9 @@ * irv: let the d3 tree layout look like in the QGIS IRMT plugin * irv: handle case in which a zone with no available data is clicked on the map * irv: when switching project definition, restyle the map accordingly + * irv: display charts in separate widgets instead of tabs + * irv: fix displaying the 'median' text when moving the mouse over a median line + * irv: enable zooming/panning for all d3 charts python-oq-platform (1.3.1) diff --git a/openquakeplatform/openquakeplatform/irv/static/irv/css/irv_legend.css b/openquakeplatform/openquakeplatform/irv/static/irv/css/irv_legend.css index 991d4fcd5..455a63ea2 100644 --- a/openquakeplatform/openquakeplatform/irv/static/irv/css/irv_legend.css +++ b/openquakeplatform/openquakeplatform/irv/static/irv/css/irv_legend.css @@ -7,10 +7,12 @@ #mapInfo { position: fixed; + margin-top: 40px; right: 20px; padding: 10px 10px 15px; background-color: whitesmoke; border-radius: 15px; + visibility: hidden; } .my-legend .legend-title { @@ -47,4 +49,4 @@ } .my-legend a { color: #777; - } \ No newline at end of file + } diff --git a/openquakeplatform/openquakeplatform/irv/static/irv/js/irv_viewer.js b/openquakeplatform/openquakeplatform/irv/static/irv/js/irv_viewer.js index cf0de60b2..200338892 100644 --- a/openquakeplatform/openquakeplatform/irv/static/irv/js/irv_viewer.js +++ b/openquakeplatform/openquakeplatform/irv/static/irv/js/irv_viewer.js @@ -14,6 +14,21 @@ You should have received a copy of the GNU Affero General Public License along with this program. If not, see . */ +var widgetsAndButtons = { + 'projDef': {'widget': '#project-def-widget', + 'button': '#toggleProjDefWidgetBtn', + 'buttonText': 'Show Project Definition'}, + 'iri': {'widget': '#iri-chart-widget', + 'button': '#toggleIriChartWidgetBtn', + 'buttonText': 'Show IRI Chart Widget'}, + 'svi': {'widget': '#cat-chart-widget', + 'button': '#toggleSviThemeWidgetBtn', + 'buttonText': 'Show SVI Theme Chart'}, + 'indicators': {'widget': '#primary-tab-widget', + 'button': '#toggleCompIndWidgetBtn', + 'buttonText': 'Show Composite Indicator Chart'} +}; + $(document).ready(function() { $('#cover').remove(); @@ -49,10 +64,19 @@ var baseMapUrl = new L.TileLayer('http://otile1.mqcdn.com/tiles/1.0.0/map/{z}/{x var app = new OQLeaflet.OQLeafletApp(baseMapUrl); var indicatorChildrenKey = []; -$(document).ready(function() { - $('#cover').remove(); - $('.alert-unscaled-data').hide(); -}); +function setWidgetsToDefault(){ + $('#pdSelection').empty(); + // set tabs back default + $('#projectDef-spinner').text('Loading ...'); + $('#projectDef-spinner').append(''); + $('#projectDef-spinner').show(); + $('#iri-spinner').show(); + $('#regionSelectionDialog').empty(); + $('#projectDef-tree').empty(); + $('#iri-chart').empty(); + $('#cat-chart').empty(); + $('#primary-chart').empty(); +} function scaleTheData() { // Create a list of primary indicators that need to be scaled @@ -765,8 +789,8 @@ function processIndicators(layerAttributes, projectDef) { SVI.plotElement = "SVI"; // Label within the object iriPcpData.push(SVI); } else { - // Disable the primary tab. - $("#themeTabs").tabs("disable", 3); + disableWidget(widgetsAndButtons.svi); + disableWidget(widgetsAndButtons.indicators); } if (riskIndicators !== undefined) { @@ -779,6 +803,15 @@ function processIndicators(layerAttributes, projectDef) { } // End processIndicators +function disableWidget(widgetAndBtn) { + // if the widget is visible, click the button to toggle it + if ($(widgetAndBtn.widget).is(':visible')) { + $(widgetAndBtn.button).click(); + } + // in any case, disable the button that shows the widget + $(widgetAndBtn.button).prop('disabled', true); +} + function scale(IndicatorObj) { var ValueArray = []; var scaledValues = []; @@ -794,9 +827,9 @@ function scale(IndicatorObj) { if (tempMax == tempMin) { scaledValues = [1]; // Disable the chart tabs - $("#themeTabs").tabs("disable", 1); - $("#themeTabs").tabs("disable", 2); - $("#themeTabs").tabs("disable", 3); + $.each(['indicators', 'svi', 'iri'], function(i, widgetName) { + disableWidget(widgetsAndButtons[widgetName]); + }); } else { scaledValues.push( (ValueArray[j] - tempMin) / (tempMax - tempMin) ); } @@ -1120,6 +1153,7 @@ function mapboxGlLayerCreation() { map.featuresAt(e.point, { radius : 6}, function(err, features) { if (err) throw err; $('#mapInfo').empty(); + $('#mapInfo').css({'visibility': 'visible'}); if (typeof features[0] === 'undefined') { $('#mapInfo').append('No data available'); } else { @@ -1415,21 +1449,35 @@ var startApp = function() { webGl = webglDetect(); + // using the list, otherwise we would lose the order + $.each(['projDef', 'iri', 'svi', 'indicators'], function(i, widgetName) { + // Theme tabs behavior + var widget = $(widgetsAndButtons[widgetName].widget); + widget.resizable({ + minHeight: 220, + minWidth: 220 + }); - // Theme tabs behavior - $('#themeTabs').resizable({ - minHeight: 220, - minWidth: 220 - }); - - $('#themeTabs').tabs({ - collapsible: false, - selected: -1, - active: false, - }); + widget.tabs({ + collapsible: false, + selected: -1, + active: false, + }); - $( "#themeTabs" ).draggable({ - cancel: "#project-def" + widget.draggable({ + stack: "div", // put on top of the others when dragging + distance: 0, // do it even if it's not actually moved + cancel: "#project-def, #primary-tab, #cat-chart, #iri-chart" + }); + widget.css({ + 'display': 'none', + 'width': '700px', + 'height': '600px', + 'overflow': 'hidden', + 'position': 'fixed', + 'left': (10 + i * 40) + 'px', + 'top': (110 + i * 40) + 'px' + }); }); $('#cover').remove(); @@ -1457,6 +1505,15 @@ var startApp = function() { $('#map-tools').append( '' ); + // Using the list in order to keep the order + $.each(['indicators', 'svi', 'iri', 'projDef'], function(i, widgetName) { + // slice(1) removes the heading # from the selector + var buttonId = widgetsAndButtons[widgetName].button.slice(1); + var buttonText = widgetsAndButtons[widgetName].buttonText; + $('#map-tools').append( + '' + ); + }); if (webGl === false) { $('#map-tools').append( @@ -1497,6 +1554,27 @@ var startApp = function() { $('#loadProjectDialog').dialog('open'); }); + function toggleWidget(widgetAndBtn) { + // toggle widget and change text on the corresponding button + var btnText = $(widgetAndBtn.button).html(); + // If the widget is visible, the button text is 'Hide Widgetname' + // Otherwise it is 'Show Widgetname' + // Let's change the button text before toggling the widget + if (btnText.indexOf('Hide ') >= 0) { // Change Hide -> Show + btnText = 'Show ' + btnText.slice(5); + } else { // Change Show -> Hide + btnText = 'Hide ' + btnText.slice(5); + } + $(widgetAndBtn.button).html(btnText); + $(widgetAndBtn.widget).toggle(); + } + + $.each(widgetsAndButtons, function(key, widgetAndBtn) { + $(widgetAndBtn.button).click(function() { + toggleWidget(widgetAndBtn); + }); + }); + // TODO check these are all needed $('#region-selection-list').hide(); $('#svir-project-list').hide(); @@ -1510,21 +1588,7 @@ var startApp = function() { }); $('#loadProjectBtn').click(function() { - $('#pdSelection').empty(); - // set tabs back default - $("#themeTabs").tabs("enable", 2); - $("#themeTabs").tabs("enable", 3); - - $('#themeTabs').tabs('option', 'active', 0); - $('#projectDef-spinner').text('Loading ...'); - $('#projectDef-spinner').append(''); - $('#projectDef-spinner').show(); - $('#iri-spinner').show(); - $('#regionSelectionDialog').empty(); - $('#projectDef-tree').empty(); - $('#iri-chart').empty(); - $('#cat-chart').empty(); - $('#primary-chart').empty(); + setWidgetsToDefault(); // FIXME This will not work if the title contains '(' or ')' // Get the selected layer @@ -1561,6 +1625,11 @@ var startApp = function() { closeOnEscape: true }); + $('#loadProjectDialog').draggable({ + stack: "div", // put on top of the others when dragging + distance: 0, // do it even if it's not actually moved + }); + $('#map-tools').css({ 'padding': '6px', 'position': 'absolute', @@ -1570,20 +1639,19 @@ var startApp = function() { 'z-index': 6 }); - $('#themeTabs').css({ - 'width': '700px', - 'height': '600px', - 'overflow': 'hidden', - 'position': 'fixed', - 'left': '10px', - 'top': '110px' - }); - $('#loadProjectdialogBtn').css({ 'position': 'fixed', 'left': '50px' }); + $.each(widgetsAndButtons, function(key, widgetAndBtn) { + $(widgetAndBtn.button).css({ + 'position': 'relative', + 'float': 'right', + 'margin-left': '2px' + }); + }); + $('#base-map-menu').css({ 'position': 'fixed', 'left': '390px' @@ -1619,24 +1687,17 @@ var startApp = function() { }; function loadProject() { - $('#pdSelection').empty(); - // set tabs to back default - $("#themeTabs").tabs("enable", 2); - $("#themeTabs").tabs("enable", 3); - - $('#themeTabs').tabs('option', 'active', 0); + setWidgetsToDefault(); $('#thematic-map-selection').show(); - $('#projectDef-spinner').text('Loading ...'); - $('#projectDef-spinner').append(''); - $('#projectDef-spinner').show(); - $('#iri-spinner').show(); - $('#regionSelectionDialog').empty(); - $('#projectDef-tree').empty(); - $('#iri-chart').empty(); - $('#cat-chart').empty(); - $('#primary-chart').empty(); - attributeInfoRequest(selectedLayer); + $.each(widgetsAndButtons, function(key, widgetAndBtn) { + // just enable buttons without opening widgets + $(widgetAndBtn.button).prop('disabled', false); + }); + // open the project definition widget if it's not already open + if (!$(widgetsAndButtons.projDef.widget).is(':visible')) { + $(widgetsAndButtons.projDef.button).click(); + } } function attributeInfoRequest(selectedLayer) { diff --git a/openquakeplatform/openquakeplatform/irv/static/irv/js/irv_viewer_PCP_IRI.js b/openquakeplatform/openquakeplatform/irv/static/irv/js/irv_viewer_PCP_IRI.js index 8b764189f..bef1ee949 100644 --- a/openquakeplatform/openquakeplatform/irv/static/irv/js/irv_viewer_PCP_IRI.js +++ b/openquakeplatform/openquakeplatform/irv/static/irv/js/irv_viewer_PCP_IRI.js @@ -69,10 +69,16 @@ function IRI_PCP_Chart(iriPcpData) { .scale(x); $("#iri-chart").empty(); + $("#iri-chart").css({'height': '100%'}); var svg = d3.select("#iri-chart").append("svg") + .attr("width", "100%") + .attr("height", "100%") .attr("viewBox", "-30 -20 " +winW+" " + (winH +20)) .attr("id", "IRI-svg-element") + .call(d3.behavior.zoom().scaleExtent([0.1, 5]).on("zoom", function () { + svg.attr("transform", "translate(" + d3.event.translate + ")" + " scale(" + d3.event.scale + ")"); + })) .append("svg:g") .attr("transform", "translate(" + m[3] + ",5)"); @@ -210,42 +216,51 @@ function IRI_PCP_Chart(iriPcpData) { //// Median line //// ////////////////////// - // Build skeleton array - for (var t in iriPcpData[0]) { - sum[t] = 0; - } - - // Sum all the paths - // Access the objects contained in the theme data array - for (var region_idx = 0; region_idx < iriPcpData.length; region_idx++) { - // iterate over the each - for (var elementName in iriPcpData[region_idx]) { - // This will sum all the values inside each theme object - sum[elementName] += iriPcpData[region_idx][elementName]; - } - } - - // Get the mean - for (var f in sum) { - var thisSum = sum[f]; - sumMean[f] = (thisSum / iriPcpData.length); - } - - sumMeanArray.push(sumMean); - - // Plot the median line - meanPath = svg.append("g") - .attr("class", "PI-meanPath") - .selectAll("path") - .data(sumMeanArray) - .enter().append("path") - .attr("d", path) - .attr('id', function(d) { return d.region; }) - .on('mouseover', function() { - textTop.text('Median'); - }).on('mouseout', function() { - textTop.text(''); - }); + // Build skeleton array + for (var t in iriPcpData[0]) { + sum[t] = 0; + } + + // Sum all the paths + // Access the objects contained in the theme data array + for (var region_idx = 0; region_idx < iriPcpData.length; region_idx++) { + // iterate over the each + for (var elementName in iriPcpData[region_idx]) { + // This will sum all the values inside each theme object + sum[elementName] += iriPcpData[region_idx][elementName]; + } + } + + // Get the mean + for (var f in sum) { + var thisSum = sum[f]; + sumMean[f] = (thisSum / iriPcpData.length); + } + + sumMeanArray.push(sumMean); + + var textTop = svg.append('text') + .attr("class", "text90") + .style('font-size','30px') + .style('font-style', 'bold') + .text(''); + + // Plot the median line + meanPath = svg.append("g") + .attr("class", "PI-meanPath") + .selectAll("path") + .data(sumMeanArray) + .enter().append("path") + .attr("d", path) + .attr('id', function(d) { return d.region; }) + .on('mouseover', function(d) { + textTop.attr('x', d.x); + textTop.attr('y', d.y); + textTop.attr('dy', '.35em'); + textTop.text('Median'); + }).on('mouseout', function() { + textTop.text(''); + }); // Handles a brush event, toggling the display of foreground lines. function brush() { diff --git a/openquakeplatform/openquakeplatform/irv/static/irv/js/irv_viewer_PCP_primary.js b/openquakeplatform/openquakeplatform/irv/static/irv/js/irv_viewer_PCP_primary.js index 27cd46ce2..eea9b6f5f 100644 --- a/openquakeplatform/openquakeplatform/irv/static/irv/js/irv_viewer_PCP_primary.js +++ b/openquakeplatform/openquakeplatform/irv/static/irv/js/irv_viewer_PCP_primary.js @@ -38,6 +38,9 @@ function Primary_PCP_Chart(projectDef, layerAttributes, selectedRegion) { // continue } } + if (themesWithChildren) { + $(widgetsAndButtons.indicators.button).prop('disabled', false); + } $('#primary_indicator').empty(); $('#primary_indicator').append(''); @@ -96,6 +99,7 @@ function Primary_PCP_Chart(projectDef, layerAttributes, selectedRegion) { } } + $('#primary-tab').css({'height': '100%'}); $('#primary-tab').append('
'); @@ -141,10 +145,16 @@ function Primary_PCP_Chart(projectDef, layerAttributes, selectedRegion) { .scale(x); $("#primary-chart").empty(); + $("#primary-chart").css({'height': '100%'}); var svg = d3.select("#primary-chart").append("svg") + .attr("width", "100%") + .attr("height", "100%") .attr("viewBox", "-30 -20 " +winW+" " + (winH +20)) .attr("id", "primary-svg-element") + .call(d3.behavior.zoom().scaleExtent([0.1, 5]).on("zoom", function () { + svg.attr("transform", "translate(" + d3.event.translate + ")" + " scale(" + d3.event.scale + ")"); + })) .append("svg:g") .attr("transform", "translate(" + m[3] + ",5)"); @@ -287,6 +297,12 @@ function Primary_PCP_Chart(projectDef, layerAttributes, selectedRegion) { sumMeanArray.push(sumMean); + var textTop = svg.append('text') + .attr("class", "text90") + .style('font-size','30px') + .style('font-style', 'bold') + .text(''); + // Plot the median line meanPath = svg.append("g") .attr("class", "PI-meanPath") @@ -295,7 +311,10 @@ function Primary_PCP_Chart(projectDef, layerAttributes, selectedRegion) { .enter().append("path") .attr("d", path) .attr('id', function(d) { return d.region; }) - .on('mouseover', function() { + .on('mouseover', function(d) { + textTop.attr('x', d.x); + textTop.attr('y', d.y); + textTop.attr('dy', '.35em'); textTop.text('Median'); }).on('mouseout', function() { textTop.text(''); diff --git a/openquakeplatform/openquakeplatform/irv/static/irv/js/irv_viewer_PCP_theme.js b/openquakeplatform/openquakeplatform/irv/static/irv/js/irv_viewer_PCP_theme.js index 9c08a5cb8..3facb9a5e 100644 --- a/openquakeplatform/openquakeplatform/irv/static/irv/js/irv_viewer_PCP_theme.js +++ b/openquakeplatform/openquakeplatform/irv/static/irv/js/irv_viewer_PCP_theme.js @@ -39,9 +39,11 @@ function Theme_PCP_Chart(themeData) { if (themeCount <= 2) { // Disable the theme tab. - $("#themeTabs").tabs("disable", 2); + disableWidget(widgetsAndButtons.svi); // Stop the function from continuing. return; + } else { + $(widgetsAndButtons.svi.button).prop('disabled', false); } var data = themeData; @@ -64,9 +66,9 @@ function Theme_PCP_Chart(themeData) { } } - for (var i = 0; i < eachElementInThemeData.length; i++) { - if (!isNaN(parseFloat(eachElementInThemeData[i])) && isFinite(eachElementInThemeData[i])) { - eachValueInThemeData.push(eachElementInThemeData[i]); + for (var j = 0; j < eachElementInThemeData.length; j++) { + if (!isNaN(parseFloat(eachElementInThemeData[j])) && isFinite(eachElementInThemeData[j])) { + eachValueInThemeData.push(eachElementInThemeData[j]); } } @@ -83,10 +85,16 @@ function Theme_PCP_Chart(themeData) { foreground; $('#cat-chart').empty(); + $("#cat-chart").css({'height': '100%'}); var svg = d3.select('#cat-chart').append('svg') + .attr("width", "100%") + .attr("height", "100%") .attr("viewBox", "100 20 " +(winW -400)+" " +winH) .attr("id", "CI-svg-element") + .call(d3.behavior.zoom().scaleExtent([0.1, 5]).on("zoom", function () { + svg.attr("transform", "translate(" + d3.event.translate + ")" + " scale(" + d3.event.scale + ")"); + })) .append('g') .attr('transform', 'translate(' + margin.left + ',' + margin.top + ')'); diff --git a/openquakeplatform/openquakeplatform/irv/static/irv/js/irv_viewer_d3_tree.js b/openquakeplatform/openquakeplatform/irv/static/irv/js/irv_viewer_d3_tree.js index 5a8524002..230823d62 100644 --- a/openquakeplatform/openquakeplatform/irv/static/irv/js/irv_viewer_d3_tree.js +++ b/openquakeplatform/openquakeplatform/irv/static/irv/js/irv_viewer_d3_tree.js @@ -52,7 +52,7 @@ var winW = 700; // detect tab window resize - $('#themeTabs').resize(function(event) { + $('#project-def-widget').resize(function(event) { winH = event.clientY; winW = event.clientX; }); diff --git a/openquakeplatform/openquakeplatform/irv/templates/irv/irv_viewer.html b/openquakeplatform/openquakeplatform/irv/templates/irv/irv_viewer.html index 333c61cf6..3c1d40760 100644 --- a/openquakeplatform/openquakeplatform/irv/templates/irv/irv_viewer.html +++ b/openquakeplatform/openquakeplatform/irv/templates/irv/irv_viewer.html @@ -69,28 +69,40 @@ - -
+
-
- -
-
-
-
-
+ +
+
+
+
+
+
+ +
+
Loading ...
+
+ +
+
+
+ +
+
@@ -104,9 +116,8 @@

- -
+
{% endblock middle %}