magpie-ea / magpie-modules

the reusable front-end bits in the _magpie modules
MIT License
7 stars 1 forks source link

Add possibility for setup info in babeInit #38

Closed JannisBush closed 5 years ago

JannisBush commented 5 years ago

Sometimes you want to have some information "globally" available in all your views. At the moment there is no nice way to do this. You can define a custom intro view and add properties to the babe object there (e.g. the init view in the color reference game does this). Or you could try to insert some properties through hidden text in the normal intro view (e.g. something like

text: `Thank you! <p hidden>${window["babe.data.space_target"]='circle'}</p>` 

) Or you make the information completely globally available (that is also to the console in the browser of the participants). E.g. you could add const space_target = 'circle'; in views.js (Order matters)


One idea would be to define shared info that is passed to babeInit and there it just gets added to the babe-object.

// call of babeInit
babeInit({
    views_seq: [],
    shared_info: {myinfo: 5, mylist: [1,2,3]}
};

// in babeInit
const babe = {};
babe.shared_info = config.shared_info; // new
JannisBush commented 5 years ago

The problem with this approach is that the shared_info is only available after calling babeInit in main.js, therefore you cannot use the shared_info in views.js.

const get_shared_variable = function(var_name){ return ${start_delim}${var_name}${end_delim}; };

const replace_in_string = function(element, babe){ if (typeof element !== "string"){ return element; } let start = element.search(start_delim) + start_delim.length; let end = element.search(end_delim); while (start !== -1 && end !== -1) { let var_name = element.substring(start, end); element = element.replace(var_name, babe.shared_info[var_name]); element = element.replace(start_delim, ""); element = element.replace(end_delim, ""); start = element.search(start_delim) + start_delim.length; end = element.search(end_delim); } return element; };

const replace_all_strings = function(obj, babe){ if (typeof obj === "object"){ for (let sub_obj in obj) { obj[sub_obj] = replace_all_strings(obj[sub_obj], babe) } } else { obj = replace_in_string(obj, babe); } return obj; };


- We add the line `config = (babeUtils.)replace_all_strings(config, babe)` at the start of the render function of each view (or somewhere in babeInit). You could now use `(babeUtils.)get_shared_variable("var_name")` in the instantiation of the views in `views.js` and `trials.js` and the placeholders are replaced with their values, when you see the view. 
- The downsides are: this would only work for Strings, is probably hard to debug and won't work in the name and title of a view

---

- The easiest solution is to just make all shared information globally available in the first file (now `custom_views.js` and not to add it to `babeInit`. 
michael-franke commented 5 years ago

I’m not convinced (yet) by the string replace approach.

The first file that gets loaded is actually trials.js. As far as I can see, this info (e.g., object main_trials) /is/ globally available. An easy solution would be to conceive of trials.js more generally, rename it, for example, to data_input.js (bad name, first shot), and include global information there.

On 29. Mar 2019, at 13:04, JannisBush notifications@github.com wrote:

The problem with this approach is that the shared_info is only available after calling babeInit in main.js, therefore you cannot use the shared_info in views.js.

• One workaround would be to first fill the strings with placeholders in view.js, e.g. `Click on place_startplace_end and later replace the placeholders with the information from shared_info (babe.shared_info[var_name]) const start_delim = "ä,ä,ä,ä,ä,ä,ä,ä" ;

const end_delim = "ü,ü,ü,ü,ü,ü,ü,ü,ü" ;

const get_shared_variable = function(var_name ){

return ${start_delim}${var_name}${end_delim} ; };

const replace_in_string = function(element, babe ){

if (typeof element !== "string" ){

return element; }

let start = element.search(start_delim) + start_delim.length ;

let end = element.search (end_delim);

while (start !== -1 && end !== -1 ) {

let var_name = element.substring (start, end); element = element.replace(var_name, babe.shared_info [var_name]); element = element.replace(start_delim, "" ); element = element.replace(end_delim, "" ); start = element.search(start_delim) + start_delim.length ; end = element.search (end_delim); }

return element; };

const replace_all_strings = function(obj, babe ){

if (typeof obj === "object" ){

for (let sub_obj in obj) { obj[sub_obj] = replace_all_strings (obj[sub_obj], babe) } } else { obj = replace_in_string (obj, babe); }

return obj; };

• We add the line config = (babeUtils.)replace_all_strings(config, babe) at the start of the render function of each view (or somewhere in babeInit). You could now use (babeUtils.)get_shared_variable("var_name") in the instantiation of the views in views.js and trials.js and the placeholders are replaced with their values, when you see the view. • The downsides are: this would only work for Strings, is probably hard to debug and won't work in the name and title of a view • The easiest solution is to just make all shared information globally available in the first file (now custom_views.js and not to add it to babeInit. — You are receiving this because you are subscribed to this thread. Reply to this email directly, view it on GitHub, or mute the thread.

JannisBush commented 5 years ago

I agree, putting the global information in trials.js, seems to be the easiest and cleanest solution.


One more option: Instead of using Strings in the instantiation of views, we could use functions that return Strings and call them in the render function. E.g.

...
QUD: (babe) => `Press space when you see ${babe.shared_info.target}`
...
// in render
const QUD = babeUtils.view.setter.QUD(config.QUD(babe));

But the global information in trials.js is easier to use and understand.

JannisBush commented 5 years ago

You can now add global setup info in 02_custom_functions.js.