diff --git a/js/resistance-in-a-wire/ResistanceInAWireA11yStrings.js b/js/resistance-in-a-wire/ResistanceInAWireA11yStrings.js index 5bb50e4..fcc60f6 100644 --- a/js/resistance-in-a-wire/ResistanceInAWireA11yStrings.js +++ b/js/resistance-in-a-wire/ResistanceInAWireA11yStrings.js @@ -14,12 +14,48 @@ define( function( require ) { var resistanceInAWire = require( 'RESISTANCE_IN_A_WIRE/resistanceInAWire' ); var ResistanceInAWireA11yStrings = { - resistivityUnitsPatternString: '{{value}} ohm centimeters', - lengthUnitsPatternString: '{{value}} centimeters', - areaUnitsPatternString: '{{value}} centimeters squared', - resistivitySliderLabelString: 'rho, Resistivity', - lengthSliderLabelString: 'L, Length', - areaSliderLabelString: 'A, Area' + summarySimString: { + value: 'This is an interactive sim. Descriptions change as you play with it. It has a Play Area and Control Panel. ' + + 'In the Play Area you find the Resistance equation, R equals rho times L over A, and a piece of wire. ' + + 'Sliders for resistivity, length, and area allow changes to the equation and the piece of wire. ' + + 'In the Control Panel, buttons mute sound or reset the sim.' + }, + currentlyString: { + value: 'Currently,' + }, + summaryResistancePatternString: { + value: 'resistance, R, is {{value}} ohms', + }, + summaryResistivityPatternString: { + value: 'resistivity, rho is {{value}} ohm centimeters', + }, + summaryLengthPatternString: { + value: 'length, L is {{value}} centimeters', + }, + summaryAreaPatternString: { + value: 'area, A is {{value}} centimeters squared', + }, + resistivityUnitsPatternString: { + value: '{{value}} ohm centimeters', + }, + summaryInteractionHintString: { + value: 'Look for resistivity, length, and area sliders to play, or read on for details about equation and wire.' + }, + lengthUnitsPatternString: { + value: '{{value}} centimeters', + }, + areaUnitsPatternString: { + value: '{{value}} centimeters squared', + }, + resistivitySliderLabelString: { + value: 'rho, Resistivity', + }, + lengthSliderLabelString: { + value: 'L, Length', + }, + areaSliderLabelString: { + value: 'A, Area' + } }; if ( phet.chipper.queryParameters.stringTest === 'xss' ) { diff --git a/js/resistance-in-a-wire/ResistanceInAWireConstants.js b/js/resistance-in-a-wire/ResistanceInAWireConstants.js index 0eaeca7..e3a559b 100644 --- a/js/resistance-in-a-wire/ResistanceInAWireConstants.js +++ b/js/resistance-in-a-wire/ResistanceInAWireConstants.js @@ -44,7 +44,17 @@ define( function( require ) { TAIL_LENGTH: 140, HEAD_HEIGHT: 45, HEAD_WIDTH: 30, - TAIL_WIDTH: 10 + TAIL_WIDTH: 10, + + // precision of values for view + SLIDER_READOUT_DECIMALS: 2, + getResistanceDecimals: function( resistance ) { + return resistance >= 100 ? 0 : // Over 100, show no decimal points, like 102 + resistance >= 10 ? 1 : // between 10.0 and 99.9, show 2 decimal points + resistance < 0.001 ? 4 : // when less than 0.001, show 4 decimals, see #125 + resistance < 1 ? 3 : // when less than 1, show 3 decimal places, see #125 + 2; // Numbers less than 10 show 2 decimal points, like 8.35 + } }; diff --git a/js/resistance-in-a-wire/view/AccessibleSummaryNode.js b/js/resistance-in-a-wire/view/AccessibleSummaryNode.js new file mode 100644 index 0000000..9f22de6 --- /dev/null +++ b/js/resistance-in-a-wire/view/AccessibleSummaryNode.js @@ -0,0 +1,110 @@ +// Copyright 2018, University of Colorado Boulder + +/** + * The Scene Summary for Resistance in a Wire. This summary is at the top of the document, and is the first thing + * that a screen reader user reads when using the sim. It provides overview information about the resistance + * equation, visualization of the circuit, and the controls in the interface. + * + * @author Jesse Greenberg (PhET Interactive Simulations) + */ + +define( function( require ) { + 'use strict'; + + // modules + var AccessibleSectionNode = require( 'SCENERY_PHET/accessibility/AccessibleSectionNode' ); + var inherit = require( 'PHET_CORE/inherit' ); + var JoistA11yStrings = require( 'JOIST/JoistA11yStrings' ); + var Node = require( 'SCENERY/nodes/Node' ); + var resistanceInAWire = require( 'RESISTANCE_IN_A_WIRE/resistanceInAWire' ); + var ResistanceInAWireA11yStrings = require( 'RESISTANCE_IN_A_WIRE/resistance-in-a-wire/ResistanceInAWireA11yStrings' ); + var ResistanceInAWireConstants = require( 'RESISTANCE_IN_A_WIRE/resistance-in-a-wire/ResistanceInAWireConstants' ); + var StringUtils = require( 'PHETCOMMON/util/StringUtils' ); + var Util = require( 'DOT/Util' ); + + var sceneSummaryString = JoistA11yStrings.sceneSummaryString; + var summarySimString = ResistanceInAWireA11yStrings.summarySimString.value; + var currentlyString = ResistanceInAWireA11yStrings.currentlyString.value; + var summaryResistancePatternString = ResistanceInAWireA11yStrings.summaryResistancePatternString.value; + var summaryResistivityPatternString = ResistanceInAWireA11yStrings.summaryResistivityPatternString.value; + var summaryLengthPatternString = ResistanceInAWireA11yStrings.summaryLengthPatternString.value; + var summaryAreaPatternString = ResistanceInAWireA11yStrings.summaryAreaPatternString.value; + var summaryInteractionHintString = ResistanceInAWireA11yStrings.summaryInteractionHintString.value; + var checkOutShortcutsString = JoistA11yStrings.checkOutShortcutsString; + + // constants + function AccessibleSummaryNode( model ) { + AccessibleSectionNode.call( this, sceneSummaryString ); + + // main summary for this sim - this content never changes + this.addChild( new Node( { + tagName: 'p', + accessibleLabelAsHTML: summarySimString + } ) ); + + // indicates that the summary updates with model changes + this.addChild( new Node( { tagName: 'p', accessibleLabel: currentlyString } ) ); + + // list that updates according to model Properties + var listNode = new Node( { tagName: 'ul' } ); + var resistanceItemNode = new Node( { tagName: 'li' } ); + var resistivityItemNode = new Node( { tagName: 'li' } ); + var lengthItemNode = new Node( { tagName: 'li' } ); + var areaItemNode = new Node( { tagName: 'li' } ); + this.addChild( listNode ); + listNode.children = [ resistanceItemNode, resistivityItemNode, lengthItemNode, areaItemNode ]; + + // hint to look for other elements in the UI + this.addChild( new Node( { tagName: 'p', accessibleLabel: summaryInteractionHintString } ) ); + + // hint to look for help dialog for more information + this.addChild( new Node( { tagName: 'p', accessibleLabel: checkOutShortcutsString } ) ); + + // add listeners - add all values to a list so we can easily iterate and add listeners to update descriptions + // with each property + var valueItemList = [ + { + property: model.resistivityProperty, + patternString: summaryResistivityPatternString, + node: resistivityItemNode, + precision: ResistanceInAWireConstants.SLIDER_READOUT_DECIMALS + }, + { + property: model.lengthProperty, + patternString: summaryLengthPatternString, + node: lengthItemNode, + precision: ResistanceInAWireConstants.SLIDER_READOUT_DECIMALS + }, + { + property: model.areaProperty, + patternString: summaryAreaPatternString, + node: areaItemNode, + precision: ResistanceInAWireConstants.SLIDER_READOUT_DECIMALS + }, + { + property: model.resistanceProperty, + patternString: summaryResistancePatternString, + node: resistanceItemNode, + precision: ResistanceInAWireConstants.getResistanceDecimals // TODO: get dynamically, it will update + } + ]; + + // register listeners that update the labels in the scene summary - this summary exists for life of sim, + // no need to dispose + valueItemList.forEach( function( item ) { + item.property.link( function( value ) { + + // the precision might change during interaction, get precision if property is a function + var precision = typeof item.precision === 'number' ? item.precision : item.precision( value ); + console.log( item.patternString ); + item.node.accessibleLabelAsHTML = StringUtils.fillIn( item.patternString, { + value: Util.toFixed( value, precision ) + } ); + } ); + } ); + } + + resistanceInAWire.register( 'AccessibleSummaryNode', AccessibleSummaryNode ); + + return inherit( AccessibleSectionNode, AccessibleSummaryNode, {} ); +} ); \ No newline at end of file diff --git a/js/resistance-in-a-wire/view/ControlPanel.js b/js/resistance-in-a-wire/view/ControlPanel.js index 4a399c9..26e1d4d 100644 --- a/js/resistance-in-a-wire/view/ControlPanel.js +++ b/js/resistance-in-a-wire/view/ControlPanel.js @@ -36,12 +36,12 @@ define( function( require ) { var resistivitySymbolString = require( 'string!RESISTANCE_IN_A_WIRE/resistivitySymbol' ); // a11y strings (not ready for i18n) - var resistivityUnitsPatternString = ResistanceInAWireA11yStrings.resistivityUnitsPatternString; - var lengthUnitsPatternString = ResistanceInAWireA11yStrings.lengthUnitsPatternString; - var areaUnitsPatternString = ResistanceInAWireA11yStrings.areaUnitsPatternString; - var resistivitySliderLabelString = ResistanceInAWireA11yStrings.resistivitySliderLabelString; - var lengthSliderLabelString = ResistanceInAWireA11yStrings.lengthSliderLabelString; - var areaSliderLabelString = ResistanceInAWireA11yStrings.areaSliderLabelString; + var resistivityUnitsPatternString = ResistanceInAWireA11yStrings.resistivityUnitsPatternString.value; + var lengthUnitsPatternString = ResistanceInAWireA11yStrings.lengthUnitsPatternString.value; + var areaUnitsPatternString = ResistanceInAWireA11yStrings.areaUnitsPatternString.value; + var resistivitySliderLabelString = ResistanceInAWireA11yStrings.resistivitySliderLabelString.value; + var lengthSliderLabelString = ResistanceInAWireA11yStrings.lengthSliderLabelString.value; + var areaSliderLabelString = ResistanceInAWireA11yStrings.areaSliderLabelString.value; // constants var SLIDER_SPACING = 50; diff --git a/js/resistance-in-a-wire/view/ResistanceInAWireScreenView.js b/js/resistance-in-a-wire/view/ResistanceInAWireScreenView.js index d58d93c..9923f23 100644 --- a/js/resistance-in-a-wire/view/ResistanceInAWireScreenView.js +++ b/js/resistance-in-a-wire/view/ResistanceInAWireScreenView.js @@ -10,6 +10,7 @@ define( function( require ) { 'use strict'; // modules + var AccessibleSummaryNode = require( 'RESISTANCE_IN_A_WIRE/resistance-in-a-wire/view/AccessibleSummaryNode' ); var ArrowNode = require( 'SCENERY_PHET/ArrowNode' ); var ControlPanel = require( 'RESISTANCE_IN_A_WIRE/resistance-in-a-wire/view/ControlPanel' ); var FocusHighlightPath = require( 'SCENERY/accessibility/FocusHighlightPath' ); @@ -33,6 +34,10 @@ define( function( require ) { tandem: tandem } ); + // a11y - Create and add the summary for this simulation, the first thing screen reader users encounter + var summaryNode = new AccessibleSummaryNode( model ); + this.addChild( summaryNode ); + // Create the control panel with sliders that change the values of the equation's variables. Hard coded var controlPanel = new ControlPanel( model, tandem.createTandem( 'controlPanel' ), { right: this.layoutBounds.right - 30, @@ -88,7 +93,7 @@ define( function( require ) { this.addChild( controlPanel ); // a11y - the reset all button should come last, control panel first - this.accessibleOrder = [ controlPanel ]; + this.accessibleOrder = [ summaryNode, controlPanel ]; } resistanceInAWire.register( 'ResistanceInAWireScreenView', ResistanceInAWireScreenView );