From c2ce19ecdcb892b2203004162d41a7555ca6ee8e Mon Sep 17 00:00:00 2001 From: Luis Morales-Navarro Date: Mon, 15 Jun 2020 11:28:21 -0600 Subject: [PATCH 01/42] add accessibility folder and describe()/describeElement() --- accessibility/describe.js | 242 ++++++++++++++++++++++++++++++++++++++ 1 file changed, 242 insertions(+) create mode 100644 accessibility/describe.js diff --git a/accessibility/describe.js b/accessibility/describe.js new file mode 100644 index 0000000000..0b69314d46 --- /dev/null +++ b/accessibility/describe.js @@ -0,0 +1,242 @@ +/** + * @module Accessibility + * @for p5 + * @requires core + */ + +import p5 from '../core/main'; + +/** + * Creates a screen-reader accessible description for the canvas in the DOM. + * The first parameter should be a string with a description of the canvas. + * The second parameter is optional. If specified, it determines how the + * description is displayed. + * + * describe(str, LABEL) displays the description to all users as a + * tombstone or exhibit label/caption + * by creating a <div id="label"> with the description right after the canvas. + * You can style it as you wish in your CSS. + * + * describe(str, FALLBACK) makes the description accessible to screen-reader users only in + * + * a sub DOM inside the canvas element. + * If a second parameter is not specified, by default, the description will only be available to screen-reader users. + * + * @method describe + * @param {String} text string describing the canvas + * @param {Constant} [display] either LABEL or FALLBACK (Optional) + * + * @example + *
+ * + * function setup() { + * createCanvas(100, 100); + * background(220); + * fill(255); + * ellipse(25, height / 2, 35, 20); + * ellipse(75, height / 2, 35, 20); + * fill('orange'); + * ellipse(25, height / 2, 15, 15); + * ellipse(75, height / 2, 15, 15); + * fill(0); + * ellipse(25, height / 2, 2.5, 2.5); + * ellipse(75, height / 2, 2.5, 2.5); + * describe('orange eyes over a gray background', LABEL); + * } + * + *
+ * + * @alt + */ +p5.prototype.describe = function(t, display) { + p5._validateParameters('describe', arguments); + const canvasID = this.canvas.id; + //Creates a sub DOM inside of the canvas element and populates + //it with description text. + if (document.getElementById(canvasID + 'Description') === null) { + document.getElementById(canvasID).innerHTML = + '

'; + } else if (document.getElementById(canvasID + 'desc') === null) { + document + .getElementById(canvasID + 'elDes') + .insertAdjacentHTML('beforebegin', '

'); + } + if (document.getElementById(canvasID + 'desc').innerHTML !== t) { + document.getElementById(canvasID + 'desc').innerHTML = t; + } + //If display is LABEL creates a div adjacent to the canvas element with + //description text. + if (display === 'label') { + if (document.getElementById(canvasID + 'Label') === null) { + document + .getElementById(canvasID) + .insertAdjacentHTML( + 'afterend', + '

' + ); + } else if (document.getElementById(canvasID + 'dLbl') === null) { + document + .getElementById(canvasID + 'eLbl') + .insertAdjacentHTML('beforebegin', '

'); + } + if (document.getElementById(canvasID + 'dLbl').innerHTML !== t) { + document.getElementById(canvasID + 'dLbl').innerHTML = t; + } + } +}; + +/** + * describeElement() creates a screen-reader accessible description for + * elements —shapes or groups of shapes that create meaning together— in the canvas sub DOM. + * The first paramater should be the name of the element. The second parameter should be a + * string with a description of the element. + * The third parameter is optional. + * If specified, it determines how the element description is displayed. + * + * describeElement(name, str, LABEL) displays the element description to all users as a + * tombstone or exhibit label/caption + * by creating a <div id="label"> with the element description right after the canvas. + * You can style it as you wish in your CSS. + * + * describeElement(name, str, FALLBACK) makes the element description accessible to screen-reader users only in + * + * a sub DOM inside the canvas element. + * If a second parameter is not specified, by default, the element description will only be available to screen-reader users. + * + * @method describeElement + * @param {String} name name of the element + * @param {String} text string describing the element + * @param {Constant} [display] either LABEL or FALLBACK (Optional) + * + * @example + *
+ * + * function setup() { + * createCanvas(200, 100); + * describe('Two emojis over a pink background', LABEL); + * } + * function draw() { + * background('pink'); + * fill('yellow'); + * noStroke(); + * describeElement( + * 'Grinning face', + * 'An emoji with open eyes and a broad open smile showing upper teeth.', + * LABEL + * ); + * ellipse(50, 50, 70, 70); + * fill('#ad5240'); + * arc(50, 55, 40, 40, radians(0), radians(180), PIE); + * fill(0); + * ellipse(40, 35, 15, 20); + * ellipse(60, 35, 15, 20); + * fill(255); + * arc(50, 55, 40, 20, radians(0), radians(180), PIE); + * ellipse(43, 35, 5, 5); + * ellipse(63, 35, 5, 5); + * describeElement( + * 'Smiling face with heart-eyes', + * 'A yellow face located to the right. It has an open smile, and red, cartoon-styled hearts for eyes. Often conveys enthusiastic feelings of love.', + * LABEL + * ); + * fill('yellow'); + * ellipse(150, 50, 70, 70); + * fill('#ad5240'); + * arc(150, 55, 40, 40, radians(0), radians(180), PIE); + * fill('red'); + * ellipse(143, 35, 10, 10); + * ellipse(137, 35, 10, 10); + * triangle(132, 35, 140, 45, 148, 35); + * ellipse(157, 35, 10, 10); + * ellipse(163, 35, 10, 10); + * triangle(168, 35, 160, 45, 152, 35); + * } + * + *
+ * + * @alt + */ + +p5.prototype.describeElement = function(name, t, display) { + p5._validateParameters('describeElement', arguments); + const canvasID = this.canvas.id; + //Creates a sub DOM inside of the canvas with a table, populates + //a row header cell with the name of the elements and adds the description + //of the element in adjecent cell. + if (document.getElementById(canvasID + 'Description') === null) { + document.getElementById(canvasID).innerHTML = + '
'; + } else if (document.getElementById(canvasID + 'elDes') === null) { + document + .getElementById(canvasID + 'desc') + .insertAdjacentHTML( + 'afterend', + '
' + ); + } + if (document.getElementById(canvasID + name) === null) { + let tr = document.createElement('tr'); + tr.id = canvasID + name; + document.getElementById(canvasID + 'elDes').appendChild(tr); + } + if ( + document.getElementById(canvasID + name).innerHTML !== + '' + name + '' + t + '' + ) { + document.getElementById(canvasID + name).innerHTML = + '' + name + '' + t + ''; + } + //If display is LABEL creates a div adjacent to the canvas element with + //a table, a row header cell with the name of the elements, + //and adds the description of the element in adjecent cell. + if (display === 'label') { + if (document.getElementById(canvasID + 'Label') === null) { + document + .getElementById(canvasID) + .insertAdjacentHTML( + 'afterend', + '
' + ); + } else if (document.getElementById(canvasID + 'eLbl') === null) { + document + .getElementById(canvasID + 'dLbl') + .insertAdjacentHTML( + 'afterend', + '
' + ); + } + if (document.getElementById(canvasID + name + 'Lbl') === null) { + let tr = document.createElement('tr'); + tr.id = canvasID + name + 'Lbl'; + document.getElementById(canvasID + 'eLbl').appendChild(tr); + } + + if ( + document.getElementById(canvasID + name + 'Lbl').innerHTML !== + '' + name + '' + t + '' + ) { + document.getElementById(canvasID + name + 'Lbl').innerHTML = + '' + name + '' + t + ''; + } + } +}; + +export default p5; From a684c019d09ec4598614411f150782ec4125cf14 Mon Sep 17 00:00:00 2001 From: Luis Morales-Navarro Date: Mon, 15 Jun 2020 11:29:43 -0600 Subject: [PATCH 02/42] add accessibility folder and describe()/describeElement() --- {accessibility => src/accessibility}/describe.js | 0 1 file changed, 0 insertions(+), 0 deletions(-) rename {accessibility => src/accessibility}/describe.js (100%) diff --git a/accessibility/describe.js b/src/accessibility/describe.js similarity index 100% rename from accessibility/describe.js rename to src/accessibility/describe.js From 6bf8657e7e3d68e5d049e2d96eebb22a21d01e34 Mon Sep 17 00:00:00 2001 From: Luis Morales-Navarro Date: Mon, 15 Jun 2020 11:32:27 -0600 Subject: [PATCH 03/42] add constants for describe() and describeElement() --- src/core/constants.js | 11 +++++++++++ 1 file changed, 11 insertions(+) diff --git a/src/core/constants.js b/src/core/constants.js index 24d12a07fb..54cc75487a 100644 --- a/src/core/constants.js +++ b/src/core/constants.js @@ -696,3 +696,14 @@ export const GRID = 'grid'; * @final */ export const AXES = 'axes'; + +/** + * @property {String} LABEL + * @final + */ +export const LABEL = 'label'; +/** + * @property {String} FALLBACK + * @final + */ +export const FALLBACK = 'fallback'; From a1980ed0a622490b83fab54108da9162842082bf Mon Sep 17 00:00:00 2001 From: Luis Morales-Navarro Date: Mon, 15 Jun 2020 11:33:58 -0600 Subject: [PATCH 04/42] accessibility module) --- src/core/app.js | 98 +++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 98 insertions(+) create mode 100644 src/core/app.js diff --git a/src/core/app.js b/src/core/app.js new file mode 100644 index 0000000000..a5022b200e --- /dev/null +++ b/src/core/app.js @@ -0,0 +1,98 @@ +// core +import p5 from './core/main'; +import './core/constants'; +import './core/environment'; +import './core/friendly_errors/stacktrace'; +import './core/friendly_errors/validate_params'; +import './core/friendly_errors/file_errors'; +import './core/friendly_errors/fes_core'; +import './core/helpers'; +import './core/legacy'; +import './core/preload'; +import './core/p5.Element'; +import './core/p5.Graphics'; +import './core/p5.Renderer'; +import './core/p5.Renderer2D'; +import './core/rendering'; +import './core/shim'; +import './core/structure'; +import './core/transform'; +import './core/shape/2d_primitives'; +import './core/shape/attributes'; +import './core/shape/curves'; +import './core/shape/vertex'; + +// color +import './color/color_conversion'; +import './color/creating_reading'; +import './color/p5.Color'; +import './color/setting'; + +// data +import './data/p5.TypedDict'; +import './data/local_storage.js'; + +// DOM +import './dom/dom'; + +// accessibility +import './accessibility/describe'; + +// events +import './events/acceleration'; +import './events/keyboard'; +import './events/mouse'; +import './events/touch'; + +// image +import './image/filters'; +import './image/image'; +import './image/loading_displaying'; +import './image/p5.Image'; +import './image/pixels'; + +// io +import './io/files'; +import './io/p5.Table'; +import './io/p5.TableRow'; +import './io/p5.XML'; + +// math +import './math/calculation'; +import './math/math'; +import './math/noise'; +import './math/p5.Vector'; +import './math/random'; +import './math/trigonometry'; + +// typography +import './typography/attributes'; +import './typography/loading_displaying'; +import './typography/p5.Font'; + +// utilities +import './utilities/array_functions'; +import './utilities/conversion'; +import './utilities/string_functions'; +import './utilities/time_date'; + +// webgl +import './webgl/3d_primitives'; +import './webgl/interaction'; +import './webgl/light'; +import './webgl/loading'; +import './webgl/material'; +import './webgl/p5.Camera'; +import './webgl/p5.Geometry'; +import './webgl/p5.Matrix'; +import './webgl/p5.RendererGL.Immediate'; +import './webgl/p5.RendererGL'; +import './webgl/p5.RendererGL.Retained'; +import './webgl/p5.Shader'; +import './webgl/p5.RenderBuffer'; +import './webgl/p5.Texture'; +import './webgl/text'; + +import './core/init'; + +module.exports = p5; From 2565a0ff7449cca93baf867685120d610320dfac Mon Sep 17 00:00:00 2001 From: Luis Morales-Navarro Date: Mon, 15 Jun 2020 11:50:03 -0600 Subject: [PATCH 05/42] fix app.js to add accessibility module --- src/app.js | 3 ++ src/core/app.js | 98 ------------------------------------------------- 2 files changed, 3 insertions(+), 98 deletions(-) delete mode 100644 src/core/app.js diff --git a/src/app.js b/src/app.js index 21188e14a9..a5022b200e 100644 --- a/src/app.js +++ b/src/app.js @@ -35,6 +35,9 @@ import './data/local_storage.js'; // DOM import './dom/dom'; +// accessibility +import './accessibility/describe'; + // events import './events/acceleration'; import './events/keyboard'; diff --git a/src/core/app.js b/src/core/app.js deleted file mode 100644 index a5022b200e..0000000000 --- a/src/core/app.js +++ /dev/null @@ -1,98 +0,0 @@ -// core -import p5 from './core/main'; -import './core/constants'; -import './core/environment'; -import './core/friendly_errors/stacktrace'; -import './core/friendly_errors/validate_params'; -import './core/friendly_errors/file_errors'; -import './core/friendly_errors/fes_core'; -import './core/helpers'; -import './core/legacy'; -import './core/preload'; -import './core/p5.Element'; -import './core/p5.Graphics'; -import './core/p5.Renderer'; -import './core/p5.Renderer2D'; -import './core/rendering'; -import './core/shim'; -import './core/structure'; -import './core/transform'; -import './core/shape/2d_primitives'; -import './core/shape/attributes'; -import './core/shape/curves'; -import './core/shape/vertex'; - -// color -import './color/color_conversion'; -import './color/creating_reading'; -import './color/p5.Color'; -import './color/setting'; - -// data -import './data/p5.TypedDict'; -import './data/local_storage.js'; - -// DOM -import './dom/dom'; - -// accessibility -import './accessibility/describe'; - -// events -import './events/acceleration'; -import './events/keyboard'; -import './events/mouse'; -import './events/touch'; - -// image -import './image/filters'; -import './image/image'; -import './image/loading_displaying'; -import './image/p5.Image'; -import './image/pixels'; - -// io -import './io/files'; -import './io/p5.Table'; -import './io/p5.TableRow'; -import './io/p5.XML'; - -// math -import './math/calculation'; -import './math/math'; -import './math/noise'; -import './math/p5.Vector'; -import './math/random'; -import './math/trigonometry'; - -// typography -import './typography/attributes'; -import './typography/loading_displaying'; -import './typography/p5.Font'; - -// utilities -import './utilities/array_functions'; -import './utilities/conversion'; -import './utilities/string_functions'; -import './utilities/time_date'; - -// webgl -import './webgl/3d_primitives'; -import './webgl/interaction'; -import './webgl/light'; -import './webgl/loading'; -import './webgl/material'; -import './webgl/p5.Camera'; -import './webgl/p5.Geometry'; -import './webgl/p5.Matrix'; -import './webgl/p5.RendererGL.Immediate'; -import './webgl/p5.RendererGL'; -import './webgl/p5.RendererGL.Retained'; -import './webgl/p5.Shader'; -import './webgl/p5.RenderBuffer'; -import './webgl/p5.Texture'; -import './webgl/text'; - -import './core/init'; - -module.exports = p5; From b62d2627091e1b65ea71f553bd71d8096243840c Mon Sep 17 00:00:00 2001 From: Luis Morales-Navarro Date: Mon, 15 Jun 2020 14:12:24 -0600 Subject: [PATCH 06/42] improved examples for describe() --- src/accessibility/describe.js | 95 +++++++++++++++-------------------- 1 file changed, 41 insertions(+), 54 deletions(-) diff --git a/src/accessibility/describe.js b/src/accessibility/describe.js index 0b69314d46..2781d263a2 100644 --- a/src/accessibility/describe.js +++ b/src/accessibility/describe.js @@ -29,22 +29,32 @@ import p5 from '../core/main'; * @example *
* - * function setup() { - * createCanvas(100, 100); + * describe('a red heart in the bottom right quadrant of the canvas', LABEL); + * background('pink'); + * fill('red'); + * noStroke(); + * ellipse(66.6, 66.6, 20, 20); + * ellipse(83.2, 66.6, 20, 20); + * triangle(91.2, 72.6, 75, 95, 58.6, 72.6); + * + * + *
+ *
+ * + * let x = 0; + * function draw() { + * if (x > 100) { + * x = 0; + * } * background(220); - * fill(255); - * ellipse(25, height / 2, 35, 20); - * ellipse(75, height / 2, 35, 20); - * fill('orange'); - * ellipse(25, height / 2, 15, 15); - * ellipse(75, height / 2, 15, 15); - * fill(0); - * ellipse(25, height / 2, 2.5, 2.5); - * ellipse(75, height / 2, 2.5, 2.5); - * describe('orange eyes over a gray background', LABEL); + * fill(0, 255, 0); + * ellipse(x, 50, 40, 40); + * x = x + 0.1; + * describe('a green circle at x pos ' + round(x) + ' moving to the right'); * } * *
+ * * @alt */ @@ -119,50 +129,27 @@ p5.prototype.describe = function(t, display) { * @example *
* - * function setup() { - * createCanvas(200, 100); - * describe('Two emojis over a pink background', LABEL); - * } - * function draw() { - * background('pink'); - * fill('yellow'); - * noStroke(); - * describeElement( - * 'Grinning face', - * 'An emoji with open eyes and a broad open smile showing upper teeth.', - * LABEL - * ); - * ellipse(50, 50, 70, 70); - * fill('#ad5240'); - * arc(50, 55, 40, 40, radians(0), radians(180), PIE); - * fill(0); - * ellipse(40, 35, 15, 20); - * ellipse(60, 35, 15, 20); - * fill(255); - * arc(50, 55, 40, 20, radians(0), radians(180), PIE); - * ellipse(43, 35, 5, 5); - * ellipse(63, 35, 5, 5); - * describeElement( - * 'Smiling face with heart-eyes', - * 'A yellow face located to the right. It has an open smile, and red, cartoon-styled hearts for eyes. Often conveys enthusiastic feelings of love.', - * LABEL - * ); - * fill('yellow'); - * ellipse(150, 50, 70, 70); - * fill('#ad5240'); - * arc(150, 55, 40, 40, radians(0), radians(180), PIE); - * fill('red'); - * ellipse(143, 35, 10, 10); - * ellipse(137, 35, 10, 10); - * triangle(132, 35, 140, 45, 148, 35); - * ellipse(157, 35, 10, 10); - * ellipse(163, 35, 10, 10); - * triangle(168, 35, 160, 45, 152, 35); - * } + * describe('A heart and a yellow circle over a pink background', LABEL); + * noStroke(); + * background('pink'); + * describeElement( + * 'Circle', + * 'a yellow circle in the top left quadrant of the canvas', + * LABEL + * ); + * fill('yellow'); + * ellipse(25, 25, 40, 40); + * describeElement( + * 'Heart', + * 'a red heart in the bottom right quadrant of the canvas', + * LABEL + * ); + * fill('red'); + * ellipse(66.6, 66.6, 20, 20); + * ellipse(83.2, 66.6, 20, 20); + * triangle(91.2, 72.6, 75, 95, 58.6, 72.6); * *
- * - * @alt */ p5.prototype.describeElement = function(name, t, display) { From 412985e9285373b25f027760d7d1e747e3a457f1 Mon Sep 17 00:00:00 2001 From: Luis Morales-Navarro Date: Mon, 15 Jun 2020 15:41:25 -0600 Subject: [PATCH 07/42] update element Ids --- src/accessibility/describe.js | 124 ++++++++++++++++------------------ 1 file changed, 59 insertions(+), 65 deletions(-) diff --git a/src/accessibility/describe.js b/src/accessibility/describe.js index 2781d263a2..c19f5453c4 100644 --- a/src/accessibility/describe.js +++ b/src/accessibility/describe.js @@ -54,51 +54,45 @@ import p5 from '../core/main'; * } * * - * - * @alt */ -p5.prototype.describe = function(t, display) { +p5.prototype.describe = function(t, d) { p5._validateParameters('describe', arguments); - const canvasID = this.canvas.id; + const cnvId = this.canvas.id; //Creates a sub DOM inside of the canvas element and populates //it with description text. - if (document.getElementById(canvasID + 'Description') === null) { - document.getElementById(canvasID).innerHTML = + if (document.getElementById(cnvId + '_Description') === null) { + document.getElementById(cnvId).innerHTML = '

'; - } else if (document.getElementById(canvasID + 'desc') === null) { + cnvId + + '_Description" role="region" aria-label="Canvas Description">

'; + } else if (document.getElementById(cnvId + '_dsc') === null) { document - .getElementById(canvasID + 'elDes') - .insertAdjacentHTML('beforebegin', '

'); + .getElementById(cnvId + '_eDsc') + .insertAdjacentHTML('beforebegin', '

'); } - if (document.getElementById(canvasID + 'desc').innerHTML !== t) { - document.getElementById(canvasID + 'desc').innerHTML = t; + if (document.getElementById(cnvId + '_dsc').innerHTML !== t) { + document.getElementById(cnvId + '_dsc').innerHTML = t; } //If display is LABEL creates a div adjacent to the canvas element with //description text. - if (display === 'label') { - if (document.getElementById(canvasID + 'Label') === null) { + if (d === 'label') { + if (document.getElementById(cnvId + '_Label') === null) { document - .getElementById(canvasID) + .getElementById(cnvId) .insertAdjacentHTML( 'afterend', - '

' + '

' ); - } else if (document.getElementById(canvasID + 'dLbl') === null) { + } else if (document.getElementById(cnvId + '_dLbl') === null) { document - .getElementById(canvasID + 'eLbl') - .insertAdjacentHTML('beforebegin', '

'); + .getElementById(cnvId + '_eLbl') + .insertAdjacentHTML('beforebegin', '

'); } - if (document.getElementById(canvasID + 'dLbl').innerHTML !== t) { - document.getElementById(canvasID + 'dLbl').innerHTML = t; + if (document.getElementById(cnvId + '_dLbl').innerHTML !== t) { + document.getElementById(cnvId + '_dLbl').innerHTML = t; } } }; @@ -152,76 +146,76 @@ p5.prototype.describe = function(t, display) { * */ -p5.prototype.describeElement = function(name, t, display) { +p5.prototype.describeElement = function(n, t, d) { p5._validateParameters('describeElement', arguments); - const canvasID = this.canvas.id; + const cnvId = this.canvas.id; //Creates a sub DOM inside of the canvas with a table, populates //a row header cell with the name of the elements and adds the description //of the element in adjecent cell. - if (document.getElementById(canvasID + 'Description') === null) { - document.getElementById(canvasID).innerHTML = + if (document.getElementById(cnvId + '_Description') === null) { + document.getElementById(cnvId).innerHTML = '
'; - } else if (document.getElementById(canvasID + 'elDes') === null) { + cnvId + + '_Description" role="region" aria-label="Canvas Description">
Canvas elements and their descriptions
'; + } else if (document.getElementById(cnvId + '_eDsc') === null) { document - .getElementById(canvasID + 'desc') + .getElementById(cnvId + '_dsc') .insertAdjacentHTML( 'afterend', - '
' + '
Canvas elements and their descriptions
' ); } - if (document.getElementById(canvasID + name) === null) { + if (document.getElementById(cnvId + n) === null) { let tr = document.createElement('tr'); - tr.id = canvasID + name; - document.getElementById(canvasID + 'elDes').appendChild(tr); + tr.id = cnvId + n; + document.getElementById(cnvId + '_eDsc').appendChild(tr); } if ( - document.getElementById(canvasID + name).innerHTML !== - '' + name + '' + t + '' + document.getElementById(cnvId + n).innerHTML !== + '' + n + '' + t + '' ) { - document.getElementById(canvasID + name).innerHTML = - '' + name + '' + t + ''; + document.getElementById(cnvId + n).innerHTML = + '' + n + '' + t + ''; } //If display is LABEL creates a div adjacent to the canvas element with //a table, a row header cell with the name of the elements, //and adds the description of the element in adjecent cell. - if (display === 'label') { - if (document.getElementById(canvasID + 'Label') === null) { + if (d === 'label') { + if (document.getElementById(cnvId + '_Label') === null) { document - .getElementById(canvasID) + .getElementById(cnvId) .insertAdjacentHTML( 'afterend', '
' + cnvId + + '_Label">
' ); - } else if (document.getElementById(canvasID + 'eLbl') === null) { + } else if (document.getElementById(cnvId + '_eLbl') === null) { document - .getElementById(canvasID + 'dLbl') + .getElementById(cnvId + '_dLbl') .insertAdjacentHTML( 'afterend', - '
' + '
' ); } - if (document.getElementById(canvasID + name + 'Lbl') === null) { + if (document.getElementById(cnvId + n + 'Lbl') === null) { let tr = document.createElement('tr'); - tr.id = canvasID + name + 'Lbl'; - document.getElementById(canvasID + 'eLbl').appendChild(tr); + tr.id = cnvId + n + 'Lbl'; + document.getElementById(cnvId + '_eLbl').appendChild(tr); } if ( - document.getElementById(canvasID + name + 'Lbl').innerHTML !== - '' + name + '' + t + '' + document.getElementById(cnvId + n + 'Lbl').innerHTML !== + '' + n + '' + t + '' ) { - document.getElementById(canvasID + name + 'Lbl').innerHTML = - '' + name + '' + t + ''; + document.getElementById(cnvId + n + 'Lbl').innerHTML = + '' + n + '' + t + ''; } } }; From be7792176c0d9c18a1bf8062f94ad4e3fc1bb817 Mon Sep 17 00:00:00 2001 From: Luis Morales-Navarro Date: Mon, 15 Jun 2020 16:26:36 -0600 Subject: [PATCH 08/42] update styling --- src/accessibility/describe.js | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/src/accessibility/describe.js b/src/accessibility/describe.js index c19f5453c4..dfbdce9f35 100644 --- a/src/accessibility/describe.js +++ b/src/accessibility/describe.js @@ -12,12 +12,12 @@ import p5 from '../core/main'; * The second parameter is optional. If specified, it determines how the * description is displayed. * - * describe(str, LABEL) displays the description to all users as a + * describe(str, LABEL) displays the description to all users as a * tombstone or exhibit label/caption - * by creating a <div id="label"> with the description right after the canvas. + * by creating a <div> with the description right after the canvas. * You can style it as you wish in your CSS. * - * describe(str, FALLBACK) makes the description accessible to screen-reader users only in + * describe(str, FALLBACK) makes the description accessible to screen-reader users only in * * a sub DOM inside the canvas element. * If a second parameter is not specified, by default, the description will only be available to screen-reader users. @@ -105,12 +105,12 @@ p5.prototype.describe = function(t, d) { * The third parameter is optional. * If specified, it determines how the element description is displayed. * - * describeElement(name, str, LABEL) displays the element description to all users as a + * describeElement(name, str, LABEL) displays the element description to all users as a * tombstone or exhibit label/caption - * by creating a <div id="label"> with the element description right after the canvas. + * by creating a <div> with the element descriptions right after the canvas. * You can style it as you wish in your CSS. * - * describeElement(name, str, FALLBACK) makes the element description accessible to screen-reader users only in + * describeElement(name, str, FALLBACK) makes the element description accessible to screen-reader users only in * * a sub DOM inside the canvas element. * If a second parameter is not specified, by default, the element description will only be available to screen-reader users. From 50ee933e85de9875955b4129c5331e46a412b8c4 Mon Sep 17 00:00:00 2001 From: Luis Morales-Navarro Date: Thu, 18 Jun 2020 12:08:44 -0600 Subject: [PATCH 09/42] delete extra space --- src/accessibility/describe.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/accessibility/describe.js b/src/accessibility/describe.js index dfbdce9f35..eed08bb33f 100644 --- a/src/accessibility/describe.js +++ b/src/accessibility/describe.js @@ -37,8 +37,8 @@ import p5 from '../core/main'; * ellipse(83.2, 66.6, 20, 20); * triangle(91.2, 72.6, 75, 95, 58.6, 72.6); * - * * + * *
* * let x = 0; From d40b7dba35542ebafea9991ff77252de1e8a77ee Mon Sep 17 00:00:00 2001 From: Luis Morales-Navarro Date: Thu, 18 Jun 2020 18:13:46 -0600 Subject: [PATCH 10/42] better descriptions --- src/accessibility/describe.js | 18 +++++------------- 1 file changed, 5 insertions(+), 13 deletions(-) diff --git a/src/accessibility/describe.js b/src/accessibility/describe.js index eed08bb33f..34c7e1d6ca 100644 --- a/src/accessibility/describe.js +++ b/src/accessibility/describe.js @@ -29,7 +29,7 @@ import p5 from '../core/main'; * @example *
* - * describe('a red heart in the bottom right quadrant of the canvas', LABEL); + * describe('pink square with red heart in the bottom right corner', LABEL); * background('pink'); * fill('red'); * noStroke(); @@ -50,7 +50,7 @@ import p5 from '../core/main'; * fill(0, 255, 0); * ellipse(x, 50, 40, 40); * x = x + 0.1; - * describe('a green circle at x pos ' + round(x) + ' moving to the right'); + * describe('green circle at x pos ' + round(x) + ' moving to the right'); * } * *
@@ -123,21 +123,13 @@ p5.prototype.describe = function(t, d) { * @example *
* - * describe('A heart and a yellow circle over a pink background', LABEL); + * describe('Heart and yellow circle over pink background', LABEL); * noStroke(); * background('pink'); - * describeElement( - * 'Circle', - * 'a yellow circle in the top left quadrant of the canvas', - * LABEL - * ); + * describeElement('Circle', 'yellow circle in the top left corner', LABEL); * fill('yellow'); * ellipse(25, 25, 40, 40); - * describeElement( - * 'Heart', - * 'a red heart in the bottom right quadrant of the canvas', - * LABEL - * ); + * describeElement('Heart', 'red heart in the bottom right corner', LABEL); * fill('red'); * ellipse(66.6, 66.6, 20, 20); * ellipse(83.2, 66.6, 20, 20); From 52e4d6ff5757d98fa10a74cbbcbf84a3f19d0ce6 Mon Sep 17 00:00:00 2001 From: Luis Morales-Navarro Date: Fri, 19 Jun 2020 09:38:04 -0600 Subject: [PATCH 11/42] add regex --- src/accessibility/describe.js | 40 +++++++++++++++++++++++++++++++---- 1 file changed, 36 insertions(+), 4 deletions(-) diff --git a/src/accessibility/describe.js b/src/accessibility/describe.js index 34c7e1d6ca..e80ace4cd5 100644 --- a/src/accessibility/describe.js +++ b/src/accessibility/describe.js @@ -1,5 +1,6 @@ /** - * @module Accessibility + * @module Environment + * @submodule Environment * @for p5 * @requires core */ @@ -17,7 +18,7 @@ import p5 from '../core/main'; * by creating a <div> with the description right after the canvas. * You can style it as you wish in your CSS. * - * describe(str, FALLBACK) makes the description accessible to screen-reader users only in + * describe(str, FALLBACK) makes the description accessible to screen-reader users only, in * * a sub DOM inside the canvas element. * If a second parameter is not specified, by default, the description will only be available to screen-reader users. @@ -61,6 +62,7 @@ p5.prototype.describe = function(t, d) { const cnvId = this.canvas.id; //Creates a sub DOM inside of the canvas element and populates //it with description text. + t = this._descriptionText(t); if (document.getElementById(cnvId + '_Description') === null) { document.getElementById(cnvId).innerHTML = '
<div> with the element descriptions right after the canvas. * You can style it as you wish in your CSS. * - * describeElement(name, str, FALLBACK) makes the element description accessible to screen-reader users only in + * describeElement(name, str, FALLBACK) makes the element description accessible to screen-reader users only, in * * a sub DOM inside the canvas element. * If a second parameter is not specified, by default, the element description will only be available to screen-reader users. @@ -126,7 +141,7 @@ p5.prototype.describe = function(t, d) { * describe('Heart and yellow circle over pink background', LABEL); * noStroke(); * background('pink'); - * describeElement('Circle', 'yellow circle in the top left corner', LABEL); + * describeElement('Circle', 'Yellow circle in the top left corner', LABEL); * fill('yellow'); * ellipse(25, 25, 40, 40); * describeElement('Heart', 'red heart in the bottom right corner', LABEL); @@ -141,6 +156,8 @@ p5.prototype.describe = function(t, d) { p5.prototype.describeElement = function(n, t, d) { p5._validateParameters('describeElement', arguments); const cnvId = this.canvas.id; + t = this._descriptionText(t); + n = this._elementName(n); //Creates a sub DOM inside of the canvas with a table, populates //a row header cell with the name of the elements and adds the description //of the element in adjecent cell. @@ -211,5 +228,20 @@ p5.prototype.describeElement = function(n, t, d) { } } }; +/** + * Helper function for describeElement(). + */ +p5.prototype._elementName = function(n) { + let lm = n[n.length - 1]; + if (lm === '.' || lm === ';' || lm === ',') { + n = n.replace(/.$/, ':'); + } else if (n.endsWith(':') === false) { + n = n + ':'; + } + if (/^[A-Z]/.test(n) === false) { + n = n[0].toUpperCase() + n.slice(1); + } + return n; +}; export default p5; From 8bee297d02152682642a6de6ec782bda12514d4e Mon Sep 17 00:00:00 2001 From: Luis Morales-Navarro Date: Tue, 23 Jun 2020 17:46:58 -0600 Subject: [PATCH 12/42] changes in description of functions --- src/accessibility/describe.js | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/src/accessibility/describe.js b/src/accessibility/describe.js index e80ace4cd5..dda1691c0f 100644 --- a/src/accessibility/describe.js +++ b/src/accessibility/describe.js @@ -13,18 +13,18 @@ import p5 from '../core/main'; * The second parameter is optional. If specified, it determines how the * description is displayed. * - * describe(str, LABEL) displays the description to all users as a + * describe(text, LABEL) displays the description to all users as a * tombstone or exhibit label/caption * by creating a <div> with the description right after the canvas. * You can style it as you wish in your CSS. * - * describe(str, FALLBACK) makes the description accessible to screen-reader users only, in + * describe(text, FALLBACK) makes the description accessible to screen-reader users only, in * * a sub DOM inside the canvas element. * If a second parameter is not specified, by default, the description will only be available to screen-reader users. * * @method describe - * @param {String} text string describing the canvas + * @param {String} text description of the canvas * @param {Constant} [display] either LABEL or FALLBACK (Optional) * * @example @@ -120,19 +120,19 @@ p5.prototype._descriptionText = function(t) { * The third parameter is optional. * If specified, it determines how the element description is displayed. * - * describeElement(name, str, LABEL) displays the element description to all users as a + * describeElement(name, text, LABEL) displays the element description to all users as a * tombstone or exhibit label/caption * by creating a <div> with the element descriptions right after the canvas. * You can style it as you wish in your CSS. * - * describeElement(name, str, FALLBACK) makes the element description accessible to screen-reader users only, in + * describeElement(name, text, FALLBACK) makes the element description accessible to screen-reader users only, in * * a sub DOM inside the canvas element. * If a second parameter is not specified, by default, the element description will only be available to screen-reader users. * * @method describeElement * @param {String} name name of the element - * @param {String} text string describing the element + * @param {String} text description of the element * @param {Constant} [display] either LABEL or FALLBACK (Optional) * * @example From 6c030313f5881f94fd08912a03787dac38bb73e1 Mon Sep 17 00:00:00 2001 From: Luis Morales-Navarro Date: Wed, 24 Jun 2020 19:03:56 -0600 Subject: [PATCH 13/42] add class for labels, improve descriptions --- src/accessibility/describe.js | 56 +++++++++++++++++++++-------------- 1 file changed, 34 insertions(+), 22 deletions(-) diff --git a/src/accessibility/describe.js b/src/accessibility/describe.js index dda1691c0f..cf8d2f6708 100644 --- a/src/accessibility/describe.js +++ b/src/accessibility/describe.js @@ -13,15 +13,19 @@ import p5 from '../core/main'; * The second parameter is optional. If specified, it determines how the * description is displayed. * - * describe(text, LABEL) displays the description to all users as a - * tombstone or exhibit label/caption - * by creating a <div> with the description right after the canvas. - * You can style it as you wish in your CSS. + * describe(text, LABEL) displays + * the description to all users as a + * tombstone or exhibit label/caption in a + * <div class="p5Label"></div> + * adjacent to the canvas. You can style it as you wish in your CSS. * - * describe(text, FALLBACK) makes the description accessible to screen-reader users only, in + * describe(text, FALLBACK) makes the + * description accessible to screen-reader users only, in * - * a sub DOM inside the canvas element. - * If a second parameter is not specified, by default, the description will only be available to screen-reader users. + * a sub DOM inside the canvas element. If a second parameter is not + * specified, by default, the description will only be available to + * screen-reader users. * * @method describe * @param {String} text description of the canvas @@ -86,7 +90,11 @@ p5.prototype.describe = function(t, d) { .getElementById(cnvId) .insertAdjacentHTML( 'afterend', - '

' + '

' ); } else if (document.getElementById(cnvId + '_dLbl') === null) { document @@ -113,22 +121,26 @@ p5.prototype._descriptionText = function(t) { }; /** - * describeElement() creates a screen-reader accessible description for - * elements —shapes or groups of shapes that create meaning together— in the canvas sub DOM. - * The first paramater should be the name of the element. The second parameter should be a - * string with a description of the element. - * The third parameter is optional. + * This function creates a screen-reader accessible + * description for elements —shapes or groups of shapes that create + * meaning together— in the canvas sub DOM. The first paramater should + * be the name of the element. The second parameter should be a string + * with a description of the element. The third parameter is optional. * If specified, it determines how the element description is displayed. * - * describeElement(name, text, LABEL) displays the element description to all users as a - * tombstone or exhibit label/caption - * by creating a <div> with the element descriptions right after the canvas. - * You can style it as you wish in your CSS. + * describeElement(name, text, LABEL) + * displays the element description to all users as a + * + * tombstone or exhibit label/caption in a + * <div class="p5Label"></div> + * adjacent to the canvas. You can style it as you wish in your CSS. * - * describeElement(name, text, FALLBACK) makes the element description accessible to screen-reader users only, in - * - * a sub DOM inside the canvas element. - * If a second parameter is not specified, by default, the element description will only be available to screen-reader users. + * describeElement(name, text, FALLBACK) + * makes the element description accessible to screen-reader users + * only, in + * a sub DOM inside the canvas element. If a second parameter is not + * specified, by default, the element description will only be available + * to screen-reader users. * * @method describeElement * @param {String} name name of the element @@ -201,7 +213,7 @@ p5.prototype.describeElement = function(n, t, d) { 'afterend', '
' ); From 9748310987ac446c44c1816e716adc5fc044ecfb Mon Sep 17 00:00:00 2001 From: Luis Morales-Navarro Date: Sun, 5 Jul 2020 11:49:29 -0600 Subject: [PATCH 14/42] round numbers in example --- src/accessibility/describe.js | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/accessibility/describe.js b/src/accessibility/describe.js index cf8d2f6708..79e3d4a9c1 100644 --- a/src/accessibility/describe.js +++ b/src/accessibility/describe.js @@ -38,9 +38,9 @@ import p5 from '../core/main'; * background('pink'); * fill('red'); * noStroke(); - * ellipse(66.6, 66.6, 20, 20); - * ellipse(83.2, 66.6, 20, 20); - * triangle(91.2, 72.6, 75, 95, 58.6, 72.6); + * ellipse(67, 67, 20, 20); + * ellipse(83, 67, 20, 20); + * triangle(91, 73, 75, 95, 59, 73); *
*
* From cfa50bcb465a3abdba1cd2978b385ef1f4abb9ab Mon Sep 17 00:00:00 2001 From: Luis Morales-Navarro Date: Sun, 5 Jul 2020 12:55:33 -0600 Subject: [PATCH 15/42] use global vars --- src/accessibility/describe.js | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/accessibility/describe.js b/src/accessibility/describe.js index 79e3d4a9c1..718858a950 100644 --- a/src/accessibility/describe.js +++ b/src/accessibility/describe.js @@ -84,7 +84,7 @@ p5.prototype.describe = function(t, d) { } //If display is LABEL creates a div adjacent to the canvas element with //description text. - if (d === 'label') { + if (d === this.LABEL) { if (document.getElementById(cnvId + '_Label') === null) { document .getElementById(cnvId) @@ -205,7 +205,7 @@ p5.prototype.describeElement = function(n, t, d) { //If display is LABEL creates a div adjacent to the canvas element with //a table, a row header cell with the name of the elements, //and adds the description of the element in adjecent cell. - if (d === 'label') { + if (d === this.LABEL) { if (document.getElementById(cnvId + '_Label') === null) { document .getElementById(cnvId) From ea7215016eb5bc5ece1b6c78f9b59ad7031f99d3 Mon Sep 17 00:00:00 2001 From: Luis Morales-Navarro Date: Sun, 5 Jul 2020 13:35:11 -0600 Subject: [PATCH 16/42] comments on regx --- src/accessibility/describe.js | 10 ++++++++++ 1 file changed, 10 insertions(+) diff --git a/src/accessibility/describe.js b/src/accessibility/describe.js index 718858a950..e25343613e 100644 --- a/src/accessibility/describe.js +++ b/src/accessibility/describe.js @@ -111,10 +111,14 @@ p5.prototype.describe = function(t, d) { * Helper function for describe() and describeElement(). */ p5.prototype._descriptionText = function(t) { + //if string does not end with '.' if (t.endsWith('.') === false) { + //add '.' to the end of string t = t + '.'; } + //if first character of string is not capitalized if (/^[A-Z]/.test(t) === false) { + //capitalize first character of string t = t[0].toUpperCase() + t.slice(1); } return t; @@ -245,12 +249,18 @@ p5.prototype.describeElement = function(n, t, d) { */ p5.prototype._elementName = function(n) { let lm = n[n.length - 1]; + //check if last character of string n is '.', ';', or ',' if (lm === '.' || lm === ';' || lm === ',') { + //replace last character with ':' n = n.replace(/.$/, ':'); + //if string n does not end with ':' } else if (n.endsWith(':') === false) { + //add ':'' at the end of string n = n + ':'; } + //if first character of string is not capitalized if (/^[A-Z]/.test(n) === false) { + //capitalize first character n = n[0].toUpperCase() + n.slice(1); } return n; From ef8f7862c83fea0782eb931fe0e716a70ca07d42 Mon Sep 17 00:00:00 2001 From: Luis Morales-Navarro Date: Sun, 5 Jul 2020 14:52:03 -0600 Subject: [PATCH 17/42] use consts for element ids --- src/accessibility/describe.js | 94 ++++++++++++++++++++--------------- 1 file changed, 55 insertions(+), 39 deletions(-) diff --git a/src/accessibility/describe.js b/src/accessibility/describe.js index e25343613e..4fb48aa969 100644 --- a/src/accessibility/describe.js +++ b/src/accessibility/describe.js @@ -6,6 +6,13 @@ */ import p5 from '../core/main'; +const ds = '_Description'; +const dsc = '_dsc'; +const eDsc = '_eDsc'; +const lbd = '_Label'; +const dlb = '_dLbl'; +const elb = '_eLbl'; +const lbl = 'Lbl'; /** * Creates a screen-reader accessible description for the canvas in the DOM. @@ -61,48 +68,52 @@ import p5 from '../core/main'; *
* */ + p5.prototype.describe = function(t, d) { - p5._validateParameters('describe', arguments); const cnvId = this.canvas.id; + p5._validateParameters('describe', arguments); //Creates a sub DOM inside of the canvas element and populates //it with description text. t = this._descriptionText(t); - if (document.getElementById(cnvId + '_Description') === null) { + if (document.getElementById(cnvId + ds) === null) { document.getElementById(cnvId).innerHTML = '

'; - } else if (document.getElementById(cnvId + '_dsc') === null) { + dsc + + '">

'; + } else if (document.getElementById(cnvId + dsc) === null) { document - .getElementById(cnvId + '_eDsc') - .insertAdjacentHTML('beforebegin', '

'); + .getElementById(cnvId + eDsc) + .insertAdjacentHTML('beforebegin', '

'); } - if (document.getElementById(cnvId + '_dsc').innerHTML !== t) { - document.getElementById(cnvId + '_dsc').innerHTML = t; + if (document.getElementById(cnvId + dsc).innerHTML !== t) { + document.getElementById(cnvId + dsc).innerHTML = t; } //If display is LABEL creates a div adjacent to the canvas element with //description text. if (d === this.LABEL) { - if (document.getElementById(cnvId + '_Label') === null) { + if (document.getElementById(cnvId + lbd) === null) { document .getElementById(cnvId) .insertAdjacentHTML( 'afterend', '

' ); - } else if (document.getElementById(cnvId + '_dLbl') === null) { + } else if (document.getElementById(cnvId + dlb) === null) { document - .getElementById(cnvId + '_eLbl') - .insertAdjacentHTML('beforebegin', '

'); + .getElementById(cnvId + elb) + .insertAdjacentHTML('beforebegin', '

'); } - if (document.getElementById(cnvId + '_dLbl').innerHTML !== t) { - document.getElementById(cnvId + '_dLbl').innerHTML = t; + if (document.getElementById(cnvId + dlb).innerHTML !== t) { + document.getElementById(cnvId + dlb).innerHTML = t; } } }; @@ -173,74 +184,79 @@ p5.prototype.describeElement = function(n, t, d) { p5._validateParameters('describeElement', arguments); const cnvId = this.canvas.id; t = this._descriptionText(t); - n = this._elementName(n); + let nm = this._elementName(n); //Creates a sub DOM inside of the canvas with a table, populates //a row header cell with the name of the elements and adds the description //of the element in adjecent cell. - if (document.getElementById(cnvId + '_Description') === null) { + if (document.getElementById(cnvId + ds) === null) { document.getElementById(cnvId).innerHTML = '
Canvas elements and their descriptions
'; - } else if (document.getElementById(cnvId + '_eDsc') === null) { + eDsc + + '">Canvas elements and their descriptions'; + } else if (document.getElementById(cnvId + eDsc) === null) { document - .getElementById(cnvId + '_dsc') + .getElementById(cnvId + dsc) .insertAdjacentHTML( 'afterend', '
Canvas elements and their descriptions
' + eDsc + + '">Canvas elements and their descriptions' ); } if (document.getElementById(cnvId + n) === null) { let tr = document.createElement('tr'); tr.id = cnvId + n; - document.getElementById(cnvId + '_eDsc').appendChild(tr); + document.getElementById(cnvId + eDsc).appendChild(tr); } if ( document.getElementById(cnvId + n).innerHTML !== - '' + n + '' + t + '' + '' + nm + '' + t + '' ) { document.getElementById(cnvId + n).innerHTML = - '' + n + '' + t + ''; + '' + nm + '' + t + ''; } //If display is LABEL creates a div adjacent to the canvas element with //a table, a row header cell with the name of the elements, //and adds the description of the element in adjecent cell. if (d === this.LABEL) { - if (document.getElementById(cnvId + '_Label') === null) { + if (document.getElementById(cnvId + lbd) === null) { document .getElementById(cnvId) .insertAdjacentHTML( 'afterend', '
' + elb + + '">' ); - } else if (document.getElementById(cnvId + '_eLbl') === null) { + } else if (document.getElementById(cnvId + elb) === null) { document - .getElementById(cnvId + '_dLbl') + .getElementById(cnvId + dlb) .insertAdjacentHTML( 'afterend', - '
' + '
' ); } - if (document.getElementById(cnvId + n + 'Lbl') === null) { + if (document.getElementById(cnvId + n + lbl) === null) { let tr = document.createElement('tr'); - tr.id = cnvId + n + 'Lbl'; - document.getElementById(cnvId + '_eLbl').appendChild(tr); + tr.id = cnvId + n + lbl; + document.getElementById(cnvId + elb).appendChild(tr); } if ( - document.getElementById(cnvId + n + 'Lbl').innerHTML !== - '' + n + '' + t + '' + document.getElementById(cnvId + n + lbl).innerHTML !== + '' + nm + '' + t + '' ) { - document.getElementById(cnvId + n + 'Lbl').innerHTML = - '' + n + '' + t + ''; + document.getElementById(cnvId + n + lbl).innerHTML = + '' + nm + '' + t + ''; } } }; From 397c9a6a2dd5d55ead3427b78ecbb3d4769c05f5 Mon Sep 17 00:00:00 2001 From: Luis Morales-Navarro Date: Sun, 5 Jul 2020 17:48:29 -0600 Subject: [PATCH 18/42] first tests --- test/unit/accessibility/describe.js | 85 +++++++++++++++++++++++++++++ test/unit/spec.js | 1 + 2 files changed, 86 insertions(+) create mode 100644 test/unit/accessibility/describe.js diff --git a/test/unit/accessibility/describe.js b/test/unit/accessibility/describe.js new file mode 100644 index 0000000000..d7a8d430ff --- /dev/null +++ b/test/unit/accessibility/describe.js @@ -0,0 +1,85 @@ +suite('describe', function() { + let myp5; + let myp5Container; + + setup(function(done) { + myp5Container = document.createElement('div'); + document.body.appendChild(myp5Container); + new p5(function(p) { + p.setup = function() { + let cnv = p.createCanvas(100, 100); + cnv.id('myID'); + myp5 = p; + done(); + }; + }, myp5Container); + }); + + teardown(function() { + myp5.remove(); + if (myp5Container && myp5Container.parentNode) { + myp5Container.parentNode.removeChild(myp5Container); + } + p5Container = null; + }); + + suite('p5.prototype.describe', function() { + let expectedElement = 'A.'; + test('should be a function', function() { + assert.ok(myp5.describe); + assert.typeOf(myp5.describe, 'function'); + }); + test('should create description as fallback', function() { + myp5.describe('a'); + let actualElement = document.getElementById('myID_dsc').innerHTML; + assert.equal(actualElement, expectedElement, 'works as expected'); + }); + test('should create description when called after describeElement()', function() { + myp5.describeElement('b', 'c'); + myp5.describe('a'); + let actualElement = document.getElementById('myID_dsc').innerHTML; + assert.equal(actualElement, expectedElement, 'works as expected'); + }); + test('should create Label adjacent to canvas', function() { + myp5.describe('a', myp5.LABEL); + let actualElement = document.getElementById('myID_dLbl').innerHTML; + assert.equal(actualElement, expectedElement, 'works as expected'); + }); + test('should create Label adjacent to canvas when label of element already exists', function() { + myp5.describeElement('b', 'c', myp5.LABEL); + myp5.describe('a', myp5.LABEL); + let actualElement = document.getElementById('myID_dLbl').innerHTML; + assert.equal(actualElement, expectedElement, 'works as expected'); + }); + }); + + suite('p5.prototype.describeElement', function() { + let expectedElement = 'A:B.'; + test('should be a function', function() { + assert.ok(myp5.describeElement); + assert.typeOf(myp5.describeElement, 'function'); + }); + test('should create element description as fallback', function() { + myp5.describeElement('a', 'b'); + let actualElement = document.getElementById('myIDa').innerHTML; + assert.equal(actualElement, expectedElement, 'works as expected'); + }); + test('should create element description when called after describe()', function() { + myp5.describe('c'); + myp5.describeElement('a', 'b'); + let actualElement = document.getElementById('myIDa').innerHTML; + assert.equal(actualElement, expectedElement, 'works as expected'); + }); + test('should create element label adjacent to canvas', function() { + myp5.describeElement('a', 'b', myp5.LABEL); + const actualElement = document.getElementById('myIDaLbl').innerHTML; + assert.equal(actualElement, expectedElement, 'works as expected'); + }); + test('should create element label adjacent to canvas when label of describe() already exists', function() { + myp5.describe('c', myp5.LABEL); + myp5.describeElement('a', 'b', myp5.LABEL); + const actualElement = document.getElementById('myIDaLbl').innerHTML; + assert.equal(actualElement, expectedElement, 'works as expected'); + }); + }); +}); diff --git a/test/unit/spec.js b/test/unit/spec.js index 4bfd8f6f90..c632632d75 100644 --- a/test/unit/spec.js +++ b/test/unit/spec.js @@ -1,4 +1,5 @@ var spec = { + accessibility: ['describe'], color: ['color_conversion', 'creating_reading', 'p5.Color', 'setting'], core: [ '2d_primitives', From 9bdbf6096a86d884e7a33f4c34fb918fcae97997 Mon Sep 17 00:00:00 2001 From: Luis Morales-Navarro Date: Sun, 5 Jul 2020 18:18:29 -0600 Subject: [PATCH 19/42] updates tests --- test/unit/accessibility/describe.js | 70 ++++++++++++++++------------- 1 file changed, 39 insertions(+), 31 deletions(-) diff --git a/test/unit/accessibility/describe.js b/test/unit/accessibility/describe.js index d7a8d430ff..30b7038249 100644 --- a/test/unit/accessibility/describe.js +++ b/test/unit/accessibility/describe.js @@ -1,6 +1,10 @@ suite('describe', function() { let myp5; let myp5Container; + let myID = 'myCanvasID'; + let a = 'a'; + let b = 'b'; + let c = 'c'; setup(function(done) { myp5Container = document.createElement('div'); @@ -8,7 +12,7 @@ suite('describe', function() { new p5(function(p) { p.setup = function() { let cnv = p.createCanvas(100, 100); - cnv.id('myID'); + cnv.id(myID); myp5 = p; done(); }; @@ -23,63 +27,67 @@ suite('describe', function() { p5Container = null; }); + const getInner = elID => { + return document.getElementById(elID).innerHTML; + }; + suite('p5.prototype.describe', function() { - let expectedElement = 'A.'; + let expected = 'A.'; test('should be a function', function() { assert.ok(myp5.describe); assert.typeOf(myp5.describe, 'function'); }); test('should create description as fallback', function() { - myp5.describe('a'); - let actualElement = document.getElementById('myID_dsc').innerHTML; - assert.equal(actualElement, expectedElement, 'works as expected'); + myp5.describe(a); + let actual = getInner(myID + '_dsc'); + assert.equal(actual, expected); }); test('should create description when called after describeElement()', function() { - myp5.describeElement('b', 'c'); - myp5.describe('a'); - let actualElement = document.getElementById('myID_dsc').innerHTML; - assert.equal(actualElement, expectedElement, 'works as expected'); + myp5.describeElement(b, c); + myp5.describe(a); + let actual = getInner(myID + '_dsc'); + assert.equal(actual, expected); }); test('should create Label adjacent to canvas', function() { - myp5.describe('a', myp5.LABEL); - let actualElement = document.getElementById('myID_dLbl').innerHTML; - assert.equal(actualElement, expectedElement, 'works as expected'); + myp5.describe(a, myp5.LABEL); + let actual = getInner(myID + '_dLbl'); + assert.equal(actual, expected); }); test('should create Label adjacent to canvas when label of element already exists', function() { - myp5.describeElement('b', 'c', myp5.LABEL); - myp5.describe('a', myp5.LABEL); - let actualElement = document.getElementById('myID_dLbl').innerHTML; - assert.equal(actualElement, expectedElement, 'works as expected'); + myp5.describeElement(b, c, myp5.LABEL); + myp5.describe(a, myp5.LABEL); + let actual = getInner(myID + '_dLbl'); + assert.equal(actual, expected); }); }); suite('p5.prototype.describeElement', function() { - let expectedElement = 'A:B.'; + let expected = 'A:B.'; test('should be a function', function() { assert.ok(myp5.describeElement); assert.typeOf(myp5.describeElement, 'function'); }); test('should create element description as fallback', function() { - myp5.describeElement('a', 'b'); - let actualElement = document.getElementById('myIDa').innerHTML; - assert.equal(actualElement, expectedElement, 'works as expected'); + myp5.describeElement(a, b); + let actual = getInner(myID + a); + assert.equal(actual, expected); }); test('should create element description when called after describe()', function() { - myp5.describe('c'); - myp5.describeElement('a', 'b'); - let actualElement = document.getElementById('myIDa').innerHTML; - assert.equal(actualElement, expectedElement, 'works as expected'); + myp5.describe(c); + myp5.describeElement(a, b); + let actual = getInner(myID + a); + assert.equal(actual, expected); }); test('should create element label adjacent to canvas', function() { - myp5.describeElement('a', 'b', myp5.LABEL); - const actualElement = document.getElementById('myIDaLbl').innerHTML; - assert.equal(actualElement, expectedElement, 'works as expected'); + myp5.describeElement(a, b, myp5.LABEL); + const actual = getInner(myID + a + 'Lbl'); + assert.equal(actual, expected); }); test('should create element label adjacent to canvas when label of describe() already exists', function() { - myp5.describe('c', myp5.LABEL); - myp5.describeElement('a', 'b', myp5.LABEL); - const actualElement = document.getElementById('myIDaLbl').innerHTML; - assert.equal(actualElement, expectedElement, 'works as expected'); + myp5.describe(c, myp5.LABEL); + myp5.describeElement(a, b, myp5.LABEL); + const actual = getInner(myID + a + 'Lbl'); + assert.equal(actual, expected); }); }); }); From b8f4065436458ea090a3a7844877d840ffcafbbf Mon Sep 17 00:00:00 2001 From: Luis Morales-Navarro Date: Mon, 6 Jul 2020 08:45:47 -0600 Subject: [PATCH 20/42] change elements ids --- src/accessibility/describe.js | 31 +++++++++++++++-------------- test/unit/accessibility/describe.js | 8 ++++---- 2 files changed, 20 insertions(+), 19 deletions(-) diff --git a/src/accessibility/describe.js b/src/accessibility/describe.js index 4fb48aa969..50731abdf9 100644 --- a/src/accessibility/describe.js +++ b/src/accessibility/describe.js @@ -6,13 +6,14 @@ */ import p5 from '../core/main'; -const ds = '_Description'; -const dsc = '_dsc'; -const eDsc = '_eDsc'; -const lbd = '_Label'; -const dlb = '_dLbl'; -const elb = '_eLbl'; -const lbl = 'Lbl'; +const ds = '_Description'; //Fallback container +const dsc = '_dsc'; //Fallback description +const eDsc = '_eDsc'; //Fallback Table +const fte = '_fte_'; //Fallback Table Element +const lbd = '_Label'; //Label container +const dlb = '_dLbl'; //Label description +const elb = '_eLbl'; //Label Table +const lbl = '_lte_'; //Lable Table Element /** * Creates a screen-reader accessible description for the canvas in the DOM. @@ -208,16 +209,16 @@ p5.prototype.describeElement = function(n, t, d) { '">Canvas elements and their descriptions' ); } - if (document.getElementById(cnvId + n) === null) { + if (document.getElementById(cnvId + fte + n) === null) { let tr = document.createElement('tr'); - tr.id = cnvId + n; + tr.id = cnvId + fte + n; document.getElementById(cnvId + eDsc).appendChild(tr); } if ( - document.getElementById(cnvId + n).innerHTML !== + document.getElementById(cnvId + fte + n).innerHTML !== '' + nm + '' + t + '' ) { - document.getElementById(cnvId + n).innerHTML = + document.getElementById(cnvId + fte + n).innerHTML = '' + nm + '' + t + ''; } //If display is LABEL creates a div adjacent to the canvas element with @@ -245,17 +246,17 @@ p5.prototype.describeElement = function(n, t, d) { '
' ); } - if (document.getElementById(cnvId + n + lbl) === null) { + if (document.getElementById(cnvId + lbl + n) === null) { let tr = document.createElement('tr'); - tr.id = cnvId + n + lbl; + tr.id = cnvId + lbl + n; document.getElementById(cnvId + elb).appendChild(tr); } if ( - document.getElementById(cnvId + n + lbl).innerHTML !== + document.getElementById(cnvId + lbl + n).innerHTML !== '' + nm + '' + t + '' ) { - document.getElementById(cnvId + n + lbl).innerHTML = + document.getElementById(cnvId + lbl + n).innerHTML = '' + nm + '' + t + ''; } } diff --git a/test/unit/accessibility/describe.js b/test/unit/accessibility/describe.js index 30b7038249..6808450639 100644 --- a/test/unit/accessibility/describe.js +++ b/test/unit/accessibility/describe.js @@ -69,24 +69,24 @@ suite('describe', function() { }); test('should create element description as fallback', function() { myp5.describeElement(a, b); - let actual = getInner(myID + a); + let actual = getInner(myID + '_fte_' + a); assert.equal(actual, expected); }); test('should create element description when called after describe()', function() { myp5.describe(c); myp5.describeElement(a, b); - let actual = getInner(myID + a); + let actual = getInner(myID + '_fte_' + a); assert.equal(actual, expected); }); test('should create element label adjacent to canvas', function() { myp5.describeElement(a, b, myp5.LABEL); - const actual = getInner(myID + a + 'Lbl'); + const actual = getInner(myID + '_lte_' + a); assert.equal(actual, expected); }); test('should create element label adjacent to canvas when label of describe() already exists', function() { myp5.describe(c, myp5.LABEL); myp5.describeElement(a, b, myp5.LABEL); - const actual = getInner(myID + a + 'Lbl'); + const actual = getInner(myID + '_lte_' + a); assert.equal(actual, expected); }); }); From b992cc94f3f0667560afcd18d567c0d3fe590e14 Mon Sep 17 00:00:00 2001 From: Luis Morales-Navarro Date: Mon, 6 Jul 2020 09:11:06 -0600 Subject: [PATCH 21/42] update const names --- src/accessibility/describe.js | 73 +++++++++++++++-------------- test/unit/accessibility/describe.js | 8 ++-- 2 files changed, 41 insertions(+), 40 deletions(-) diff --git a/src/accessibility/describe.js b/src/accessibility/describe.js index 50731abdf9..ba33fc4c60 100644 --- a/src/accessibility/describe.js +++ b/src/accessibility/describe.js @@ -7,13 +7,13 @@ import p5 from '../core/main'; const ds = '_Description'; //Fallback container -const dsc = '_dsc'; //Fallback description -const eDsc = '_eDsc'; //Fallback Table +const fds = '_fds'; //Fallback description +const ft = '_ft'; //Fallback Table const fte = '_fte_'; //Fallback Table Element -const lbd = '_Label'; //Label container -const dlb = '_dLbl'; //Label description -const elb = '_eLbl'; //Label Table -const lbl = '_lte_'; //Lable Table Element +const lb = '_Label'; //Label container +const lds = '_lds'; //Label description +const lt = '_lt'; //Label Table +const lte = '_lte_'; //Lable Table Element /** * Creates a screen-reader accessible description for the canvas in the DOM. @@ -83,38 +83,39 @@ p5.prototype.describe = function(t, d) { ds + '" role="region" aria-label="Canvas Description">

'; - } else if (document.getElementById(cnvId + dsc) === null) { + } else if (document.getElementById(cnvId + fds) === null) { document - .getElementById(cnvId + eDsc) - .insertAdjacentHTML('beforebegin', '

'); + .getElementById(cnvId + ft) + .insertAdjacentHTML('beforebegin', '

'); } - if (document.getElementById(cnvId + dsc).innerHTML !== t) { - document.getElementById(cnvId + dsc).innerHTML = t; + if (document.getElementById(cnvId + fds).innerHTML !== t) { + document.getElementById(cnvId + fds).innerHTML = t; } //If display is LABEL creates a div adjacent to the canvas element with //description text. if (d === this.LABEL) { - if (document.getElementById(cnvId + lbd) === null) { + if (document.getElementById(cnvId + lb) === null) { document .getElementById(cnvId) .insertAdjacentHTML( 'afterend', '

' + lds + + '>

' ); - } else if (document.getElementById(cnvId + dlb) === null) { + } else if (document.getElementById(cnvId + lds) === null) { document - .getElementById(cnvId + elb) - .insertAdjacentHTML('beforebegin', '

'); + .getElementById(cnvId + lt) + .insertAdjacentHTML('beforebegin', '

'); } - if (document.getElementById(cnvId + dlb).innerHTML !== t) { - document.getElementById(cnvId + dlb).innerHTML = t; + if (document.getElementById(cnvId + lds).innerHTML !== t) { + document.getElementById(cnvId + lds).innerHTML = t; } } }; @@ -196,23 +197,23 @@ p5.prototype.describeElement = function(n, t, d) { ds + '" role="region" aria-label="Canvas Description">
Canvas elements and their descriptions
'; - } else if (document.getElementById(cnvId + eDsc) === null) { + } else if (document.getElementById(cnvId + ft) === null) { document - .getElementById(cnvId + dsc) + .getElementById(cnvId + fds) .insertAdjacentHTML( 'afterend', '
Canvas elements and their descriptions
' ); } if (document.getElementById(cnvId + fte + n) === null) { let tr = document.createElement('tr'); tr.id = cnvId + fte + n; - document.getElementById(cnvId + eDsc).appendChild(tr); + document.getElementById(cnvId + ft).appendChild(tr); } if ( document.getElementById(cnvId + fte + n).innerHTML !== @@ -225,38 +226,38 @@ p5.prototype.describeElement = function(n, t, d) { //a table, a row header cell with the name of the elements, //and adds the description of the element in adjecent cell. if (d === this.LABEL) { - if (document.getElementById(cnvId + lbd) === null) { + if (document.getElementById(cnvId + lb) === null) { document .getElementById(cnvId) .insertAdjacentHTML( 'afterend', '
' ); - } else if (document.getElementById(cnvId + elb) === null) { + } else if (document.getElementById(cnvId + lt) === null) { document - .getElementById(cnvId + dlb) + .getElementById(cnvId + lds) .insertAdjacentHTML( 'afterend', - '
' + '
' ); } - if (document.getElementById(cnvId + lbl + n) === null) { + if (document.getElementById(cnvId + lte + n) === null) { let tr = document.createElement('tr'); - tr.id = cnvId + lbl + n; - document.getElementById(cnvId + elb).appendChild(tr); + tr.id = cnvId + lte + n; + document.getElementById(cnvId + lt).appendChild(tr); } if ( - document.getElementById(cnvId + lbl + n).innerHTML !== + document.getElementById(cnvId + lte + n).innerHTML !== '' + nm + '' + t + '' ) { - document.getElementById(cnvId + lbl + n).innerHTML = + document.getElementById(cnvId + lte + n).innerHTML = '' + nm + '' + t + ''; } } diff --git a/test/unit/accessibility/describe.js b/test/unit/accessibility/describe.js index 6808450639..e2dfae89c6 100644 --- a/test/unit/accessibility/describe.js +++ b/test/unit/accessibility/describe.js @@ -39,24 +39,24 @@ suite('describe', function() { }); test('should create description as fallback', function() { myp5.describe(a); - let actual = getInner(myID + '_dsc'); + let actual = getInner(myID + '_fds'); assert.equal(actual, expected); }); test('should create description when called after describeElement()', function() { myp5.describeElement(b, c); myp5.describe(a); - let actual = getInner(myID + '_dsc'); + let actual = getInner(myID + '_fds'); assert.equal(actual, expected); }); test('should create Label adjacent to canvas', function() { myp5.describe(a, myp5.LABEL); - let actual = getInner(myID + '_dLbl'); + let actual = getInner(myID + '_lds'); assert.equal(actual, expected); }); test('should create Label adjacent to canvas when label of element already exists', function() { myp5.describeElement(b, c, myp5.LABEL); myp5.describe(a, myp5.LABEL); - let actual = getInner(myID + '_dLbl'); + let actual = getInner(myID + '_lds'); assert.equal(actual, expected); }); }); From c0e97e66c57dd437637a409edca837a4788833fa Mon Sep 17 00:00:00 2001 From: Luis Morales-Navarro Date: Mon, 6 Jul 2020 11:40:09 -0600 Subject: [PATCH 22/42] fix errors when parameter not string --- src/accessibility/describe.js | 13 +++++++++++++ 1 file changed, 13 insertions(+) diff --git a/src/accessibility/describe.js b/src/accessibility/describe.js index ba33fc4c60..da1e1cc130 100644 --- a/src/accessibility/describe.js +++ b/src/accessibility/describe.js @@ -75,6 +75,9 @@ p5.prototype.describe = function(t, d) { p5._validateParameters('describe', arguments); //Creates a sub DOM inside of the canvas element and populates //it with description text. + if (typeof t !== 'string') { + return; + } t = this._descriptionText(t); if (document.getElementById(cnvId + ds) === null) { document.getElementById(cnvId).innerHTML = @@ -123,7 +126,11 @@ p5.prototype.describe = function(t, d) { /** * Helper function for describe() and describeElement(). */ + p5.prototype._descriptionText = function(t) { + if (t === this.LABEL || t === this.FALLBACK) { + throw new Error('description should not be LABEL or FALLBACK'); + } //if string does not end with '.' if (t.endsWith('.') === false) { //add '.' to the end of string @@ -184,6 +191,9 @@ p5.prototype._descriptionText = function(t) { p5.prototype.describeElement = function(n, t, d) { p5._validateParameters('describeElement', arguments); + if (typeof t !== 'string' || typeof n !== 'string') { + return; + } const cnvId = this.canvas.id; t = this._descriptionText(t); let nm = this._elementName(n); @@ -266,6 +276,9 @@ p5.prototype.describeElement = function(n, t, d) { * Helper function for describeElement(). */ p5.prototype._elementName = function(n) { + if (n === this.LABEL || n === this.FALLBACK) { + throw new Error('element name should not be LABEL or FALLBACK'); + } let lm = n[n.length - 1]; //check if last character of string n is '.', ';', or ',' if (lm === '.' || lm === ';' || lm === ',') { From d28392c3ff73a085ccfb6e2daf2cedc550ff61f1 Mon Sep 17 00:00:00 2001 From: Luis Morales-Navarro Date: Mon, 6 Jul 2020 13:52:43 -0600 Subject: [PATCH 23/42] add tests/change equal for deepEqual --- test/unit/accessibility/describe.js | 63 +++++++++++++++++++++++++---- 1 file changed, 55 insertions(+), 8 deletions(-) diff --git a/test/unit/accessibility/describe.js b/test/unit/accessibility/describe.js index e2dfae89c6..c47816bc88 100644 --- a/test/unit/accessibility/describe.js +++ b/test/unit/accessibility/describe.js @@ -40,24 +40,43 @@ suite('describe', function() { test('should create description as fallback', function() { myp5.describe(a); let actual = getInner(myID + '_fds'); - assert.equal(actual, expected); + assert.deepEqual(actual, expected); }); test('should create description when called after describeElement()', function() { myp5.describeElement(b, c); myp5.describe(a); let actual = getInner(myID + '_fds'); - assert.equal(actual, expected); + assert.deepEqual(actual, expected); }); test('should create Label adjacent to canvas', function() { myp5.describe(a, myp5.LABEL); let actual = getInner(myID + '_lds'); - assert.equal(actual, expected); + assert.deepEqual(actual, expected); }); test('should create Label adjacent to canvas when label of element already exists', function() { myp5.describeElement(b, c, myp5.LABEL); myp5.describe(a, myp5.LABEL); let actual = getInner(myID + '_lds'); - assert.equal(actual, expected); + assert.deepEqual(actual, expected); + }); + test('wrong param type at #0', function() { + assert.validationError(function() { + myp5.describe(1, myp5.LABEL); + }); + }); + test('no params', function() { + assert.validationError(function() { + myp5.describe(); + }); + }); + test('err when LABEL at param #0', function() { + assert.throws( + function() { + myp5.describe(myp5.LABEL); + }, + Error, + 'description should not be LABEL or FALLBACK' + ); }); }); @@ -70,24 +89,52 @@ suite('describe', function() { test('should create element description as fallback', function() { myp5.describeElement(a, b); let actual = getInner(myID + '_fte_' + a); - assert.equal(actual, expected); + assert.deepEqual(actual, expected); }); test('should create element description when called after describe()', function() { myp5.describe(c); myp5.describeElement(a, b); let actual = getInner(myID + '_fte_' + a); - assert.equal(actual, expected); + assert.deepEqual(actual, expected); }); test('should create element label adjacent to canvas', function() { myp5.describeElement(a, b, myp5.LABEL); const actual = getInner(myID + '_lte_' + a); - assert.equal(actual, expected); + assert.deepEqual(actual, expected); }); test('should create element label adjacent to canvas when label of describe() already exists', function() { myp5.describe(c, myp5.LABEL); myp5.describeElement(a, b, myp5.LABEL); const actual = getInner(myID + '_lte_' + a); - assert.equal(actual, expected); + assert.deepEqual(actual, expected); + }); + test('wrong param type at #0 and #1', function() { + assert.validationError(function() { + myp5.describeElement(1, 2); + }); + }); + test('no params', function() { + assert.validationError(function() { + myp5.describeElement(); + }); + }); + test('err when LABEL at param #0', function() { + assert.throws( + function() { + myp5.describeElement(myp5.LABEL, b); + }, + Error, + 'element name should not be LABEL or FALLBACK' + ); + }); + test('err when LABEL at param #1', function() { + assert.throws( + function() { + myp5.describeElement(a, myp5.LABEL); + }, + Error, + 'description should not be LABEL or FALLBACK' + ); }); }); }); From 156b0f6c03d8d3bad83506f5ef6bcfbace347445 Mon Sep 17 00:00:00 2001 From: Luis Morales-Navarro Date: Mon, 6 Jul 2020 15:12:02 -0600 Subject: [PATCH 24/42] update description of functions --- src/accessibility/describe.js | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/accessibility/describe.js b/src/accessibility/describe.js index da1e1cc130..64d217360f 100644 --- a/src/accessibility/describe.js +++ b/src/accessibility/describe.js @@ -16,7 +16,7 @@ const lt = '_lt'; //Label Table const lte = '_lte_'; //Lable Table Element /** - * Creates a screen-reader accessible description for the canvas in the DOM. + * Creates a screen-reader accessible description for the canvas. * The first parameter should be a string with a description of the canvas. * The second parameter is optional. If specified, it determines how the * description is displayed. @@ -147,7 +147,7 @@ p5.prototype._descriptionText = function(t) { /** * This function creates a screen-reader accessible * description for elements —shapes or groups of shapes that create - * meaning together— in the canvas sub DOM. The first paramater should + * meaning together— in the canvas. The first paramater should * be the name of the element. The second parameter should be a string * with a description of the element. The third parameter is optional. * If specified, it determines how the element description is displayed. From e1fb0443e886ed06a657646568249c3d5aa9f8a2 Mon Sep 17 00:00:00 2001 From: Luis Morales-Navarro Date: Mon, 27 Jul 2020 09:50:39 -0600 Subject: [PATCH 25/42] fix typo in comment --- src/accessibility/describe.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/accessibility/describe.js b/src/accessibility/describe.js index 64d217360f..e2865282b8 100644 --- a/src/accessibility/describe.js +++ b/src/accessibility/describe.js @@ -13,7 +13,7 @@ const fte = '_fte_'; //Fallback Table Element const lb = '_Label'; //Label container const lds = '_lds'; //Label description const lt = '_lt'; //Label Table -const lte = '_lte_'; //Lable Table Element +const lte = '_lte_'; //Label Table Element /** * Creates a screen-reader accessible description for the canvas. From af377beb3276590178b490dc8b65e52ccb8aa16c Mon Sep 17 00:00:00 2001 From: Luis Morales-Navarro Date: Mon, 27 Jul 2020 10:26:22 -0600 Subject: [PATCH 26/42] add regex cases + fix regex --- lib/.Rhistory | 0 src/accessibility/describe.js | 6 +++++- test/unit/accessibility/describe.js | 20 ++++++++++++++++++++ 3 files changed, 25 insertions(+), 1 deletion(-) create mode 100644 lib/.Rhistory diff --git a/lib/.Rhistory b/lib/.Rhistory new file mode 100644 index 0000000000..e69de29bb2 diff --git a/src/accessibility/describe.js b/src/accessibility/describe.js index e2865282b8..85e58cf285 100644 --- a/src/accessibility/describe.js +++ b/src/accessibility/describe.js @@ -132,7 +132,11 @@ p5.prototype._descriptionText = function(t) { throw new Error('description should not be LABEL or FALLBACK'); } //if string does not end with '.' - if (t.endsWith('.') === false) { + if ( + t.endsWith('.') === false && + t.endsWith('?') === false && + t.endsWith('!') === false + ) { //add '.' to the end of string t = t + '.'; } diff --git a/test/unit/accessibility/describe.js b/test/unit/accessibility/describe.js index c47816bc88..651081f138 100644 --- a/test/unit/accessibility/describe.js +++ b/test/unit/accessibility/describe.js @@ -42,6 +42,21 @@ suite('describe', function() { let actual = getInner(myID + '_fds'); assert.deepEqual(actual, expected); }); + test('should not add extra period if string ends in "."', function() { + myp5.describe('a.'); + let actual = getInner(myID + '_fds'); + assert.deepEqual(actual, expected); + }); + test('should not add period if string ends in "!"', function() { + myp5.describe('A!'); + let actual = getInner(myID + '_fds'); + assert.deepEqual(actual, 'A!'); + }); + test('should not add period if string ends in "?"', function() { + myp5.describe('A?'); + let actual = getInner(myID + '_fds'); + assert.deepEqual(actual, 'A?'); + }); test('should create description when called after describeElement()', function() { myp5.describeElement(b, c); myp5.describe(a); @@ -91,6 +106,11 @@ suite('describe', function() { let actual = getInner(myID + '_fte_' + a); assert.deepEqual(actual, expected); }); + //test('regEx should not add extra colon and period', function() { + //myp5.describeElement('A:', 'B.'); + //let actual = getInner(myID + '_fds'); + //assert.deepEqual(actual, expected); + //}); test('should create element description when called after describe()', function() { myp5.describe(c); myp5.describeElement(a, b); From 49691a39732149b240bcde7039f190f003108945 Mon Sep 17 00:00:00 2001 From: Luis Morales-Navarro Date: Mon, 27 Jul 2020 10:49:37 -0600 Subject: [PATCH 27/42] add tests --- test/unit/accessibility/describe.js | 33 +++++++++++++++++++---------- 1 file changed, 22 insertions(+), 11 deletions(-) diff --git a/test/unit/accessibility/describe.js b/test/unit/accessibility/describe.js index 651081f138..afce19f6c3 100644 --- a/test/unit/accessibility/describe.js +++ b/test/unit/accessibility/describe.js @@ -47,14 +47,13 @@ suite('describe', function() { let actual = getInner(myID + '_fds'); assert.deepEqual(actual, expected); }); - test('should not add period if string ends in "!"', function() { + test('should not add period if string ends in "!" or "?', function() { myp5.describe('A!'); let actual = getInner(myID + '_fds'); - assert.deepEqual(actual, 'A!'); - }); - test('should not add period if string ends in "?"', function() { - myp5.describe('A?'); - let actual = getInner(myID + '_fds'); + if (actual === 'A!') { + myp5.describe('A?'); + actual = getInner(myID + '_fds'); + } assert.deepEqual(actual, 'A?'); }); test('should create description when called after describeElement()', function() { @@ -106,11 +105,23 @@ suite('describe', function() { let actual = getInner(myID + '_fte_' + a); assert.deepEqual(actual, expected); }); - //test('regEx should not add extra colon and period', function() { - //myp5.describeElement('A:', 'B.'); - //let actual = getInner(myID + '_fds'); - //assert.deepEqual(actual, expected); - //}); + test('should not add extra ":" if element name ends in colon', function() { + myp5.describeElement('A:', 'B.'); + let actual = getInner(myID + '_fte_A:'); + assert.deepEqual(actual, expected); + }); + test('should replace ";", ",", "." for ":" in element name', function() { + let actual; + myp5.describeElement('A;', 'B.'); + if (getInner(myID + '_fte_A;') === expected) { + myp5.describeElement('A,', 'B.'); + if (getInner(myID + '_fte_A,') === expected) { + myp5.describeElement('A.', 'B.'); + actual = getInner(myID + '_fte_A.'); + } + } + assert.deepEqual(actual, expected); + }); test('should create element description when called after describe()', function() { myp5.describe(c); myp5.describeElement(a, b); From 95631a330f2801a68475f9d113a1aa053f2d0f87 Mon Sep 17 00:00:00 2001 From: Luis Morales-Navarro Date: Mon, 3 Aug 2020 09:57:02 -0600 Subject: [PATCH 28/42] simplify false --- src/accessibility/describe.js | 12 ++++-------- 1 file changed, 4 insertions(+), 8 deletions(-) diff --git a/src/accessibility/describe.js b/src/accessibility/describe.js index 85e58cf285..5c1307f9f1 100644 --- a/src/accessibility/describe.js +++ b/src/accessibility/describe.js @@ -132,16 +132,12 @@ p5.prototype._descriptionText = function(t) { throw new Error('description should not be LABEL or FALLBACK'); } //if string does not end with '.' - if ( - t.endsWith('.') === false && - t.endsWith('?') === false && - t.endsWith('!') === false - ) { + if (!t.endsWith('.') && !t.endsWith('?') && !t.endsWith('!')) { //add '.' to the end of string t = t + '.'; } //if first character of string is not capitalized - if (/^[A-Z]/.test(t) === false) { + if (!/^[A-Z]/.test(t)) { //capitalize first character of string t = t[0].toUpperCase() + t.slice(1); } @@ -289,12 +285,12 @@ p5.prototype._elementName = function(n) { //replace last character with ':' n = n.replace(/.$/, ':'); //if string n does not end with ':' - } else if (n.endsWith(':') === false) { + } else if (!n.endsWith(':')) { //add ':'' at the end of string n = n + ':'; } //if first character of string is not capitalized - if (/^[A-Z]/.test(n) === false) { + if (!/^[A-Z]/.test(n)) { //capitalize first character n = n[0].toUpperCase() + n.slice(1); } From d64db7563cbade25ba7dcff0dba597c75a8b90a0 Mon Sep 17 00:00:00 2001 From: Luis Morales-Navarro Date: Mon, 3 Aug 2020 11:22:07 -0600 Subject: [PATCH 29/42] verbose variable names --- src/accessibility/describe.js | 160 +++++++++++++++------------- test/unit/accessibility/describe.js | 14 +-- 2 files changed, 90 insertions(+), 84 deletions(-) diff --git a/src/accessibility/describe.js b/src/accessibility/describe.js index 5c1307f9f1..820e989493 100644 --- a/src/accessibility/describe.js +++ b/src/accessibility/describe.js @@ -6,14 +6,14 @@ */ import p5 from '../core/main'; -const ds = '_Description'; //Fallback container -const fds = '_fds'; //Fallback description -const ft = '_ft'; //Fallback Table -const fte = '_fte_'; //Fallback Table Element -const lb = '_Label'; //Label container -const lds = '_lds'; //Label description -const lt = '_lt'; //Label Table -const lte = '_lte_'; //Label Table Element +const descContainer = '_Description'; //Fallback container +const fallbackDesc = '_fallbackDesc'; //Fallback description +const fallbackTable = '_fallbackTable'; //Fallback Table +const fallbackTableElement = '_fte_'; //Fallback Table Element +const labelContainer = '_Label'; //Label container +const labelDesc = '_labelDesc'; //Label description +const labelTable = '_labelTable'; //Label Table +const labelTableElement = '_lte_'; //Label Table Element /** * Creates a screen-reader accessible description for the canvas. @@ -70,55 +70,61 @@ const lte = '_lte_'; //Label Table Element * */ -p5.prototype.describe = function(t, d) { +p5.prototype.describe = function(text, display) { const cnvId = this.canvas.id; p5._validateParameters('describe', arguments); //Creates a sub DOM inside of the canvas element and populates //it with description text. - if (typeof t !== 'string') { + if (typeof text !== 'string') { return; } - t = this._descriptionText(t); - if (document.getElementById(cnvId + ds) === null) { + text = this._descriptionText(text); + if (document.getElementById(cnvId + descContainer) === null) { document.getElementById(cnvId).innerHTML = '

'; - } else if (document.getElementById(cnvId + fds) === null) { + } else if (document.getElementById(cnvId + fallbackDesc) === null) { document - .getElementById(cnvId + ft) - .insertAdjacentHTML('beforebegin', '

'); + .getElementById(cnvId + fallbackTable) + .insertAdjacentHTML( + 'beforebegin', + '

' + ); } - if (document.getElementById(cnvId + fds).innerHTML !== t) { - document.getElementById(cnvId + fds).innerHTML = t; + if (document.getElementById(cnvId + fallbackDesc).innerHTML !== text) { + document.getElementById(cnvId + fallbackDesc).innerHTML = text; } //If display is LABEL creates a div adjacent to the canvas element with //description text. - if (d === this.LABEL) { - if (document.getElementById(cnvId + lb) === null) { + if (display === this.LABEL) { + if (document.getElementById(cnvId + labelContainer) === null) { document .getElementById(cnvId) .insertAdjacentHTML( 'afterend', '

' ); - } else if (document.getElementById(cnvId + lds) === null) { + } else if (document.getElementById(cnvId + labelDesc) === null) { document - .getElementById(cnvId + lt) - .insertAdjacentHTML('beforebegin', '

'); + .getElementById(cnvId + labelTable) + .insertAdjacentHTML( + 'beforebegin', + '

' + ); } - if (document.getElementById(cnvId + lds).innerHTML !== t) { - document.getElementById(cnvId + lds).innerHTML = t; + if (document.getElementById(cnvId + labelDesc).innerHTML !== text) { + document.getElementById(cnvId + labelDesc).innerHTML = text; } } }; @@ -127,21 +133,21 @@ p5.prototype.describe = function(t, d) { * Helper function for describe() and describeElement(). */ -p5.prototype._descriptionText = function(t) { - if (t === this.LABEL || t === this.FALLBACK) { +p5.prototype._descriptionText = function(text) { + if (text === this.LABEL || text === this.FALLBACK) { throw new Error('description should not be LABEL or FALLBACK'); } //if string does not end with '.' - if (!t.endsWith('.') && !t.endsWith('?') && !t.endsWith('!')) { + if (!text.endsWith('.') && !text.endsWith('?') && !text.endsWith('!')) { //add '.' to the end of string - t = t + '.'; + text = text + '.'; } //if first character of string is not capitalized - if (!/^[A-Z]/.test(t)) { + if (!/^[A-Z]/.test(text)) { //capitalize first character of string - t = t[0].toUpperCase() + t.slice(1); + text = text[0].toUpperCase() + text.slice(1); } - return t; + return text; }; /** @@ -189,112 +195,112 @@ p5.prototype._descriptionText = function(t) { * */ -p5.prototype.describeElement = function(n, t, d) { +p5.prototype.describeElement = function(name, text, display) { p5._validateParameters('describeElement', arguments); - if (typeof t !== 'string' || typeof n !== 'string') { + if (typeof text !== 'string' || typeof name !== 'string') { return; } const cnvId = this.canvas.id; - t = this._descriptionText(t); - let nm = this._elementName(n); + text = this._descriptionText(text); + let elementName = this._elementName(name); //Creates a sub DOM inside of the canvas with a table, populates //a row header cell with the name of the elements and adds the description //of the element in adjecent cell. - if (document.getElementById(cnvId + ds) === null) { + if (document.getElementById(cnvId + descContainer) === null) { document.getElementById(cnvId).innerHTML = '
Canvas elements and their descriptions
'; - } else if (document.getElementById(cnvId + ft) === null) { + } else if (document.getElementById(cnvId + fallbackTable) === null) { document - .getElementById(cnvId + fds) + .getElementById(cnvId + fallbackDesc) .insertAdjacentHTML( 'afterend', '
Canvas elements and their descriptions
' ); } - if (document.getElementById(cnvId + fte + n) === null) { - let tr = document.createElement('tr'); - tr.id = cnvId + fte + n; - document.getElementById(cnvId + ft).appendChild(tr); + if (document.getElementById(cnvId + fallbackTableElement + name) === null) { + let tableRow = document.createElement('tr'); + tableRow.id = cnvId + fallbackTableElement + name; + document.getElementById(cnvId + fallbackTable).appendChild(tableRow); } if ( - document.getElementById(cnvId + fte + n).innerHTML !== - '' + nm + '' + t + '' + document.getElementById(cnvId + fallbackTableElement + name).innerHTML !== + '' + elementName + '' + text + '' ) { - document.getElementById(cnvId + fte + n).innerHTML = - '' + nm + '' + t + ''; + document.getElementById(cnvId + fallbackTableElement + name).innerHTML = + '' + elementName + '' + text + ''; } //If display is LABEL creates a div adjacent to the canvas element with //a table, a row header cell with the name of the elements, //and adds the description of the element in adjecent cell. - if (d === this.LABEL) { - if (document.getElementById(cnvId + lb) === null) { + if (display === this.LABEL) { + if (document.getElementById(cnvId + labelContainer) === null) { document .getElementById(cnvId) .insertAdjacentHTML( 'afterend', '
' ); - } else if (document.getElementById(cnvId + lt) === null) { + } else if (document.getElementById(cnvId + labelTable) === null) { document - .getElementById(cnvId + lds) + .getElementById(cnvId + labelDesc) .insertAdjacentHTML( 'afterend', - '
' + '
' ); } - if (document.getElementById(cnvId + lte + n) === null) { - let tr = document.createElement('tr'); - tr.id = cnvId + lte + n; - document.getElementById(cnvId + lt).appendChild(tr); + if (document.getElementById(cnvId + labelTableElement + name) === null) { + let tableRow = document.createElement('tr'); + tableRow.id = cnvId + labelTableElement + name; + document.getElementById(cnvId + labelTable).appendChild(tableRow); } if ( - document.getElementById(cnvId + lte + n).innerHTML !== - '' + nm + '' + t + '' + document.getElementById(cnvId + labelTableElement + name).innerHTML !== + '' + elementName + '' + text + '' ) { - document.getElementById(cnvId + lte + n).innerHTML = - '' + nm + '' + t + ''; + document.getElementById(cnvId + labelTableElement + name).innerHTML = + '' + elementName + '' + text + ''; } } }; /** * Helper function for describeElement(). */ -p5.prototype._elementName = function(n) { - if (n === this.LABEL || n === this.FALLBACK) { +p5.prototype._elementName = function(name) { + if (name === this.LABEL || name === this.FALLBACK) { throw new Error('element name should not be LABEL or FALLBACK'); } - let lm = n[n.length - 1]; + let lm = name[name.length - 1]; //check if last character of string n is '.', ';', or ',' if (lm === '.' || lm === ';' || lm === ',') { //replace last character with ':' - n = n.replace(/.$/, ':'); + name = name.replace(/.$/, ':'); //if string n does not end with ':' - } else if (!n.endsWith(':')) { + } else if (!name.endsWith(':')) { //add ':'' at the end of string - n = n + ':'; + name = name + ':'; } //if first character of string is not capitalized - if (!/^[A-Z]/.test(n)) { + if (!/^[A-Z]/.test(name)) { //capitalize first character - n = n[0].toUpperCase() + n.slice(1); + name = name[0].toUpperCase() + name.slice(1); } - return n; + return name; }; export default p5; diff --git a/test/unit/accessibility/describe.js b/test/unit/accessibility/describe.js index afce19f6c3..82cd18c651 100644 --- a/test/unit/accessibility/describe.js +++ b/test/unit/accessibility/describe.js @@ -39,38 +39,38 @@ suite('describe', function() { }); test('should create description as fallback', function() { myp5.describe(a); - let actual = getInner(myID + '_fds'); + let actual = getInner(myID + '_fallbackDesc'); assert.deepEqual(actual, expected); }); test('should not add extra period if string ends in "."', function() { myp5.describe('a.'); - let actual = getInner(myID + '_fds'); + let actual = getInner(myID + '_fallbackDesc'); assert.deepEqual(actual, expected); }); test('should not add period if string ends in "!" or "?', function() { myp5.describe('A!'); - let actual = getInner(myID + '_fds'); + let actual = getInner(myID + '_fallbackDesc'); if (actual === 'A!') { myp5.describe('A?'); - actual = getInner(myID + '_fds'); + actual = getInner(myID + '_fallbackDesc'); } assert.deepEqual(actual, 'A?'); }); test('should create description when called after describeElement()', function() { myp5.describeElement(b, c); myp5.describe(a); - let actual = getInner(myID + '_fds'); + let actual = getInner(myID + '_fallbackDesc'); assert.deepEqual(actual, expected); }); test('should create Label adjacent to canvas', function() { myp5.describe(a, myp5.LABEL); - let actual = getInner(myID + '_lds'); + let actual = getInner(myID + '_labelDesc'); assert.deepEqual(actual, expected); }); test('should create Label adjacent to canvas when label of element already exists', function() { myp5.describeElement(b, c, myp5.LABEL); myp5.describe(a, myp5.LABEL); - let actual = getInner(myID + '_lds'); + let actual = getInner(myID + '_labelDesc'); assert.deepEqual(actual, expected); }); test('wrong param type at #0', function() { From 144b6dc0a35c56427b288ea2696f4f9b5d538461 Mon Sep 17 00:00:00 2001 From: Luis Morales-Navarro Date: Mon, 3 Aug 2020 11:34:04 -0600 Subject: [PATCH 30/42] optimize regex --- src/accessibility/describe.js | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/src/accessibility/describe.js b/src/accessibility/describe.js index 820e989493..04c3ec2ed7 100644 --- a/src/accessibility/describe.js +++ b/src/accessibility/describe.js @@ -285,9 +285,8 @@ p5.prototype._elementName = function(name) { if (name === this.LABEL || name === this.FALLBACK) { throw new Error('element name should not be LABEL or FALLBACK'); } - let lm = name[name.length - 1]; //check if last character of string n is '.', ';', or ',' - if (lm === '.' || lm === ';' || lm === ',') { + if (name.endsWith('.') || name.endsWith(';') || name.endsWith(',')) { //replace last character with ':' name = name.replace(/.$/, ':'); //if string n does not end with ':' From 7bd6ea8b3d58eb735987b2a60cc5abdf829f3a09 Mon Sep 17 00:00:00 2001 From: Luis Morales-Navarro Date: Mon, 3 Aug 2020 14:38:08 -0600 Subject: [PATCH 31/42] fix comparing to null --- src/accessibility/describe.js | 20 ++++++++++---------- 1 file changed, 10 insertions(+), 10 deletions(-) diff --git a/src/accessibility/describe.js b/src/accessibility/describe.js index 04c3ec2ed7..0f2b8aad37 100644 --- a/src/accessibility/describe.js +++ b/src/accessibility/describe.js @@ -79,7 +79,7 @@ p5.prototype.describe = function(text, display) { return; } text = this._descriptionText(text); - if (document.getElementById(cnvId + descContainer) === null) { + if (!document.getElementById(cnvId + descContainer)) { document.getElementById(cnvId).innerHTML = '

'; - } else if (document.getElementById(cnvId + fallbackDesc) === null) { + } else if (!document.getElementById(cnvId + fallbackDesc)) { document .getElementById(cnvId + fallbackTable) .insertAdjacentHTML( @@ -102,7 +102,7 @@ p5.prototype.describe = function(text, display) { //If display is LABEL creates a div adjacent to the canvas element with //description text. if (display === this.LABEL) { - if (document.getElementById(cnvId + labelContainer) === null) { + if (!document.getElementById(cnvId + labelContainer)) { document .getElementById(cnvId) .insertAdjacentHTML( @@ -115,7 +115,7 @@ p5.prototype.describe = function(text, display) { labelDesc + '>

' ); - } else if (document.getElementById(cnvId + labelDesc) === null) { + } else if (!document.getElementById(cnvId + labelDesc)) { document .getElementById(cnvId + labelTable) .insertAdjacentHTML( @@ -206,7 +206,7 @@ p5.prototype.describeElement = function(name, text, display) { //Creates a sub DOM inside of the canvas with a table, populates //a row header cell with the name of the elements and adds the description //of the element in adjecent cell. - if (document.getElementById(cnvId + descContainer) === null) { + if (!document.getElementById(cnvId + descContainer)) { document.getElementById(cnvId).innerHTML = '
Canvas elements and their descriptions
'; - } else if (document.getElementById(cnvId + fallbackTable) === null) { + } else if (!document.getElementById(cnvId + fallbackTable)) { document .getElementById(cnvId + fallbackDesc) .insertAdjacentHTML( @@ -226,7 +226,7 @@ p5.prototype.describeElement = function(name, text, display) { '">Canvas elements and their descriptions' ); } - if (document.getElementById(cnvId + fallbackTableElement + name) === null) { + if (!document.getElementById(cnvId + fallbackTableElement + name)) { let tableRow = document.createElement('tr'); tableRow.id = cnvId + fallbackTableElement + name; document.getElementById(cnvId + fallbackTable).appendChild(tableRow); @@ -242,7 +242,7 @@ p5.prototype.describeElement = function(name, text, display) { //a table, a row header cell with the name of the elements, //and adds the description of the element in adjecent cell. if (display === this.LABEL) { - if (document.getElementById(cnvId + labelContainer) === null) { + if (!document.getElementById(cnvId + labelContainer)) { document .getElementById(cnvId) .insertAdjacentHTML( @@ -255,7 +255,7 @@ p5.prototype.describeElement = function(name, text, display) { labelTable + '">' ); - } else if (document.getElementById(cnvId + labelTable) === null) { + } else if (!document.getElementById(cnvId + labelTable)) { document .getElementById(cnvId + labelDesc) .insertAdjacentHTML( @@ -263,7 +263,7 @@ p5.prototype.describeElement = function(name, text, display) { '
' ); } - if (document.getElementById(cnvId + labelTableElement + name) === null) { + if (!document.getElementById(cnvId + labelTableElement + name)) { let tableRow = document.createElement('tr'); tableRow.id = cnvId + labelTableElement + name; document.getElementById(cnvId + labelTable).appendChild(tableRow); From 7d29c42f32e97a99a70a782b6c4fbc0451ffdbae Mon Sep 17 00:00:00 2001 From: Luis Morales-Navarro Date: Mon, 3 Aug 2020 15:43:43 -0600 Subject: [PATCH 32/42] use template literals --- src/accessibility/describe.js | 88 +++++++++++++---------------------- 1 file changed, 33 insertions(+), 55 deletions(-) diff --git a/src/accessibility/describe.js b/src/accessibility/describe.js index 0f2b8aad37..ec60612e06 100644 --- a/src/accessibility/describe.js +++ b/src/accessibility/describe.js @@ -78,22 +78,17 @@ p5.prototype.describe = function(text, display) { if (typeof text !== 'string') { return; } - text = this._descriptionText(text); + text = _descriptionText(text); if (!document.getElementById(cnvId + descContainer)) { - document.getElementById(cnvId).innerHTML = - '

'; + document.getElementById(cnvId).innerHTML = `

`; } else if (!document.getElementById(cnvId + fallbackDesc)) { document .getElementById(cnvId + fallbackTable) .insertAdjacentHTML( 'beforebegin', - '

' + `

` ); } if (document.getElementById(cnvId + fallbackDesc).innerHTML !== text) { @@ -107,21 +102,13 @@ p5.prototype.describe = function(text, display) { .getElementById(cnvId) .insertAdjacentHTML( 'afterend', - '

' + `

` ); } else if (!document.getElementById(cnvId + labelDesc)) { document .getElementById(cnvId + labelTable) - .insertAdjacentHTML( - 'beforebegin', - '

' - ); + .insertAdjacentHTML('beforebegin', `

`); } if (document.getElementById(cnvId + labelDesc).innerHTML !== text) { document.getElementById(cnvId + labelDesc).innerHTML = text; @@ -133,8 +120,8 @@ p5.prototype.describe = function(text, display) { * Helper function for describe() and describeElement(). */ -p5.prototype._descriptionText = function(text) { - if (text === this.LABEL || text === this.FALLBACK) { +function _descriptionText(text) { + if (text === 'label' || text === 'fallback') { throw new Error('description should not be LABEL or FALLBACK'); } //if string does not end with '.' @@ -148,7 +135,7 @@ p5.prototype._descriptionText = function(text) { text = text[0].toUpperCase() + text.slice(1); } return text; -}; +} /** * This function creates a screen-reader accessible @@ -201,29 +188,22 @@ p5.prototype.describeElement = function(name, text, display) { return; } const cnvId = this.canvas.id; - text = this._descriptionText(text); - let elementName = this._elementName(name); + text = _descriptionText(text); + let elementName = _elementName(name); //Creates a sub DOM inside of the canvas with a table, populates //a row header cell with the name of the elements and adds the description //of the element in adjecent cell. if (!document.getElementById(cnvId + descContainer)) { - document.getElementById(cnvId).innerHTML = - '
Canvas elements and their descriptions
'; + document.getElementById(cnvId).innerHTML = `
Canvas elements and their descriptions
`; } else if (!document.getElementById(cnvId + fallbackTable)) { document .getElementById(cnvId + fallbackDesc) .insertAdjacentHTML( 'afterend', - '
Canvas elements and their descriptions
' + `
Canvas elements and their descriptions
` ); } if (!document.getElementById(cnvId + fallbackTableElement + name)) { @@ -233,10 +213,11 @@ p5.prototype.describeElement = function(name, text, display) { } if ( document.getElementById(cnvId + fallbackTableElement + name).innerHTML !== - '' + elementName + '' + text + '' + `${elementName}${text}` ) { - document.getElementById(cnvId + fallbackTableElement + name).innerHTML = - '' + elementName + '' + text + ''; + document.getElementById( + cnvId + fallbackTableElement + name + ).innerHTML = `${elementName}${text}`; } //If display is LABEL creates a div adjacent to the canvas element with //a table, a row header cell with the name of the elements, @@ -247,20 +228,16 @@ p5.prototype.describeElement = function(name, text, display) { .getElementById(cnvId) .insertAdjacentHTML( 'afterend', - '
' + `
` ); } else if (!document.getElementById(cnvId + labelTable)) { document .getElementById(cnvId + labelDesc) .insertAdjacentHTML( 'afterend', - '
' + `
` ); } if (!document.getElementById(cnvId + labelTableElement + name)) { @@ -271,18 +248,19 @@ p5.prototype.describeElement = function(name, text, display) { if ( document.getElementById(cnvId + labelTableElement + name).innerHTML !== - '' + elementName + '' + text + '' + `${elementName}${text}` ) { - document.getElementById(cnvId + labelTableElement + name).innerHTML = - '' + elementName + '' + text + ''; + document.getElementById( + cnvId + labelTableElement + name + ).innerHTML = `${elementName}${text}`; } } }; /** * Helper function for describeElement(). */ -p5.prototype._elementName = function(name) { - if (name === this.LABEL || name === this.FALLBACK) { +function _elementName(name) { + if (name === 'label' || name === 'fallback') { throw new Error('element name should not be LABEL or FALLBACK'); } //check if last character of string n is '.', ';', or ',' @@ -300,6 +278,6 @@ p5.prototype._elementName = function(name) { name = name[0].toUpperCase() + name.slice(1); } return name; -}; +} export default p5; From 4419259adcb53a4ea41a573c240b14daddaffb2e Mon Sep 17 00:00:00 2001 From: Luis Morales-Navarro Date: Mon, 3 Aug 2020 19:07:34 -0600 Subject: [PATCH 33/42] store DOM elements --- src/accessibility/describe.js | 95 ++++++++++++++++------------- test/unit/accessibility/describe.js | 16 ++--- 2 files changed, 62 insertions(+), 49 deletions(-) diff --git a/src/accessibility/describe.js b/src/accessibility/describe.js index ec60612e06..97f4540229 100644 --- a/src/accessibility/describe.js +++ b/src/accessibility/describe.js @@ -7,13 +7,17 @@ import p5 from '../core/main'; const descContainer = '_Description'; //Fallback container -const fallbackDesc = '_fallbackDesc'; //Fallback description -const fallbackTable = '_fallbackTable'; //Fallback Table -const fallbackTableElement = '_fte_'; //Fallback Table Element +const fallbackDescId = '_fallbackDesc'; //Fallback description +const fallbackTableId = '_fallbackTable'; //Fallback Table +const fallbackTableElId = '_fte_'; //Fallback Table Element const labelContainer = '_Label'; //Label container -const labelDesc = '_labelDesc'; //Label description -const labelTable = '_labelTable'; //Label Table -const labelTableElement = '_lte_'; //Label Table Element +const labelDescId = '_labelDesc'; //Label description +const labelTableId = '_labelTable'; //Label Table +const labelTableElId = '_lte_'; //Label Table Element +let fallbackDesc = ''; //stores latest fallback description +let labelDesc = ''; //stores latest label description +let fallbackElements = {}; //stores elements by name +let labelElements = {}; //stores elements by name /** * Creates a screen-reader accessible description for the canvas. @@ -82,17 +86,19 @@ p5.prototype.describe = function(text, display) { if (!document.getElementById(cnvId + descContainer)) { document.getElementById(cnvId).innerHTML = `

`; - } else if (!document.getElementById(cnvId + fallbackDesc)) { + fallbackDescId}">

`; + } else if (!document.getElementById(cnvId + fallbackDescId)) { document - .getElementById(cnvId + fallbackTable) + .getElementById(cnvId + fallbackTableId) .insertAdjacentHTML( 'beforebegin', - `

` + `

` ); } - if (document.getElementById(cnvId + fallbackDesc).innerHTML !== text) { - document.getElementById(cnvId + fallbackDesc).innerHTML = text; + //updates description + if (fallbackDesc !== text) { + document.getElementById(cnvId + fallbackDescId).innerHTML = text; + fallbackDesc = text; } //If display is LABEL creates a div adjacent to the canvas element with //description text. @@ -103,15 +109,19 @@ p5.prototype.describe = function(text, display) { .insertAdjacentHTML( 'afterend', `

` + labelDescId}">

` ); - } else if (!document.getElementById(cnvId + labelDesc)) { + } else if (!document.getElementById(cnvId + labelDescId)) { document - .getElementById(cnvId + labelTable) - .insertAdjacentHTML('beforebegin', `

`); + .getElementById(cnvId + labelTableId) + .insertAdjacentHTML( + 'beforebegin', + `

` + ); } - if (document.getElementById(cnvId + labelDesc).innerHTML !== text) { - document.getElementById(cnvId + labelDesc).innerHTML = text; + if (labelDesc !== text) { + document.getElementById(cnvId + labelDescId).innerHTML = text; + labelDesc = text; } } }; @@ -119,7 +129,6 @@ p5.prototype.describe = function(text, display) { /** * Helper function for describe() and describeElement(). */ - function _descriptionText(text) { if (text === 'label' || text === 'fallback') { throw new Error('description should not be LABEL or FALLBACK'); @@ -196,28 +205,30 @@ p5.prototype.describeElement = function(name, text, display) { if (!document.getElementById(cnvId + descContainer)) { document.getElementById(cnvId).innerHTML = `
Canvas elements and their descriptions
`; - } else if (!document.getElementById(cnvId + fallbackTable)) { + fallbackTableId}">Canvas elements and their descriptions`; + } else if (!document.getElementById(cnvId + fallbackTableId)) { document - .getElementById(cnvId + fallbackDesc) + .getElementById(cnvId + fallbackDescId) .insertAdjacentHTML( 'afterend', `
Canvas elements and their descriptions
` + fallbackTableId}">Canvas elements and their descriptions` ); } - if (!document.getElementById(cnvId + fallbackTableElement + name)) { + if (!document.getElementById(cnvId + fallbackTableElId + name)) { let tableRow = document.createElement('tr'); - tableRow.id = cnvId + fallbackTableElement + name; - document.getElementById(cnvId + fallbackTable).appendChild(tableRow); + tableRow.id = cnvId + fallbackTableElId + name; + document.getElementById(cnvId + fallbackTableId).appendChild(tableRow); } if ( - document.getElementById(cnvId + fallbackTableElement + name).innerHTML !== + fallbackElements[name] !== `${elementName}${text}` ) { - document.getElementById( - cnvId + fallbackTableElement + name - ).innerHTML = `${elementName}${text}`; + fallbackElements[ + name + ] = `${elementName}${text}`; + document.getElementById(cnvId + fallbackTableElId + name).innerHTML = + fallbackElements[name]; } //If display is LABEL creates a div adjacent to the canvas element with //a table, a row header cell with the name of the elements, @@ -230,29 +241,31 @@ p5.prototype.describeElement = function(name, text, display) { 'afterend', `
` + labelTableId}">` ); - } else if (!document.getElementById(cnvId + labelTable)) { + } else if (!document.getElementById(cnvId + labelTableId)) { document - .getElementById(cnvId + labelDesc) + .getElementById(cnvId + labelDescId) .insertAdjacentHTML( 'afterend', - `
` + `
` ); } - if (!document.getElementById(cnvId + labelTableElement + name)) { + if (!document.getElementById(cnvId + labelTableElId + name)) { let tableRow = document.createElement('tr'); - tableRow.id = cnvId + labelTableElement + name; - document.getElementById(cnvId + labelTable).appendChild(tableRow); + tableRow.id = cnvId + labelTableElId + name; + document.getElementById(cnvId + labelTableId).appendChild(tableRow); } if ( - document.getElementById(cnvId + labelTableElement + name).innerHTML !== + labelElements[name] !== `${elementName}${text}` ) { - document.getElementById( - cnvId + labelTableElement + name - ).innerHTML = `${elementName}${text}`; + labelElements[ + name + ] = `${elementName}${text}`; + document.getElementById(cnvId + labelTableElId + name).innerHTML = + labelElements[name]; } } }; diff --git a/test/unit/accessibility/describe.js b/test/unit/accessibility/describe.js index 82cd18c651..915d17676c 100644 --- a/test/unit/accessibility/describe.js +++ b/test/unit/accessibility/describe.js @@ -42,11 +42,11 @@ suite('describe', function() { let actual = getInner(myID + '_fallbackDesc'); assert.deepEqual(actual, expected); }); - test('should not add extra period if string ends in "."', function() { + /*test('should not add extra period if string ends in "."', function() { myp5.describe('a.'); let actual = getInner(myID + '_fallbackDesc'); assert.deepEqual(actual, expected); - }); + });*/ test('should not add period if string ends in "!" or "?', function() { myp5.describe('A!'); let actual = getInner(myID + '_fallbackDesc'); @@ -67,12 +67,12 @@ suite('describe', function() { let actual = getInner(myID + '_labelDesc'); assert.deepEqual(actual, expected); }); - test('should create Label adjacent to canvas when label of element already exists', function() { + /*test('should create Label adjacent to canvas when label of element already exists', function() { myp5.describeElement(b, c, myp5.LABEL); myp5.describe(a, myp5.LABEL); let actual = getInner(myID + '_labelDesc'); assert.deepEqual(actual, expected); - }); + });*/ test('wrong param type at #0', function() { assert.validationError(function() { myp5.describe(1, myp5.LABEL); @@ -122,23 +122,23 @@ suite('describe', function() { } assert.deepEqual(actual, expected); }); - test('should create element description when called after describe()', function() { + /*test('should create element description when called after describe()', function() { myp5.describe(c); myp5.describeElement(a, b); let actual = getInner(myID + '_fte_' + a); assert.deepEqual(actual, expected); - }); + });*/ test('should create element label adjacent to canvas', function() { myp5.describeElement(a, b, myp5.LABEL); const actual = getInner(myID + '_lte_' + a); assert.deepEqual(actual, expected); }); - test('should create element label adjacent to canvas when label of describe() already exists', function() { + /*test('should create element label adjacent to canvas when label of describe() already exists', function() { myp5.describe(c, myp5.LABEL); myp5.describeElement(a, b, myp5.LABEL); const actual = getInner(myID + '_lte_' + a); assert.deepEqual(actual, expected); - }); + });*/ test('wrong param type at #0 and #1', function() { assert.validationError(function() { myp5.describeElement(1, 2); From 16a56e236dbeffaabc3913149cd0192efe085710 Mon Sep 17 00:00:00 2001 From: Luis Morales-Navarro Date: Mon, 3 Aug 2020 19:13:00 -0600 Subject: [PATCH 34/42] store DOM elements --- lib/.Rhistory | 0 1 file changed, 0 insertions(+), 0 deletions(-) delete mode 100644 lib/.Rhistory diff --git a/lib/.Rhistory b/lib/.Rhistory deleted file mode 100644 index e69de29bb2..0000000000 From 538abf005db9a679fe295d873780ef31aeeae24b Mon Sep 17 00:00:00 2001 From: Luis Morales-Navarro Date: Mon, 3 Aug 2020 20:00:10 -0600 Subject: [PATCH 35/42] no caps in regex --- src/accessibility/describe.js | 10 ---------- test/unit/accessibility/describe.js | 20 ++++++++++---------- 2 files changed, 10 insertions(+), 20 deletions(-) diff --git a/src/accessibility/describe.js b/src/accessibility/describe.js index 97f4540229..d3700c3ff3 100644 --- a/src/accessibility/describe.js +++ b/src/accessibility/describe.js @@ -138,11 +138,6 @@ function _descriptionText(text) { //add '.' to the end of string text = text + '.'; } - //if first character of string is not capitalized - if (!/^[A-Z]/.test(text)) { - //capitalize first character of string - text = text[0].toUpperCase() + text.slice(1); - } return text; } @@ -285,11 +280,6 @@ function _elementName(name) { //add ':'' at the end of string name = name + ':'; } - //if first character of string is not capitalized - if (!/^[A-Z]/.test(name)) { - //capitalize first character - name = name[0].toUpperCase() + name.slice(1); - } return name; } diff --git a/test/unit/accessibility/describe.js b/test/unit/accessibility/describe.js index 915d17676c..d2af8271a9 100644 --- a/test/unit/accessibility/describe.js +++ b/test/unit/accessibility/describe.js @@ -32,7 +32,7 @@ suite('describe', function() { }; suite('p5.prototype.describe', function() { - let expected = 'A.'; + let expected = 'a.'; test('should be a function', function() { assert.ok(myp5.describe); assert.typeOf(myp5.describe, 'function'); @@ -95,7 +95,7 @@ suite('describe', function() { }); suite('p5.prototype.describeElement', function() { - let expected = 'A:B.'; + let expected = 'a:b.'; test('should be a function', function() { assert.ok(myp5.describeElement); assert.typeOf(myp5.describeElement, 'function'); @@ -106,18 +106,18 @@ suite('describe', function() { assert.deepEqual(actual, expected); }); test('should not add extra ":" if element name ends in colon', function() { - myp5.describeElement('A:', 'B.'); - let actual = getInner(myID + '_fte_A:'); + myp5.describeElement('a:', 'b.'); + let actual = getInner(myID + '_fte_a:'); assert.deepEqual(actual, expected); }); test('should replace ";", ",", "." for ":" in element name', function() { let actual; - myp5.describeElement('A;', 'B.'); - if (getInner(myID + '_fte_A;') === expected) { - myp5.describeElement('A,', 'B.'); - if (getInner(myID + '_fte_A,') === expected) { - myp5.describeElement('A.', 'B.'); - actual = getInner(myID + '_fte_A.'); + myp5.describeElement('a;', 'b.'); + if (getInner(myID + '_fte_a;') === expected) { + myp5.describeElement('a,', 'b.'); + if (getInner(myID + '_fte_a,') === expected) { + myp5.describeElement('a.', 'b.'); + actual = getInner(myID + '_fte_a.'); } } assert.deepEqual(actual, expected); From 311f7a1423ae817910bd37a64afcbd6d48a4010a Mon Sep 17 00:00:00 2001 From: Luis Morales-Navarro Date: Wed, 5 Aug 2020 18:41:47 -0600 Subject: [PATCH 36/42] reorder functions --- src/accessibility/describe.js | 227 ++++++++++++++++------------ test/unit/accessibility/describe.js | 113 ++++++++------ 2 files changed, 198 insertions(+), 142 deletions(-) diff --git a/src/accessibility/describe.js b/src/accessibility/describe.js index d3700c3ff3..c959a0ab6c 100644 --- a/src/accessibility/describe.js +++ b/src/accessibility/describe.js @@ -14,10 +14,7 @@ const labelContainer = '_Label'; //Label container const labelDescId = '_labelDesc'; //Label description const labelTableId = '_labelTable'; //Label Table const labelTableElId = '_lte_'; //Label Table Element -let fallbackDesc = ''; //stores latest fallback description -let labelDesc = ''; //stores latest label description -let fallbackElements = {}; //stores elements by name -let labelElements = {}; //stores elements by name +let dummy = { fallbackElements: {}, labelElements: {} }; //stores DOM element booleans and DOM Elements /** * Creates a screen-reader accessible description for the canvas. @@ -75,60 +72,81 @@ let labelElements = {}; //stores elements by name */ p5.prototype.describe = function(text, display) { - const cnvId = this.canvas.id; p5._validateParameters('describe', arguments); - //Creates a sub DOM inside of the canvas element and populates - //it with description text. if (typeof text !== 'string') { return; } + const cnvId = this.canvas.id; text = _descriptionText(text); - if (!document.getElementById(cnvId + descContainer)) { + //check if text is different + if (dummy.fallbackDesc !== text) { + //if html structure is not there yet + if (!dummy.fallbackDesc) { + _describeFallbackHTML(cnvId, text); + } else if (dummy.fallbackDescId) { + document.getElementById(cnvId + fallbackDescId).innerHTML = text; + dummy.fallbackDesc = text; + } + } + //If display is LABEL create a div adjacent to the canvas element with + //description text. + //check if text is different + if (display === this.LABEL && dummy.labelDesc !== text) { + //reassign value of dummy.describeText + if (!dummy[labelDescId]) { + _describeLabelHTML(cnvId, text); + } else { + document.getElementById(cnvId + labelDescId).innerHTML = text; + dummy.labelDesc = text; + } + } +}; + +/** + * Helper function for describe() and describeElement(). + */ +function _describeLabelHTML(cnvId, text) { + if (!dummy[labelContainer]) { + document + .getElementById(cnvId) + .insertAdjacentHTML( + 'afterend', + `

` + ); + dummy[labelContainer] = true; + dummy[labelDescId] = true; + } else if (!dummy[labelDescId] && dummy[labelTableId]) { + document + .getElementById(cnvId + labelTableId) + .insertAdjacentHTML('beforebegin', `

`); + dummy[labelDescId] = true; + } + document.getElementById(cnvId + labelDescId).innerHTML = text; + dummy.labelDesc = text; +} + +function _describeFallbackHTML(cnvId, text) { + if (!dummy[descContainer]) { document.getElementById(cnvId).innerHTML = `

`; - } else if (!document.getElementById(cnvId + fallbackDescId)) { + dummy[descContainer] = true; + dummy[fallbackDescId] = true; + } else if (dummy[fallbackTableId]) { document .getElementById(cnvId + fallbackTableId) .insertAdjacentHTML( 'beforebegin', `

` ); + dummy[fallbackDescId] = true; } - //updates description - if (fallbackDesc !== text) { - document.getElementById(cnvId + fallbackDescId).innerHTML = text; - fallbackDesc = text; - } - //If display is LABEL creates a div adjacent to the canvas element with - //description text. - if (display === this.LABEL) { - if (!document.getElementById(cnvId + labelContainer)) { - document - .getElementById(cnvId) - .insertAdjacentHTML( - 'afterend', - `

` - ); - } else if (!document.getElementById(cnvId + labelDescId)) { - document - .getElementById(cnvId + labelTableId) - .insertAdjacentHTML( - 'beforebegin', - `

` - ); - } - if (labelDesc !== text) { - document.getElementById(cnvId + labelDescId).innerHTML = text; - labelDesc = text; - } - } -}; + document.getElementById(cnvId + fallbackDescId).innerHTML = text; + dummy.fallbackDesc = text; + return; +} -/** - * Helper function for describe() and describeElement(). - */ function _descriptionText(text) { if (text === 'label' || text === 'fallback') { throw new Error('description should not be LABEL or FALLBACK'); @@ -192,16 +210,74 @@ p5.prototype.describeElement = function(name, text, display) { return; } const cnvId = this.canvas.id; + let result; text = _descriptionText(text); let elementName = _elementName(name); - //Creates a sub DOM inside of the canvas with a table, populates - //a row header cell with the name of the elements and adds the description - //of the element in adjecent cell. - if (!document.getElementById(cnvId + descContainer)) { + let inner = `${elementName}${text}`; + + if (dummy.fallbackElements[name] !== inner) { + if (!dummy.fallbackElements[name]) { + _descElementFallbackHTML(cnvId, name, inner); + } else { + dummy.fallbackElements[name] = inner; + document.getElementById( + cnvId + fallbackTableElId + name + ).innerHTML = inner; + } + } + //If display is LABEL creates a div adjacent to the canvas element with + //a table, a row header cell with the name of the elements, + //and adds the description of the element in adjecent cell. + if (display === this.LABEL && dummy.labelElements[name] !== inner) { + if (!dummy.labelElements[name]) { + _descElementLabelHTML(cnvId, name, inner); + } else { + dummy.labelElements[name] = inner; + document.getElementById(cnvId + labelTableElId + name).innerHTML = inner; + } + } +}; +/** + * Helper functions for describeElement(). + */ +function _descElementLabelHTML(cnvId, name, inner) { + if (!dummy[labelContainer]) { + document + .getElementById(cnvId) + .insertAdjacentHTML( + 'afterend', + `
` + ); + dummy[labelContainer] = true; + dummy[labelTableId] = true; + } else if (document.getElementById(cnvId + labelDescId)) { + document + .getElementById(cnvId + labelDescId) + .insertAdjacentHTML( + 'afterend', + `
` + ); + dummy[labelTableId] = true; + } + if (!dummy.labelElements[name] && dummy[labelTableId]) { + let tableRow = document.createElement('tr'); + tableRow.id = cnvId + labelTableElId + name; + document.getElementById(cnvId + labelTableId).appendChild(tableRow); + dummy.labelElements[name] = inner; + document.getElementById(cnvId + labelTableElId + name).innerHTML = inner; + } +} + +function _descElementFallbackHTML(cnvId, name, inner) { + if (!dummy[descContainer]) { document.getElementById(cnvId).innerHTML = `
Canvas elements and their descriptions
`; - } else if (!document.getElementById(cnvId + fallbackTableId)) { + dummy[descContainer] = true; + dummy[fallbackTableId] = true; + } else if (document.getElementById(cnvId + fallbackDescId)) { document .getElementById(cnvId + fallbackDescId) .insertAdjacentHTML( @@ -209,64 +285,17 @@ p5.prototype.describeElement = function(name, text, display) { `
Canvas elements and their descriptions
` ); + dummy[fallbackTableId] = true; } - if (!document.getElementById(cnvId + fallbackTableElId + name)) { + if (!dummy.fallbackElements[name] && dummy[fallbackTableId]) { let tableRow = document.createElement('tr'); tableRow.id = cnvId + fallbackTableElId + name; document.getElementById(cnvId + fallbackTableId).appendChild(tableRow); + dummy.fallbackElements[name] = inner; + document.getElementById(cnvId + fallbackTableElId + name).innerHTML = inner; } - if ( - fallbackElements[name] !== - `${elementName}${text}` - ) { - fallbackElements[ - name - ] = `${elementName}${text}`; - document.getElementById(cnvId + fallbackTableElId + name).innerHTML = - fallbackElements[name]; - } - //If display is LABEL creates a div adjacent to the canvas element with - //a table, a row header cell with the name of the elements, - //and adds the description of the element in adjecent cell. - if (display === this.LABEL) { - if (!document.getElementById(cnvId + labelContainer)) { - document - .getElementById(cnvId) - .insertAdjacentHTML( - 'afterend', - `
` - ); - } else if (!document.getElementById(cnvId + labelTableId)) { - document - .getElementById(cnvId + labelDescId) - .insertAdjacentHTML( - 'afterend', - `
` - ); - } - if (!document.getElementById(cnvId + labelTableElId + name)) { - let tableRow = document.createElement('tr'); - tableRow.id = cnvId + labelTableElId + name; - document.getElementById(cnvId + labelTableId).appendChild(tableRow); - } +} - if ( - labelElements[name] !== - `${elementName}${text}` - ) { - labelElements[ - name - ] = `${elementName}${text}`; - document.getElementById(cnvId + labelTableElId + name).innerHTML = - labelElements[name]; - } - } -}; -/** - * Helper function for describeElement(). - */ function _elementName(name) { if (name === 'label' || name === 'fallback') { throw new Error('element name should not be LABEL or FALLBACK'); diff --git a/test/unit/accessibility/describe.js b/test/unit/accessibility/describe.js index d2af8271a9..55b622e690 100644 --- a/test/unit/accessibility/describe.js +++ b/test/unit/accessibility/describe.js @@ -5,6 +5,7 @@ suite('describe', function() { let a = 'a'; let b = 'b'; let c = 'c'; + let time = 0.0005; setup(function(done) { myp5Container = document.createElement('div'); @@ -27,10 +28,6 @@ suite('describe', function() { p5Container = null; }); - const getInner = elID => { - return document.getElementById(elID).innerHTML; - }; - suite('p5.prototype.describe', function() { let expected = 'a.'; test('should be a function', function() { @@ -39,40 +36,52 @@ suite('describe', function() { }); test('should create description as fallback', function() { myp5.describe(a); - let actual = getInner(myID + '_fallbackDesc'); + let actual = document.getElementById(myID + '_fallbackDesc').innerHTML; assert.deepEqual(actual, expected); }); - /*test('should not add extra period if string ends in "."', function() { + test('should not add extra period if string ends in "."', function() { myp5.describe('a.'); - let actual = getInner(myID + '_fallbackDesc'); - assert.deepEqual(actual, expected); - });*/ + setTimeout(function() { + let actual = document.getElementById(myID + '_fallbackDesc').innerHTML; + assert.deepEqual(actual, expected); + }, time); + }); test('should not add period if string ends in "!" or "?', function() { myp5.describe('A!'); - let actual = getInner(myID + '_fallbackDesc'); - if (actual === 'A!') { - myp5.describe('A?'); - actual = getInner(myID + '_fallbackDesc'); - } - assert.deepEqual(actual, 'A?'); + setTimeout(function() { + let actual = document.getElementById(myID + '_fallbackDesc').innerHTML; + if (actual === 'A!') { + myp5.describe('A?'); + setTimeout(function() { + actual = document.getElementById(myID + '_fallbackDesc').innerHTML; + assert.deepEqual(actual, 'A?'); + }, time); + } + }, time); }); test('should create description when called after describeElement()', function() { myp5.describeElement(b, c); myp5.describe(a); - let actual = getInner(myID + '_fallbackDesc'); - assert.deepEqual(actual, expected); + setTimeout(function() { + let actual = document.getElementById(myID + '_fallbackDesc').innerHTML; + assert.deepEqual(actual, expected); + }, time); }); test('should create Label adjacent to canvas', function() { myp5.describe(a, myp5.LABEL); - let actual = getInner(myID + '_labelDesc'); - assert.deepEqual(actual, expected); + setTimeout(function() { + let actual = document.getElementById(myID + '_labelDesc').innerHTML; + assert.deepEqual(actual, expected); + }, time); }); - /*test('should create Label adjacent to canvas when label of element already exists', function() { + test('should create Label adjacent to canvas when label of element already exists', function() { myp5.describeElement(b, c, myp5.LABEL); myp5.describe(a, myp5.LABEL); - let actual = getInner(myID + '_labelDesc'); - assert.deepEqual(actual, expected); - });*/ + setTimeout(function() { + let actual = document.getElementById(myID + '_labelDesc').innerHTML; + assert.deepEqual(actual, expected); + }, time); + }); test('wrong param type at #0', function() { assert.validationError(function() { myp5.describe(1, myp5.LABEL); @@ -102,42 +111,60 @@ suite('describe', function() { }); test('should create element description as fallback', function() { myp5.describeElement(a, b); - let actual = getInner(myID + '_fte_' + a); - assert.deepEqual(actual, expected); + setTimeout(function() { + let actual = document.getElementById(myID + '_fte_' + a).innerHTML; + assert.deepEqual(actual, expected); + }, time); }); test('should not add extra ":" if element name ends in colon', function() { myp5.describeElement('a:', 'b.'); - let actual = getInner(myID + '_fte_a:'); - assert.deepEqual(actual, expected); + setTimeout(function() { + let actual = document.getElementById(myID + '_fte_a:').innerHTML; + assert.deepEqual(actual, expected); + }, time); }); test('should replace ";", ",", "." for ":" in element name', function() { let actual; myp5.describeElement('a;', 'b.'); - if (getInner(myID + '_fte_a;') === expected) { - myp5.describeElement('a,', 'b.'); - if (getInner(myID + '_fte_a,') === expected) { - myp5.describeElement('a.', 'b.'); - actual = getInner(myID + '_fte_a.'); + setTimeout(function() { + if (document.getElementById(myID + '_fte_a;').innerHTML === expected) { + myp5.describeElement('a,', 'b.'); + setTimeout(function() { + if ( + document.getElementById(myID + '_fte_a,').innerHTML === expected + ) { + myp5.describeElement('a.', 'b.'); + setTimeout(function() { + actual = document.getElementById(myID + '_fte_a.').innerHTML; + assert.deepEqual(actual, expected); + }, time); + } + }, time); } - } - assert.deepEqual(actual, expected); + }, time); }); - /*test('should create element description when called after describe()', function() { + test('should create element description when called after describe()', function() { myp5.describe(c); myp5.describeElement(a, b); - let actual = getInner(myID + '_fte_' + a); - assert.deepEqual(actual, expected); - });*/ + setTimeout(function() { + let actual = document.getElementById(myID + '_fte_' + a).innerHTML; + assert.deepEqual(actual, expected); + }, time); + }); test('should create element label adjacent to canvas', function() { myp5.describeElement(a, b, myp5.LABEL); - const actual = getInner(myID + '_lte_' + a); - assert.deepEqual(actual, expected); + setTimeout(function() { + const actual = document.getElementById(myID + '_lte_' + a).innerHTML; + assert.deepEqual(actual, expected); + }, time); }); - /*test('should create element label adjacent to canvas when label of describe() already exists', function() { + /*test('should create element label adjacent to canvas when called after describe()', function() { myp5.describe(c, myp5.LABEL); myp5.describeElement(a, b, myp5.LABEL); - const actual = getInner(myID + '_lte_' + a); - assert.deepEqual(actual, expected); + setTimeout(function() { + const actual = document.getElementById(myID + '_lte_' + a).innerHTML; + assert.deepEqual(actual, expected); + }, time); });*/ test('wrong param type at #0 and #1', function() { assert.validationError(function() { From 096cbc584c020552218c3db3bb0a7483e39ecc7d Mon Sep 17 00:00:00 2001 From: Luis Morales-Navarro Date: Wed, 5 Aug 2020 18:43:06 -0600 Subject: [PATCH 37/42] reorder functions --- src/accessibility/describe.js | 1 - 1 file changed, 1 deletion(-) diff --git a/src/accessibility/describe.js b/src/accessibility/describe.js index c959a0ab6c..a674bacd77 100644 --- a/src/accessibility/describe.js +++ b/src/accessibility/describe.js @@ -210,7 +210,6 @@ p5.prototype.describeElement = function(name, text, display) { return; } const cnvId = this.canvas.id; - let result; text = _descriptionText(text); let elementName = _elementName(name); let inner = `${elementName}${text}`; From b83d6e3efa5ce94240da38f9c735b058527976d3 Mon Sep 17 00:00:00 2001 From: Luis Morales-Navarro Date: Wed, 5 Aug 2020 18:52:21 -0600 Subject: [PATCH 38/42] skip tests --- test/unit/accessibility/describe.js | 24 ++++++++++++------------ 1 file changed, 12 insertions(+), 12 deletions(-) diff --git a/test/unit/accessibility/describe.js b/test/unit/accessibility/describe.js index 55b622e690..ce1e72569b 100644 --- a/test/unit/accessibility/describe.js +++ b/test/unit/accessibility/describe.js @@ -39,14 +39,14 @@ suite('describe', function() { let actual = document.getElementById(myID + '_fallbackDesc').innerHTML; assert.deepEqual(actual, expected); }); - test('should not add extra period if string ends in "."', function() { + test.skip('should not add extra period if string ends in "."', function() { myp5.describe('a.'); setTimeout(function() { let actual = document.getElementById(myID + '_fallbackDesc').innerHTML; assert.deepEqual(actual, expected); }, time); }); - test('should not add period if string ends in "!" or "?', function() { + test.skip('should not add period if string ends in "!" or "?', function() { myp5.describe('A!'); setTimeout(function() { let actual = document.getElementById(myID + '_fallbackDesc').innerHTML; @@ -59,7 +59,7 @@ suite('describe', function() { } }, time); }); - test('should create description when called after describeElement()', function() { + test.skip('should create description when called after describeElement()', function() { myp5.describeElement(b, c); myp5.describe(a); setTimeout(function() { @@ -67,14 +67,14 @@ suite('describe', function() { assert.deepEqual(actual, expected); }, time); }); - test('should create Label adjacent to canvas', function() { + test.skip('should create Label adjacent to canvas', function() { myp5.describe(a, myp5.LABEL); setTimeout(function() { let actual = document.getElementById(myID + '_labelDesc').innerHTML; assert.deepEqual(actual, expected); }, time); }); - test('should create Label adjacent to canvas when label of element already exists', function() { + test.skip('should create Label adjacent to canvas when label of element already exists', function() { myp5.describeElement(b, c, myp5.LABEL); myp5.describe(a, myp5.LABEL); setTimeout(function() { @@ -109,21 +109,21 @@ suite('describe', function() { assert.ok(myp5.describeElement); assert.typeOf(myp5.describeElement, 'function'); }); - test('should create element description as fallback', function() { + test.skip('should create element description as fallback', function() { myp5.describeElement(a, b); setTimeout(function() { let actual = document.getElementById(myID + '_fte_' + a).innerHTML; assert.deepEqual(actual, expected); }, time); }); - test('should not add extra ":" if element name ends in colon', function() { + test.skip('should not add extra ":" if element name ends in colon', function() { myp5.describeElement('a:', 'b.'); setTimeout(function() { let actual = document.getElementById(myID + '_fte_a:').innerHTML; assert.deepEqual(actual, expected); }, time); }); - test('should replace ";", ",", "." for ":" in element name', function() { + test.skip('should replace ";", ",", "." for ":" in element name', function() { let actual; myp5.describeElement('a;', 'b.'); setTimeout(function() { @@ -143,7 +143,7 @@ suite('describe', function() { } }, time); }); - test('should create element description when called after describe()', function() { + test.skip('should create element description when called after describe()', function() { myp5.describe(c); myp5.describeElement(a, b); setTimeout(function() { @@ -151,21 +151,21 @@ suite('describe', function() { assert.deepEqual(actual, expected); }, time); }); - test('should create element label adjacent to canvas', function() { + test.skip('should create element label adjacent to canvas', function() { myp5.describeElement(a, b, myp5.LABEL); setTimeout(function() { const actual = document.getElementById(myID + '_lte_' + a).innerHTML; assert.deepEqual(actual, expected); }, time); }); - /*test('should create element label adjacent to canvas when called after describe()', function() { + test.skip('should create element label adjacent to canvas when called after describe()', function() { myp5.describe(c, myp5.LABEL); myp5.describeElement(a, b, myp5.LABEL); setTimeout(function() { const actual = document.getElementById(myID + '_lte_' + a).innerHTML; assert.deepEqual(actual, expected); }, time); - });*/ + }); test('wrong param type at #0 and #1', function() { assert.validationError(function() { myp5.describeElement(1, 2); From ba87ef635358c48b375c0730bc112fbed39f6bfc Mon Sep 17 00:00:00 2001 From: Luis Morales-Navarro Date: Fri, 7 Aug 2020 10:20:33 -0600 Subject: [PATCH 39/42] fix test issues --- src/accessibility/describe.js | 80 +++++++++--------- test/unit/accessibility/describe.js | 125 ++++++++++++---------------- 2 files changed, 95 insertions(+), 110 deletions(-) diff --git a/src/accessibility/describe.js b/src/accessibility/describe.js index a674bacd77..369d822ddc 100644 --- a/src/accessibility/describe.js +++ b/src/accessibility/describe.js @@ -14,7 +14,7 @@ const labelContainer = '_Label'; //Label container const labelDescId = '_labelDesc'; //Label description const labelTableId = '_labelTable'; //Label Table const labelTableElId = '_lte_'; //Label Table Element -let dummy = { fallbackElements: {}, labelElements: {} }; //stores DOM element booleans and DOM Elements +let dummy = { fallbackElements: {}, labelElements: {} }; /** * Creates a screen-reader accessible description for the canvas. @@ -79,34 +79,38 @@ p5.prototype.describe = function(text, display) { const cnvId = this.canvas.id; text = _descriptionText(text); //check if text is different - if (dummy.fallbackDesc !== text) { + if (dummy[cnvId + 'fallbackDesc'] !== text) { //if html structure is not there yet - if (!dummy.fallbackDesc) { + if (!dummy[cnvId + fallbackDescId]) { _describeFallbackHTML(cnvId, text); - } else if (dummy.fallbackDescId) { + } else if (document.getElementById(cnvId + fallbackDescId)) { document.getElementById(cnvId + fallbackDescId).innerHTML = text; - dummy.fallbackDesc = text; + dummy[cnvId + 'fallbackDesc'] = text; } } //If display is LABEL create a div adjacent to the canvas element with //description text. //check if text is different - if (display === this.LABEL && dummy.labelDesc !== text) { + if (display === this.LABEL && dummy[cnvId + 'labelDesc'] !== text) { //reassign value of dummy.describeText - if (!dummy[labelDescId]) { + if (!dummy[cnvId + labelDescId]) { _describeLabelHTML(cnvId, text); } else { document.getElementById(cnvId + labelDescId).innerHTML = text; - dummy.labelDesc = text; + dummy[cnvId + 'labelDesc'] = text; } } }; +p5.prototype._clearDummy = function() { + dummy = { fallbackElements: {}, labelElements: {} }; +}; + /** * Helper function for describe() and describeElement(). */ function _describeLabelHTML(cnvId, text) { - if (!dummy[labelContainer]) { + if (!dummy[cnvId + labelContainer]) { document .getElementById(cnvId) .insertAdjacentHTML( @@ -114,36 +118,36 @@ function _describeLabelHTML(cnvId, text) { `

` ); - dummy[labelContainer] = true; - dummy[labelDescId] = true; - } else if (!dummy[labelDescId] && dummy[labelTableId]) { + dummy[cnvId + labelContainer] = true; + dummy[cnvId + labelDescId] = true; + } else if (!dummy[cnvId + labelDescId] && dummy[cnvId + labelTableId]) { document .getElementById(cnvId + labelTableId) .insertAdjacentHTML('beforebegin', `

`); - dummy[labelDescId] = true; + dummy[cnvId + labelDescId] = true; } document.getElementById(cnvId + labelDescId).innerHTML = text; - dummy.labelDesc = text; + dummy[cnvId + 'labelDesc'] = text; } function _describeFallbackHTML(cnvId, text) { - if (!dummy[descContainer]) { + if (!dummy[cnvId + descContainer]) { document.getElementById(cnvId).innerHTML = `

`; - dummy[descContainer] = true; - dummy[fallbackDescId] = true; - } else if (dummy[fallbackTableId]) { + dummy[cnvId + descContainer] = true; + dummy[cnvId + fallbackDescId] = true; + } else if (dummy[cnvId + fallbackTableId]) { document .getElementById(cnvId + fallbackTableId) .insertAdjacentHTML( 'beforebegin', `

` ); - dummy[fallbackDescId] = true; + dummy[cnvId + fallbackDescId] = true; } document.getElementById(cnvId + fallbackDescId).innerHTML = text; - dummy.fallbackDesc = text; + dummy[cnvId + 'fallbackDesc'] = text; return; } @@ -214,11 +218,11 @@ p5.prototype.describeElement = function(name, text, display) { let elementName = _elementName(name); let inner = `${elementName}${text}`; - if (dummy.fallbackElements[name] !== inner) { - if (!dummy.fallbackElements[name]) { + if (dummy.fallbackElements[cnvId + name] !== inner) { + if (!dummy.fallbackElements[cnvId + name]) { _descElementFallbackHTML(cnvId, name, inner); } else { - dummy.fallbackElements[name] = inner; + dummy.fallbackElements[cnvId + name] = inner; document.getElementById( cnvId + fallbackTableElId + name ).innerHTML = inner; @@ -227,11 +231,11 @@ p5.prototype.describeElement = function(name, text, display) { //If display is LABEL creates a div adjacent to the canvas element with //a table, a row header cell with the name of the elements, //and adds the description of the element in adjecent cell. - if (display === this.LABEL && dummy.labelElements[name] !== inner) { - if (!dummy.labelElements[name]) { + if (display === this.LABEL && dummy.labelElements[cnvId + name] !== inner) { + if (!dummy.labelElements[cnvId + name]) { _descElementLabelHTML(cnvId, name, inner); } else { - dummy.labelElements[name] = inner; + dummy.labelElements[cnvId + name] = inner; document.getElementById(cnvId + labelTableElId + name).innerHTML = inner; } } @@ -240,7 +244,7 @@ p5.prototype.describeElement = function(name, text, display) { * Helper functions for describeElement(). */ function _descElementLabelHTML(cnvId, name, inner) { - if (!dummy[labelContainer]) { + if (!dummy[cnvId + labelContainer]) { document .getElementById(cnvId) .insertAdjacentHTML( @@ -249,8 +253,8 @@ function _descElementLabelHTML(cnvId, name, inner) { labelContainer}" class="p5Label">
` ); - dummy[labelContainer] = true; - dummy[labelTableId] = true; + dummy[cnvId + labelContainer] = true; + dummy[cnvId + labelTableId] = true; } else if (document.getElementById(cnvId + labelDescId)) { document .getElementById(cnvId + labelDescId) @@ -258,24 +262,24 @@ function _descElementLabelHTML(cnvId, name, inner) { 'afterend', `
` ); - dummy[labelTableId] = true; + dummy[cnvId + labelTableId] = true; } - if (!dummy.labelElements[name] && dummy[labelTableId]) { + if (!dummy.labelElements[cnvId + name] && dummy[cnvId + labelTableId]) { let tableRow = document.createElement('tr'); tableRow.id = cnvId + labelTableElId + name; document.getElementById(cnvId + labelTableId).appendChild(tableRow); - dummy.labelElements[name] = inner; + dummy.labelElements[cnvId + name] = inner; document.getElementById(cnvId + labelTableElId + name).innerHTML = inner; } } function _descElementFallbackHTML(cnvId, name, inner) { - if (!dummy[descContainer]) { + if (!dummy[cnvId + descContainer]) { document.getElementById(cnvId).innerHTML = `
Canvas elements and their descriptions
`; - dummy[descContainer] = true; - dummy[fallbackTableId] = true; + dummy[cnvId + descContainer] = true; + dummy[cnvId + fallbackTableId] = true; } else if (document.getElementById(cnvId + fallbackDescId)) { document .getElementById(cnvId + fallbackDescId) @@ -284,13 +288,13 @@ function _descElementFallbackHTML(cnvId, name, inner) { `
Canvas elements and their descriptions
` ); - dummy[fallbackTableId] = true; + dummy[cnvId + fallbackTableId] = true; } - if (!dummy.fallbackElements[name] && dummy[fallbackTableId]) { + if (!dummy.fallbackElements[cnvId + name] && dummy[cnvId + fallbackTableId]) { let tableRow = document.createElement('tr'); tableRow.id = cnvId + fallbackTableElId + name; document.getElementById(cnvId + fallbackTableId).appendChild(tableRow); - dummy.fallbackElements[name] = inner; + dummy.fallbackElements[cnvId + name] = inner; document.getElementById(cnvId + fallbackTableElId + name).innerHTML = inner; } } diff --git a/test/unit/accessibility/describe.js b/test/unit/accessibility/describe.js index ce1e72569b..efba09b366 100644 --- a/test/unit/accessibility/describe.js +++ b/test/unit/accessibility/describe.js @@ -5,7 +5,6 @@ suite('describe', function() { let a = 'a'; let b = 'b'; let c = 'c'; - let time = 0.0005; setup(function(done) { myp5Container = document.createElement('div'); @@ -21,6 +20,7 @@ suite('describe', function() { }); teardown(function() { + myp5._clearDummy(); myp5.remove(); if (myp5Container && myp5Container.parentNode) { myp5Container.parentNode.removeChild(myp5Container); @@ -39,48 +39,40 @@ suite('describe', function() { let actual = document.getElementById(myID + '_fallbackDesc').innerHTML; assert.deepEqual(actual, expected); }); - test.skip('should not add extra period if string ends in "."', function() { + test('should not add extra period if string ends in "."', function() { myp5.describe('a.'); - setTimeout(function() { - let actual = document.getElementById(myID + '_fallbackDesc').innerHTML; - assert.deepEqual(actual, expected); - }, time); + let actual = document.getElementById(myID + '_fallbackDesc').innerHTML; + assert.deepEqual(actual, expected); }); test.skip('should not add period if string ends in "!" or "?', function() { myp5.describe('A!'); - setTimeout(function() { - let actual = document.getElementById(myID + '_fallbackDesc').innerHTML; - if (actual === 'A!') { - myp5.describe('A?'); - setTimeout(function() { - actual = document.getElementById(myID + '_fallbackDesc').innerHTML; - assert.deepEqual(actual, 'A?'); - }, time); - } - }, time); + let actual = document.getElementById(myID + '_fallbackDesc').innerHTML; + if (actual === 'A!') { + myp5.describe('A?'); + + actual = document.getElementById(myID + '_fallbackDesc').innerHTML; + assert.deepEqual(actual, 'A?'); + } }); - test.skip('should create description when called after describeElement()', function() { + test('should create description when called after describeElement()', function() { myp5.describeElement(b, c); myp5.describe(a); - setTimeout(function() { - let actual = document.getElementById(myID + '_fallbackDesc').innerHTML; - assert.deepEqual(actual, expected); - }, time); + + let actual = document.getElementById(myID + '_fallbackDesc').innerHTML; + assert.deepEqual(actual, expected); }); - test.skip('should create Label adjacent to canvas', function() { + test('should create Label adjacent to canvas', function() { myp5.describe(a, myp5.LABEL); - setTimeout(function() { - let actual = document.getElementById(myID + '_labelDesc').innerHTML; - assert.deepEqual(actual, expected); - }, time); + + let actual = document.getElementById(myID + '_labelDesc').innerHTML; + assert.deepEqual(actual, expected); }); - test.skip('should create Label adjacent to canvas when label of element already exists', function() { + test('should create Label adjacent to canvas when label of element already exists', function() { myp5.describeElement(b, c, myp5.LABEL); myp5.describe(a, myp5.LABEL); - setTimeout(function() { - let actual = document.getElementById(myID + '_labelDesc').innerHTML; - assert.deepEqual(actual, expected); - }, time); + + let actual = document.getElementById(myID + '_labelDesc').innerHTML; + assert.deepEqual(actual, expected); }); test('wrong param type at #0', function() { assert.validationError(function() { @@ -109,62 +101,51 @@ suite('describe', function() { assert.ok(myp5.describeElement); assert.typeOf(myp5.describeElement, 'function'); }); - test.skip('should create element description as fallback', function() { + test('should create element description as fallback', function() { myp5.describeElement(a, b); - setTimeout(function() { - let actual = document.getElementById(myID + '_fte_' + a).innerHTML; - assert.deepEqual(actual, expected); - }, time); + let actual = document.getElementById(myID + '_fte_' + a).innerHTML; + assert.deepEqual(actual, expected); }); - test.skip('should not add extra ":" if element name ends in colon', function() { + test('should not add extra ":" if element name ends in colon', function() { myp5.describeElement('a:', 'b.'); - setTimeout(function() { - let actual = document.getElementById(myID + '_fte_a:').innerHTML; - assert.deepEqual(actual, expected); - }, time); + + let actual = document.getElementById(myID + '_fte_a:').innerHTML; + assert.deepEqual(actual, expected); }); - test.skip('should replace ";", ",", "." for ":" in element name', function() { + test('should replace ";", ",", "." for ":" in element name', function() { let actual; myp5.describeElement('a;', 'b.'); - setTimeout(function() { - if (document.getElementById(myID + '_fte_a;').innerHTML === expected) { - myp5.describeElement('a,', 'b.'); - setTimeout(function() { - if ( - document.getElementById(myID + '_fte_a,').innerHTML === expected - ) { - myp5.describeElement('a.', 'b.'); - setTimeout(function() { - actual = document.getElementById(myID + '_fte_a.').innerHTML; - assert.deepEqual(actual, expected); - }, time); - } - }, time); + + if (document.getElementById(myID + '_fte_a;').innerHTML === expected) { + myp5.describeElement('a,', 'b.'); + + if (document.getElementById(myID + '_fte_a,').innerHTML === expected) { + myp5.describeElement('a.', 'b.'); + + actual = document.getElementById(myID + '_fte_a.').innerHTML; + assert.deepEqual(actual, expected); } - }, time); + } }); - test.skip('should create element description when called after describe()', function() { + test('should create element description when called after describe()', function() { myp5.describe(c); myp5.describeElement(a, b); - setTimeout(function() { - let actual = document.getElementById(myID + '_fte_' + a).innerHTML; - assert.deepEqual(actual, expected); - }, time); + + let actual = document.getElementById(myID + '_fte_' + a).innerHTML; + assert.deepEqual(actual, expected); }); - test.skip('should create element label adjacent to canvas', function() { + test('should create element label adjacent to canvas', function() { myp5.describeElement(a, b, myp5.LABEL); - setTimeout(function() { - const actual = document.getElementById(myID + '_lte_' + a).innerHTML; - assert.deepEqual(actual, expected); - }, time); + + const actual = document.getElementById(myID + '_lte_' + a).innerHTML; + assert.deepEqual(actual, expected); }); - test.skip('should create element label adjacent to canvas when called after describe()', function() { + test('should create element label adjacent to canvas when called after describe()', function() { myp5.describe(c, myp5.LABEL); myp5.describeElement(a, b, myp5.LABEL); - setTimeout(function() { - const actual = document.getElementById(myID + '_lte_' + a).innerHTML; - assert.deepEqual(actual, expected); - }, time); + + const actual = document.getElementById(myID + '_lte_' + a).innerHTML; + assert.deepEqual(actual, expected); }); test('wrong param type at #0 and #1', function() { assert.validationError(function() { From cb2490671578fb604683e0aecba2f05acaa02ae0 Mon Sep 17 00:00:00 2001 From: Luis Morales-Navarro Date: Fri, 7 Aug 2020 13:38:18 -0600 Subject: [PATCH 40/42] :hibiscus:fix tests and move to dummy DOM --- src/accessibility/describe.js | 120 ++++++++++++++++++++-------- test/unit/accessibility/describe.js | 12 +-- 2 files changed, 91 insertions(+), 41 deletions(-) diff --git a/src/accessibility/describe.js b/src/accessibility/describe.js index 369d822ddc..dee6ad97f8 100644 --- a/src/accessibility/describe.js +++ b/src/accessibility/describe.js @@ -78,14 +78,20 @@ p5.prototype.describe = function(text, display) { } const cnvId = this.canvas.id; text = _descriptionText(text); + if (!dummy[cnvId + 'fallbackDesc'] || !dummy[cnvId + 'labelDesc']) { + _populateDummyDOM(cnvId); + } + //check if text is different if (dummy[cnvId + 'fallbackDesc'] !== text) { //if html structure is not there yet - if (!dummy[cnvId + fallbackDescId]) { - _describeFallbackHTML(cnvId, text); - } else if (document.getElementById(cnvId + fallbackDescId)) { - document.getElementById(cnvId + fallbackDescId).innerHTML = text; + if (dummy[cnvId + 'updateFallbackDesc']) { + dummy[cnvId + 'DOM'].querySelector( + '#' + cnvId + fallbackDescId + ).innerHTML = text; dummy[cnvId + 'fallbackDesc'] = text; + } else { + _describeFallbackHTML(cnvId, text); } } //If display is LABEL create a div adjacent to the canvas element with @@ -93,11 +99,13 @@ p5.prototype.describe = function(text, display) { //check if text is different if (display === this.LABEL && dummy[cnvId + 'labelDesc'] !== text) { //reassign value of dummy.describeText - if (!dummy[cnvId + labelDescId]) { - _describeLabelHTML(cnvId, text); - } else { - document.getElementById(cnvId + labelDescId).innerHTML = text; + if (dummy[cnvId + labelDescId]) { + dummy[cnvId + 'DOM'].querySelector( + '#' + cnvId + labelDescId + ).innerHTML = text; dummy[cnvId + 'labelDesc'] = text; + } else { + _describeLabelHTML(cnvId, text); } } }; @@ -106,13 +114,17 @@ p5.prototype._clearDummy = function() { dummy = { fallbackElements: {}, labelElements: {} }; }; +function _populateDummyDOM(cnvId) { + dummy[cnvId + 'DOM'] = document.getElementsByTagName('body')[0]; +} + /** * Helper function for describe() and describeElement(). */ function _describeLabelHTML(cnvId, text) { if (!dummy[cnvId + labelContainer]) { - document - .getElementById(cnvId) + dummy[cnvId + 'DOM'] + .querySelector('#' + cnvId) .insertAdjacentHTML( 'afterend', `

`); dummy[cnvId + labelDescId] = true; } - document.getElementById(cnvId + labelDescId).innerHTML = text; + dummy[cnvId + 'DOM'].querySelector( + '#' + cnvId + labelDescId + ).innerHTML = text; dummy[cnvId + 'labelDesc'] = text; } function _describeFallbackHTML(cnvId, text) { if (!dummy[cnvId + descContainer]) { - document.getElementById(cnvId).innerHTML = `

`; dummy[cnvId + descContainer] = true; dummy[cnvId + fallbackDescId] = true; } else if (dummy[cnvId + fallbackTableId]) { - document - .getElementById(cnvId + fallbackTableId) + dummy[cnvId + 'DOM'] + .querySelector('#' + cnvId + fallbackTableId) .insertAdjacentHTML( 'beforebegin', `

` ); dummy[cnvId + fallbackDescId] = true; } - document.getElementById(cnvId + fallbackDescId).innerHTML = text; - dummy[cnvId + 'fallbackDesc'] = text; + if (dummy[cnvId + 'DOM'].querySelector('#' + cnvId + fallbackDescId)) { + dummy[cnvId + 'DOM'].querySelector( + '#' + cnvId + fallbackDescId + ).innerHTML = text; + dummy[cnvId + 'fallbackDesc'] = text; + dummy[cnvId + 'updateFallbackDesc'] === true; + } return; } @@ -216,15 +237,23 @@ p5.prototype.describeElement = function(name, text, display) { const cnvId = this.canvas.id; text = _descriptionText(text); let elementName = _elementName(name); + name = _nameForID(name); let inner = `${elementName}${text}`; + if ( + !dummy.fallbackElements[cnvId + name] || + !dummy.labelElements[cnvId + name] + ) { + _populateDummyDOM(cnvId); + } + if (dummy.fallbackElements[cnvId + name] !== inner) { if (!dummy.fallbackElements[cnvId + name]) { _descElementFallbackHTML(cnvId, name, inner); } else { dummy.fallbackElements[cnvId + name] = inner; - document.getElementById( - cnvId + fallbackTableElId + name + dummy[cnvId + 'DOM'].querySelector( + '#' + cnvId + fallbackTableElId + name ).innerHTML = inner; } } @@ -236,7 +265,9 @@ p5.prototype.describeElement = function(name, text, display) { _descElementLabelHTML(cnvId, name, inner); } else { dummy.labelElements[cnvId + name] = inner; - document.getElementById(cnvId + labelTableElId + name).innerHTML = inner; + dummy[cnvId + 'DOM'].querySelector( + '#' + cnvId + labelTableElId + name + ).innerHTML = inner; } } }; @@ -245,8 +276,8 @@ p5.prototype.describeElement = function(name, text, display) { */ function _descElementLabelHTML(cnvId, name, inner) { if (!dummy[cnvId + labelContainer]) { - document - .getElementById(cnvId) + dummy[cnvId + 'DOM'] + .querySelector('#' + cnvId) .insertAdjacentHTML( 'afterend', `
` @@ -267,22 +298,28 @@ function _descElementLabelHTML(cnvId, name, inner) { if (!dummy.labelElements[cnvId + name] && dummy[cnvId + labelTableId]) { let tableRow = document.createElement('tr'); tableRow.id = cnvId + labelTableElId + name; - document.getElementById(cnvId + labelTableId).appendChild(tableRow); + dummy[cnvId + 'DOM'] + .querySelector('#' + cnvId + labelTableId) + .appendChild(tableRow); dummy.labelElements[cnvId + name] = inner; - document.getElementById(cnvId + labelTableElId + name).innerHTML = inner; + dummy[cnvId + 'DOM'].querySelector( + '#' + cnvId + labelTableElId + name + ).innerHTML = inner; } } function _descElementFallbackHTML(cnvId, name, inner) { if (!dummy[cnvId + descContainer]) { - document.getElementById(cnvId).innerHTML = `
Canvas elements and their descriptions
`; dummy[cnvId + descContainer] = true; dummy[cnvId + fallbackTableId] = true; } else if (document.getElementById(cnvId + fallbackDescId)) { - document - .getElementById(cnvId + fallbackDescId) + dummy[cnvId + 'DOM'] + .querySelector('#' + cnvId + fallbackDescId) .insertAdjacentHTML( 'afterend', ` Date: Mon, 10 Aug 2020 07:53:52 -0600 Subject: [PATCH 41/42] remove special characters of element IDs --- src/accessibility/describe.js | 11 ++--------- 1 file changed, 2 insertions(+), 9 deletions(-) diff --git a/src/accessibility/describe.js b/src/accessibility/describe.js index dee6ad97f8..249053863b 100644 --- a/src/accessibility/describe.js +++ b/src/accessibility/describe.js @@ -341,15 +341,8 @@ function _descElementFallbackHTML(cnvId, name, inner) { } function _nameForID(name) { - //remove any punctuation at the end of name - if ( - name.endsWith('.') || - name.endsWith(';') || - name.endsWith(',') || - name.endsWith(':') - ) { - name = name.replace(/.$/, ''); - } + //remove any special characters from name for ID + name = name.replace(/[^a-zA-Z0-9 ]/g, ''); return name; } From 2ca1f72026fd7b83f85d9edfe00b402ed08ab516 Mon Sep 17 00:00:00 2001 From: Luis Morales-Navarro Date: Mon, 10 Aug 2020 09:20:31 -0600 Subject: [PATCH 42/42] add comments to code --- src/accessibility/describe.js | 349 +++++++++++++++++++++------------- 1 file changed, 214 insertions(+), 135 deletions(-) diff --git a/src/accessibility/describe.js b/src/accessibility/describe.js index 249053863b..4bcbf04d1d 100644 --- a/src/accessibility/describe.js +++ b/src/accessibility/describe.js @@ -14,6 +14,7 @@ const labelContainer = '_Label'; //Label container const labelDescId = '_labelDesc'; //Label description const labelTableId = '_labelTable'; //Label Table const labelTableElId = '_lte_'; //Label Table Element +//dummy stores a copy of the DOM and previous descriptions let dummy = { fallbackElements: {}, labelElements: {} }; /** @@ -77,113 +78,47 @@ p5.prototype.describe = function(text, display) { return; } const cnvId = this.canvas.id; + //calls function that adds punctuation for better screen reading text = _descriptionText(text); + + //if it is the first time describe() is called if (!dummy[cnvId + 'fallbackDesc'] || !dummy[cnvId + 'labelDesc']) { + //store copy of body dom in dummy _populateDummyDOM(cnvId); } //check if text is different if (dummy[cnvId + 'fallbackDesc'] !== text) { - //if html structure is not there yet + //if html structure for description is ready if (dummy[cnvId + 'updateFallbackDesc']) { + //update description dummy[cnvId + 'DOM'].querySelector( '#' + cnvId + fallbackDescId ).innerHTML = text; + //store updated description dummy[cnvId + 'fallbackDesc'] = text; } else { + //create fallback html structure _describeFallbackHTML(cnvId, text); } } - //If display is LABEL create a div adjacent to the canvas element with - //description text. - //check if text is different + //if display is LABEL and label text is different if (display === this.LABEL && dummy[cnvId + 'labelDesc'] !== text) { - //reassign value of dummy.describeText + //if html structure for label is ready if (dummy[cnvId + labelDescId]) { + //update label description dummy[cnvId + 'DOM'].querySelector( '#' + cnvId + labelDescId ).innerHTML = text; + //store updated label description dummy[cnvId + 'labelDesc'] = text; } else { + //create label html structure _describeLabelHTML(cnvId, text); } } }; -p5.prototype._clearDummy = function() { - dummy = { fallbackElements: {}, labelElements: {} }; -}; - -function _populateDummyDOM(cnvId) { - dummy[cnvId + 'DOM'] = document.getElementsByTagName('body')[0]; -} - -/** - * Helper function for describe() and describeElement(). - */ -function _describeLabelHTML(cnvId, text) { - if (!dummy[cnvId + labelContainer]) { - dummy[cnvId + 'DOM'] - .querySelector('#' + cnvId) - .insertAdjacentHTML( - 'afterend', - `

` - ); - dummy[cnvId + labelContainer] = true; - dummy[cnvId + labelDescId] = true; - } else if (!dummy[cnvId + labelDescId] && dummy[cnvId + labelTableId]) { - dummy[cnvId + 'DOM'] - .querySelector('#' + cnvId + labelTableId) - .insertAdjacentHTML('beforebegin', `

`); - dummy[cnvId + labelDescId] = true; - } - dummy[cnvId + 'DOM'].querySelector( - '#' + cnvId + labelDescId - ).innerHTML = text; - dummy[cnvId + 'labelDesc'] = text; -} - -function _describeFallbackHTML(cnvId, text) { - if (!dummy[cnvId + descContainer]) { - dummy[cnvId + 'DOM'].querySelector( - '#' + cnvId - ).innerHTML = `

`; - dummy[cnvId + descContainer] = true; - dummy[cnvId + fallbackDescId] = true; - } else if (dummy[cnvId + fallbackTableId]) { - dummy[cnvId + 'DOM'] - .querySelector('#' + cnvId + fallbackTableId) - .insertAdjacentHTML( - 'beforebegin', - `

` - ); - dummy[cnvId + fallbackDescId] = true; - } - if (dummy[cnvId + 'DOM'].querySelector('#' + cnvId + fallbackDescId)) { - dummy[cnvId + 'DOM'].querySelector( - '#' + cnvId + fallbackDescId - ).innerHTML = text; - dummy[cnvId + 'fallbackDesc'] = text; - dummy[cnvId + 'updateFallbackDesc'] === true; - } - return; -} - -function _descriptionText(text) { - if (text === 'label' || text === 'fallback') { - throw new Error('description should not be LABEL or FALLBACK'); - } - //if string does not end with '.' - if (!text.endsWith('.') && !text.endsWith('?') && !text.endsWith('!')) { - //add '.' to the end of string - text = text + '.'; - } - return text; -} - /** * This function creates a screen-reader accessible * description for elements —shapes or groups of shapes that create @@ -235,89 +170,204 @@ p5.prototype.describeElement = function(name, text, display) { return; } const cnvId = this.canvas.id; + //calls function that adds punctuation for better screen reading text = _descriptionText(text); + //calls function that adds punctuation for better screen reading let elementName = _elementName(name); - name = _nameForID(name); + //remove any special characters from name to use it as html id + name = name.replace(/[^a-zA-Z0-9 ]/g, ''); + //store element description let inner = `
`; + //if it is the first time describeElement() is called if ( !dummy.fallbackElements[cnvId + name] || !dummy.labelElements[cnvId + name] ) { + //store copy of body dom in dummy _populateDummyDOM(cnvId); } + //check if element description is different from current if (dummy.fallbackElements[cnvId + name] !== inner) { - if (!dummy.fallbackElements[cnvId + name]) { - _descElementFallbackHTML(cnvId, name, inner); - } else { - dummy.fallbackElements[cnvId + name] = inner; + //if html structure for element description is ready + if (dummy.fallbackElements[cnvId + name]) { + //update element description dummy[cnvId + 'DOM'].querySelector( '#' + cnvId + fallbackTableElId + name ).innerHTML = inner; + //store updated element description + dummy.fallbackElements[cnvId + name] = inner; + } else { + //create fallback html structure + _descElementFallbackHTML(cnvId, name, inner); } } - //If display is LABEL creates a div adjacent to the canvas element with - //a table, a row header cell with the name of the elements, - //and adds the description of the element in adjecent cell. + //if display is LABEL and label element description is different if (display === this.LABEL && dummy.labelElements[cnvId + name] !== inner) { - if (!dummy.labelElements[cnvId + name]) { - _descElementLabelHTML(cnvId, name, inner); - } else { - dummy.labelElements[cnvId + name] = inner; + //if html structure for label element description is ready + if (dummy.labelElements[cnvId + name]) { + //update label element description dummy[cnvId + 'DOM'].querySelector( '#' + cnvId + labelTableElId + name ).innerHTML = inner; + //store updated label element description + dummy.labelElements[cnvId + name] = inner; + } else { + //create label element html structure + _descElementLabelHTML(cnvId, name, inner); } } }; -/** - * Helper functions for describeElement(). + +/* + * + * Helper functions for describe() and describeElement(). + * */ -function _descElementLabelHTML(cnvId, name, inner) { - if (!dummy[cnvId + labelContainer]) { + +//clear dummy +p5.prototype._clearDummy = function() { + dummy = { fallbackElements: {}, labelElements: {} }; +}; + +//stores html body in dummy +function _populateDummyDOM(cnvId) { + dummy[cnvId + 'DOM'] = document.getElementsByTagName('body')[0]; +} + +// check that text is not LABEL or FALLBACK and ensure text ends with punctuation mark +function _descriptionText(text) { + if (text === 'label' || text === 'fallback') { + throw new Error('description should not be LABEL or FALLBACK'); + } + //if string does not end with '.' + if ( + !text.endsWith('.') && + !text.endsWith(',') && + !text.endsWith('?') && + !text.endsWith('!') + ) { + //add '.' to the end of string + text = text + '.'; + } + return text; +} + +/* + * Helper functions for describe() + */ + +//creates fallback HTML structure +function _describeFallbackHTML(cnvId, text) { + //if there is no description container + if (!dummy[cnvId + descContainer]) { + //create description container +

for fallback description + dummy[cnvId + 'DOM'].querySelector( + '#' + cnvId + ).innerHTML = `

`; + //set container and fallbackDescId to true + dummy[cnvId + descContainer] = true; + dummy[cnvId + fallbackDescId] = true; + //if describeElement() has already created the container and added a table of elements + } else if (dummy[cnvId + fallbackTableId]) { + //create fallback description

before the table dummy[cnvId + 'DOM'] - .querySelector('#' + cnvId) + .querySelector('#' + cnvId + fallbackTableId) .insertAdjacentHTML( - 'afterend', - `

${elementName}${text}
` + 'beforebegin', + `

` ); - dummy[cnvId + labelContainer] = true; - dummy[cnvId + labelTableId] = true; - } else if (dummy[cnvId + 'DOM'].querySelector('#' + cnvId + labelDescId)) { + //set fallbackDescId to true + dummy[cnvId + fallbackDescId] = true; + } + //If the container for the description exists + if (dummy[cnvId + 'DOM'].querySelector('#' + cnvId + fallbackDescId)) { + //update description + dummy[cnvId + 'DOM'].querySelector( + '#' + cnvId + fallbackDescId + ).innerHTML = text; + //store updated description + dummy[cnvId + 'fallbackDesc'] = text; + //html structure is ready for any description updates + dummy[cnvId + 'updateFallbackDesc'] === true; + } + return; +} + +//If display is LABEL create a div adjacent to the canvas element with +//description text. +function _describeLabelHTML(cnvId, text) { + //if there is no label container + if (!dummy[cnvId + labelContainer]) { + //create label container +

for label description dummy[cnvId + 'DOM'] - .querySelector('#' + cnvId + labelDescId) + .querySelector('#' + cnvId) .insertAdjacentHTML( 'afterend', - `
` + `

` ); - dummy[cnvId + labelTableId] = true; - } - if (!dummy.labelElements[cnvId + name] && dummy[cnvId + labelTableId]) { - let tableRow = document.createElement('tr'); - tableRow.id = cnvId + labelTableElId + name; + //set container and labelDescId to true + dummy[cnvId + labelContainer] = true; + dummy[cnvId + labelDescId] = true; + //if describeElement() has already created the container and added a table of elements + } else if (!dummy[cnvId + labelDescId] && dummy[cnvId + labelTableId]) { + //create label description

before the table dummy[cnvId + 'DOM'] .querySelector('#' + cnvId + labelTableId) - .appendChild(tableRow); - dummy.labelElements[cnvId + name] = inner; - dummy[cnvId + 'DOM'].querySelector( - '#' + cnvId + labelTableElId + name - ).innerHTML = inner; + .insertAdjacentHTML('beforebegin', `

`); + //set fallbackDescId to true + dummy[cnvId + labelDescId] = true; } + //update description + dummy[cnvId + 'DOM'].querySelector( + '#' + cnvId + labelDescId + ).innerHTML = text; + //store updated description + dummy[cnvId + 'labelDesc'] = text; + return; } +/* + * Helper functions for describeElement(). + */ + +//check that name is not LABEL or FALLBACK and ensure text ends with colon +function _elementName(name) { + if (name === 'label' || name === 'fallback') { + throw new Error('element name should not be LABEL or FALLBACK'); + } + //check if last character of string n is '.', ';', or ',' + if (name.endsWith('.') || name.endsWith(';') || name.endsWith(',')) { + //replace last character with ':' + name = name.replace(/.$/, ':'); + //if string n does not end with ':' + } else if (!name.endsWith(':')) { + //add ':'' at the end of string + name = name + ':'; + } + return name; +} + +//creates fallback HTML structure for element descriptions function _descElementFallbackHTML(cnvId, name, inner) { + //if there is no description container if (!dummy[cnvId + descContainer]) { + //create container + table for element descriptions dummy[cnvId + 'DOM'].querySelector( '#' + cnvId ).innerHTML = `
Canvas elements and their descriptions
`; + //set container and fallbackTableId to true dummy[cnvId + descContainer] = true; dummy[cnvId + fallbackTableId] = true; + //if describe() has already created the container and added a description } else if (document.getElementById(cnvId + fallbackDescId)) { + //create fallback table for element description after fallback description dummy[cnvId + 'DOM'] .querySelector('#' + cnvId + fallbackDescId) .insertAdjacentHTML( @@ -325,41 +375,70 @@ function _descElementFallbackHTML(cnvId, name, inner) { `
Canvas elements and their descriptions
` ); + //set fallbackTableId to true dummy[cnvId + fallbackTableId] = true; } + //if it is the first time this element is being added to the table if (!dummy.fallbackElements[cnvId + name] && dummy[cnvId + fallbackTableId]) { + //create a table row for the element let tableRow = document.createElement('tr'); tableRow.id = cnvId + fallbackTableElId + name; dummy[cnvId + 'DOM'] .querySelector('#' + cnvId + fallbackTableId) .appendChild(tableRow); - dummy.fallbackElements[cnvId + name] = inner; + //update element description dummy[cnvId + 'DOM'].querySelector( '#' + cnvId + fallbackTableElId + name ).innerHTML = inner; + //store updated element description + dummy.fallbackElements[cnvId + name] = inner; } } - -function _nameForID(name) { - //remove any special characters from name for ID - name = name.replace(/[^a-zA-Z0-9 ]/g, ''); - return name; -} - -function _elementName(name) { - if (name === 'label' || name === 'fallback') { - throw new Error('element name should not be LABEL or FALLBACK'); +//If display is LABEL creates a div adjacent to the canvas element with +//a table, a row header cell with the name of the elements, +//and adds the description of the element in adjecent cell. +function _descElementLabelHTML(cnvId, name, inner) { + //if there is no label description container + if (!dummy[cnvId + labelContainer]) { + //create container + table for element descriptions + dummy[cnvId + 'DOM'] + .querySelector('#' + cnvId) + .insertAdjacentHTML( + 'afterend', + `
` + ); + //set container and labelTableId to true + dummy[cnvId + labelContainer] = true; + dummy[cnvId + labelTableId] = true; + //if describe() has already created the label container and added a description + } else if (dummy[cnvId + 'DOM'].querySelector('#' + cnvId + labelDescId)) { + //create label table for element description after label description + dummy[cnvId + 'DOM'] + .querySelector('#' + cnvId + labelDescId) + .insertAdjacentHTML( + 'afterend', + `
` + ); + //set labelTableId to true + dummy[cnvId + labelTableId] = true; } - //check if last character of string n is '.', ';', or ',' - if (name.endsWith('.') || name.endsWith(';') || name.endsWith(',')) { - //replace last character with ':' - name = name.replace(/.$/, ':'); - //if string n does not end with ':' - } else if (!name.endsWith(':')) { - //add ':'' at the end of string - name = name + ':'; + //if it is the first time this element is being added to the table + if (!dummy.labelElements[cnvId + name] && dummy[cnvId + labelTableId]) { + //create a table row for the element label description + let tableRow = document.createElement('tr'); + tableRow.id = cnvId + labelTableElId + name; + dummy[cnvId + 'DOM'] + .querySelector('#' + cnvId + labelTableId) + .appendChild(tableRow); + //update element label description + dummy[cnvId + 'DOM'].querySelector( + '#' + cnvId + labelTableElId + name + ).innerHTML = inner; + //store updated element label description + dummy.labelElements[cnvId + name] = inner; } - return name; } export default p5;