简体   繁体   中英

Google Visualization - Trying to format each tooltip to display a percentage by formatter, or query

I've been trying to format the tooltips of my charts into percentages with no success. Here are the following features of my project reduced to bare minimum:

  • UI consists of 2 groups of radio buttons and 1 checkmark.
  • User can switch to view data sources displayed by different chart types.
  • Source is queried from 7 Google Sheets that the user can view.
  • The user can view these data sources with 4 chart types.
  • The initial data source is displayed by a chartWrapper() ( chart called by drawChart() )
  • The next 6 data sources share one chartWrapper() ( main called by alterChart() )

I've have commented within the MCVE details of the 3 failed attempts, they are as follows:

  1. First attempt: Adding encoded query string to data source url.
  2. Second attempt: Using setQuery()
  3. Third attempt: Using formatter object.

Any help to resolve this by using any of the 3 ways previously mentioned is welcome. I'm open to anything I didn't cover, but I may need more details since I'm still learning this API. Thank you for your valuable time, I appreciate it.

[ PLUNKER ]

SNIPPET

 <!DOCTYPE html> <html> <head> <meta charset="utf-8"> <meta name="viewport" content="width=device-width,initial-scale=1, user-scalable=no"> <title>MCVE - GVis Formatting Tooltips</title> <link href='https://glpro.s3.amazonaws.com/_css/glb.css' rel='stylesheet'> <style> @import url('https://fonts.googleapis.com/css?family=Open+Sans'); *, *:before, *:after { font-style: normal !important; } body { position: relative; } form { background-color: #333; } #ii { margin-top: 80px } .panel { display: flex; flex-wrap: wrap; justify-content: center; align-items: center; } #chart { height: 70vh; width: 96vw; } .group.group:after, .chart.chart:after, .root.root:after { color: #333; } div.google-visualization-tooltip { background-color: rgba(0, 0, 0, .6); border-radius: 6px; min-width: 325px; max-height: 75px; } div.google-visualization-tooltip > ul > li { display: table-cell; margin: 0 5px; } div.google-visualization-tooltip > ul > li > span { color: gold; } #groupOpt { display: none; } #groupOpt.on { display: block; } </style> </head> <body class='sl'> <header class='panel'> <!--THIS PART REMOVED--> </form> </header> <section id="ii"> <h1>Sources</h1> <figure id='chart'></figure> </section> <footer> </footer> <script src="https://ajax.googleapis.com/ajax/libs/jquery/2.2.2/jquery.min.js"></script> <script type="text/javascript" src="https://www.gstatic.com/charts/loader.js"></script> <script type="text/javascript"> google.charts.load('current', { packages: ['corechart'] }); google.charts.setOnLoadCallback(drawChart); var options = { backgroundColor: { fill: 'transparent' }, tooltip: { textStyle: { color: 'gold', fontSize: 16, fontName: 'Verdana' }, trigger: 'focus', isHtml: true }, animation: { startup: true, duration: 1000, easing: 'out' }, title: 'Percentage of Americans in Favor of Same-sex Marriage (2001-16)', titleTextStyle: { color: 'gold', fontName: 'Open Sans', fontSize: 22 }, hAxis: { textStyle: { color: 'cyan' }, title: 'Year', titleTextStyle: { color: 'gold', fontName: 'Open Sans', fontSize: 22 }, format: '####' }, vAxis: { maxValue: .85, format: '#%', textStyle: { fontName: 'Open Sans', color: 'cyan' }, title: 'Percentage of Sub-Population that Approves of Same-sex Marriage', titleTextStyle: { color: 'gold', fontName: 'Arial', fontSize: 16 } }, legend: { textStyle: { color: 'white', fontName: 'Verdana' }, position: 'bottom' }, crosshair: { trigger: 'both', orientation: 'both', focused: { color: 'gold', opacity: .7 }, selected: { color: 'cyan', opacity: .7 } }, pointSize: 12, theme: 'materials', chartArea: { left: 100, top: 75, width: '90%', height: '60%' } } var dataTable; var chart; var data; var main; var cArray = ['LineChart', 'AreaChart', 'ColumnChart', 'ScatterChart']; var qArray = [THIS DATA REMOVED] ]; /* Attempt #1 - Using encoded query string with data query source url // No Errors - QUERY_STRING = select * (# * 100)% -- Syntax is wrong, but I couldn't find any solid examples. var qArray = [ 'https://docs.google.com/spreadsheets/d/1EY13wZB9IUet4e5gVeMEFLQcHdNfr--S4j741XVAfxo/gviz/tq?gid=1104711743&select%20*%20(%23%20*%20100)%25','https://docs.google.com/spreadsheets/d/1EH9C-_OviFTLwC5Z30HTATZqtFnOx_JcOIDHYzF7-FY/gviz/tq?gid=1552974580&select%20*%20(%23%20*%20100)%25 ', 'https://docs.google.com/spreadsheets/d/1EY13wZB9IUet4e5gVeMEFLQcHdNfr--S4j741XVAfxo/gviz/tq?gid=2111420909&select%20*%20(%23%20*%20100)%25', 'https://docs.google.com/spreadsheets/d/1EY13wZB9IUet4e5gVeMEFLQcHdNfr--S4j741XVAfxo/gviz/tq?gid=1379142381&select%20*%20(%23%20*%20100)%25', 'https://docs.google.com/spreadsheets/d/1EY13wZB9IUet4e5gVeMEFLQcHdNfr--S4j741XVAfxo/gviz/tq?gid=1749299608&select%20*%20(%23%20*%20100)%25', 'https://docs.google.com/spreadsheets/d/1EY13wZB9IUet4e5gVeMEFLQcHdNfr--S4j741XVAfxo/gviz/tq?gid=268750266&select%20*%20(%23%20*%20100)%25', 'https://docs.google.com/spreadsheets/d/1EY13wZB9IUet4e5gVeMEFLQcHdNfr--S4j741XVAfxo/gviz/tq?gid=148086622&select%20*%20(%23%20*%20100)%25', 'https://docs.google.com/spreadsheets/d/1EY13wZB9IUet4e5gVeMEFLQcHdNfr--S4j741XVAfxo/gviz/tq?gid=1474413858&select%20*%20(%23%20*%20100)%25' ]; */ // function drawChart() { chart = new google.visualization.ChartWrapper(); chart.setDataSourceUrl(qArray[1]); /* Attempt #2 - Using setQuery // Error -- Syntax is wrong but as stated previously, I could not find a solid example. INVALID_QUERY Invalid query: PARSE_ERROR: Encountered &quot;format&quot; at line 1, column 8. Was expecting one of: &quot;true&quot; ... &quot;false&quot; ... &quot;date&quot; ... &quot;timeofday&quot; ... &quot;datetime&quot; ... &quot;timestamp&quot; ... &quot;min&quot; ... &quot;max&quot; ... &quot;avg&quot; ... &quot;count&quot; ... &quot;sum&quot; ... &quot;no_values&quot; ... &quot;no_format&quot; ... &quot;is&quot; ... &quot;null&quot; ... &quot;year&quot; ... &quot;month&quot; ... &quot;day&quot; ... &quot;hour&quot; ... &quot;minute&quot; ... &quot;second&quot; ... &quot;millisecond&quot; ... &quot;with&quot; ... &quot;contains&quot; ... &quot;starts&quot; ... &quot;ends&quot; ... &quot;matches&quot; ... &quot;like&quot; ... &quot;now&quot; ... &quot;dateDiff&quot; ... &quot;quarter&quot; ... &quot;lower&quot; ... &quot;upper&quot; ... &quot;dayOfWeek&quot; ... &quot;toDate&quot; ... &lt;ID&gt; ... &lt;INTEGER_LITERAL&gt; ... &lt;DECIMAL_LITERAL&gt; ... &lt;STRING_LITERAL&gt; ... &lt;QUOTED_ID&gt; ... &quot;(&quot; ... &quot;*&quot; ... &quot;-&quot; ... */ //chart.setQuery('select format #%'); dataTable = new google.visualization.DataTable(); /* Attempt #3 Using formatter object // Uncaught Error: Table has no columns -- I believe the syntax is correct, just not it's location and/or specific requirements such as properly handling the data from the ResponseQuery? formatter = new google.visualization.NumberFormat({pattern:'#%'}); formatter.format(dataTable, 1); formatter.format(dataTable, 2); formatter.format(dataTable, 3); formatter.format(dataTable, 4); formatter.format(dataTable, 5); formatter.format(dataTable, 6); formatter.format(dataTable, 7); formatter.format(dataTable, 8); formatter.format(dataTable, 9); formatter.format(dataTable, 10); formatter.format(dataTable, 11); formatter.format(dataTable, 12); formatter.format(dataTable, 13); formatter.format(dataTable, 14); formatter.format(dataTable, 15); */ chart.setChartType('LineChart'); chart.setContainerId('chart'); chart.setOptions(options); chart.draw(); } function alterChart(C, Q) { C = Number(C); Q = Number(Q); var URL = qArray[Q]; var VIS = cArray[C]; main = new google.visualization.ChartWrapper(); main.setDataSourceUrl(URL); // Attempt #2 // main.setQuery('select format #%'); data = new google.visualization.DataTable(); /* Attempt #3 // Uncaught Error: Table has no columns pattern = new google.visualization.NumberFormat({pattern:'#%'}); pattern.format(data, 1); pattern.format(data, 2); pattern.format(data, 3); pattern.format(data, 4); pattern.format(data, 5); pattern.format(data, 6); pattern.format(data, 7); pattern.format(data, 8); pattern.format(data, 9); pattern.format(data, 10); pattern.format(data, 11); pattern.format(data, 12); pattern.format(data, 13); pattern.format(data, 14); pattern.format(data, 15); */ // main.setChartType(VIS); main.setContainerId('chart'); main.setOptions(options); main.draw(); } $('#chartOpt, #groupOpt, #rootOpt').on('change', function(e) { var chartSel = $("input[name='chart']:checked").val(); var groupSel = $("input[name='group']:checked").val(); if (e.target !== e.currentTarget) { var target = e.target.id; var status = $(target).hasClass('on') ? true : false; } if (target === 'root0') { $('#' + target).toggleClass('on'); if (status === true) { $('#groupOpt').slideUp().removeClass('on'); return alterChart(chartSel, '1'); } else if (status === false) { $('#groupOpt').slideDown().addClass('on'); return alterChart(chartSel, groupSel); } else return false; } else if (target === 'chart0' || target === 'chart1' || target === 'chart2' || target === 'chart3') { if (status === true) { return alterChart(chartSel, '1'); } else { return alterChart(chartSel, groupSel); } } else { if (status === true) { return false; } else { return alterChart(chartSel, groupSel); } } }); var group = document.getElementsByName('group'); var len = group.length; var rad; var i; for (i = 0; i < len; i++) { group[i].onclick = function() { if (rad == this) { this.checked = false; rad = null; } else { rad = this; } } } </script> <!--<script src='gvis-api.js'></script>--> </body> </html> 

You were setting the chart's data source URL and it was rendering itself before you had a chance to format the data. The solution is to query the data yourself, format it, and then pass it into the chart.

 <!DOCTYPE html> <html> <head> <meta charset="utf-8"> <meta name="viewport" content="width=device-width,initial-scale=1, user-scalable=no"> <title>MCVE - GVis Formatting Tooltips</title> <link href='https://glpro.s3.amazonaws.com/_css/glb.css' rel='stylesheet'> <style> @import url('https://fonts.googleapis.com/css?family=Open+Sans'); *, *:before, *:after { font-style: normal !important; } body { position: relative; } form { background-color: #333; } #ii { margin-top: 80px } .panel { display: flex; flex-wrap:wrap; justify-content: center; align-items: center; } #chart { height: 70vh; width: 96vw; } .group.group:after, .chart.chart:after, .root.root:after { color: #333; } div.google-visualization-tooltip { background-color: rgba(0,0,0,.6); border-radius: 6px; min-width: 325px; max-height: 75px;} div.google-visualization-tooltip > ul > li { display: table-cell; margin:0 5px; } div.google-visualization-tooltip > ul > li > span { color: gold; } #groupOpt { display:none; } #groupOpt.on { display:block;} </style> </head> <body class='sl'> <header class='panel'> <form id="rootOpt" class="sgc" style="width: 20%; color: #fffff"> <input type="checkbox" name="group" id="root0" value='1' checked> <label for="root0" class="root" id="switch0" data-value="Results">Groups</label> </form> <form id="chartOpt" class="sgc" style="width: 80%; color: #ffcc00"> <input type="radio" name="chart" id="chart0" value='0' checked> <input type="radio" name="chart" id="chart1" value='1'> <input type="radio" name="chart" id="chart2" value='2'> <input type="radio" name="chart" id="chart3" value='3'> <label for="chart0" class="chart" data-value="Line Chart">Line Chart</label> <label for="chart1" class="chart" data-value="Area Chart">Area Chart</label> <label for="chart2" class="chart" data-value="Column Chart">Column Chart</label> <label for="chart3" class="chart" data-value="Scatter Chart">Scatter Chart</label> </form> <form id="groupOpt" class='sgc' style="width:100%; color: #00ffff; display:none"> <input type="radio" name="group" id="group0" data-format='4' value='2' checked> <input type="radio" name="group" id="group1" data-format='5' value='3'> <input type="radio" name="group" id="group2" data-format='3' value='4'> <input type="radio" name="group" id="group3" data-format='3' value='5'> <input type="radio" name="group" id="group4" data-format='2' value='6'> <input type="radio" name="group" id="group5" data-format='2' value='7'> <label for="group0" class="group" data-value="Generation">Generation</label> <label for="group1" class="group" data-value="Religion">Religion</label> <label for="group2" class="group" data-value="Party Affiliation">Party Affiliation</label> <label for="group3" class="group" data-value="Political Ideology">Political Ideology</label> <label for="group4" class="group" data-value="Race">Race</label> <label for="group5" class="group" data-value="Gender">Gender</label> </form> </header> <section id="ii"> <h1>Sources</h1> <figure id='chart'></figure> </section> <footer> </footer> <script src="https://ajax.googleapis.com/ajax/libs/jquery/2.2.2/jquery.min.js"></script> <script type="text/javascript" src="http://www.google.com/jsapi"></script> <script type="text/javascript"> google.setOnLoadCallback(runQuery); google.load('visualization', '1', { packages: ['corechart', 'table', 'geomap'] }); var options = { backgroundColor: { fill: 'transparent' }, tooltip: { textStyle: { color: 'gold', fontSize: 16, fontName: 'Verdana' }, trigger: 'focus', isHtml: true }, animation: { startup: true, duration: 1000, easing: 'out' }, title: 'Percentage of Americans in Favor of Same-sex Marriage (2001-16)', titleTextStyle: { color: 'gold', fontName: 'Open Sans', fontSize: 22 }, hAxis: { textStyle: { color: 'cyan' }, title: 'Year', titleTextStyle: { color: 'gold', fontName: 'Open Sans', fontSize: 22 }, format: '####' }, vAxis: { maxValue: .85, format: '#%', textStyle: { fontName: 'Open Sans', color: 'cyan' }, title: 'Percentage of Sub-Population that Approves of Same-sex Marriage', titleTextStyle: { color: 'gold', fontName: 'Arial', fontSize: 16 } }, legend: { textStyle: { color: 'white', fontName: 'Verdana' }, position: 'bottom' }, crosshair: { trigger: 'both', orientation: 'both', focused: { color: 'gold', opacity: .7 }, selected: { color: 'cyan', opacity: .7 } }, pointSize: 12, theme: 'materials', chartArea: { left: 100, top: 75, width: '90%', height: '60%' } } var dataTable; var chart; var data; var main; var cArray = ['LineChart', 'AreaChart', 'ColumnChart', 'ScatterChart']; var qArray = ['https://docs.google.com/spreadsheets/d/1EY13wZB9IUet4e5gVeMEFLQcHdNfr--S4j741XVAfxo/gviz/tq?gid=1104711743', 'https://docs.google.com/spreadsheets/d/1EH9C-_OviFTLwC5Z30HTATZqtFnOx_JcOIDHYzF7-FY/gviz/tq?gid=1552974580', 'https://docs.google.com/spreadsheets/d/1EY13wZB9IUet4e5gVeMEFLQcHdNfr--S4j741XVAfxo/gviz/tq?gid=2111420909', 'https://docs.google.com/spreadsheets/d/1EY13wZB9IUet4e5gVeMEFLQcHdNfr--S4j741XVAfxo/gviz/tq?gid=1379142381', 'https://docs.google.com/spreadsheets/d/1EY13wZB9IUet4e5gVeMEFLQcHdNfr--S4j741XVAfxo/gviz/tq?gid=1749299608', 'https://docs.google.com/spreadsheets/d/1EY13wZB9IUet4e5gVeMEFLQcHdNfr--S4j741XVAfxo/gviz/tq?gid=268750266', 'https://docs.google.com/spreadsheets/d/1EY13wZB9IUet4e5gVeMEFLQcHdNfr--S4j741XVAfxo/gviz/tq?gid=148086622', 'https://docs.google.com/spreadsheets/d/1EY13wZB9IUet4e5gVeMEFLQcHdNfr--S4j741XVAfxo/gviz/tq?gid=1474413858' ]; function runQuery() { var opts = { sendMethod: 'auto' }; if (!google.visualization) return; var query = new google.visualization.Query(qArray[1], opts); query.send(handleQueryResponse); } function handleQueryResponse(response) { if (!response) return; if (!response.getDataTable()) return; drawChart(response.getDataTable()); } function drawChart(dataTable) { console.debug(dataTable) chart = new google.visualization.LineChart(document.getElementById('chart')); if (dataTable && dataTable.getNumberOfColumns() > 0) { var formatter = new google.visualization.NumberFormat({ pattern: '#%', fractionDigits: 0 }); formatter.format(dataTable, 1); formatter.format(dataTable, 2); } chart.draw(dataTable, options); } function alterChart(C, Q) { C = Number(C); Q = Number(Q); var URL = qArray[Q]; var VIS = cArray[C]; main = new google.visualization.ChartWrapper(); main.setDataSourceUrl(URL); if (dataTable.getNumberOfColumns() > 0) { //formatter = new google.visualization.NumberFormat({pattern:'#\\'%\\''}); var formatter = new google.visualization.NumberFormat({ pattern: '#%', fractionDigits: 0 }); formatter.format(dataTable, 1); formatter.format(dataTable, 2); } main.setChartType(VIS); main.setContainerId('chart'); main.setOptions(options); main.draw(); } runQuery(); $('#chartOpt, #groupOpt, #rootOpt').on('change', function(e) { var chartSel = $("input[name='chart']:checked").val(); var groupSel = $("input[name='group']:checked").val(); if (e.target !== e.currentTarget) { var target = e.target.id; var status = $(target).hasClass('on') ? true : false; } if (target === 'root0') { $('#' + target).toggleClass('on'); if (status === true) { $('#groupOpt').slideUp().removeClass('on'); return alterChart(chartSel, '1'); } else if (status === false) { $('#groupOpt').slideDown().addClass('on'); return alterChart(chartSel, groupSel); } else return false; } else if (target === 'chart0' || target === 'chart1' || target === 'chart2' || target === 'chart3') { if (status === true) { return alterChart(chartSel, '1'); } else { return alterChart(chartSel, groupSel); } } else { if (status === true) { return false; } else { return alterChart(chartSel, groupSel); } } }); var group = document.getElementsByName('group'); var len = group.length; var rad; var i; for (i = 0; i < len; i++) { group[i].onclick = function() { if (rad == this) { this.checked = false; rad = null; } else { rad = this; } } } </script> </body> </html> 

I just resolved my issue, I formatted the actual source in Google Sheets and now the tooltips are percentages. So simple it never occurred to me. The following array is the only thing changed. Each new url points to a preformatted table in Google Sheets:

 var qArray = ['https://docs.google.com/spreadsheets/d/1c9xyhR1_BavywsAOvpkf65Nhf9o0j8KHqRrEYC25mus/gviz/tq?gid=1104711743&range=A:T', 'https://docs.google.com/spreadsheets/d/1c9xyhR1_BavywsAOvpkf65Nhf9o0j8KHqRrEYC25mus/gviz/tq?gid=1552974580&range=A:C', 'https://docs.google.com/spreadsheets/d/1c9xyhR1_BavywsAOvpkf65Nhf9o0j8KHqRrEYC25mus/gviz/tq?gid=2111420909&range=A:E', 'https://docs.google.com/spreadsheets/d/1c9xyhR1_BavywsAOvpkf65Nhf9o0j8KHqRrEYC25mus/gviz/tq?gid=1379142381&range=A:F', 'https://docs.google.com/spreadsheets/d/1c9xyhR1_BavywsAOvpkf65Nhf9o0j8KHqRrEYC25mus/gviz/tq?gid=1749299608&range=A:D', 'https://docs.google.com/spreadsheets/d/1c9xyhR1_BavywsAOvpkf65Nhf9o0j8KHqRrEYC25mus/gviz/tq?gid=268750266&range=A:D', 'https://docs.google.com/spreadsheets/d/1c9xyhR1_BavywsAOvpkf65Nhf9o0j8KHqRrEYC25mus/gviz/tq?gid=148086622&range=A:C', 'https://docs.google.com/spreadsheets/d/1c9xyhR1_BavywsAOvpkf65Nhf9o0j8KHqRrEYC25mus/gviz/tq?gid=1474413858&range=A:C']; 

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM