Uh oh!
There was an error while loading. Please reload this page.
Uh oh!
There was an error while loading. Please reload this page.
- Notifications
You must be signed in to change notification settings - Fork 2k
add Chart2Music keyboard and sound accessibility features#6680
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
base:main
Are you sure you want to change the base?
Uh oh!
There was an error while loading. Please reload this page.
Changes from all commits
6fb9c6587b4c5c64ae505d37d24fd0467bb3a73776b4df95997b608f6205d627e40cde6d9185b935cf5444deae2c38ab67c6a27becac174c159ca1b7467a4708b820b41b0fb994e25c361ea8cec9a0b91cc926397baa0d33127dee2429e5500572e830f4e11247b301d08adfbdbce5dae1f95633f4ab5492d97b76b2dcc9b5bb51725ca44a732832400b2750b04bb17d4bd71baf2ff8080b4cf3ee99f353841640d84d1080c434074c750353c49ed6f7be6664a260aff67c51341baab926754b7ed189071e4bcef2c1abf4614fb8b5f5e599fe9736e59ad5c6d18c584043d408129eb3bacc8517c5ad2400113d90771029ebfbbbf1cadfd7f56e582d8e55f9886d75d815671b0057e06744f7ad38e3b62baed1e021777fba3a0384fdba0b5356f2ebcFile filter
Filter by extension
Conversations
Uh oh!
There was an error while loading. Please reload this page.
Jump to
Uh oh!
There was an error while loading. Please reload this page.
Diff view
Diff view
There are no files selected for viewing
Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.
Uh oh!
There was an error while loading. Please reload this page.
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -460,7 +460,20 @@ var configAttributes = { | ||
| 'instead of MM/DD/YYYY). Currently `grouping` and `currency` are ignored', | ||
| 'for our automatic number formatting, but can be used in custom formats.' | ||
| ].join(' ') | ||
| } | ||
| }, | ||
| sonification: { | ||
| valType: 'any', | ||
| dflt: { | ||
| enabled: false, | ||
| options: {}, | ||
| info: {}, | ||
| closedCaptions: {generate: false, elId: 'c2m-plotly-cc', elClassname: 'c2m-plotly-closed_captions'} | ||
marthacryan marked this conversation as resolved.
Uh oh!There was an error while loading. Please reload this page. | ||
| }, | ||
| description: ['Sonification options: whether to enable, options to pass to the library, info to pass to the library, closedCaptions to control how plotly renders the closed-captions element.', | ||
| 'chart2music is supported and options here include Options and Info from https://www.chart2music.com/docs/API/Config. ' | ||
| ].join(' ') | ||
| }, | ||
| }; | ||
| var dfltConfig = {}; | ||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,29 @@ | ||
| # `plotly.js` wrapper for `chart2music`, sonified charts | ||
| This wrapper attaches a context object to `gd._context._c2m` with the following properties: | ||
| * `.options`: the options object as required by c2m | ||
| * `.info`: the info object as required by c2m | ||
| * `.ccOptions`: information about where to place the closed caption div | ||
| * `.c2mHandler`: the object returned by calling the c2m library's initializer | ||
| The first three have most of their values set by the defaults in *src/plot_api/plot_config.js*. | ||
| ### index.js | ||
| **index.js** exposes the following api: | ||
| * `initC2M(gd, defaultConfig)` full resets the `c2mChart` object. | ||
| * `defaultConfig` is equal to `gd._context.sonification`, as defined in *src/plot_api/plot_config.js*. | ||
| ### all_codecs.js | ||
| **all_codecs.js** agregates all the individual **_codec.js* files, all are expect to export exactly two functions: `test` and `process`. | ||
| I chose to aggregate all codecs in a separate file because it will ultimately be a 1-1 conversion if `plotly.js` adopts ES modules. | ||
| ## Writing a Codec | ||
| This section is TODO | ||
| chart2music supports N types of graphs. We should figure out how how to convert as many plotly types to chart2music types. I will write descriptions for each type in the folder, if not the actual code, along with what `test` must return and what `process` must return. |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,5 @@ | ||
| 'use strict'; | ||
| var scatterXY = require('./xy_scatter_codec'); | ||
| exports.codecs = [ scatterXY ]; |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,10 @@ | ||
| 'use strict'; | ||
| var c2mPlotly = require('.'); | ||
| function enable_sonification(gd) { | ||
| // Collecting defaults | ||
| var defaultConfig = gd._context.sonification; | ||
| c2mPlotly.initC2M(gd, defaultConfig); | ||
| } | ||
| exports.enable_sonification = enable_sonification; |
| Original file line number | Diff line number | Diff line change | ||||||||||
|---|---|---|---|---|---|---|---|---|---|---|---|---|
| @@ -0,0 +1,96 @@ | ||||||||||||
| 'use strict'; | ||||||||||||
| var c2m = require('chart2music'); | ||||||||||||
| var Fx = require('../components/fx'); | ||||||||||||
| var Lib = require('../lib'); | ||||||||||||
| var codecs = require('./all_codecs').codecs; | ||||||||||||
| /* initClosedCaptionDiv: Initialize the closed caption div with the given configuration. | ||||||||||||
| * This function works by either creating a new div or returning the existing div | ||||||||||||
| */ | ||||||||||||
| function initClosedCaptionDiv(gd, config) { | ||||||||||||
| if(config.generate) { | ||||||||||||
| var closedCaptions = document.createElement('div'); | ||||||||||||
| closedCaptions.id = config.elId; | ||||||||||||
| closedCaptions.className = config.elClassname; | ||||||||||||
| gd.parentNode.insertBefore(closedCaptions, gd.nextSibling); // this really might not work | ||||||||||||
| return closedCaptions; | ||||||||||||
| } else { | ||||||||||||
| return document.getElementById(config.elId); | ||||||||||||
| } | ||||||||||||
Comment on lines
+19
to
+21
Contributor There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. We could simply return and drop else.
Suggested change
| ||||||||||||
| } | ||||||||||||
| /* initC2M: Initialize the chart2music library with the given configuration. | ||||||||||||
| * This function works by resetting the c2m context of the given graph div | ||||||||||||
| */ | ||||||||||||
| function initC2M(gd, defaultConfig) { | ||||||||||||
| var c2mContext = gd._context._c2m = {}; | ||||||||||||
| c2mContext.options = Lib.extendDeepAll({}, defaultConfig.options); | ||||||||||||
| c2mContext.info = Lib.extendDeepAll({}, defaultConfig.info); | ||||||||||||
| c2mContext.ccOptions = Lib.extendDeepAll({}, defaultConfig.closedCaptions); | ||||||||||||
| var labels = []; | ||||||||||||
| // Set the onFocusCallback to highlight the hovered point | ||||||||||||
| c2mContext.options.onFocusCallback = function(dataInfo) { | ||||||||||||
| Fx.hover(gd, [{ | ||||||||||||
| curveNumber: labels.indexOf(dataInfo.slice), | ||||||||||||
| pointNumber: dataInfo.index | ||||||||||||
| }]); | ||||||||||||
| }; | ||||||||||||
| var ccElement = initClosedCaptionDiv(gd, c2mContext.ccOptions); | ||||||||||||
| // Get the chart, x, and y axis titles from the layout. | ||||||||||||
| // This will be used for the closed captions. | ||||||||||||
| var titleText = 'Chart'; | ||||||||||||
| if((gd._fullLayout.title !== undefined) && (gd._fullLayout.title.text !== undefined)) { | ||||||||||||
| titleText = gd._fullLayout.title.text; | ||||||||||||
| } | ||||||||||||
| var xAxisText = 'X Axis'; | ||||||||||||
| if((gd._fullLayout.xaxis !== undefined) && | ||||||||||||
| (gd._fullLayout.xaxis.title !== undefined) && | ||||||||||||
| (gd._fullLayout.xaxis.title.text !== undefined)) { | ||||||||||||
| xAxisText = gd._fullLayout.xaxis.title.text; | ||||||||||||
| } | ||||||||||||
| var yAxisText = 'Y Axis'; | ||||||||||||
| if((gd._fullLayout.yaxis !== undefined) && | ||||||||||||
| (gd._fullLayout.yaxis.title !== undefined) && | ||||||||||||
| (gd._fullLayout.yaxis.title.text !== undefined)) { | ||||||||||||
| yAxisText = gd._fullLayout.yaxis.title.text; | ||||||||||||
| } | ||||||||||||
| // Convert the data to the format that c2m expects | ||||||||||||
| var c2mData = {}; | ||||||||||||
| var types = []; | ||||||||||||
| var fullData = gd._fullData; | ||||||||||||
| // Iterate through the traces and find the codec that matches the trace | ||||||||||||
| for (var trace of fullData) { | ||||||||||||
| for (var codec of codecs) { | ||||||||||||
| var test = codec.test(trace); | ||||||||||||
| if (!test) continue; | ||||||||||||
| // Generate a unique label for the trace | ||||||||||||
| var label = test.name; | ||||||||||||
| labels.push(label); | ||||||||||||
| types.push(test.type); | ||||||||||||
| c2mData[label] = codec.process(trace); | ||||||||||||
| } | ||||||||||||
| } | ||||||||||||
| c2mContext.c2mHandler = c2m.c2mChart({ | ||||||||||||
| title: titleText, | ||||||||||||
| type: types, | ||||||||||||
| axes: { | ||||||||||||
| x: { label: xAxisText }, | ||||||||||||
| y: { label: yAxisText }, | ||||||||||||
| }, | ||||||||||||
| element: gd, | ||||||||||||
| cc: ccElement, | ||||||||||||
| data: c2mData, | ||||||||||||
| options: c2mContext.options, | ||||||||||||
| info: c2mContext.info | ||||||||||||
| }); | ||||||||||||
| } | ||||||||||||
| exports.initC2M = initC2M; | ||||||||||||
Uh oh!
There was an error while loading. Please reload this page.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
IS
sonificationkey always present?