FelixHenninger / lab.js

Online research made easy
https://lab.js.org/
Other
239 stars 107 forks source link

Images not loading #228

Open alexandrakirby opened 4 months ago

alexandrakirby commented 4 months ago

I am trying to help a dissertation student add distractor images to their N-Back test. For content, I am using the following html code:

<header>
  <h2>Set 1</h2>
</header>

<main class="content-vertical-center content-horizontal-center" id="main-container">
  <div class="stimulus">
    ${ parameters.stimulus }
  </div>
</main>

<img id="distractor-image" src="{ $this.files[this.parameters.distractor] } /">

<footer>
  Press <kbd>j</kbd> if the current letter is a <strong>B</strong> or a <strong>b</strong>. Otherwise press <kbd>k</kbd>.
</footer>

In scripts, I am using the following JavaScript so that the letter for the N-Back appears in the centre of the screen, and the image randomly appears above, below, to the right, or to the left of the main stimulus:

// Define HTML template
var htmlTemplate = `
<header>
  <h2>Set 1</h2>
</header>

<main class="content-vertical-center content-horizontal-center" id="main-container">
  <div class="stimulus">
    ${ parameters.stimulus }
  </div>
</main>

<img id="distractor-image" src="{ $this.files[this.parameters.distractor] } /">

<footer>
  Press <kbd>j</kbd> if the current letter is a <strong>B</strong> or a <strong>b</strong>. Otherwise press <kbd>k</kbd>.
</footer>
`;

// Create HTML template object
var html = new lab.html.Template(htmlTemplate);

// Define function to position distractor image randomly
function positionDistractorRandomly() {
    var mainContainer = document.getElementById("main-container");
    var distractorImage = document.getElementById("distractor-image");

    var mainRect = mainContainer.getBoundingClientRect();
    var mainCenterX = mainRect.left + mainRect.width / 2;
    var mainCenterY = mainRect.top + mainRect.height / 2;

    var offset = 50; // Adjust this value as needed for spacing between containers

    // Randomly select a direction (top, right, bottom, left)
    var randomDirection = Math.floor(Math.random() * 4);

    // Calculate random position for the distractor image
    switch(randomDirection) {
        case 0: // Above main-container
            distractorImage.style.left = mainCenterX - distractorImage.width / 2 + "px";
            distractorImage.style.top = mainRect.top - distractorImage.height - offset + "px";
            break;
        case 1: // To the right of main-container
            distractorImage.style.left = mainRect.right + offset + "px";
            distractorImage.style.top = mainCenterY - distractorImage.height / 2 + "px";
            break;
        case 2: // Below main-container
            distractorImage.style.left = mainCenterX - distractorImage.width / 2 + "px";
            distractorImage.style.top = mainRect.bottom + offset + "px";
            break;
        case 3: // To the left of main-container
            distractorImage.style.left = mainRect.left - distractorImage.width - offset + "px";
            distractorImage.style.top = mainCenterY - distractorImage.height / 2 + "px";
            break;
        default:
            break;
    }
}

// Create a sequence
var sequence = new lab.flow.Sequence({
    content: [html],
    // Execute positioning JavaScript after the HTML has been rendered
    onNew: function() {
        positionDistractorRandomly();
    }
});

// Run the sequence
sequence.run();

When testing the study, a broken image link symbol appears in the bottom left corner. Can anyone help me adjust the code so that the image loads? There are three images files uploaded.

mcfarla9 commented 4 months ago

Try replacing <img id="distractor-image" src="{ $this.files[this.parameters.distractor] } /"> with either <img id="distractor-image" src="{ $this.files[this.parameters.distractor] }" /> or even simply <img id="distractor-image" src="{ $this.files[this.parameters.distractor] }"> (personally I prefer including the explicit "/>" to close the element, but that is a style issue).

alexandrakirby commented 4 months ago

Thanks @mcfarla9, I have tried this both ways and I am still receiving the same issue: image

Perhaps I am not defining the parameter properly? I have done this in the loop section where the main stimuli is defined: image

mcfarla9 commented 4 months ago

At this stage I would set aside the main project and work through some small demos in order to figure out how things work, then import what I learned into the main project.

In particular, here I would set aside all the scripting. I would make a demo that does nothing but present a sequence of stimulus images (using a Loop component) in a fixed order (I always save randomizaiton for the last step in development, it greatly simplifies the testing!). Then I would add a distractor image. Etc.

Anyway, I did some fussing around myself, and it looks like the following should work in your Content: <img id="distractor-image" src=${this.files[this.parameters.distractor]} />

You have to pay attention to where each $, {}, and [] should go.

mcfarla9 commented 4 months ago

Oh, since you used this.files in your Content, I assumed that you were storing the distractor files directly within the stimulus component. But from your screen shot it looks like you are storing your distractor files out in the static area. That changes everything. In that case you would reduce that line in your Content to simply <img id="distractor-image" src=${this.parameters.distractor} />

Or if in your Loop you would rather put just the distractor file names without "static/" at the front of each one, you could add the "static/" string in the Content thus <img id="distractor-image" src="static/${this.parameters.distractor}" />