@@ -293,17 +293,9 @@ class FreeSortOrderedPlugin implements JsPsychPlugin<Info> {
293
293
// on pointer move, check if the stimulus is inside a box and update its position
294
294
const on_pointer_move = ( { clientX, clientY } : PointerEvent ) => {
295
295
inside [ i ] = Utils . inside_box ( clientX - x , clientY - y , boxAreas ) ;
296
- this . style . top =
297
- Math . min (
298
- window . innerHeight - trial . stim_height , // Bottom boundary of the viewport
299
- Math . max ( 0 , clientY - y ) // Top boundary of the viewport
300
- ) + "px" ;
301
-
302
- this . style . left =
303
- Math . min (
304
- window . innerWidth - trial . stim_width , // Right boundary of the viewport
305
- Math . max ( 0 , clientX - x ) // Left boundary of the viewport
306
- ) + "px" ;
296
+ this . style . top = clientY - y + "px" ;
297
+
298
+ this . style . left = clientX - x + "px" ;
307
299
308
300
// modify text and background if all items are inside
309
301
if ( inside . every ( Boolean ) ) {
@@ -322,6 +314,22 @@ class FreeSortOrderedPlugin implements JsPsychPlugin<Info> {
322
314
const on_pointer_up = ( e ) => {
323
315
document . removeEventListener ( "pointermove" , on_pointer_move ) ;
324
316
this . style . transform = "scale(1, 1)" ;
317
+ let snapped = false ;
318
+ for ( const box of boxAreas ) {
319
+ const distanceX = Math . abs ( this . offsetLeft - box . left ) ;
320
+ const distanceY = Math . abs ( this . offsetTop - box . top ) ;
321
+
322
+ // Define a snapping threshold (e.g., 20px)
323
+ const snappingThreshold = 20 ;
324
+
325
+ if ( distanceX <= snappingThreshold && distanceY <= snappingThreshold ) {
326
+ // Snap the draggable to the box
327
+ this . style . left = box . left + "px" ;
328
+ this . style . top = box . top + "px" ;
329
+ snapped = true ;
330
+ break ;
331
+ }
332
+ }
325
333
moves . push ( {
326
334
src : this . dataset . src ,
327
335
x : this . offsetLeft ,
0 commit comments