babe-project
Advanced tools
Comparing version 0.0.7 to 0.0.8
@@ -1,1 +0,1 @@ | ||
function loop(arr,count,shuffleFlag){return _.flatMapDeep(_.range(count),function(i){return arr})}function loopShuffled(arr,count){return _.flatMapDeep(_.range(count),function(i){return _.shuffle(arr)})}const errors={contactEmail:`There is no contact_email given. Please give a contact_email to the babeInit function,\n\nfor example:\n\nbabeInit({\n ...\n deploy: {\n ...\n contact_email: 'yourcontactemail@email.sample',\n ...\n },\n ...\n});`,prolificURL:`There is no prolificURL given. Please give a prolificURL to the babeInit function,\n\nfor example:\n\nbabeInit({\n ...\n deploy: {\n ...\n prolificURL: 'https://app.prolific.ac/submissions/complete?cc=SAMPLE',\n ...\n },\n ...\n});`,noTrials:`No trials given. Each _babe view takes an object with an obligatory 'trial' property.\n\nfor example:\n\nvar introView = intro({\n ...\n trials: 1,\n ...\n});\n\nYou can find more information at https://github.com/babe-project/babe-base#views-in-_babe`,noName:`No name given. Each _babe view takes an object with an obligatory 'name' property\n\nfor example:\n\nvar introView = intro({\n ...\n name: 'introView',\n ...\n});\n\nYou can find more information at https://github.com/babe-project/babe-base#views-in-_babe`,noData:`No data given. Each _babe view takes an object with an obligatory 'data' property\n\nfor example:\n\nvar mainTrials = forcedChoice({\n ...\n data: my_main_trials,\n ...\n});\n\nThe data is a list of objects defined in your local js file.\n\n_babe's trial views expect each trial object to have specific properties. Here is an example of a forcedCoice view trial:\n\n{\n question: 'How are you today?',\n option1: 'fine',\n option2: 'good'\n}\n\nYou can find more information at https://github.com/babe-project/babe-base#views-in-_babe`,noTrialType:`No trial_type given. Each _babe view takes an object with an obligatory 'trial_type' property\n\nfor example:\n\nvar mainTrials = forcedChoice({\n ...\n trial_type: 'main trials',\n ...\n});\n\nThe trial type is needed for recording the results of your experiment.\n\nYou can find more information at https://github.com/babe-project/babe-base#views-in-_babe`,notAnArray:`The data is not an array. Trial views get an array of objects.\n\nfor example:\n\nvar mainTrials = forcedChoice({\n ...\n data: [\n {\n prop: val,\n prop: val\n },\n {\n prop: val,\n prop:val\n }\n ],\n ...\n});`,noSuchViewName:`The view name listed in progress_bar.in does not exist. Use the view names to reference the views in progress_bar.in.\n\nfor example:\n\nvar mainView = forcedChoice({\n ...\n name: 'myMainView',\n ...\n});\n\nvar introView = intro({\n ...\n name: 'intro',\n ...\n});\n\nbabeInit({\n ...\n progress_bar: {\n in: [\n "myMainView"\n ],\n style: "chunks"\n width: 100\n },\n ...\n});\n`};const _babeViews={intro:function(config){paramsChecker(config,"intro");const _intro={name:config.name,title:config.title,text:config.text,buttonText:config.buttonText,render:function(CT,_babe){const viewTemplate=`<div class='view'>\n {{# title }}\n <h1 class="title">{{ title }}</h1>\n {{/ title }}\n {{# text }}\n <section class="text-container">\n <p class="text">{{{ text }}}</p>\n </section>\n {{/ text }}\n <p id="prolific-id-form">\n <label for="prolific-id">Please, enter your Prolific ID</label>\n <input type="text" id="prolific-id" />\n </p>\n {{# button }}\n <button id="next" class="nodisplay">{{ button }}</button>\n {{/ button }}\n {{^ button }}\n <button id="next" class="nodisplay">Begin Experiment</button>\n {{/ button }}\n </div>`;$("#main").html(Mustache.render(viewTemplate,{title:this.title,text:this.text,button:this.buttonText}));const prolificId=$("#prolific-id");const IDform=$("#prolific-id-form");const next=$("#next");function showNextBtn(){if(prolificId.val().trim()!==""){next.removeClass("nodisplay")}else{next.addClass("nodisplay")}}if(_babe.deploy.deployMethod!=="Prolific"){IDform.addClass("nodisplay");next.removeClass("nodisplay")}prolificId.on("keyup",function(){showNextBtn()});prolificId.on("focus",function(){showNextBtn()});next.on("click",function(){if(_babe.deploy.deployMethod==="Prolific"){_babe.global_data.prolific_id=prolificId.val().trim()}_babe.findNextView()})},CT:0,trials:config.trials};return _intro},instructions:function(config){paramsChecker(config,"instructions");const _instructions={name:config.name,title:config.title,text:config.text,buttonText:config.buttonText,render:function(CT,_babe){const viewTemplate=`<div class="view">\n {{# title }}\n <h1>{{ title }}</h1>\n {{/ title }}\n {{# text }}\n <section class="text-container">\n <p class="text">{{ text }}</p>\n </section>\n {{/ text }}\n {{# button }}\n <button id="next">{{ button }}</button>\n {{/ button }}\n </div>`;$("#main").html(Mustache.render(viewTemplate,{title:this.title,text:this.text,button:this.buttonText}));$("#next").on("click",function(){_babe.findNextView()})},CT:0,trials:config.trials};return _instructions},begin:function(config){paramsChecker(config,"begin experiment");const _begin={name:config.name,text:config.text,render:function(CT,_babe){const viewTemplate=`<div class="view">\n {{# text }}\n <section class="text-container">\n <p class="text">{{ text }}</p>\n </section>\n {{/ text }}\n <button id="next">Begin Experiment</button>\n </div>`;$("#main").html(Mustache.render(viewTemplate,{title:this.title,text:this.text}));$("#next").on("click",function(e){_babe.findNextView()})},CT:0,trials:config.trials};return _begin},forcedChoice:function(config){checkTrialView(config,"forced choice");paramsChecker(config,"forced choice");const _forcedChoice={name:config.name,render:function(CT,_babe){const viewTemplate=`<div class="view">\n <div class="picture", align = "center">\n <img src={{picture}} alt="a picture" height="100" width="100">\n </div>\n <p class="question">\n {{# question }}\n {{ question }}\n {{/ question }}\n </p>\n <p class="answer-container buttons-container">\n <label for="yes" class="button-answer">{{ option1 }}</label>\n <input type="radio" name="answer" id="yes" value={{ option1 }} />\n <input type="radio" name="answer" id="no" value={{ option2 }} />\n <label for="no" class="button-answer">{{option2}}</label>\n </p>\n </div>`;$("#main").html(Mustache.render(viewTemplate,{question:config.data[CT].question,option1:config.data[CT].option1,option2:config.data[CT].option2,picture:config.data[CT].picture}));const startingTime=Date.now();$("input[name=answer]").on("change",function(){const RT=Date.now()-startingTime;const trial_data={trial_type:config.trial_type,trial_number:CT+1,question:config.data[CT].question,option1:config.data[CT].option1,option2:config.data[CT].option2,option_chosen:$("input[name=answer]:checked").val(),RT:RT};_babe.trial_data.push(trial_data);_babe.findNextView()})},CT:0,trials:config.trials};return _forcedChoice},sliderRating:function(config){checkTrialView(config,"slider rating");paramsChecker(config,"slider rating");const _sliderRating={name:config.name,render:function(CT,_babe){const viewTemplate=`<div class="view">\n <div class="picture", align = "center">\n <img src={{ picture }} alt="a picture" height="100" width="100">\n </div>\n <p class="question">\n {{# question }}\n {{ question }}\n {{/ question }}\n </p>\n <p class="answer-container slider-container">\n <span class="unnatural">{{ option1 }}</span>\n <input type="range" id="response" class="slider-response" min="0" max="100" value="50"/>\n <span class="natural">{{ option2 }}</span>\n </p>\n <button id="next" class="nodisplay">Next</button>\n </div>`;let response;$("#main").html(Mustache.render(viewTemplate,{question:config.data[CT].question,option1:config.data[CT].option1,option2:config.data[CT].option2,picture:config.data[CT].picture}));const startingTime=Date.now();response=$("#response");response.on("change",function(){$("#next").removeClass("nodisplay")});response.on("click",function(){$("#next").removeClass("nodisplay")});$("#next").on("click",function(){const RT=Date.now()-startingTime;const trial_data={trial_type:config.trial_type,trial_number:CT+1,question:config.data[CT].question,option1:config.data[CT].option1,option2:config.data[CT].option2,rating_slider:response.val(),RT:RT};_babe.trial_data.push(trial_data);_babe.findNextView()})},CT:0,trials:config.trials};return _sliderRating},textboxInput:function(config){checkTrialView(config,"textbox input");paramsChecker(config,"textbox input");const _textboxInput={name:config.name,render:function(CT,_babe){const viewTemplate=`<div class="view">\n <p class="question">\n {{# question }}\n {{/ question }}\n {{ question }}\n </p>\n {{# picture }}\n <div class="picture", align = "center">\n <img src={{ picture }} alt="picture" height="100" width="100">\n </div>\n {{/ picture }}\n <p class="answer-container">\n <textarea name="textbox-input" rows=10 cols=50 class="textbox-input" />\n </p>\n <button id="next" class="nodisplay">next</button>\n </div>`;$("#main").html(Mustache.render(viewTemplate,{question:config.data[CT].question,picture:config.data[CT].picture}));const next=$("#next");const textInput=$("textarea");const startingTime=Date.now();textInput.on("keyup",function(){if(textInput.val().trim().length>10){next.removeClass("nodisplay")}else{next.addClass("nodisplay")}});next.on("click",function(){var RT=Date.now()-startingTime;var trial_data={trial_type:config.trial_type,trial_number:CT+1,question:config.data[CT].question,text_input:textInput.val().trim(),RT:RT};_babe.trial_data.push(trial_data);_babe.findNextView()})},CT:0,trials:config.trials};return _textboxInput},dropdownChoice:function(config){checkTrialView(config,"dropdown choice");paramsChecker(config,"dropdown choice");const _dropdownChoice={name:config.name,render:function(CT,_babe){const viewTemplate=`<div class="view">\n <div class="picture", align = "center">\n <img src={{ picture }} alt="a picture" height="100" width="100">\n </div>\n\n {{# question }}\n <p class="answer-container dropdown-container">\n <p class="question">\n {{ question }}\n <select id="response" name="answer">\n <option disabled selected></option>\n <option value={{ option1 }}>{{ option1 }}</option>\n <option value={{ option2 }}>{{ option2 }}</option>\n </select>\n </p>\n <button id="next" class="nodisplay">Next</button>\n </p>\n {{/ question }}\n {{# questionLeftPart }}\n <p class="answer-container dropdown-container">\n <p class="question">\n {{ questionLeftPart }}\n <select id="response" name="answer">\n <option disabled selected></option>\n <option value={{ option1 }}>{{ option1 }}</option>\n <option value={{ option2 }}>{{ option2 }}</option>\n </select>\n {{ questionRightPart }}\n </p>\n <button id="next" class="nodisplay">Next</button>\n </p>\n {{/ questionLeftPart }}\n </div>`;let response;$("#main").html(Mustache.render(viewTemplate,{question:config.data[CT].question,questionLeftPart:config.data[CT].questionLeftPart,questionRightPart:config.data[CT].questionRightPart,option1:config.data[CT].option1,option2:config.data[CT].option2,picture:config.data[CT].picture}));const startingTime=Date.now();response=$("#response");response.on("change",function(){$("#next").removeClass("nodisplay")});$("#next").on("click",function(){const RT=Date.now()-startingTime;const trial_data={trial_type:config.trial_type,trial_number:CT+1,question:config.data[CT].question,option1:config.data[CT].option1,option2:config.data[CT].option2,dropdown_choice:$(response).val(),RT:RT};_babe.trial_data.push(trial_data);_babe.findNextView()})},CT:0,trials:config.trials};return _dropdownChoice},ratingScale:function(config){checkTrialView(config,"rating scale");paramsChecker(config,"rating scale");const _ratingScale={name:config.name,render:function(CT,_babe){const viewTemplate=`<div class="view">\n {{# picture }}\n <div class="picture", align = "center">\n <img src={{ picture }} alt="picture" height="100" width="100">\n </div>\n {{/ picture }}\n\n <p class="question">\n {{# question }}\n {{ question }}\n {{/ question }}\n </p>\n\n <p class="answer-container buttons-container">\n <strong>{{ option1 }}</strong>\n <label for="1" class="rating-answer">1</label>\n <input type="radio" name="answer" id="1" value="1" />\n <label for="2" class="rating-answer">2</label>\n <input type="radio" name="answer" id="2" value="2" />\n <label for="3" class="rating-answer">3</label>\n <input type="radio" name="answer" id="3" value="3" />\n <label for="4" class="rating-answer">4</label>\n <input type="radio" name="answer" id="4" value="4" />\n <label for="5" class="rating-answer">5</label>\n <input type="radio" name="answer" id="5" value="5" />\n <label for="6" class="rating-answer">6</label>\n <input type="radio" name="answer" id="6" value="6" />\n <label for="7" class="rating-answer">7</label>\n <input type="radio" name="answer" id="7" value="7" />\n <strong>{{ option2 }}</strong>\n </p>\n </div>`;$("#main").html(Mustache.render(viewTemplate,{question:config.data[CT].question,option1:config.data[CT].option1,option2:config.data[CT].option2,picture:config.data[CT].picture}));const startingTime=Date.now();$("input[name=answer]").on("change",function(){const RT=Date.now()-startingTime;const trial_data={trial_type:config.trial_type,trial_number:CT+1,question:config.data[CT].question,option1:config.data[CT].option1,option2:config.data[CT].option2,option_chosen:$("input[name=answer]:checked").val(),RT:RT};_babe.trial_data.push(trial_data);_babe.findNextView()})},CT:0,trials:config.trials};return _ratingScale},sentenceChoice:function(config){checkTrialView(config,"sentence choice");paramsChecker(config,"sentence choice");const _sentenceChoice={name:config.name,render:function(CT,_babe){var viewTemplate=`<div class="view">\n {{# picture }}\n <div class="picture" align = "center">\n <img src={{ picture }} alt="picture" height="100" width="100">\n </div>\n {{/ picture }}\n\n <p class="question">\n {{# question }}\n {{ question }}\n {{/ question }}\n </p>\n\n <p class="answer-container buttons-container">\n <label for="1" class="sentence-selection">{{ option1 }}</label>\n <input type="radio" name="answer" id="1" value="{{ option1 }}"/>\n <label for="2" class="sentence-selection">{{ option2 }}</label>\n <input type="radio" name="answer" id="2" value="{{ option2 }}"/>\n </p>\n </div>`;$("#main").html(Mustache.render(viewTemplate,{question:config.data[CT].question,option1:config.data[CT].option1,option2:config.data[CT].option2,picture:config.data[CT].picture}));var startingTime=Date.now();$("input[name=answer]").on("change",function(){var RT=Date.now()-startingTime;var trial_data={trial_type:config.trial_type,trial_number:CT+1,question:config.data[CT].question,option1:config.data[CT].option1,option2:config.data[CT].option2,option_chosen:$("input[name=answer]:checked").val(),RT:RT};_babe.trial_data.push(trial_data);_babe.findNextView()})},CT:0,trials:config.trials};return _sentenceChoice},imageSelection:function(config){checkTrialView(config,"image selection");paramsChecker(config,"image selection");const _imageSelection={name:config.name,render:function(CT,_babe){const viewTemplate=`<div class="view">\n <p class="question">\n {{# question }}\n {{ question }}\n {{/ question }}\n </p>\n\n <p class="answer-container imgs-container">\n <label for="img1" class="img-answer"><img src={{ picture1 }} alt="picture" height="100" width="100"></label>\n <input type="radio" name="answer" id="img1" value={{ option1 }} />\n <input type="radio" name="answer" id="img2" value={{ option2 }} />\n <label for="img2" class="img-answer"><img src={{ picture2 }} alt="picture" height="100" width="100"></label>\n </p>\n </div>`;$("#main").html(Mustache.render(viewTemplate,{question:config.data[CT].question,option1:config.data[CT].option1,option2:config.data[CT].option2,picture1:config.data[CT].picture1,picture2:config.data[CT].picture2}));const startingTime=Date.now();$("input[name=answer]").on("change",function(){const RT=Date.now()-startingTime;const trial_data={trial_type:config.trial_type,trial_number:CT+1,question:config.data[CT].question,option1:config.data[CT].option1,option2:config.data[CT].option2,picture1:config.data[CT].picture1,picture2:config.data[CT].picture2,image_selected:$("input[name=answer]:checked").val(),RT:RT};_babe.trial_data.push(trial_data);_babe.findNextView()})},CT:0,trials:config.trials};return _imageSelection},keyPress:function(config){checkTrialView(config,"key press");paramsChecker(config,"key press");const _keyPress={name:config.name,render:function(CT,_babe){const viewTemplate=`<div class="view">\n <h3>{{ key1 }} = {{ value1 }}, {{ key2 }} = {{ value2 }}</h3>\n <p class="question">\n {{# question }}\n {{/ question }}\n {{ question }}\n </p>\n {{# picture }}\n <div class="picture", align = "center">\n <img src={{ picture }} alt="picture" height="100" width="100">\n </div>\n {{/ picture }}\n </div>`;const key1=config.data[CT].key1;const key2=config.data[CT].key2;$("#main").html(Mustache.render(viewTemplate,{question:config.data[CT].question,picture:config.data[CT].picture,key1:key1,key2:key2,value1:config.data[CT][key1],value2:config.data[CT][key2]}));const startingTime=Date.now();function handleKeyPress(e){const keyPressed=String.fromCharCode(e.which).toLowerCase();if(keyPressed===key1||keyPressed===key2){let correctness;const RT=Date.now()-startingTime;if(config.data[CT].expected===config.data[CT][keyPressed.toLowerCase()]){correctness="correct"}else{correctness="incorrect"}const trial_data={trial_type:config.trial_type,trial_number:CT+1,question:config.data[CT].question,expected:config.data[CT].expected,key_pressed:keyPressed,correctness:correctness,RT:RT};trial_data["key1"]=config.data[CT][key1];trial_data["key2"]=config.data[CT][key2];if(config.data[CT].picture!==undefined){trial_data["picture"]=config.data[CT].picture}if(config.data[CT].question!==undefined){trial_data["question"]=config.data[CT].question}_babe.trial_data.push(trial_data);$("body").off("keydown",handleKeyPress);_babe.findNextView()}}$("body").on("keydown",handleKeyPress)},CT:0,trials:config.trials};return _keyPress},postTest:function(config){paramsChecker(config,"post test");const _postTest={name:config.name,title:config.title,text:config.text,buttonText:config.buttonText,render:function(CT,_babe){const viewTemplate=`<div class="view post-test-templ">\n {{# title }}\n <h1>{{ title }}</h1>\n {{/ title }}\n {{# text }}\n <section class="text-container">\n <p class="text">{{ text }}</p>\n </section>\n {{/ text }}\n <form>\n <p>\n <label for="age">Age:</label>\n <input type="number" name="age" min="18" max="110" id="age" />\n </p>\n <p>\n <label for="gender">Gender:</label>\n <select id="gender" name="gender">\n <option></option>\n <option value="male">male</option>\n <option value="female">female</option>\n <option value="other">other</option>\n </select>\n </p>\n <p>\n <label for="education">Level of Education:</label>\n <select id="education" name="education">\n <option></option>\n <option value="graduated_high_school">Graduated High School</option>\n <option value="graduated_college">Graduated College</option>\n <option value="higher_degree">Higher Degree</option>\n </select>\n </p>\n <p>\n <label for="languages" name="languages">Native Languages: <br /><span>(i.e. the language(s) spoken at home when you were a child)</</span></label>\n <input type="text" id="languages"/>\n </p>\n <p class="comment-sect">\n <label for="comments">Further comments</label>\n <textarea name="comments" id="comments"\n rows="6" cols="40"></textarea>\n </p>\n {{# buttonText }}\n <button id="next">{{ buttonText }}</button>\n {{/ buttonText }}\n {{^ buttonText }}\n <button id="next">Next</button>\n {{/ buttonText }}\n </form>\n </div>`;$("#main").html(Mustache.render(viewTemplate,{title:this.title,text:this.text,buttonText:this.buttonText}));$("#next").on("click",function(e){e.preventDefault();_babe.global_data.age=$("#age").val();_babe.global_data.gender=$("#gender").val();_babe.global_data.education=$("#education").val();_babe.global_data.languages=$("#languages").val();_babe.global_data.comments=$("#comments").val().trim();_babe.global_data.endTime=Date.now();_babe.global_data.timeSpent=(_babe.global_data.endTime-_babe.global_data.startTime)/6e4;_babe.findNextView()})},CT:0,trials:config.trials};return _postTest},thanks:function(config){paramsChecker(config,"thanks");const _thanks={name:config.name,message:config.title,render:function(CT,_babe){var viewTemplate=`<div class="view thanks-templ">\n <h4 class="warning-message">submitting the data\n <div class="loader"></div>\n </h4>\n {{# thanksMessage }}\n <h1 class="thanks-message nodisplay">{{ thanksMessage }}</h1>\n {{/ thanksMessage }}\n {{^ thanksMessage }}\n <h1 class="thanks-message nodisplay">Thank you for taking part in this experiment!</h1>\n {{/ thanksMessage }}\n {{# extraMessage }}\n <h2 class="extra-message nodisplay">{{{ extraMessage }}}</h2>\n {{/ extraMessage }}\n </div>`;if(_babe.deploy.is_MTurk||_babe.deploy.deployMethod==="directLink"){$("#main").html(Mustache.render(viewTemplate,{thanksMessage:this.message}))}else if(_babe.deploy.deployMethod==="Prolific"){$("main").html(Mustache.render(viewTemplate,{thanksMessage:this.message,extraMessage:"Please press the button below to confirm that you completed the experiment with Prolific<br />".concat("<a href=",_babe.deploy.prolificURL,' class="prolific-url">Confirm</a>')}))}else if(_babe.deploy.deployMethod==="debug"){$("main").html(Mustache.render(viewTemplate,{}))}else{console.log("no such _babe.deploy.deployMethod")}_babe.submission.submit(_babe)},CT:0,trials:1};return _thanks}};function paramsChecker(config,view){if(config.trials===undefined||config.trials===""){throw new Error(errors.noTrials.concat(findFile(view)))}if(config.name===undefined||config.name===""){throw new Error(errors.noName.concat(findFile(view)))}}function checkTrialView(config,view){if(config.data===undefined||config.data===null){throw new Error(errors.noData.concat(findFile(view)))}if(config.data instanceof Array===false){throw new Error(errors.notAnArray.concat(findFile(view)))}if(config.trial_type===undefined||config.trial_type===""){throw new Error(errors.noTrialType.concat(findFile(view)))}}function findFile(view){return`\n\nThe problem is in ${view} view.`}function _babeInit(config){const _babe={};_babe.views_seq=_.flatten(config.views_seq);_babe.currentViewCounter=0;_babe.currentTrialCounter=0;_babe.currentTrialInViewCounter=0;_babe.progress_bar=config.progress_bar;_babe.global_data={startDate:Date(),startTime:Date.now()};_babe.trial_data=[];_babe.deploy=config.deploy;_babe.deploy.MTurk_server=_babe.deploy.deployMethod=="MTurkSandbox"?"https://workersandbox.mturk.com/mturk/externalSubmit":_babe.deploy.deployMethod=="MTurk"?"https://www.mturk.com/mturk/externalSubmit":"";_babe.deploy.liveExperiment=_babe.deploy.deployMethod!=="debug";_babe.deploy.is_MTurk=_babe.deploy.MTurk_server!=="";_babe.deploy.submissionURL=_babe.deploy.deployMethod=="localServer"?"http://localhost:4000/api/submit_experiment/"+_babe.deploy.experimentID:_babe.deploy.serverAppURL+_babe.deploy.experimentID;_babe.progress=_babeProgress(_babe);_babe.submission=_babeSubmit(_babe);_babe.findNextView=function(){let currentView=_babe.views_seq[_babe.currentViewCounter];if(_babe.currentTrialInViewCounter<currentView.trials){currentView.render(currentView.CT,_babe)}else{_babe.currentViewCounter++;currentView=_babe.views_seq[_babe.currentViewCounter];_babe.currentTrialInViewCounter=0;if(currentView!==undefined){currentView.render(currentView.CT,_babe)}else{$("#main").html(Mustache.render(`<div class='view'>\n <h1 class="title">Nothing more to show</h1>\n </div>`));return}}_babe.currentTrialInViewCounter++;_babe.currentTrialCounter++;currentView.CT++;if(currentView.hasProgressBar){_babe.progress.update()}};(function(){if(_babe.deploy.deployMethod==="MTurk"||_babe.deploy.deployMethod==="MTurkSandbox"){console.info(`The experiment runs on MTurk (or MTurk's sandbox)\n----------------------------\n\nThe ID of your experiment is ${_babe.deploy.experimentID}\n\nThe results will be submitted ${_babe.deploy.submissionURL}\n\nand\n\nMTurk's server: ${_babe.deploy.MTurk_server}`)}else if(_babe.deploy.deployMethod==="Prolific"){console.info(`The experiment runs on Prolific\n-------------------------------\n\nThe ID of your experiment is ${_babe.deploy.experimentID}\n\nThe results will be submitted to ${_babe.deploy.submissionURL}\n\nwith\n\nProlific URL (must be the same as in the website): ${_babe.deploy.prolificURL}`)}else if(_babe.deploy.deployMethod==="directLink"){console.info(`The experiment uses Direct Link\n-------------------------------\n\nThe ID of your experiment is ${_babe.deploy.experimentID}\n\nThe results will be submitted to ${_babe.deploy.submissionURL}`)}else if(_babe.deploy.deployMethod==="debug"){console.info(`The experiment is in Debug Mode\n-------------------------------\n\nThe results will be displayed in a table at the end of the experiment and available to download in CSV format.`)}else{throw new Error(`There is no such deployMethod.\n\nPlease use 'debug', 'directLink', 'Mturk', 'MTurkSandbox' or 'Prolific'.\n\nThe deploy method you provided is '${_babe.deploy.deployMethod}'.\n\nYou can find more information at https://github.com/babe-project/babe-base`)}if(_babe.deploy.deployMethod==="Prolific"&&(_babe.deploy.prolificURL===undefined||_babe.deploy.prolificURL==="")){throw new Error(errors.prolificURL)}if(_babe.deploy.contact_email===undefined||_babe.deploy.contact_email===""){throw new Error(errors.contactEmail)}})();_babe.progress.add();_babe.findNextView()}function _babeProgress(_babe){let totalProgressParts=0;let progressTrials=0;let totalProgressChunks=0;let filledChunks=0;let fillChunk=false;const _progress={add:function(){_babe.views_seq.map(view=>{for(let j=0;j<_babe.progress_bar.in.length;j++){if(view.name===_babe.progress_bar.in[j]){totalProgressChunks++;totalProgressParts+=view.trials;view.hasProgressBar=true}}})},update:function(){try{addToDOM()}catch(e){console.error(e.message)}const progressBars=$(".progress-bar");let div,filledPart;if(_babe.progress_bar.style==="default"){div=$(".progress-bar").width()/totalProgressParts;filledPart=progressTrials*div}else{div=$(".progress-bar").width()/_babe.views_seq[_babe.currentViewCounter].trials;filledPart=(_babe.currentTrialInViewCounter-1)*div}const filledElem=jQuery("<span/>",{id:"filled"}).appendTo(progressBars[filledChunks]);$("#filled").css("width",filledPart);progressTrials++;if(_babe.progress_bar.style==="chunks"){if(fillChunk===true){filledChunks++;fillChunk=false}if(filledElem.width()===$(".progress-bar").width()-div){fillChunk=true}for(var i=0;i<filledChunks;i++){progressBars[i].style.backgroundColor="#5187BA"}}}};function addToDOM(){var bar;var i;var view=$(".view");var barWidth=_babe.progress_bar.width;var clearfix=jQuery("<div/>",{class:"clearfix"});var container=jQuery("<div/>",{class:"progress-bar-container"});view.css("padding-top",30);view.prepend(clearfix);view.prepend(container);if(_babe.progress_bar.style==="chunks"){for(i=0;i<totalProgressChunks;i++){bar=jQuery("<div/>",{class:"progress-bar"});bar.css("width",barWidth);container.append(bar)}}else if(_babe.progress_bar.style==="separate"){bar=jQuery("<div/>",{class:"progress-bar"});bar.css("width",barWidth);container.append(bar)}else if(_babe.progress_bar.style==="default"){bar=jQuery("<div/>",{class:"progress-bar"});bar.css("width",barWidth);container.append(bar)}else{throw new Error('Progress_bar.style can be set to "default", "separate" or "chunks" in experiment.js')}}return _progress}function _babeSubmit(_babe){const _submit={submit:function(_babe){let data={experiment_id:_babe.deploy.experimentID,trials:addEmptyColumns(_babe.trial_data)};data=_.merge(_babe.global_data,data);if(_babe.deploy.is_MTurk){try{const HITData=getHITData();data["assignment_id"]=HITData["assignmentId"];data["worker_id"]=HITData["workerId"];data["hit_id"]=HITData["hitId"];var form=jQuery("<form/>",{id:"mturk-submission-form",action:config_deploy.MTurk_server}).appendTo(".thanks-templ");jQuery("<input/>",{type:"hidden",name:"data",value:JSON.stringify(data)}).appendTo(form);jQuery("<input/>",{type:"hidden",name:"assignmentId",value:HITData["assignmentId"]}).appendTo(form)}catch(e){console.error(e)}}if(_babe.deploy.liveExperiment){console.log("submits");submitResults(_babe.deploy.contact_email,_babe.deploy.submissionURL,flattenData(data),_babe.deploy)}else{const flattenedData=flattenData(data);$(".warning-message").addClass("nodisplay");jQuery("<h3/>",{text:"Debug Mode"}).appendTo($(".view"));jQuery("<div/>",{class:"debug-results",html:formatDebugData(flattenedData)}).appendTo($(".view"));createCSVForDownload(flattenedData)}}};function submitResults(contactEmail,submissionURL,data,config){contactEmail=typeof contactEmail!=="undefined"?contactEmail:"not provided";$.ajax({type:"POST",url:submissionURL,crossDomain:true,contentType:"application/json",data:JSON.stringify(data),success:function(responseData,textStatus,jqXHR){console.log(textStatus);$(".warning-message").addClass("nodisplay");$(".thanks-message").removeClass("nodisplay");$(".extra-message").removeClass("nodisplay");if(config.is_MTurk){setTimeout(function(){submitToMTurk(data),500})}},error:function(responseData,textStatus,errorThrown){if(config.is_MTurk){submitToMTurk(data);$(".thanks-message").removeClass("nodisplay")}else{if(textStatus=="timeout"){alert("Oops, the submission timed out. Please try again. If the problem persists, please contact "+contactEmail+", including your ID")}else{alert("Oops, the submission failed. The server says: "+responseData.responseText+"\nPlease try again. If the problem persists, please contact "+contactEmail+"with this error message, including your ID")}}}})}function submitToMTurk(){var form=$("#mturk-submission-form");form.submit()}function addEmptyColumns(trialData){var columns=[];for(var i=0;i<trialData.length;i++){for(var prop in trialData[i]){if(trialData[i].hasOwnProperty(prop)&&columns.indexOf(prop)===-1){columns.push(prop)}}}for(var j=0;j<trialData.length;j++){for(var k=0;k<columns.length;k++){if(!trialData[j].hasOwnProperty(columns[k])){trialData[j][columns[k]]="NA"}}}return trialData}function formatDebugData(flattenedData){var output="<table id='debugresults'>";var t=flattenedData[0];output+="<thead><tr>";for(var key in t){if(t.hasOwnProperty(key)){output+="<th>"+key+"</th>"}}output+="</tr></thead>";output+="<tbody><tr>";var entry="";for(var i=0;i<flattenedData.length;i++){var currentTrial=flattenedData[i];for(var k in t){if(currentTrial.hasOwnProperty(k)){entry=String(currentTrial[k]);output+="<td>"+entry.replace(/ /g," ")+"</td>"}}output+="</tr>"}output+="</tbody></table>";return output}function createCSVForDownload(flattenedData){var csvOutput="";var t=flattenedData[0];for(var key in t){if(t.hasOwnProperty(key)){csvOutput+='"'+String(key)+'",'}}csvOutput+="\n";for(var i=0;i<flattenedData.length;i++){var currentTrial=flattenedData[i];for(var k in t){if(currentTrial.hasOwnProperty(k)){csvOutput+='"'+String(currentTrial[k])+'",'}}csvOutput+="\n"}var blob=new Blob([csvOutput],{type:"text/csv"});if(window.navigator.msSaveOrOpenBlob){window.navigator.msSaveBlob(blob,"results.csv")}else{jQuery("<a/>",{class:"button download-btn",html:"Download the results as CSV",href:window.URL.createObjectURL(blob),download:"results.csv"}).appendTo($(".view"))}}function flattenData(data){var trials=data.trials;delete data.trials;var sample_trial=trials[0];for(var trial_key in sample_trial){if(sample_trial.hasOwnProperty(trial_key)){if(data.hasOwnProperty(trial_key)){var new_data_key="glb_"+trial_key;data[new_data_key]=data[trial_key];delete data[trial_key]}}}var out=_.map(trials,function(t){return _.merge(t,data)});return out}function getHITData(){const url=window.location.href;const qArray=url.split("?");const HITData={};if(qArray[1]===undefined){throw new Error("Cannot get participant' s assignmentId from the URL (happens if the experiment does NOT run on MTurk or MTurkSandbox).")}else{qArray=qArray[1].split("&");for(var i=0;i<qArray.length;i++){HITData[qArray[i].split("=")[0]]=qArray[i].split("=")[1]}}return HITData}return _submit} | ||
function _babeInit(config){const _babe={};_babe.views_seq=_.flatten(config.views_seq);_babe.currentViewCounter=0;_babe.currentTrialCounter=0;_babe.currentTrialInViewCounter=0;_babe.progress_bar=config.progress_bar;_babe.global_data={startDate:Date(),startTime:Date.now()};_babe.trial_data=[];_babe.deploy=config.deploy;_babe.deploy.MTurk_server=_babe.deploy.deployMethod=="MTurkSandbox"?"https://workersandbox.mturk.com/mturk/externalSubmit":_babe.deploy.deployMethod=="MTurk"?"https://www.mturk.com/mturk/externalSubmit":"";_babe.deploy.liveExperiment=_babe.deploy.deployMethod!=="debug";_babe.deploy.is_MTurk=_babe.deploy.MTurk_server!=="";_babe.deploy.submissionURL=_babe.deploy.deployMethod=="localServer"?"http://localhost:4000/api/submit_experiment/"+_babe.deploy.experimentID:_babe.deploy.serverAppURL+_babe.deploy.experimentID;_babe.progress=_babeProgress(_babe);_babe.submission=_babeSubmit(_babe);_babe.findNextView=function(){let currentView=_babe.views_seq[_babe.currentViewCounter];if(_babe.currentTrialInViewCounter<currentView.trials){currentView.render(currentView.CT,_babe)}else{_babe.currentViewCounter++;currentView=_babe.views_seq[_babe.currentViewCounter];_babe.currentTrialInViewCounter=0;if(currentView!==undefined){currentView.render(currentView.CT,_babe)}else{$("#main").html(Mustache.render(`<div class='view'>\n <h1 class="title">Nothing more to show</h1>\n </div>`));return}}_babe.currentTrialInViewCounter++;_babe.currentTrialCounter++;currentView.CT++;if(currentView.hasProgressBar){_babe.progress.update()}};(function(){if(_babe.deploy.deployMethod==="MTurk"||_babe.deploy.deployMethod==="MTurkSandbox"){console.info(`The experiment runs on MTurk (or MTurk's sandbox)\n----------------------------\n\nThe ID of your experiment is ${_babe.deploy.experimentID}\n\nThe results will be submitted ${_babe.deploy.submissionURL}\n\nand\n\nMTurk's server: ${_babe.deploy.MTurk_server}`)}else if(_babe.deploy.deployMethod==="Prolific"){console.info(`The experiment runs on Prolific\n-------------------------------\n\nThe ID of your experiment is ${_babe.deploy.experimentID}\n\nThe results will be submitted to ${_babe.deploy.submissionURL}\n\nwith\n\nProlific URL (must be the same as in the website): ${_babe.deploy.prolificURL}`)}else if(_babe.deploy.deployMethod==="directLink"){console.info(`The experiment uses Direct Link\n-------------------------------\n\nThe ID of your experiment is ${_babe.deploy.experimentID}\n\nThe results will be submitted to ${_babe.deploy.submissionURL}`)}else if(_babe.deploy.deployMethod==="debug"){console.info(`The experiment is in Debug Mode\n-------------------------------\n\nThe results will be displayed in a table at the end of the experiment and available to download in CSV format.`)}else{throw new Error(`There is no such deployMethod.\n\nPlease use 'debug', 'directLink', 'Mturk', 'MTurkSandbox' or 'Prolific'.\n\nThe deploy method you provided is '${_babe.deploy.deployMethod}'.\n\nYou can find more information at https://github.com/babe-project/babe-base`)}if(_babe.deploy.deployMethod==="Prolific"&&(_babe.deploy.prolificURL===undefined||_babe.deploy.prolificURL==="")){throw new Error(errors.prolificURL)}if(_babe.deploy.contact_email===undefined||_babe.deploy.contact_email===""){throw new Error(errors.contactEmail)}})();_babe.progress.add();_babe.findNextView()}const _babeViews={intro:function(config){paramsChecker(config,"intro");const _intro={name:config.name,title:config.title,text:config.text,buttonText:config.buttonText,render:function(CT,_babe){const viewTemplate=`<div class='view'>\n {{# title }}\n <h1 class="title">{{ title }}</h1>\n {{/ title }}\n {{# text }}\n <section class="text-container">\n <p class="text">{{{ text }}}</p>\n </section>\n {{/ text }}\n <p id="prolific-id-form">\n <label for="prolific-id">Please, enter your Prolific ID</label>\n <input type="text" id="prolific-id" />\n </p>\n {{# button }}\n <button id="next" class="nodisplay">{{ button }}</button>\n {{/ button }}\n {{^ button }}\n <button id="next" class="nodisplay">Begin Experiment</button>\n {{/ button }}\n </div>`;$("#main").html(Mustache.render(viewTemplate,{title:this.title,text:this.text,button:this.buttonText}));const prolificId=$("#prolific-id");const IDform=$("#prolific-id-form");const next=$("#next");function showNextBtn(){if(prolificId.val().trim()!==""){next.removeClass("nodisplay")}else{next.addClass("nodisplay")}}if(_babe.deploy.deployMethod!=="Prolific"){IDform.addClass("nodisplay");next.removeClass("nodisplay")}prolificId.on("keyup",function(){showNextBtn()});prolificId.on("focus",function(){showNextBtn()});next.on("click",function(){if(_babe.deploy.deployMethod==="Prolific"){_babe.global_data.prolific_id=prolificId.val().trim()}_babe.findNextView()})},CT:0,trials:config.trials};return _intro},instructions:function(config){paramsChecker(config,"instructions");const _instructions={name:config.name,title:config.title,text:config.text,buttonText:config.buttonText,render:function(CT,_babe){const viewTemplate=`<div class="view">\n {{# title }}\n <h1>{{ title }}</h1>\n {{/ title }}\n {{# text }}\n <section class="text-container">\n <p class="text">{{ text }}</p>\n </section>\n {{/ text }}\n {{# button }}\n <button id="next">{{ button }}</button>\n {{/ button }}\n </div>`;$("#main").html(Mustache.render(viewTemplate,{title:this.title,text:this.text,button:this.buttonText}));$("#next").on("click",function(){_babe.findNextView()})},CT:0,trials:config.trials};return _instructions},begin:function(config){paramsChecker(config,"begin experiment");const _begin={name:config.name,text:config.text,render:function(CT,_babe){const viewTemplate=`<div class="view">\n {{# text }}\n <section class="text-container">\n <p class="text">{{ text }}</p>\n </section>\n {{/ text }}\n <button id="next">Begin Experiment</button>\n </div>`;$("#main").html(Mustache.render(viewTemplate,{title:this.title,text:this.text}));$("#next").on("click",function(e){_babe.findNextView()})},CT:0,trials:config.trials};return _begin},forcedChoice:function(config){checkTrialView(config,"forced choice");paramsChecker(config,"forced choice");const _forcedChoice={name:config.name,render:function(CT,_babe){const viewTemplate=`<div class="view">\n <div class="picture", align = "center">\n <img src={{picture}} alt="a picture" height="100" width="100">\n </div>\n <p class="question">\n {{# question }}\n {{ question }}\n {{/ question }}\n </p>\n <p class="answer-container buttons-container">\n <label for="yes" class="button-answer">{{ option1 }}</label>\n <input type="radio" name="answer" id="yes" value={{ option1 }} />\n <input type="radio" name="answer" id="no" value={{ option2 }} />\n <label for="no" class="button-answer">{{option2}}</label>\n </p>\n </div>`;$("#main").html(Mustache.render(viewTemplate,{question:config.data[CT].question,option1:config.data[CT].option1,option2:config.data[CT].option2,picture:config.data[CT].picture}));const startingTime=Date.now();$("input[name=answer]").on("change",function(){const RT=Date.now()-startingTime;const trial_data={trial_type:config.trial_type,trial_number:CT+1,question:config.data[CT].question,option1:config.data[CT].option1,option2:config.data[CT].option2,option_chosen:$("input[name=answer]:checked").val(),RT:RT};_babe.trial_data.push(trial_data);_babe.findNextView()})},CT:0,trials:config.trials};return _forcedChoice},sliderRating:function(config){checkTrialView(config,"slider rating");paramsChecker(config,"slider rating");const _sliderRating={name:config.name,render:function(CT,_babe){const viewTemplate=`<div class="view">\n <div class="picture", align = "center">\n <img src={{ picture }} alt="a picture" height="100" width="100">\n </div>\n <p class="question">\n {{# question }}\n {{ question }}\n {{/ question }}\n </p>\n <p class="answer-container slider-container">\n <span class="unnatural">{{ option1 }}</span>\n <input type="range" id="response" class="slider-response" min="0" max="100" value="50"/>\n <span class="natural">{{ option2 }}</span>\n </p>\n <button id="next" class="nodisplay">Next</button>\n </div>`;let response;$("#main").html(Mustache.render(viewTemplate,{question:config.data[CT].question,option1:config.data[CT].option1,option2:config.data[CT].option2,picture:config.data[CT].picture}));const startingTime=Date.now();response=$("#response");response.on("change",function(){$("#next").removeClass("nodisplay")});response.on("click",function(){$("#next").removeClass("nodisplay")});$("#next").on("click",function(){const RT=Date.now()-startingTime;const trial_data={trial_type:config.trial_type,trial_number:CT+1,question:config.data[CT].question,option1:config.data[CT].option1,option2:config.data[CT].option2,rating_slider:response.val(),RT:RT};_babe.trial_data.push(trial_data);_babe.findNextView()})},CT:0,trials:config.trials};return _sliderRating},textboxInput:function(config){checkTrialView(config,"textbox input");paramsChecker(config,"textbox input");const _textboxInput={name:config.name,render:function(CT,_babe){const viewTemplate=`<div class="view">\n <p class="question">\n {{# question }}\n {{/ question }}\n {{ question }}\n </p>\n {{# picture }}\n <div class="picture", align = "center">\n <img src={{ picture }} alt="picture" height="100" width="100">\n </div>\n {{/ picture }}\n <p class="answer-container">\n <textarea name="textbox-input" rows=10 cols=50 class="textbox-input" />\n </p>\n <button id="next" class="nodisplay">next</button>\n </div>`;$("#main").html(Mustache.render(viewTemplate,{question:config.data[CT].question,picture:config.data[CT].picture}));const next=$("#next");const textInput=$("textarea");const startingTime=Date.now();textInput.on("keyup",function(){if(textInput.val().trim().length>10){next.removeClass("nodisplay")}else{next.addClass("nodisplay")}});next.on("click",function(){var RT=Date.now()-startingTime;var trial_data={trial_type:config.trial_type,trial_number:CT+1,question:config.data[CT].question,text_input:textInput.val().trim(),RT:RT};_babe.trial_data.push(trial_data);_babe.findNextView()})},CT:0,trials:config.trials};return _textboxInput},dropdownChoice:function(config){checkTrialView(config,"dropdown choice");paramsChecker(config,"dropdown choice");const _dropdownChoice={name:config.name,render:function(CT,_babe){const viewTemplate=`<div class="view">\n <div class="picture", align = "center">\n <img src={{ picture }} alt="a picture" height="100" width="100">\n </div>\n\n {{# question }}\n <p class="answer-container dropdown-container">\n <p class="question">\n {{ question }}\n <select id="response" name="answer">\n <option disabled selected></option>\n <option value={{ option1 }}>{{ option1 }}</option>\n <option value={{ option2 }}>{{ option2 }}</option>\n </select>\n </p>\n <button id="next" class="nodisplay">Next</button>\n </p>\n {{/ question }}\n {{# questionLeftPart }}\n <p class="answer-container dropdown-container">\n <p class="question">\n {{ questionLeftPart }}\n <select id="response" name="answer">\n <option disabled selected></option>\n <option value={{ option1 }}>{{ option1 }}</option>\n <option value={{ option2 }}>{{ option2 }}</option>\n </select>\n {{ questionRightPart }}\n </p>\n <button id="next" class="nodisplay">Next</button>\n </p>\n {{/ questionLeftPart }}\n </div>`;let response;$("#main").html(Mustache.render(viewTemplate,{question:config.data[CT].question,questionLeftPart:config.data[CT].questionLeftPart,questionRightPart:config.data[CT].questionRightPart,option1:config.data[CT].option1,option2:config.data[CT].option2,picture:config.data[CT].picture}));const startingTime=Date.now();response=$("#response");response.on("change",function(){$("#next").removeClass("nodisplay")});$("#next").on("click",function(){const RT=Date.now()-startingTime;const trial_data={trial_type:config.trial_type,trial_number:CT+1,question:config.data[CT].question,option1:config.data[CT].option1,option2:config.data[CT].option2,dropdown_choice:$(response).val(),RT:RT};_babe.trial_data.push(trial_data);_babe.findNextView()})},CT:0,trials:config.trials};return _dropdownChoice},ratingScale:function(config){checkTrialView(config,"rating scale");paramsChecker(config,"rating scale");const _ratingScale={name:config.name,render:function(CT,_babe){const viewTemplate=`<div class="view">\n {{# picture }}\n <div class="picture", align = "center">\n <img src={{ picture }} alt="picture" height="100" width="100">\n </div>\n {{/ picture }}\n\n <p class="question">\n {{# question }}\n {{ question }}\n {{/ question }}\n </p>\n\n <p class="answer-container buttons-container">\n <strong>{{ option1 }}</strong>\n <label for="1" class="rating-answer">1</label>\n <input type="radio" name="answer" id="1" value="1" />\n <label for="2" class="rating-answer">2</label>\n <input type="radio" name="answer" id="2" value="2" />\n <label for="3" class="rating-answer">3</label>\n <input type="radio" name="answer" id="3" value="3" />\n <label for="4" class="rating-answer">4</label>\n <input type="radio" name="answer" id="4" value="4" />\n <label for="5" class="rating-answer">5</label>\n <input type="radio" name="answer" id="5" value="5" />\n <label for="6" class="rating-answer">6</label>\n <input type="radio" name="answer" id="6" value="6" />\n <label for="7" class="rating-answer">7</label>\n <input type="radio" name="answer" id="7" value="7" />\n <strong>{{ option2 }}</strong>\n </p>\n </div>`;$("#main").html(Mustache.render(viewTemplate,{question:config.data[CT].question,option1:config.data[CT].option1,option2:config.data[CT].option2,picture:config.data[CT].picture}));const startingTime=Date.now();$("input[name=answer]").on("change",function(){const RT=Date.now()-startingTime;const trial_data={trial_type:config.trial_type,trial_number:CT+1,question:config.data[CT].question,option1:config.data[CT].option1,option2:config.data[CT].option2,option_chosen:$("input[name=answer]:checked").val(),RT:RT};_babe.trial_data.push(trial_data);_babe.findNextView()})},CT:0,trials:config.trials};return _ratingScale},sentenceChoice:function(config){checkTrialView(config,"sentence choice");paramsChecker(config,"sentence choice");const _sentenceChoice={name:config.name,render:function(CT,_babe){var viewTemplate=`<div class="view">\n {{# picture }}\n <div class="picture" align = "center">\n <img src={{ picture }} alt="picture" height="100" width="100">\n </div>\n {{/ picture }}\n\n <p class="question">\n {{# question }}\n {{ question }}\n {{/ question }}\n </p>\n\n <p class="answer-container buttons-container">\n <label for="1" class="sentence-selection">{{ option1 }}</label>\n <input type="radio" name="answer" id="1" value="{{ option1 }}"/>\n <label for="2" class="sentence-selection">{{ option2 }}</label>\n <input type="radio" name="answer" id="2" value="{{ option2 }}"/>\n </p>\n </div>`;$("#main").html(Mustache.render(viewTemplate,{question:config.data[CT].question,option1:config.data[CT].option1,option2:config.data[CT].option2,picture:config.data[CT].picture}));var startingTime=Date.now();$("input[name=answer]").on("change",function(){var RT=Date.now()-startingTime;var trial_data={trial_type:config.trial_type,trial_number:CT+1,question:config.data[CT].question,option1:config.data[CT].option1,option2:config.data[CT].option2,option_chosen:$("input[name=answer]:checked").val(),RT:RT};_babe.trial_data.push(trial_data);_babe.findNextView()})},CT:0,trials:config.trials};return _sentenceChoice},imageSelection:function(config){checkTrialView(config,"image selection");paramsChecker(config,"image selection");const _imageSelection={name:config.name,render:function(CT,_babe){const viewTemplate=`<div class="view">\n <p class="question">\n {{# question }}\n {{ question }}\n {{/ question }}\n </p>\n\n <p class="answer-container imgs-container">\n <label for="img1" class="img-answer"><img src={{ picture1 }} alt="picture" height="100" width="100"></label>\n <input type="radio" name="answer" id="img1" value={{ option1 }} />\n <input type="radio" name="answer" id="img2" value={{ option2 }} />\n <label for="img2" class="img-answer"><img src={{ picture2 }} alt="picture" height="100" width="100"></label>\n </p>\n </div>`;$("#main").html(Mustache.render(viewTemplate,{question:config.data[CT].question,option1:config.data[CT].option1,option2:config.data[CT].option2,picture1:config.data[CT].picture1,picture2:config.data[CT].picture2}));const startingTime=Date.now();$("input[name=answer]").on("change",function(){const RT=Date.now()-startingTime;const trial_data={trial_type:config.trial_type,trial_number:CT+1,question:config.data[CT].question,option1:config.data[CT].option1,option2:config.data[CT].option2,picture1:config.data[CT].picture1,picture2:config.data[CT].picture2,image_selected:$("input[name=answer]:checked").val(),RT:RT};_babe.trial_data.push(trial_data);_babe.findNextView()})},CT:0,trials:config.trials};return _imageSelection},keyPress:function(config){checkTrialView(config,"key press");paramsChecker(config,"key press");const _keyPress={name:config.name,render:function(CT,_babe){const viewTemplate=`<div class="view">\n <h3>{{ key1 }} = {{ value1 }}, {{ key2 }} = {{ value2 }}</h3>\n <p class="question">\n {{# question }}\n {{/ question }}\n {{ question }}\n </p>\n {{# picture }}\n <div class="picture", align = "center">\n <img src={{ picture }} alt="picture" height="100" width="100">\n </div>\n {{/ picture }}\n </div>`;const key1=config.data[CT].key1;const key2=config.data[CT].key2;$("#main").html(Mustache.render(viewTemplate,{question:config.data[CT].question,picture:config.data[CT].picture,key1:key1,key2:key2,value1:config.data[CT][key1],value2:config.data[CT][key2]}));const startingTime=Date.now();function handleKeyPress(e){const keyPressed=String.fromCharCode(e.which).toLowerCase();if(keyPressed===key1||keyPressed===key2){let correctness;const RT=Date.now()-startingTime;if(config.data[CT].expected===config.data[CT][keyPressed.toLowerCase()]){correctness="correct"}else{correctness="incorrect"}const trial_data={trial_type:config.trial_type,trial_number:CT+1,question:config.data[CT].question,expected:config.data[CT].expected,key_pressed:keyPressed,correctness:correctness,RT:RT};trial_data["key1"]=config.data[CT][key1];trial_data["key2"]=config.data[CT][key2];if(config.data[CT].picture!==undefined){trial_data["picture"]=config.data[CT].picture}if(config.data[CT].question!==undefined){trial_data["question"]=config.data[CT].question}_babe.trial_data.push(trial_data);$("body").off("keydown",handleKeyPress);_babe.findNextView()}}$("body").on("keydown",handleKeyPress)},CT:0,trials:config.trials};return _keyPress},postTest:function(config){paramsChecker(config,"post test");const _postTest={name:config.name,title:config.title,text:config.text,buttonText:config.buttonText,render:function(CT,_babe){const viewTemplate=`<div class="view post-test-templ">\n {{# title }}\n <h1>{{ title }}</h1>\n {{/ title }}\n {{# text }}\n <section class="text-container">\n <p class="text">{{ text }}</p>\n </section>\n {{/ text }}\n <form>\n <p>\n <label for="age">Age:</label>\n <input type="number" name="age" min="18" max="110" id="age" />\n </p>\n <p>\n <label for="gender">Gender:</label>\n <select id="gender" name="gender">\n <option></option>\n <option value="male">male</option>\n <option value="female">female</option>\n <option value="other">other</option>\n </select>\n </p>\n <p>\n <label for="education">Level of Education:</label>\n <select id="education" name="education">\n <option></option>\n <option value="graduated_high_school">Graduated High School</option>\n <option value="graduated_college">Graduated College</option>\n <option value="higher_degree">Higher Degree</option>\n </select>\n </p>\n <p>\n <label for="languages" name="languages">Native Languages: <br /><span>(i.e. the language(s) spoken at home when you were a child)</</span></label>\n <input type="text" id="languages"/>\n </p>\n <p class="comment-sect">\n <label for="comments">Further comments</label>\n <textarea name="comments" id="comments"\n rows="6" cols="40"></textarea>\n </p>\n {{# buttonText }}\n <button id="next">{{ buttonText }}</button>\n {{/ buttonText }}\n {{^ buttonText }}\n <button id="next">Next</button>\n {{/ buttonText }}\n </form>\n </div>`;$("#main").html(Mustache.render(viewTemplate,{title:this.title,text:this.text,buttonText:this.buttonText}));$("#next").on("click",function(e){e.preventDefault();_babe.global_data.age=$("#age").val();_babe.global_data.gender=$("#gender").val();_babe.global_data.education=$("#education").val();_babe.global_data.languages=$("#languages").val();_babe.global_data.comments=$("#comments").val().trim();_babe.global_data.endTime=Date.now();_babe.global_data.timeSpent=(_babe.global_data.endTime-_babe.global_data.startTime)/6e4;_babe.findNextView()})},CT:0,trials:config.trials};return _postTest},thanks:function(config){paramsChecker(config,"thanks");const _thanks={name:config.name,message:config.title,render:function(CT,_babe){var viewTemplate=`<div class="view thanks-templ">\n <h4 class="warning-message">submitting the data\n <div class="loader"></div>\n </h4>\n {{# thanksMessage }}\n <h1 class="thanks-message nodisplay">{{ thanksMessage }}</h1>\n {{/ thanksMessage }}\n {{^ thanksMessage }}\n <h1 class="thanks-message nodisplay">Thank you for taking part in this experiment!</h1>\n {{/ thanksMessage }}\n {{# extraMessage }}\n <h2 class="extra-message nodisplay">{{{ extraMessage }}}</h2>\n {{/ extraMessage }}\n </div>`;if(_babe.deploy.is_MTurk||_babe.deploy.deployMethod==="directLink"){$("#main").html(Mustache.render(viewTemplate,{thanksMessage:this.message}))}else if(_babe.deploy.deployMethod==="Prolific"){$("main").html(Mustache.render(viewTemplate,{thanksMessage:this.message,extraMessage:"Please press the button below to confirm that you completed the experiment with Prolific<br />".concat("<a href=",_babe.deploy.prolificURL,' class="prolific-url">Confirm</a>')}))}else if(_babe.deploy.deployMethod==="debug"){$("main").html(Mustache.render(viewTemplate,{}))}else{console.log("no such _babe.deploy.deployMethod")}_babe.submission.submit(_babe)},CT:0,trials:1};return _thanks}};function paramsChecker(config,view){if(config.trials===undefined||config.trials===""){throw new Error(errors.noTrials.concat(findFile(view)))}if(config.name===undefined||config.name===""){throw new Error(errors.noName.concat(findFile(view)))}}function checkTrialView(config,view){if(config.data===undefined||config.data===null){throw new Error(errors.noData.concat(findFile(view)))}if(config.data instanceof Array===false){throw new Error(errors.notAnArray.concat(findFile(view)))}if(config.trial_type===undefined||config.trial_type===""){throw new Error(errors.noTrialType.concat(findFile(view)))}}function findFile(view){return`\n\nThe problem is in ${view} view.`}const errors={contactEmail:`There is no contact_email given. Please give a contact_email to the babeInit function,\n\nfor example:\n\nbabeInit({\n ...\n deploy: {\n ...\n contact_email: 'yourcontactemail@email.sample',\n ...\n },\n ...\n});`,prolificURL:`There is no prolificURL given. Please give a prolificURL to the babeInit function,\n\nfor example:\n\nbabeInit({\n ...\n deploy: {\n ...\n prolificURL: 'https://app.prolific.ac/submissions/complete?cc=SAMPLE',\n ...\n },\n ...\n});`,noTrials:`No trials given. Each _babe view takes an object with an obligatory 'trial' property.\n\nfor example:\n\nvar introView = intro({\n ...\n trials: 1,\n ...\n});\n\nYou can find more information at https://github.com/babe-project/babe-base#views-in-_babe`,noName:`No name given. Each _babe view takes an object with an obligatory 'name' property\n\nfor example:\n\nvar introView = intro({\n ...\n name: 'introView',\n ...\n});\n\nYou can find more information at https://github.com/babe-project/babe-base#views-in-_babe`,noData:`No data given. Each _babe view takes an object with an obligatory 'data' property\n\nfor example:\n\nvar mainTrials = forcedChoice({\n ...\n data: my_main_trials,\n ...\n});\n\nThe data is a list of objects defined in your local js file.\n\n_babe's trial views expect each trial object to have specific properties. Here is an example of a forcedCoice view trial:\n\n{\n question: 'How are you today?',\n option1: 'fine',\n option2: 'good'\n}\n\nYou can find more information at https://github.com/babe-project/babe-base#views-in-_babe`,noTrialType:`No trial_type given. Each _babe view takes an object with an obligatory 'trial_type' property\n\nfor example:\n\nvar mainTrials = forcedChoice({\n ...\n trial_type: 'main trials',\n ...\n});\n\nThe trial type is needed for recording the results of your experiment.\n\nYou can find more information at https://github.com/babe-project/babe-base#views-in-_babe`,notAnArray:`The data is not an array. Trial views get an array of objects.\n\nfor example:\n\nvar mainTrials = forcedChoice({\n ...\n data: [\n {\n prop: val,\n prop: val\n },\n {\n prop: val,\n prop:val\n }\n ],\n ...\n});`,noSuchViewName:`The view name listed in progress_bar.in does not exist. Use the view names to reference the views in progress_bar.in.\n\nfor example:\n\nvar mainView = forcedChoice({\n ...\n name: 'myMainView',\n ...\n});\n\nvar introView = intro({\n ...\n name: 'intro',\n ...\n});\n\nbabeInit({\n ...\n progress_bar: {\n in: [\n "myMainView"\n ],\n style: "chunks"\n width: 100\n },\n ...\n});\n`};function _babeProgress(_babe){let totalProgressParts=0;let progressTrials=0;let totalProgressChunks=0;let filledChunks=0;let fillChunk=false;const _progress={add:function(){_babe.views_seq.map(view=>{for(let j=0;j<_babe.progress_bar.in.length;j++){if(view.name===_babe.progress_bar.in[j]){totalProgressChunks++;totalProgressParts+=view.trials;view.hasProgressBar=true}}})},update:function(){try{addToDOM()}catch(e){console.error(e.message)}const progressBars=$(".progress-bar");let div,filledPart;if(_babe.progress_bar.style==="default"){div=$(".progress-bar").width()/totalProgressParts;filledPart=progressTrials*div}else{div=$(".progress-bar").width()/_babe.views_seq[_babe.currentViewCounter].trials;filledPart=(_babe.currentTrialInViewCounter-1)*div}const filledElem=jQuery("<span/>",{id:"filled"}).appendTo(progressBars[filledChunks]);$("#filled").css("width",filledPart);progressTrials++;if(_babe.progress_bar.style==="chunks"){if(fillChunk===true){filledChunks++;fillChunk=false}if(filledElem.width()===$(".progress-bar").width()-div){fillChunk=true}for(var i=0;i<filledChunks;i++){progressBars[i].style.backgroundColor="#5187BA"}}}};function addToDOM(){var bar;var i;var view=$(".view");var barWidth=_babe.progress_bar.width;var clearfix=jQuery("<div/>",{class:"clearfix"});var container=jQuery("<div/>",{class:"progress-bar-container"});view.css("padding-top",30);view.prepend(clearfix);view.prepend(container);if(_babe.progress_bar.style==="chunks"){for(i=0;i<totalProgressChunks;i++){bar=jQuery("<div/>",{class:"progress-bar"});bar.css("width",barWidth);container.append(bar)}}else if(_babe.progress_bar.style==="separate"){bar=jQuery("<div/>",{class:"progress-bar"});bar.css("width",barWidth);container.append(bar)}else if(_babe.progress_bar.style==="default"){bar=jQuery("<div/>",{class:"progress-bar"});bar.css("width",barWidth);container.append(bar)}else{throw new Error('Progress_bar.style can be set to "default", "separate" or "chunks" in experiment.js')}}return _progress}function loop(arr,count,shuffleFlag){return _.flatMapDeep(_.range(count),function(i){return arr})}function loopShuffled(arr,count){return _.flatMapDeep(_.range(count),function(i){return _.shuffle(arr)})}function _babeSubmit(_babe){const _submit={submit:function(_babe){let data={experiment_id:_babe.deploy.experimentID,trials:addEmptyColumns(_babe.trial_data)};data=_.merge(_babe.global_data,data);if(_babe.deploy.is_MTurk){try{const HITData=getHITData();data["assignment_id"]=HITData["assignmentId"];data["worker_id"]=HITData["workerId"];data["hit_id"]=HITData["hitId"];var form=jQuery("<form/>",{id:"mturk-submission-form",action:config_deploy.MTurk_server}).appendTo(".thanks-templ");jQuery("<input/>",{type:"hidden",name:"data",value:JSON.stringify(data)}).appendTo(form);jQuery("<input/>",{type:"hidden",name:"assignmentId",value:HITData["assignmentId"]}).appendTo(form)}catch(e){console.error(e)}}if(_babe.deploy.liveExperiment){console.log("submits");submitResults(_babe.deploy.contact_email,_babe.deploy.submissionURL,flattenData(data),_babe.deploy)}else{const flattenedData=flattenData(data);$(".warning-message").addClass("nodisplay");jQuery("<h3/>",{text:"Debug Mode"}).appendTo($(".view"));jQuery("<div/>",{class:"debug-results",html:formatDebugData(flattenedData)}).appendTo($(".view"));createCSVForDownload(flattenedData)}}};function submitResults(contactEmail,submissionURL,data,config){contactEmail=typeof contactEmail!=="undefined"?contactEmail:"not provided";$.ajax({type:"POST",url:submissionURL,crossDomain:true,contentType:"application/json",data:JSON.stringify(data),success:function(responseData,textStatus,jqXHR){console.log(textStatus);$(".warning-message").addClass("nodisplay");$(".thanks-message").removeClass("nodisplay");$(".extra-message").removeClass("nodisplay");if(config.is_MTurk){setTimeout(function(){submitToMTurk(data),500})}},error:function(responseData,textStatus,errorThrown){if(config.is_MTurk){submitToMTurk(data);$(".thanks-message").removeClass("nodisplay")}else{if(textStatus=="timeout"){alert("Oops, the submission timed out. Please try again. If the problem persists, please contact "+contactEmail+", including your ID")}else{alert("Oops, the submission failed. The server says: "+responseData.responseText+"\nPlease try again. If the problem persists, please contact "+contactEmail+"with this error message, including your ID")}}}})}function submitToMTurk(){var form=$("#mturk-submission-form");form.submit()}function addEmptyColumns(trialData){var columns=[];for(var i=0;i<trialData.length;i++){for(var prop in trialData[i]){if(trialData[i].hasOwnProperty(prop)&&columns.indexOf(prop)===-1){columns.push(prop)}}}for(var j=0;j<trialData.length;j++){for(var k=0;k<columns.length;k++){if(!trialData[j].hasOwnProperty(columns[k])){trialData[j][columns[k]]="NA"}}}return trialData}function formatDebugData(flattenedData){var output="<table id='debugresults'>";var t=flattenedData[0];output+="<thead><tr>";for(var key in t){if(t.hasOwnProperty(key)){output+="<th>"+key+"</th>"}}output+="</tr></thead>";output+="<tbody><tr>";var entry="";for(var i=0;i<flattenedData.length;i++){var currentTrial=flattenedData[i];for(var k in t){if(currentTrial.hasOwnProperty(k)){entry=String(currentTrial[k]);output+="<td>"+entry.replace(/ /g," ")+"</td>"}}output+="</tr>"}output+="</tbody></table>";return output}function createCSVForDownload(flattenedData){var csvOutput="";var t=flattenedData[0];for(var key in t){if(t.hasOwnProperty(key)){csvOutput+='"'+String(key)+'",'}}csvOutput+="\n";for(var i=0;i<flattenedData.length;i++){var currentTrial=flattenedData[i];for(var k in t){if(currentTrial.hasOwnProperty(k)){csvOutput+='"'+String(currentTrial[k])+'",'}}csvOutput+="\n"}var blob=new Blob([csvOutput],{type:"text/csv"});if(window.navigator.msSaveOrOpenBlob){window.navigator.msSaveBlob(blob,"results.csv")}else{jQuery("<a/>",{class:"button download-btn",html:"Download the results as CSV",href:window.URL.createObjectURL(blob),download:"results.csv"}).appendTo($(".view"))}}function flattenData(data){var trials=data.trials;delete data.trials;var sample_trial=trials[0];for(var trial_key in sample_trial){if(sample_trial.hasOwnProperty(trial_key)){if(data.hasOwnProperty(trial_key)){var new_data_key="glb_"+trial_key;data[new_data_key]=data[trial_key];delete data[trial_key]}}}var out=_.map(trials,function(t){return _.merge(t,data)});return out}function getHITData(){const url=window.location.href;const qArray=url.split("?");const HITData={};if(qArray[1]===undefined){throw new Error("Cannot get participant' s assignmentId from the URL (happens if the experiment does NOT run on MTurk or MTurkSandbox).")}else{qArray=qArray[1].split("&");for(var i=0;i<qArray.length;i++){HITData[qArray[i].split("=")[0]]=qArray[i].split("=")[1]}}return HITData}return _submit} |
{ | ||
"name": "babe-project", | ||
"version": "0.0.7", | ||
"version": "0.0.8", | ||
"description": "Basic Architecture for Browser-based experiments (https://github.com/babe-project)", | ||
@@ -9,3 +9,4 @@ "main": "babe-main.js", | ||
"jquery": "^3.3.1", | ||
"mustache": "^3.0.0" | ||
"mustache": "^3.0.0", | ||
"uglify-es": "^3.3.9" | ||
}, | ||
@@ -12,0 +13,0 @@ "devDependencies": {}, |
126
README.md
# \_babe project | ||
basic architecture for browser-based experiments | ||
## Installation | ||
#### Install with npm (recommended) | ||
## Creating a \_babe experiment with \_babe | ||
#### Option 1: Download the \_babe project package | ||
1. Download the [\_babe .zip](https://github.com/babe-project/babe-base) | ||
2. Unzip and place the folder (babe-base-master) in the `libraries/` folder of your experiment. | ||
Your experiment's structure should look something like this: | ||
`experiment/` | ||
+ `libraries/` | ||
+ `babe-babe-master` | ||
+ `_babe.full.min.js` | ||
+ `_babe.min.js` | ||
+ ... | ||
+ ... | ||
`_babe.full.min.js` includes the dependencies that \_babe uses (jQuery, Mustache and csv-js). | ||
Using `_babe.full.min.js` there is no need to install and import jQuery, Mustache and csv-js. | ||
`_babe.min.js` includes only the \_babe package, the dependencies should be installed separately for \_babe to work | ||
3. Import \_babe in your `index.html`: | ||
3.1 the full version: | ||
`<script src="libraries/babe-base-master/_babe.full.min.js></script>"` | ||
3.2 no-dependencies version: | ||
`<script src="libraries/babe-base-master/_babe.full.min.js></script>"` | ||
Note: You need to install jQuery, Mustache and csv-js in your experiment. | ||
4. Use \_babe styles: | ||
import \_babe-styles in your `index.html`: | ||
`<link rel="stylesheet" type="text/css" href="libraries/babe-base-master/_babe-styles.css">` | ||
#### Option 2: Install with npm | ||
You need npm installed on your machine. Here is more information on how to [install npm](https://www.npmjs.com/get-npm) | ||
@@ -13,22 +50,18 @@ | ||
#### Download the package | ||
Alternatively you can get the package by cloning the repo in your experiment's directory (?) | ||
Import \_babe, jQuery, Mustache and csv-js in your main .html | ||
## Usage | ||
``` | ||
<link rel="stylesheet" type="text/css" href="node_modules/babe-project/_babe-styles.css"> | ||
### \_babe Initialisation | ||
To initialise the experiment import the babe `babeInit` function in `your_js_file.js`. | ||
<script src="node_modules/mustache/mustache.min.js"></script> | ||
<script src="node_modules/jquery/dist/jquery.min.js"></script> | ||
<script src="node_modules/csv-js/csv.js"></script> | ||
<script src="node_modules/babe-project/_babe.min.js></script>" | ||
``` | ||
// your_js_file.js | ||
import { babeInit } from './link_to_your_libraries/babe-project/babe-init.js'; | ||
## Usage | ||
... | ||
... | ||
... | ||
``` | ||
### \_babe Initialisation | ||
`babeInit` takes an object as a parameter with the following properties: | ||
`_babeInit` takes an object as a parameter with the following properties: | ||
@@ -40,9 +73,7 @@ * `views_seq` - a list of view objects in the sequence you want the to appear in your experiment | ||
Sample `babeInit` call: | ||
Sample `_babeInit` call: | ||
``` | ||
import { babeInit } from './link_to_your_libraries/babe-project/babe-init.js'; | ||
$("document").ready(function() { | ||
babeInit({ | ||
_babeInit({ | ||
views_seq: [ | ||
@@ -76,3 +107,3 @@ intro, | ||
For \_babe views to render, you need to have an html tag (preferrably `div` or `main`) | ||
\_babe views get inserted in an html element with id `main`, you need to have an html tag (preferrably `div` or `main`) | ||
with `id="main"` | ||
@@ -86,20 +117,5 @@ | ||
<head> | ||
<meta charset="UTF-8" /> | ||
<title>browser-based experiments</title> | ||
<!-- fonts from Google fonts --> | ||
<link href="https://fonts.googleapis.com/css?family=Noto+Sans:400,700|Noto+Serif:400,700|Playfair+Display:700" rel="stylesheet"> | ||
<!-- css --> | ||
<link rel="stylesheet" type="text/css" href="node_modules/babe-project/babe-styles.css"> | ||
<!-- js dependencies --> | ||
<script src="node_modules/mustache/mustache.min.js"></script> | ||
<script src="node_modules/jquery/dist/jquery.min.js"></script> | ||
<script src="node_modules/csv-js/csv.js"></script> | ||
<script src="https://cdnjs.cloudflare.com/ajax/libs/lodash.js/4.17.5/lodash.js"></script> | ||
<!-- load the trials --> | ||
<script type="module" src="index.js"></script> | ||
... | ||
... | ||
... | ||
</head> | ||
@@ -165,6 +181,3 @@ | ||
import { babeInit } from './link_to_your_libraries/babe-project/babe-init.js'; | ||
import { intro, instructions, forcedChoice, thanks } from './link_to_your_libraries/babe-project/babe-views.js'; | ||
const myIntro = intro({ | ||
const intro = _babeViews.intro({ | ||
title: 'Welcome!', | ||
@@ -176,3 +189,3 @@ text: 'This is an experiment!', | ||
const myInstructions = instructions({ | ||
const instructions = _babeViews.instructions({ | ||
title: 'Instructions', | ||
@@ -184,3 +197,3 @@ text: 'Choose an answer', | ||
const main = forcedChoice({ | ||
const main = _babeViews.forcedChoice({ | ||
trial_type: 'main', | ||
@@ -191,3 +204,3 @@ data: main_trials, | ||
const thankYou = thanks({ | ||
const thanks = _babeViews.thanks({ | ||
title: 'Thank you for taking part in this experiment!', | ||
@@ -198,8 +211,8 @@ trials: 1 | ||
$("document").ready(function() { | ||
babeInit({ | ||
_babeInit({ | ||
views_seq: [ | ||
myIntro, | ||
myInstructions, | ||
intro, | ||
instructions, | ||
main, | ||
thankYou | ||
thanks | ||
], | ||
@@ -216,7 +229,6 @@ deploy: { | ||
in: [ | ||
"practice", | ||
"main" | ||
], | ||
style: "default", | ||
width: 150 | ||
width: 100 | ||
} | ||
@@ -230,2 +242,4 @@ }); | ||
!!! | ||
You can also create your own views. Here is what you need to know: | ||
@@ -251,4 +265,2 @@ | ||
import { babeInit } from './link_to_your_libraries/babe-project/babe-init.js'; | ||
const sayHello = function(info) { | ||
@@ -306,3 +318,3 @@ const sayHello = { | ||
$("document").ready(function() { | ||
babeInit({ | ||
_babeInit({ | ||
... | ||
@@ -331,3 +343,3 @@ views_seq: [ | ||
\_babe provides the option to include progress bars in the views specified in the `progress_bar.in` list passed to `babeInit`. | ||
\_babe provides the option to include progress bars in the views specified in the `progress_bar.in` list passed to `_babeInit`. | ||
@@ -346,3 +358,3 @@ You can use one of the following 3 styles (include pictues) | ||
$("document").ready(function() { | ||
babeInit({ | ||
_babeInit({ | ||
... | ||
@@ -349,0 +361,0 @@ progress_bar: { |
License Policy Violation
LicenseThis package is not allowed per your license policy. Review the package's license to ensure compliance.
Found 1 instance in 1 package
Minified code
QualityThis package contains minified code. This may be harmless in some cases where minified code is included in packaged libraries, however packages on npm should not minify code.
Found 1 instance in 1 package
License Policy Violation
LicenseThis package is not allowed per your license policy. Review the package's license to ensure compliance.
Found 1 instance in 1 package
Major refactor
Supply chain riskPackage has recently undergone a major refactor. It may be unstable or indicate significant internal changes. Use caution when updating to versions that include significant changes.
Found 1 instance in 1 package
509579
24
356
0
4
4
+ Addeduglify-es@^3.3.9
+ Addedcommander@2.14.1(transitive)
+ Addedsource-map@0.6.1(transitive)
+ Addeduglify-es@3.3.10(transitive)