Adjusting free-sort stimuli size #795
-
Hi. I'd like to adjust the free-sort plugin so that the pictures aren't a uniform size, and are instead either customizable or just the actual dimensions of the original image. I tried adjusting or commenting out the default value of stim_height and stim_width and it seems to break the dragging functionality. Any recommendations on how to do this?
|
Beta Was this translation helpful? Give feedback.
Replies: 1 comment 2 replies
-
I went ahead and removed the constant height and width requirement, this version of the plugin will not be sensitive to the stim_height and stim_width parameters and will instead use the original dimensions of the image. Here's the diff (ignore the changes to the images, I edited them to test the plugin) diff --git a/examples/img/happy_face_1.jpg b/examples/img/happy_face_1.jpg
index 00891ce..ea73289 100644
Binary files a/examples/img/happy_face_1.jpg and b/examples/img/happy_face_1.jpg differ
diff --git a/examples/img/happy_face_2.jpg b/examples/img/happy_face_2.jpg
index c895ca2..a553f2b 100644
Binary files a/examples/img/happy_face_2.jpg and b/examples/img/happy_face_2.jpg differ
diff --git a/examples/img/happy_face_3.jpg b/examples/img/happy_face_3.jpg
index d00fe2f..5dae554 100644
Binary files a/examples/img/happy_face_3.jpg and b/examples/img/happy_face_3.jpg differ
diff --git a/examples/img/happy_face_4.jpg b/examples/img/happy_face_4.jpg
index 843cb19..a249b22 100644
Binary files a/examples/img/happy_face_4.jpg and b/examples/img/happy_face_4.jpg differ
diff --git a/plugins/jspsych-free-sort.js b/plugins/jspsych-free-sort.js
index e498d7e..a32e9bd 100644
--- a/plugins/jspsych-free-sort.js
+++ b/plugins/jspsych-free-sort.js
@@ -97,15 +97,21 @@ jsPsych.plugins['free-sort'] = (function() {
var init_locations = [];
for (var i = 0; i < trial.stimuli.length; i++) {
- var coords = random_coordinate(trial.sort_area_width - trial.stim_width, trial.sort_area_height - trial.stim_height);
+ // var coords = random_coordinate(trial.sort_area_width - trial.stim_width, trial.sort_area_height - trial.stim_height);
- display_element.querySelector("#jspsych-free-sort-arena").innerHTML += '<img '+
- 'src="'+trial.stimuli[i]+'" '+
- 'data-src="'+trial.stimuli[i]+'" '+
- 'class="jspsych-free-sort-draggable" '+
- 'draggable="false" '+
- 'style="position: absolute; cursor: move; width:'+trial.stim_width+'px; height:'+trial.stim_height+'px; top:'+coords.y+'px; left:'+coords.x+'px;">'+
- '</img>';
+ const image = document.createElement('img')
+ image.src = trial.stimuli[i]
+ image.dataset.src = trial.stimuli[i]
+ image.draggable = false
+ image.classList.add('jspsych-free-sort-draggable')
+
+ display_element.querySelector("#jspsych-free-sort-arena").appendChild(image)
+
+ width = image.width
+ height = image.height
+ var coords = random_coordinate(trial.sort_area_width - width, trial.sort_area_height - height);
+
+ image.style = 'position: absolute; cursor: move; top:'+coords.y+'px; left:'+coords.x+'px;'
init_locations.push({
"src": trial.stimuli[i],
@@ -130,8 +136,8 @@ jsPsych.plugins['free-sort'] = (function() {
elem.style.zIndex = ++maxz;
var mousemoveevent = function(e){
- elem.style.top = Math.min(trial.sort_area_height - trial.stim_height, Math.max(0,(e.clientY - y))) + 'px';
- elem.style.left = Math.min(trial.sort_area_width - trial.stim_width, Math.max(0,(e.clientX - x))) + 'px';
+ elem.style.top = Math.min(trial.sort_area_height - elem.height, Math.max(0,(e.clientY - y))) + 'px';
+ elem.style.left = Math.min(trial.sort_area_width - elem.width, Math.max(0,(e.clientX - x))) + 'px';
}
document.addEventListener('mousemove', mousemoveevent);
And here's the complete plugin. /**
* jspsych-free-sort
* plugin for drag-and-drop sorting of a collection of images
* Josh de Leeuw
*
* documentation: docs.jspsych.org
*/
jsPsych.plugins['free-sort'] = (function() {
var plugin = {};
jsPsych.pluginAPI.registerPreload('free-sort', 'stimuli', 'image');
plugin.info = {
name: 'free-sort',
description: '',
parameters: {
stimuli: {
type: jsPsych.plugins.parameterType.STRING,
pretty_name: 'Stimuli',
default: undefined,
array: true,
description: 'Images to be displayed.'
},
stim_height: {
type: jsPsych.plugins.parameterType.INT,
pretty_name: 'Stimulus height',
default: 100,
description: 'Height of images in pixels.'
},
stim_width: {
type: jsPsych.plugins.parameterType.INT,
pretty_name: 'Stimulus width',
default: 100,
description: 'Width of images in pixels'
},
sort_area_height: {
type: jsPsych.plugins.parameterType.INT,
pretty_name: 'Sort area height',
default: 800,
description: 'The height of the container that subjects can move the stimuli in.'
},
sort_area_width: {
type: jsPsych.plugins.parameterType.INT,
pretty_name: 'Sort area width',
default: 800,
description: 'The width of the container that subjects can move the stimuli in.'
},
prompt: {
type: jsPsych.plugins.parameterType.STRING,
pretty_name: 'Prompt',
default: null,
description: 'It can be used to provide a reminder about the action the subject is supposed to take.'
},
prompt_location: {
type: jsPsych.plugins.parameterType.SELECT,
pretty_name: 'Prompt location',
options: ['above','below'],
default: 'above',
description: 'Indicates whether to show prompt "above" or "below" the sorting area.'
},
button_label: {
type: jsPsych.plugins.parameterType.STRING,
pretty_name: 'Button label',
default: 'Continue',
description: 'The text that appears on the button to continue to the next trial.'
}
}
}
plugin.trial = function(display_element, trial) {
var start_time = performance.now();
var html = "";
// check if there is a prompt and if it is shown above
if (trial.prompt !== null && trial.prompt_location == "above") {
html += trial.prompt;
}
html += '<div '+
'id="jspsych-free-sort-arena" '+
'class="jspsych-free-sort-arena" '+
'style="position: relative; width:'+trial.sort_area_width+'px; height:'+trial.sort_area_height+'px; border:2px solid #444;"'+
'></div>';
// check if prompt exists and if it is shown below
if (trial.prompt !== null && trial.prompt_location == "below") {
html += trial.prompt;
}
display_element.innerHTML = html;
// store initial location data
var init_locations = [];
for (var i = 0; i < trial.stimuli.length; i++) {
// var coords = random_coordinate(trial.sort_area_width - trial.stim_width, trial.sort_area_height - trial.stim_height);
const image = document.createElement('img')
image.src = trial.stimuli[i]
image.dataset.src = trial.stimuli[i]
image.draggable = false
image.classList.add('jspsych-free-sort-draggable')
display_element.querySelector("#jspsych-free-sort-arena").appendChild(image)
width = image.width
height = image.height
var coords = random_coordinate(trial.sort_area_width - width, trial.sort_area_height - height);
image.style = 'position: absolute; cursor: move; top:'+coords.y+'px; left:'+coords.x+'px;'
init_locations.push({
"src": trial.stimuli[i],
"x": coords.x,
"y": coords.y
});
}
display_element.innerHTML += '<button id="jspsych-free-sort-done-btn" class="jspsych-btn">'+trial.button_label+'</button>';
var maxz = 1;
var moves = [];
var draggables = display_element.querySelectorAll('.jspsych-free-sort-draggable');
for(var i=0;i<draggables.length; i++){
draggables[i].addEventListener('mousedown', function(event){
var x = event.pageX - event.currentTarget.offsetLeft;
var y = event.pageY - event.currentTarget.offsetTop - window.scrollY;
var elem = event.currentTarget;
elem.style.zIndex = ++maxz;
var mousemoveevent = function(e){
elem.style.top = Math.min(trial.sort_area_height - elem.height, Math.max(0,(e.clientY - y))) + 'px';
elem.style.left = Math.min(trial.sort_area_width - elem.width, Math.max(0,(e.clientX - x))) + 'px';
}
document.addEventListener('mousemove', mousemoveevent);
var mouseupevent = function(e){
document.removeEventListener('mousemove', mousemoveevent);
moves.push({
"src": elem.dataset.src,
"x": elem.offsetLeft,
"y": elem.offsetTop
});
document.removeEventListener('mouseup', mouseupevent);
}
document.addEventListener('mouseup', mouseupevent);
});
}
display_element.querySelector('#jspsych-free-sort-done-btn').addEventListener('click', function(){
var end_time = performance.now();
var rt = end_time - start_time;
// gather data
// get final position of all objects
var final_locations = [];
var matches = display_element.querySelectorAll('.jspsych-free-sort-draggable');
for(var i=0; i<matches.length; i++){
final_locations.push({
"src": matches[i].dataset.src,
"x": parseInt(matches[i].style.left),
"y": parseInt(matches[i].style.top)
});
}
var trial_data = {
"init_locations": JSON.stringify(init_locations),
"moves": JSON.stringify(moves),
"final_locations": JSON.stringify(final_locations),
"rt": rt
};
// advance to next part
display_element.innerHTML = '';
jsPsych.finishTrial(trial_data);
});
};
// helper functions
function random_coordinate(max_width, max_height) {
var rnd_x = Math.floor(Math.random() * (max_width - 1));
var rnd_y = Math.floor(Math.random() * (max_height - 1));
return {
x: rnd_x,
y: rnd_y
};
}
return plugin;
})(); |
Beta Was this translation helpful? Give feedback.
I went ahead and removed the constant height and width requirement, this version of the plugin will not be sensitive to the stim_height and stim_width parameters and will instead use the original dimensions of the image.
Here's the diff (ignore the changes to the images, I edited them to test the plugin)