| @@ -98,10 +98,12 @@ | ||
| 98 | 98 | |
| 99 | 99 | var settings = _this.dbData.options; |
| 100 | 100 | var nSettings = _this.configOptionsForCharts(settings); |
| 101 | 101 | |
| 102 | + var userLocale = navigator.language || navigator.userLanguage || 'en'; | |
| 103 | + | |
| 102 | 104 | /* == Google part == */ |
| 103 | - google.charts.load('current', {'packages':['corechart']}); | |
| 105 | + google.charts.load('current', {'packages':['corechart'], 'language': userLocale}); | |
| 104 | 106 | google.charts.setOnLoadCallback(drawChart); |
| 105 | 107 | |
| 106 | 108 | function drawChart() { |
| 107 | 109 | _this.chartData = google.visualization.arrayToDataTable( dataTypes ); |
| @@ -164,8 +166,12 @@ | ||
| 164 | 166 | _this.chartObj = new google.visualization.PieChart( document.getElementById(_this.htmlClassPrefix + _this.chartType + _this.uniqueId)); |
| 165 | 167 | |
| 166 | 168 | _this.chartObj.draw( _this.chartData, _this.chartOptions ); |
| 167 | 169 | _this.resizeChart(); |
| 170 | + // Fix ARIA attributes for accessibility compliance | |
| 171 | + setTimeout(function() { | |
| 172 | + _this.fixAriaAttributes(); | |
| 173 | + }, 100); | |
| 168 | 174 | } |
| 169 | 175 | /* */ |
| 170 | 176 | } |
| 171 | 177 | |
| @@ -177,10 +183,12 @@ | ||
| 177 | 183 | |
| 178 | 184 | var settings = _this.dbData.options; |
| 179 | 185 | var nSettings = _this.configOptionsForCharts(settings); |
| 180 | 186 | |
| 187 | + var userLocale = navigator.language || navigator.userLanguage || 'en'; | |
| 188 | + | |
| 181 | 189 | /* == Google part == */ |
| 182 | - google.charts.load('current', {'packages':['corechart']}); | |
| 190 | + google.charts.load('current', {'packages':['corechart'], 'language': userLocale}); | |
| 183 | 191 | google.charts.setOnLoadCallback(drawChart); |
| 184 | 192 | |
| 185 | 193 | function drawChart() { |
| 186 | 194 | dataTypes = nSettings.enableRowSettings ? _this.setRowOptions(dataTypes, nSettings, true) : dataTypes; |
| @@ -311,13 +319,49 @@ | ||
| 311 | 319 | duration: nSettings.animationDuration, |
| 312 | 320 | easing: nSettings.animationEasing, |
| 313 | 321 | } |
| 314 | 322 | } |
| 323 | + | |
| 315 | 324 | |
| 325 | + if(_this.chartOptions.hAxis.format == 'percent' && nSettings.hAxisEnableDividePercent){ | |
| 326 | + for (var i = 0; i < dataTypes[0].length - 1; i++) { | |
| 327 | + nSettings.seriesFormat[i] = '#%'; | |
| 328 | + } | |
| 329 | + | |
| 330 | + for (var row = 0; row < _this.chartData.getNumberOfRows(); row++) { | |
| 331 | + for (var col = 0; col < _this.chartData.getNumberOfColumns(); col++) { | |
| 332 | + var value = _this.chartData.getValue(row, col); | |
| 333 | + if (typeof value === 'number' && !isNaN(value)) { | |
| 334 | + var updatedValue = value / 100; | |
| 335 | + _this.chartData.setValue(row, col, updatedValue); | |
| 336 | + } | |
| 337 | + } | |
| 338 | + } | |
| 339 | + | |
| 340 | + }else { | |
| 341 | + for (var i = 0; i < dataTypes[0].length - 1; i++) { | |
| 342 | + if (nSettings.seriesFormat[i] === '#%') { | |
| 343 | + nSettings.seriesFormat[i] = ''; | |
| 344 | + } | |
| 345 | + } | |
| 346 | + } | |
| 347 | + | |
| 348 | + for (var i = 1; i < dataTypes[0].length; i++) { | |
| 349 | + if (nSettings.seriesFormat[i - 1]) { | |
| 350 | + var formatter = new google.visualization.NumberFormat({ | |
| 351 | + pattern: nSettings.seriesFormat[i - 1] | |
| 352 | + }); | |
| 353 | + formatter.format(_this.chartData, i); | |
| 354 | + } | |
| 355 | + } | |
| 316 | 356 | _this.chartObj = new google.visualization.BarChart(document.getElementById(_this.htmlClassPrefix + _this.chartType + _this.uniqueId)); |
| 317 | 357 | |
| 318 | 358 | _this.chartObj.draw( _this.chartData, _this.chartOptions ); |
| 319 | 359 | _this.resizeChart(); |
| 360 | + // Fix ARIA attributes for accessibility compliance | |
| 361 | + setTimeout(function() { | |
| 362 | + _this.fixAriaAttributes(); | |
| 363 | + }, 100); | |
| 320 | 364 | } |
| 321 | 365 | /* */ |
| 322 | 366 | } |
| 323 | 367 | |
| @@ -331,10 +375,12 @@ | ||
| 331 | 375 | |
| 332 | 376 | var settings = _this.dbData.options; |
| 333 | 377 | var nSettings = _this.configOptionsForCharts(settings); |
| 334 | 378 | |
| 379 | + var userLocale = navigator.language || navigator.userLanguage || 'en'; | |
| 380 | + | |
| 335 | 381 | /* == Google part == */ |
| 336 | - google.charts.load('current', {'packages':['corechart']}); | |
| 382 | + google.charts.load('current', {'packages':['corechart'], 'language': userLocale}); | |
| 337 | 383 | google.charts.setOnLoadCallback(drawChart); |
| 338 | 384 | |
| 339 | 385 | function drawChart() { |
| 340 | 386 | dataTypes = nSettings.enableRowSettings ? _this.setRowOptions(dataTypes, nSettings, true) : dataTypes; |
| @@ -458,9 +504,40 @@ | ||
| 458 | 504 | color: nSettings.seriesColor[i], |
| 459 | 505 | visibleInLegend: nSettings.seriesVisibleInLegend[i] == 'on' ? true : (typeof nSettings.seriesColor[i] !== 'undefined' ? false : true), |
| 460 | 506 | } |
| 461 | 507 | } |
| 508 | + | |
| 509 | + if(_this.chartOptions.vAxis.format == 'percent' && nSettings.vAxisEnableDividePercent){ | |
| 510 | + for (var i = 0; i < dataTypes[0].length - 1; i++) { | |
| 511 | + nSettings.seriesFormat[i] = '#%'; | |
| 512 | + } | |
| 513 | + | |
| 462 | 514 | |
| 515 | + for (var row = 0; row < _this.chartData.getNumberOfRows(); row++) { | |
| 516 | + for (var col = 0; col < _this.chartData.getNumberOfColumns(); col++) { | |
| 517 | + var value = _this.chartData.getValue(row, col); | |
| 518 | + if (typeof value === 'number' && !isNaN(value)) { | |
| 519 | + var updatedValue = value / 100; | |
| 520 | + _this.chartData.setValue(row, col, updatedValue); | |
| 521 | + } | |
| 522 | + } | |
| 523 | + } | |
| 524 | + | |
| 525 | + }else { | |
| 526 | + for (var i = 0; i < dataTypes[0].length - 1; i++) { | |
| 527 | + if (nSettings.seriesFormat[i] === '#%') { | |
| 528 | + nSettings.seriesFormat[i] = ''; | |
| 529 | + } | |
| 530 | + } | |
| 531 | + } | |
| 532 | + for (var i = 1; i < dataTypes[0].length; i++) { | |
| 533 | + if (nSettings.seriesFormat[i - 1]) { | |
| 534 | + var formatter = new google.visualization.NumberFormat({ | |
| 535 | + pattern: nSettings.seriesFormat[i - 1] | |
| 536 | + }); | |
| 537 | + formatter.format(_this.chartData, i); | |
| 538 | + } | |
| 539 | + } | |
| 463 | 540 | if (nSettings.enableAnimation) { |
| 464 | 541 | _this.chartOptions.animation = { |
| 465 | 542 | startup: nSettings.animationStartup, |
| 466 | 543 | duration: nSettings.animationDuration, |
| @@ -471,8 +548,12 @@ | ||
| 471 | 548 | _this.chartObj = new google.visualization.ColumnChart(document.getElementById(_this.htmlClassPrefix + _this.chartType + _this.uniqueId)); |
| 472 | 549 | |
| 473 | 550 | _this.chartObj.draw( _this.chartData, _this.chartOptions ); |
| 474 | 551 | _this.resizeChart(); |
| 552 | + // Fix ARIA attributes for accessibility compliance | |
| 553 | + setTimeout(function() { | |
| 554 | + _this.fixAriaAttributes(); | |
| 555 | + }, 100); | |
| 475 | 556 | } |
| 476 | 557 | /* */ |
| 477 | 558 | } |
| 478 | 559 | |
| @@ -484,10 +565,12 @@ | ||
| 484 | 565 | |
| 485 | 566 | var settings = _this.dbData.options; |
| 486 | 567 | var nSettings = _this.configOptionsForCharts(settings); |
| 487 | 568 | |
| 569 | + var userLocale = navigator.language || navigator.userLanguage || 'en'; | |
| 570 | + | |
| 488 | 571 | /* == Google part == */ |
| 489 | - google.charts.load('current', {'packages':['corechart']}); | |
| 572 | + google.charts.load('current', {'packages':['corechart'], 'language': userLocale}); | |
| 490 | 573 | google.charts.setOnLoadCallback(drawChart); |
| 491 | 574 | |
| 492 | 575 | function drawChart() { |
| 493 | 576 | dataTypes = nSettings.enableRowSettings ? _this.setRowOptions(dataTypes, nSettings, true) : dataTypes; |
| @@ -623,9 +706,38 @@ | ||
| 623 | 706 | pointSize: nSettings.seriesPointSize[i], |
| 624 | 707 | pointShape: nSettings.seriesPointShape[i], |
| 625 | 708 | } |
| 626 | 709 | } |
| 627 | - | |
| 710 | + | |
| 711 | + if(_this.chartOptions.vAxis.format == 'percent' && nSettings.vAxisEnableDividePercent){ | |
| 712 | + for (var i = 0; i < dataTypes[0].length - 1; i++) { | |
| 713 | + nSettings.seriesFormat[i] = '#%'; | |
| 714 | + } | |
| 715 | + | |
| 716 | + for (var row = 0; row < _this.chartData.getNumberOfRows(); row++) { | |
| 717 | + for (var col = 0; col < _this.chartData.getNumberOfColumns(); col++) { | |
| 718 | + var value = _this.chartData.getValue(row, col); | |
| 719 | + if (typeof value === 'number' && !isNaN(value)) { | |
| 720 | + var updatedValue = value / 100; | |
| 721 | + _this.chartData.setValue(row, col, updatedValue); | |
| 722 | + } | |
| 723 | + } | |
| 724 | + } | |
| 725 | + }else { | |
| 726 | + for (var i = 0; i < dataTypes[0].length - 1; i++) { | |
| 727 | + if (nSettings.seriesFormat[i] === '#%') { | |
| 728 | + nSettings.seriesFormat[i] = ''; | |
| 729 | + } | |
| 730 | + } | |
| 731 | + } | |
| 732 | + for (var i = 1; i < dataTypes[0].length; i++) { | |
| 733 | + if (nSettings.seriesFormat[i - 1]) { | |
| 734 | + var formatter = new google.visualization.NumberFormat({ | |
| 735 | + pattern: nSettings.seriesFormat[i - 1] | |
| 736 | + }); | |
| 737 | + formatter.format(_this.chartData, i); | |
| 738 | + } | |
| 739 | + } | |
| 628 | 740 | if (nSettings.enableAnimation) { |
| 629 | 741 | _this.chartOptions.animation = { |
| 630 | 742 | startup: nSettings.animationStartup, |
| 631 | 743 | duration: nSettings.animationDuration, |
| @@ -637,8 +749,12 @@ | ||
| 637 | 749 | |
| 638 | 750 | |
| 639 | 751 | _this.chartObj.draw( _this.chartData, _this.chartOptions ); |
| 640 | 752 | _this.resizeChart(); |
| 753 | + // Fix ARIA attributes for accessibility compliance | |
| 754 | + setTimeout(function() { | |
| 755 | + _this.fixAriaAttributes(); | |
| 756 | + }, 100); | |
| 641 | 757 | } |
| 642 | 758 | /* */ |
| 643 | 759 | } |
| 644 | 760 | |
| @@ -651,10 +767,12 @@ | ||
| 651 | 767 | |
| 652 | 768 | var settings = _this.dbData.options; |
| 653 | 769 | var nSettings = _this.configOptionsForCharts(settings); |
| 654 | 770 | |
| 771 | + var userLocale = navigator.language || navigator.userLanguage || 'en'; | |
| 772 | + | |
| 655 | 773 | /* == Google part == */ |
| 656 | - google.charts.load('current', {'packages':['corechart']}); | |
| 774 | + google.charts.load('current', {'packages':['corechart'], 'language': userLocale}); | |
| 657 | 775 | google.charts.setOnLoadCallback(drawChart); |
| 658 | 776 | |
| 659 | 777 | function drawChart() { |
| 660 | 778 | _this.chartData = google.visualization.arrayToDataTable( dataTypes ); |
| @@ -718,8 +836,12 @@ | ||
| 718 | 836 | _this.chartObj = new google.visualization.PieChart( document.getElementById(_this.htmlClassPrefix + _this.chartType + _this.uniqueId) ); |
| 719 | 837 | |
| 720 | 838 | _this.chartObj.draw( _this.chartData, _this.chartOptions ); |
| 721 | 839 | _this.resizeChart(); |
| 840 | + // Fix ARIA attributes for accessibility compliance | |
| 841 | + setTimeout(function() { | |
| 842 | + _this.fixAriaAttributes(); | |
| 843 | + }, 100); | |
| 722 | 844 | } |
| 723 | 845 | /* */ |
| 724 | 846 | } |
| 725 | 847 | |
| @@ -731,10 +853,12 @@ | ||
| 731 | 853 | |
| 732 | 854 | var settings = _this.dbData.options; |
| 733 | 855 | var nSettings = _this.configOptionsForCharts(settings); |
| 734 | 856 | |
| 857 | + var userLocale = navigator.language || navigator.userLanguage || 'en'; | |
| 858 | + | |
| 735 | 859 | /* == Google part == */ |
| 736 | - google.charts.load('current', {'packages':['orgchart']}); | |
| 860 | + google.charts.load('current', {'packages':['orgchart'], 'language': userLocale}); | |
| 737 | 861 | google.charts.setOnLoadCallback(drawChart); |
| 738 | 862 | |
| 739 | 863 | function drawChart() { |
| 740 | 864 | _this.chartData = new google.visualization.arrayToDataTable(dataTypes); |
| @@ -767,8 +891,12 @@ | ||
| 767 | 891 | |
| 768 | 892 | _this.chartObj.draw( _this.chartData, _this.chartOptions ); |
| 769 | 893 | _this.resizeChart(); |
| 770 | 894 | _this.setOrgChartCustomStyles(); |
| 895 | + // Fix ARIA attributes for accessibility compliance | |
| 896 | + setTimeout(function() { | |
| 897 | + _this.fixAriaAttributes(); | |
| 898 | + }, 100); | |
| 771 | 899 | } |
| 772 | 900 | |
| 773 | 901 | _this.$el.on('click', '.google-visualization-orgchart-node-small, .google-visualization-orgchart-node-medium, .google-visualization-orgchart-node-large', function(e) { |
| 774 | 902 | if (nSettings.orgSelectedClassname !== '') { |
| @@ -823,8 +951,10 @@ | ||
| 823 | 951 | newSettings.groupWidthFormat = settings['group_width_format'] == '%' ? '%' : ''; |
| 824 | 952 | newSettings.groupWidth = settings['group_width'] + newSettings.groupWidthFormat; |
| 825 | 953 | newSettings.hAxisTitle = settings['haxis_title']; |
| 826 | 954 | newSettings.vAxisTitle = settings['vaxis_title']; |
| 955 | + newSettings.hAxisEnableDividePercent = (settings['haxis_enable_divide_percent'] == 'on' && settings['haxis_format'] == 'percent') ? true : false; | |
| 956 | + newSettings.vAxisEnableDividePercent = (settings['vaxis_enable_divide_percent'] == 'on' && settings['vaxis_format'] == 'percent') ? true : false; | |
| 827 | 957 | newSettings.hAxisLabelFontSize = settings['haxis_label_font_size']; |
| 828 | 958 | newSettings.vAxisLabelFontSize = settings['vaxis_label_font_size']; |
| 829 | 959 | newSettings.hAxisLabelColor = settings['haxis_label_color']; |
| 830 | 960 | newSettings.vAxisLabelColor = settings['vaxis_label_color']; |
| @@ -868,8 +998,9 @@ | ||
| 868 | 998 | newSettings.animationDuration = settings['animation_duration']; |
| 869 | 999 | newSettings.animationStartup = (settings['animation_startup'] == 'off') ? false : true; |
| 870 | 1000 | newSettings.animationEasing = settings['animation_easing']; |
| 871 | 1001 | newSettings.seriesColor = settings['series_color']; |
| 1002 | + newSettings.seriesFormat = settings['series_format']; | |
| 872 | 1003 | newSettings.seriesVisibleInLegend = settings['series_visible_in_legend']; |
| 873 | 1004 | newSettings.seriesLineWidth = settings['series_line_width']; |
| 874 | 1005 | newSettings.seriesPointSize = settings['series_point_size']; |
| 875 | 1006 | newSettings.seriesPointShape = settings['series_point_shape']; |
| @@ -1070,34 +1201,45 @@ | ||
| 1070 | 1201 | // Converting chart data for org chart type |
| 1071 | 1202 | ChartBuilderGoogleCharts.prototype.orgChartConvertData = function( data ){ |
| 1072 | 1203 | var _this = this; |
| 1073 | 1204 | var dataTypes = [['Name', 'Manager', 'Tooltip', 'Url']]; |
| 1205 | + | |
| 1206 | + var ordering = (_this.dbData && Array.isArray(_this.dbData.source_ordering)) | |
| 1207 | + ? _this.dbData.source_ordering.slice() | |
| 1208 | + : []; | |
| 1209 | + | |
| 1210 | + ordering = ordering.map(String); | |
| 1211 | + | |
| 1212 | + Object.keys(data).forEach(function(key) { | |
| 1213 | + if (!ordering.includes(key)) { | |
| 1214 | + ordering.push(key); | |
| 1215 | + } | |
| 1216 | + }); | |
| 1217 | + | |
| 1074 | 1218 | // var name = ""; |
| 1075 | 1219 | // Collect data in new array for chart rendering |
| 1076 | - for ( var key in data ) { | |
| 1077 | - if ( data.hasOwnProperty( key ) ) { | |
| 1078 | - if (key != 0) { | |
| 1079 | - var name = data[key][0]; | |
| 1080 | - var description = data[key][1]; | |
| 1081 | - var image = (data[key].length > 6) ? data[key][2] : ''; | |
| 1082 | - var parent_name = (data[key].length > 6) ? data[key][3] : data[key][2]; | |
| 1083 | - var tooltip = (data[key].length > 6) ? data[key][4] : data[key][3]; | |
| 1084 | - var url = (data[key].length > 6) ? data[key][5] : ''; | |
| 1085 | - | |
| 1086 | - if (description) { | |
| 1087 | - name += _this.orgChartFormatName(description); | |
| 1088 | - } | |
| 1089 | - if (image && image != '') { | |
| 1090 | - name = _this.orgChartFormatImage(image) + name; | |
| 1091 | - } | |
| 1092 | - name = {'v': data[key][0], 'f': name}; | |
| 1093 | - dataTypes.push([ | |
| 1094 | - name, parent_name, tooltip, url | |
| 1095 | - ]); | |
| 1096 | - } | |
| 1220 | + ordering.forEach(function(key) { | |
| 1221 | + if (!data.hasOwnProperty(key) || key == 0) return; | |
| 1222 | + | |
| 1223 | + var row = data[key]; | |
| 1224 | + var name = row[0]; | |
| 1225 | + var description = row[1]; | |
| 1226 | + var image = (row.length > 6) ? row[2] : ''; | |
| 1227 | + var parent_name = (row.length > 6) ? row[3] : row[2]; | |
| 1228 | + var tooltip = (row.length > 6) ? row[4] : row[3]; | |
| 1229 | + var url = (row.length > 6) ? row[5] : ''; | |
| 1230 | + | |
| 1231 | + if (description) { | |
| 1232 | + name += _this.orgChartFormatName(description); | |
| 1097 | 1233 | } |
| 1098 | - } | |
| 1234 | + if (image && image !== '') { | |
| 1235 | + name = _this.orgChartFormatImage(image) + name; | |
| 1236 | + } | |
| 1099 | 1237 | |
| 1238 | + name = {'v': row[0], 'f': name}; | |
| 1239 | + dataTypes.push([name, parent_name, tooltip, url]); | |
| 1240 | + }); | |
| 1241 | + | |
| 1100 | 1242 | return dataTypes; |
| 1101 | 1243 | } |
| 1102 | 1244 | |
| 1103 | 1245 | ChartBuilderGoogleCharts.prototype.orgChartFormatName = function( description ){ |
| @@ -1227,13 +1369,66 @@ | ||
| 1227 | 1369 | e.innerHTML = input; |
| 1228 | 1370 | return e.childNodes[0].nodeValue; |
| 1229 | 1371 | } |
| 1230 | 1372 | |
| 1373 | + // Fix ARIA attributes for WCAG compliance | |
| 1374 | + ChartBuilderGoogleCharts.prototype.fixAriaAttributes = function() { | |
| 1375 | + var _this = this; | |
| 1376 | + var chartContainer = document.getElementById(_this.htmlClassPrefix + _this.chartType + _this.uniqueId); | |
| 1377 | + | |
| 1378 | + if (!chartContainer) { | |
| 1379 | + return; | |
| 1380 | + } | |
| 1381 | + | |
| 1382 | + // Find all divs with aria-label | |
| 1383 | + var divsWithAriaLabel = chartContainer.querySelectorAll('div[aria-label]'); | |
| 1384 | + divsWithAriaLabel.forEach(function(div) { | |
| 1385 | + // Check if this div contains a table (the data table representation) | |
| 1386 | + if (div.querySelector('table')) { | |
| 1387 | + // Add role="region" to the table container div | |
| 1388 | + if (!div.hasAttribute('role')) { | |
| 1389 | + div.setAttribute('role', 'region'); | |
| 1390 | + } | |
| 1391 | + } else { | |
| 1392 | + // Remove aria-label from divs without roles (not table containers) | |
| 1393 | + if (!div.hasAttribute('role')) { | |
| 1394 | + div.removeAttribute('aria-label'); | |
| 1395 | + } | |
| 1396 | + } | |
| 1397 | + }); | |
| 1398 | + | |
| 1399 | + // Add role="img" to SVG elements with aria-label | |
| 1400 | + var svgElements = chartContainer.querySelectorAll('svg[aria-label]'); | |
| 1401 | + svgElements.forEach(function(svg) { | |
| 1402 | + if (!svg.hasAttribute('role')) { | |
| 1403 | + svg.setAttribute('role', 'img'); | |
| 1404 | + } | |
| 1405 | + }); | |
| 1406 | + } | |
| 1407 | + | |
| 1231 | 1408 | ChartBuilderGoogleCharts.prototype.drawChartFunction = function (source, options) { |
| 1232 | 1409 | var _this = this; |
| 1233 | 1410 | |
| 1234 | 1411 | var view = new google.visualization.DataView(source); |
| 1235 | 1412 | _this.chartData = source; |
| 1413 | + | |
| 1414 | + // Set role="img" on the chart container | |
| 1415 | + var chartContainer = document.getElementById(_this.htmlClassPrefix + _this.chartType + _this.uniqueId); | |
| 1416 | + if (chartContainer) { | |
| 1417 | + chartContainer.setAttribute('role', 'img'); | |
| 1418 | + } | |
| 1419 | + | |
| 1420 | + // Fix ARIA attributes after chart is drawn | |
| 1421 | + var drawCallback = function() { | |
| 1422 | + _this.fixAriaAttributes(); | |
| 1423 | + }; | |
| 1424 | + | |
| 1425 | + // Add callback to options if it doesn't exist | |
| 1426 | + if (typeof options.chartArea === 'object') { | |
| 1427 | + options.chartArea.chartReady = drawCallback; | |
| 1428 | + } else { | |
| 1429 | + options.chartReady = drawCallback; | |
| 1430 | + } | |
| 1236 | 1431 | |
| 1237 | 1432 | if (_this.chartType == 'org_chart') { |
| 1238 | 1433 | view.setColumns([0, 1, 2]); |
| 1239 | 1434 | } |