| @@ -166,8 +166,12 @@ | ||
| 166 | 166 | _this.chartObj = new google.visualization.PieChart( document.getElementById(_this.htmlClassPrefix + _this.chartType + _this.uniqueId)); |
| 167 | 167 | |
| 168 | 168 | _this.chartObj.draw( _this.chartData, _this.chartOptions ); |
| 169 | 169 | _this.resizeChart(); |
| 170 | + // Fix ARIA attributes for accessibility compliance | |
| 171 | + setTimeout(function() { | |
| 172 | + _this.fixAriaAttributes(); | |
| 173 | + }, 100); | |
| 170 | 174 | } |
| 171 | 175 | /* */ |
| 172 | 176 | } |
| 173 | 177 | |
| @@ -315,13 +319,49 @@ | ||
| 315 | 319 | duration: nSettings.animationDuration, |
| 316 | 320 | easing: nSettings.animationEasing, |
| 317 | 321 | } |
| 318 | 322 | } |
| 323 | + | |
| 319 | 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 | + } | |
| 320 | 356 | _this.chartObj = new google.visualization.BarChart(document.getElementById(_this.htmlClassPrefix + _this.chartType + _this.uniqueId)); |
| 321 | 357 | |
| 322 | 358 | _this.chartObj.draw( _this.chartData, _this.chartOptions ); |
| 323 | 359 | _this.resizeChart(); |
| 360 | + // Fix ARIA attributes for accessibility compliance | |
| 361 | + setTimeout(function() { | |
| 362 | + _this.fixAriaAttributes(); | |
| 363 | + }, 100); | |
| 324 | 364 | } |
| 325 | 365 | /* */ |
| 326 | 366 | } |
| 327 | 367 | |
| @@ -464,9 +504,40 @@ | ||
| 464 | 504 | color: nSettings.seriesColor[i], |
| 465 | 505 | visibleInLegend: nSettings.seriesVisibleInLegend[i] == 'on' ? true : (typeof nSettings.seriesColor[i] !== 'undefined' ? false : true), |
| 466 | 506 | } |
| 467 | 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 | + | |
| 468 | 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 | + } | |
| 469 | 540 | if (nSettings.enableAnimation) { |
| 470 | 541 | _this.chartOptions.animation = { |
| 471 | 542 | startup: nSettings.animationStartup, |
| 472 | 543 | duration: nSettings.animationDuration, |
| @@ -477,8 +548,12 @@ | ||
| 477 | 548 | _this.chartObj = new google.visualization.ColumnChart(document.getElementById(_this.htmlClassPrefix + _this.chartType + _this.uniqueId)); |
| 478 | 549 | |
| 479 | 550 | _this.chartObj.draw( _this.chartData, _this.chartOptions ); |
| 480 | 551 | _this.resizeChart(); |
| 552 | + // Fix ARIA attributes for accessibility compliance | |
| 553 | + setTimeout(function() { | |
| 554 | + _this.fixAriaAttributes(); | |
| 555 | + }, 100); | |
| 481 | 556 | } |
| 482 | 557 | /* */ |
| 483 | 558 | } |
| 484 | 559 | |
| @@ -631,9 +706,38 @@ | ||
| 631 | 706 | pointSize: nSettings.seriesPointSize[i], |
| 632 | 707 | pointShape: nSettings.seriesPointShape[i], |
| 633 | 708 | } |
| 634 | 709 | } |
| 635 | - | |
| 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 | + } | |
| 636 | 740 | if (nSettings.enableAnimation) { |
| 637 | 741 | _this.chartOptions.animation = { |
| 638 | 742 | startup: nSettings.animationStartup, |
| 639 | 743 | duration: nSettings.animationDuration, |
| @@ -645,8 +749,12 @@ | ||
| 645 | 749 | |
| 646 | 750 | |
| 647 | 751 | _this.chartObj.draw( _this.chartData, _this.chartOptions ); |
| 648 | 752 | _this.resizeChart(); |
| 753 | + // Fix ARIA attributes for accessibility compliance | |
| 754 | + setTimeout(function() { | |
| 755 | + _this.fixAriaAttributes(); | |
| 756 | + }, 100); | |
| 649 | 757 | } |
| 650 | 758 | /* */ |
| 651 | 759 | } |
| 652 | 760 | |
| @@ -728,8 +836,12 @@ | ||
| 728 | 836 | _this.chartObj = new google.visualization.PieChart( document.getElementById(_this.htmlClassPrefix + _this.chartType + _this.uniqueId) ); |
| 729 | 837 | |
| 730 | 838 | _this.chartObj.draw( _this.chartData, _this.chartOptions ); |
| 731 | 839 | _this.resizeChart(); |
| 840 | + // Fix ARIA attributes for accessibility compliance | |
| 841 | + setTimeout(function() { | |
| 842 | + _this.fixAriaAttributes(); | |
| 843 | + }, 100); | |
| 732 | 844 | } |
| 733 | 845 | /* */ |
| 734 | 846 | } |
| 735 | 847 | |
| @@ -779,8 +891,12 @@ | ||
| 779 | 891 | |
| 780 | 892 | _this.chartObj.draw( _this.chartData, _this.chartOptions ); |
| 781 | 893 | _this.resizeChart(); |
| 782 | 894 | _this.setOrgChartCustomStyles(); |
| 895 | + // Fix ARIA attributes for accessibility compliance | |
| 896 | + setTimeout(function() { | |
| 897 | + _this.fixAriaAttributes(); | |
| 898 | + }, 100); | |
| 783 | 899 | } |
| 784 | 900 | |
| 785 | 901 | _this.$el.on('click', '.google-visualization-orgchart-node-small, .google-visualization-orgchart-node-medium, .google-visualization-orgchart-node-large', function(e) { |
| 786 | 902 | if (nSettings.orgSelectedClassname !== '') { |
| @@ -835,8 +951,10 @@ | ||
| 835 | 951 | newSettings.groupWidthFormat = settings['group_width_format'] == '%' ? '%' : ''; |
| 836 | 952 | newSettings.groupWidth = settings['group_width'] + newSettings.groupWidthFormat; |
| 837 | 953 | newSettings.hAxisTitle = settings['haxis_title']; |
| 838 | 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; | |
| 839 | 957 | newSettings.hAxisLabelFontSize = settings['haxis_label_font_size']; |
| 840 | 958 | newSettings.vAxisLabelFontSize = settings['vaxis_label_font_size']; |
| 841 | 959 | newSettings.hAxisLabelColor = settings['haxis_label_color']; |
| 842 | 960 | newSettings.vAxisLabelColor = settings['vaxis_label_color']; |
| @@ -880,8 +998,9 @@ | ||
| 880 | 998 | newSettings.animationDuration = settings['animation_duration']; |
| 881 | 999 | newSettings.animationStartup = (settings['animation_startup'] == 'off') ? false : true; |
| 882 | 1000 | newSettings.animationEasing = settings['animation_easing']; |
| 883 | 1001 | newSettings.seriesColor = settings['series_color']; |
| 1002 | + newSettings.seriesFormat = settings['series_format']; | |
| 884 | 1003 | newSettings.seriesVisibleInLegend = settings['series_visible_in_legend']; |
| 885 | 1004 | newSettings.seriesLineWidth = settings['series_line_width']; |
| 886 | 1005 | newSettings.seriesPointSize = settings['series_point_size']; |
| 887 | 1006 | newSettings.seriesPointShape = settings['series_point_shape']; |
| @@ -1082,34 +1201,45 @@ | ||
| 1082 | 1201 | // Converting chart data for org chart type |
| 1083 | 1202 | ChartBuilderGoogleCharts.prototype.orgChartConvertData = function( data ){ |
| 1084 | 1203 | var _this = this; |
| 1085 | 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 | + | |
| 1086 | 1218 | // var name = ""; |
| 1087 | 1219 | // Collect data in new array for chart rendering |
| 1088 | - for ( var key in data ) { | |
| 1089 | - if ( data.hasOwnProperty( key ) ) { | |
| 1090 | - if (key != 0) { | |
| 1091 | - var name = data[key][0]; | |
| 1092 | - var description = data[key][1]; | |
| 1093 | - var image = (data[key].length > 6) ? data[key][2] : ''; | |
| 1094 | - var parent_name = (data[key].length > 6) ? data[key][3] : data[key][2]; | |
| 1095 | - var tooltip = (data[key].length > 6) ? data[key][4] : data[key][3]; | |
| 1096 | - var url = (data[key].length > 6) ? data[key][5] : ''; | |
| 1097 | - | |
| 1098 | - if (description) { | |
| 1099 | - name += _this.orgChartFormatName(description); | |
| 1100 | - } | |
| 1101 | - if (image && image != '') { | |
| 1102 | - name = _this.orgChartFormatImage(image) + name; | |
| 1103 | - } | |
| 1104 | - name = {'v': data[key][0], 'f': name}; | |
| 1105 | - dataTypes.push([ | |
| 1106 | - name, parent_name, tooltip, url | |
| 1107 | - ]); | |
| 1108 | - } | |
| 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); | |
| 1109 | 1233 | } |
| 1110 | - } | |
| 1234 | + if (image && image !== '') { | |
| 1235 | + name = _this.orgChartFormatImage(image) + name; | |
| 1236 | + } | |
| 1111 | 1237 | |
| 1238 | + name = {'v': row[0], 'f': name}; | |
| 1239 | + dataTypes.push([name, parent_name, tooltip, url]); | |
| 1240 | + }); | |
| 1241 | + | |
| 1112 | 1242 | return dataTypes; |
| 1113 | 1243 | } |
| 1114 | 1244 | |
| 1115 | 1245 | ChartBuilderGoogleCharts.prototype.orgChartFormatName = function( description ){ |
| @@ -1239,13 +1369,66 @@ | ||
| 1239 | 1369 | e.innerHTML = input; |
| 1240 | 1370 | return e.childNodes[0].nodeValue; |
| 1241 | 1371 | } |
| 1242 | 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 | + | |
| 1243 | 1408 | ChartBuilderGoogleCharts.prototype.drawChartFunction = function (source, options) { |
| 1244 | 1409 | var _this = this; |
| 1245 | 1410 | |
| 1246 | 1411 | var view = new google.visualization.DataView(source); |
| 1247 | 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 | + } | |
| 1248 | 1431 | |
| 1249 | 1432 | if (_this.chartType == 'org_chart') { |
| 1250 | 1433 | view.setColumns([0, 1, 2]); |
| 1251 | 1434 | } |