@@ -39,7 +39,7 @@ window.graphTool = (containerId, options) => {
3939 underConstructionFixed : JXG . palette . red // defined to be '#d55e00'
4040 } ;
4141
42- gt . definingPointAttributes = {
42+ gt . definingPointAttributes = ( ) => ( {
4343 size : 3 ,
4444 fixed : false ,
4545 highlight : true ,
@@ -49,8 +49,9 @@ window.graphTool = (containerId, options) => {
4949 fillColor : gt . color . point ,
5050 highlightStrokeWidth : 1 ,
5151 highlightStrokeColor : gt . color . focusCurve ,
52- highlightFillColor : gt . color . pointHighlight
53- } ;
52+ highlightFillColor : gt . color . pointHighlight ,
53+ tabindex : gt . isStatic ? - 1 : 0
54+ } ) ;
5455
5556 gt . options = options ;
5657 gt . snapSizeX = options . snapSizeX ? options . snapSizeX : 1 ;
@@ -255,6 +256,113 @@ window.graphTool = (containerId, options) => {
255256 gt . board . highlightInfobox = ( _x , _y , el ) => gt . board . highlightCustomInfobox ( '' , el ) ;
256257
257258 if ( ! gt . isStatic ) {
259+ // This is a mess to work around an issue with JSXGraph versions 1.11.1 or later. Their keyDownListener
260+ // calls preventDefault on the keydown event when shift-tab is pressed. That prevents keyboard focus from
261+ // moving backward in the tab order. So this removes the JSXGraph keyboard event handlers, then overrides
262+ // the board's keyDownListener with essentially the same code with the exception that when the tab key is
263+ // pressed, preventDefault is not called. Then the keyboard event listeners are added back, using this
264+ // keydownListener.
265+ gt . board . removeKeyboardEventHandlers ( ) ;
266+ gt . board . keyDownListener = function ( evt ) {
267+ const id_node = evt . target . id ;
268+ let done = true ;
269+
270+ if ( ! this . attr . keyboard . enabled || id_node === '' ) return false ;
271+
272+ const doc = this . containerObj . shadowRoot || document ;
273+ if ( doc . activeElement ) {
274+ if ( doc . activeElement . tagName === 'INPUT' || doc . activeElement . tagName === 'textarea' ) return false ;
275+ }
276+
277+ const id = id_node . replace ( this . containerObj . id + '_' , '' ) ;
278+ const el = this . select ( id ) ;
279+
280+ if (
281+ ( JXG . evaluate ( this . attr . keyboard . panshift ) && evt . shiftKey ) ||
282+ ( JXG . evaluate ( this . attr . keyboard . panctrl ) && evt . ctrlKey )
283+ ) {
284+ const doZoom = JXG . evaluate ( this . attr . zoom . enabled ) === true ;
285+ if ( evt . keyCode === 38 ) this . clickUpArrow ( ) ;
286+ else if ( evt . keyCode === 40 ) this . clickDownArrow ( ) ;
287+ else if ( evt . keyCode === 37 ) this . clickLeftArrow ( ) ;
288+ else if ( evt . keyCode === 39 ) this . clickRightArrow ( ) ;
289+ else if ( doZoom && evt . keyCode === 171 ) this . zoomIn ( ) ;
290+ else if ( doZoom && evt . keyCode === 173 ) this . zoomOut ( ) ;
291+ else if ( doZoom && evt . keyCode === 79 ) this . zoom100 ( ) ;
292+ else done = false ;
293+ } else if ( ! evt . shiftKey && ! evt . ctrlKey ) {
294+ let dx = JXG . evaluate ( this . attr . keyboard . dx ) / this . unitX ;
295+ let dy = JXG . evaluate ( this . attr . keyboard . dy ) / this . unitY ;
296+ if ( JXG . exists ( el . visProp ) ) {
297+ if (
298+ JXG . exists ( el . visProp . snaptogrid ) &&
299+ el . visProp . snaptogrid &&
300+ el . evalVisProp ( 'snapsizex' ) &&
301+ el . evalVisProp ( 'snapsizey' )
302+ ) {
303+ const res = el . getSnapSizes ( ) ;
304+ dx = res [ 0 ] ;
305+ dy = res [ 1 ] ;
306+ } else if (
307+ JXG . exists ( el . visProp . attracttogrid ) &&
308+ el . visProp . attracttogrid &&
309+ el . evalVisProp ( 'attractordistance' ) &&
310+ el . evalVisProp ( 'attractorunit' )
311+ ) {
312+ let sX = 1.1 * el . evalVisProp ( 'attractordistance' ) ;
313+ let sY = sX ;
314+ if ( el . evalVisProp ( 'attractorunit' ) === 'screen' ) {
315+ sX /= this . unitX ;
316+ sY /= this . unitX ;
317+ }
318+ dx = Math . max ( sX , dx ) ;
319+ dy = Math . max ( sY , dy ) ;
320+ }
321+ }
322+
323+ let dir ;
324+ if ( evt . keyCode === 38 ) dir = [ 0 , dy ] ;
325+ else if ( evt . keyCode === 40 ) dir = [ 0 , - dy ] ;
326+ else if ( evt . keyCode === 37 ) dir = [ - dx , 0 ] ;
327+ else if ( evt . keyCode === 39 ) dir = [ dx , 0 ] ;
328+ else done = false ;
329+
330+ if (
331+ dir &&
332+ el . isDraggable &&
333+ el . visPropCalc . visible &&
334+ ( ( this . geonextCompatibilityMode &&
335+ ( JXG . isPoint ( el ) || el . elementClass === Const . OBJECT_CLASS_TEXT ) ) ||
336+ ! this . geonextCompatibilityMode ) &&
337+ ! el . evalVisProp ( 'fixed' )
338+ ) {
339+ this . mode = this . BOARD_MODE_DRAG ;
340+ if ( JXG . exists ( el . coords ) ) {
341+ const actPos = el . coords . usrCoords . slice ( 1 ) ;
342+ dir [ 0 ] += actPos [ 0 ] ;
343+ dir [ 1 ] += actPos [ 1 ] ;
344+ el . setPosition ( JXG . COORDS_BY_USER , dir ) ;
345+ this . updateInfobox ( el ) ;
346+ } else {
347+ this . displayInfobox ( false ) ;
348+ el . setPositionDirectly ( Const . COORDS_BY_USER , dir , [ 0 , 0 ] ) ;
349+ }
350+
351+ this . triggerEventHandlers ( [ 'keymove' , 'move' ] , [ evt , this . mode ] ) ;
352+ el . triggerEventHandlers ( [ 'keydrag' , 'drag' ] , [ evt ] ) ;
353+ this . mode = this . BOARD_MODE_NONE ;
354+ }
355+ } else if ( evt . key === 'Tab' ) {
356+ done = false ;
357+ }
358+
359+ this . update ( ) ;
360+
361+ if ( done && JXG . exists ( evt . preventDefault ) ) evt . preventDefault ( ) ;
362+ return done ;
363+ } ;
364+ gt . board . addKeyboardEventHandlers ( ) ;
365+
258366 gt . graphContainer . tabIndex = - 1 ;
259367 gt . board . containerObj . tabIndex = - 1 ;
260368
@@ -798,7 +906,7 @@ window.graphTool = (containerId, options) => {
798906 const point = gt . board . create ( 'point' , [ gt . snapRound ( x , gt . snapSizeX ) , gt . snapRound ( y , gt . snapSizeY ) ] , {
799907 snapSizeX : gt . snapSizeX ,
800908 snapSizeY : gt . snapSizeY ,
801- ...gt . definingPointAttributes
909+ ...gt . definingPointAttributes ( )
802910 } ) ;
803911 point . setAttribute ( { snapToGrid : true } ) ;
804912 if ( ! gt . isStatic ) {
0 commit comments