GrabDragInteraction¶
Overview¶
The main interaction for grabbing and dragging an object through the PDOM and assistive technology. It works by taking in a Node to augment with the PDOM interaction. In fact it works much like a mixin. In general, this type will mutate the accessible content (PDOM) of the passed in Node, toggling between an "idle" state and a "grabbed" state. When each state changes, the underlying PDOM element and general interaction does as well.
To accomplish this there are options to be filled in that keep track of the scenery inputListeners for each state, as well as options to mutate the Node for each state. By default the idle is a button
with a containing div
, and the grabbed state is a focusable div
with an "application" aria role. It is up to the client to supply a KeyboardDragListener as an arg that will be added to the Node in the "grabbed" state.
As a note on terminology, mostly things are referred to by their current "interaction state" which is either "idle" or "grabbed".
This type will alert when the grabbed state is released, but no default alert is provided when the object is grabbed. This is because in usages so far, that alert has been custom, context specific, and easier to just supply through the onGrab callback option.
NOTE: You SHOULD NOT add listeners directly to the Node where it is constructed, instead see options.listenersWhileIdle/Grabbed
. These will keep track of the listeners for each interaction state, and will set them accordingly. In rare cases it may be desirable to have a listener attached no matter the state, but that has not come up so far.
NOTE: There is no "undo" for a mutate call, so it is the client's job to make sure that idle/grabbedStateOptions objects appropriately "cancel" out the other. The same goes for any alterations that are done on onGrab
and onRelease
callbacks.
NOTE: problems may occur if you change the focusHighlight or interactiveHighlight of the Node passed in after creating this type.
NOTE: focusHighlightLayerable and interactiveHighlightLayerable is finicky with this type. In order to support it, you must have set the focusHighlight or interactiveHighlight to the wrappedNode and added the focusHighlight to the scene graph before calling this type's constructor.
NOTE on positioning the grab "cue" Node: transforming the wrappedNode after creating this type will not update the layout of the grabCueNode. This is because the cue Node is a child of the focus highlight. As a result, currently you must correctly position node before the cue Node is created.
NOTE: upon "activation" of this type, meaning that the user grabs the object and it turns into a grabbed, the wrappedNode is blurred and refocused. This means that the input event "blur()" set in listenersWhileIdle will not just fire when navigating through the sim, but also upon activation. This weirdness is to make sure that the input event "focus()" is called and supported for within listenersWhileGrabbed
NOTE: For PhET-iO instrumentation, GrabDragInteraction.enabledProperty is phetioReadOnly, it makes the most sense to link to whatever Node control's the mouse/touch input and toggle grab drag enabled when that Node's inputEnabled changes. For example see Friction.
@author Michael Kauzmann (PhET Interactive Simulations)
Class GrabDragInteraction¶
Options that can be forwarded to the target Node when the state changes. Fields that are set by the implementation of GrabDragInteraction are omitted. type StateOptions = StrictOmit<ParallelDOMOptions, 'descriptionContent' | 'helpText' | 'descriptionTagName' | 'accessibleName' | 'innerContent' | 'ariaLabel'>;
Constructor¶
new GrabDragInteraction( node : Node, keyboardDragListener : KeyboardDragListener, interactionCueParent : Node, providedOptions? : GrabDragInteractionOptions )¶
Instance Methods¶
setGrabbedStateAccessibleName( name : PDOMValueType )¶
Sets the name to be used when in the "grabbed" state. If already grabbed, the name is set to the target Node right away.
setIdleStateAccessibleName( name : PDOMValueType )¶
Sets the name to be used when in the "idle" state. If already idle, the name is set to the target Node right away. @param name
setKeyboardHelpText( text : PDOMValueType )¶
Set the help text for keboard input. If the runtime supports "gesture description" this is a no-op.
getKeyboardHelpText() : PDOMValueType¶
setGestureHelpText( text : PDOMValueType )¶
Set the help text for gesture input. If the runtime does not support "gesture description" this is a no-op.
getGestureHelpText() : PDOMValueType¶
setOnGrab( onGrab : VoidFunction )¶
Set the callback that should be used when grabbed - called when switching from idle to grabbed state.
getOnGrab() : VoidFunction¶
setOnRelease( onRelease : VoidFunction )¶
Set the callback that should be used when released - called when switching from grabbed to idle state.
getOnRelease() : VoidFunction¶
repositionCues( matrix : Matrix3 | null )¶
Set the positions of the grabCueNode and dragCueNode relative to the target Node. The position is determined by the CuePosition and the offsets.
interrupt()¶
Interrupt the grab drag interraction - interrupts any listeners attached and makes sure the Node is back in its "idle" state.
isInputFromMouseOrTouch() : boolean¶
Often onGrab callbacks need to know whether the grab was triggered from keyboard/pdom, in which case it should trigger description, OR triggered via mouse/touch which may not trigger description because another listener may be responsible.
reset()¶
Reset to initial state
Instance Properties¶
grabCueNode : GrabReleaseCueNode¶
(readonly)
public ONLY to position dynamically. Prefer options.grabCueOptions when possible.
Type CuePosition¶
Valid positions for the interaction cue nodes relative to the target Node. For top and bottom, the cue is centered horizontally. For left and right, the cue is centered vertically.
"center" | "top" | "bottom" | "left" | "right"
Source Code¶
See the source for GrabDragInteraction.ts in the scenery-phet repository.