Howdy, Stranger!

It looks like you're new here. If you want to get involved, click one of these buttons!

Supported by

Accessing and manipulating loops in Javascript?

Hi there,

I'm looking to modify the size (add rows or columns) and edit the content of a loop using Javascript. Is that actually possible to do? (I read that the loop can be accessed in Python, and I suspect it can be edited using that language using commands from Datamatrix, but I'm after a Javascript solution).

Many thanks in advance!

Fabrice.

Buy Me A Coffee

Comments

  • Hi @Fab ,

    You could inspect the matrix object from a loop item in the browser debugger.

    And there's also the _cycles array, which indicates which cycles from the matrix are still on the to-do list. So basically, this example means that only cycle 1 is still to do, and this corresponds to condition 'b'.

    Manipulating those objects from an inline_javascript is possible. However, in most complex cases it's probably more convenient to bypass the loop table altogether, and to set the experimental variables in some other way.

    — Sebastiaan

  • Hi @sebastiaan,

    Many thanks for this! I'm new to inspecting stuff in the browser and I wouldn't have thought of going to look in there without your pointers! Exciting stuff! I searched around for a bit and managed to find the info you listed in your post:

    I then proceeded to try to write to the console in OSWeb and had mixed results at first, which made me realize that the runner._experiment.experiment.items._items.block_trials.matrix does not exist until the block_trials is being executed. I tried setting its length to something different from its actual length:

    runner._experiment.experiment.items._items.block_trials.matrix["length"] = 10
    

    While the info gets written properly, the actual length of the matrix does not change, which makes sense, since the matrix is already running. So that prompted me to explore what I could find in the runner object (I'm calling that an object, though I have no idea whether this is the appropriate term for this) before the block_trials loop is executed, and that's when I came across runner._experiment.experiment.items._items.block_trials.orig_matrix. I figure this declares the loop as it stands in the OSWeb task, and that the program then uses that original matrix to create the one that will run in the loop (runner._experiment.experiment.items._items.block_trials.matrix). So I tried changing the length of the orig_matrix and... bingo!! 😃 If I set that value to 5, for example, my blocks_trials loop runs the trial sequence five times! Gonna keep playing around a bit to experiment with it a bit.

    Thanks very much for the pointers! I'll surely explore the debugger further; looks like a gold mine and a great way of looking into the inner workings of the task !

    Best,

    Fabrice.

    PS: I noticed my posts now magically have a footer 😉. Cool! Thanks for that too!!

    Buy Me A Coffee

  • FabFab
    edited August 2021

    (Update)

    Looks like I jumped the gun on the previous post...

    Setting the length of the orig_matrix isn't sufficient. It looks as if I have to populate each element of that matrix. I've tested it with the default empty table in OS (so, just one empty row). In addition to setting the length of the orig_matrix to a specific size, now I also run a loop where I set each element to be equal to the previous.

    runner._experiment.experiment.items._items.block_trials.orig_matrix["length"] = trials_per_block
    for (let i = 1; i < trials_per_block; i++) {
    runner._experiment.experiment.items._items.block_trials.orig_matrix[i]=runner._experiment.experiment.items._items.block_trials.orig_matrix[i-1];
    }
    

    That works. The task runs the number of trials I set up.

    Buy Me A Coffee

  • Hi @Fab ,

    Good to hear that you made it so far. The way that the loop table constructs the matrix is a bit messy, but here's an attempt at getting it straight (also for myself):

    • orig_matrix is, as you assumed, a regular array where each element corresponds to a row, and each row is itself a dict-like object with column to value mappings. (To clarify: it's called matrix , but has nothing to do with the DataMatrix class that is used in Python for this purpose.)
    • matrix is like the orig_matrix , but then 'unfolded' with repeats, randomization, loop operations etc. taken into account.
    • _cycles is an array of indices to matrix that still need to be executed. This array is slowly shift() -ed out of existence until the loop is done. So basically, if you want to repeat a row, then you should push() the index of that row to _cycles .

    In a nutshell, that's it. You can also look at the actual implementation here:

    — Sebastiaan

  • Hi @sebastiaan,

    Thanks for this! That's really helpful to understand how the system works 👍️. I'll look up some of the commands/properties you mentioned (like dict, shift, or push). From your description, I imagine that an alternative to what I was doing (setting up the orig_matrix ahead of the loop being executed) could be to use the push function while the loop is executed to add the desired number of trials (rows). Definitely something I'd explore in the future if a task needs a dynamic change of the loop while it's running.

    Thanks!

    Best,

    Fabrice.

    Buy Me A Coffee

Sign In or Register to comment.