Can we use template literals in Pcibex?

PennController for IBEX Forums Support Can we use template literals in Pcibex?

Viewing 6 posts - 1 through 6 (of 6 total)
  • Author
    Posts
  • #10536
    Larissa_Cury
    Participant

    Hello!
    I was wondering if we can use template literals in Pcibex, such as in the example below? In this case, I simply have a form and then I use the user’s input name and age value to salute he/she. I have 3 questions:
    a) Can we use template literals in Pcibex in general?
    b) Would I be able to do something like this as well.
    c) We cannot use raw Js in Pcibex like storing a Js, a CSS and an HTML file, I suppose? So, for example, If I pasted the code below and upload the css and html files, it wouldn’t work, right? (https://doc.pcibex.net/how-to-guides/using-javascript/)

    Code:

    *JS:

    
    "use strict";
     
    /// SELECT BUTTON:
     
    const btnSubmit = document.querySelector(".form__btn--submit");
     
    // SELECT INPUT:
     
    const inputSubmitName = document.querySelector(".form__input--name");
    const inputSubmitAge = document.querySelector(".form__input--age");
     
    // SELECT BOX MESSAGE:
     
    let welcomeMsg = document.querySelector(".welcome");
     
    // SELECT FORM DIV
     
    const formDiv = document.querySelector(".operation--welcome");
     
    // SELECT AND MANIPULATE CONTENT:
     
    btnSubmit.addEventListener("click", function (e) {
      // Prevent default:
      e.preventDefault();
     
      // Get name and age
      const name = inputSubmitName.value;
      const age = +inputSubmitAge.value; // transform string to a number
     
      // Make it disappear:
     
      formDiv.classList.add("welcome--hidden");
     
      // Display Welcome User Message:
     
      welcomeMsg.classList.remove("welcome--hidden");
      welcomeMsg.textContent = <code>Hello, ${name}! You are ${age} years old. Welcome! 🤗</code>;  ////////////// HERE!!
     
      // log
      console.log(age, name);
    });
    

    *CSS:

    
    /* // trying to select the elemtns here // */
     
    /* general properties of document */
     
    * {
      margin: 0;
      padding: 0;
      box-sizing: inherit;
    }
     
    /* html {
      font-size: 62.5%;
      box-sizing: border-box;
    } */
     
    body {
      font-family: "Poppins", sans-serif;
      font-weight: 300;
      color: yellow; /* cor do texto */
      line-height: 1.9;
      background-color: #3616d9; /* cor do fundo */
    }
     
    /* .first__image {
      width: 100px;
      border-radius: 50px;
      float: left;
      margin-right: 10px;
    } */
     
    .form--title {
      position: absolute;
      left: 400px;
      height: 350px;
      width: 550px;
      bottom: 90px;
    }
     
    .form--personal__info {
      position: absolute;
      left: 300px;
      height: 350px;
      width: 550px;
      bottom: 50px;
    }
     
    .welcome-message {
      background-color: aquamarine;
      text-align: center;
      font-size: 30px;
      width: 100%;
      position: absolute;
      height: 80px;
      bottom: 280px;
      color: red;
    }
     
    .welcome--hidden {
      opacity: 0;
      transform: translate(20px, 20px);
    }
    

    * HTML:

    
    
    <!DOCTYPE html>
    <!-- doc-type declaration -->
    <html lang="en">
      <head>
        <meta charset="UTF-8" />
        <meta http-equiv="X-UA-Compatible" content="IE=edge" />
        <meta name="viewport" content="width=device-width, initial-scale=1.0" />
        <meta name="description" content="..." />
        <link rel="stylesheet" href="style.css" />
        <script defer src="script.js"></script>
        <title>My first form</title>
                 <div class="operation operation--welcome">
                <h2 class="form--title">Personal Info:</h2>
                <form class="form form--personal__info">
                  <input type="text" 
                  class="form__input form__input--name" 
                  placeholder="Your Name here"/>
                  <input type="number" 
                  class="form__input form__input--age" 
                  placeholder="Your Age Here"/>
                  <button class="form__btn form__btn--submit">&rarr;</button>
                  <label class="form__label">Submit your data 👈</label>
                  <!-- <label class="form__label">your data 👈</label> -->
                </form>
              </div>
              <div class = "welcome welcome-message welcome--hidden">
                <h2 class="new--message">Welcome, user! 😀</h2>
     
              </div>
     
        </body>
      </head>
    </html>
    
    
    • This topic was modified 1 year, 5 months ago by Larissa_Cury. Reason: editing code blocks
    • This topic was modified 1 year, 5 months ago by Larissa_Cury.
    • This topic was modified 1 year, 5 months ago by Larissa_Cury. Reason: editing clode blocks again
    #10540
    Larissa_Cury
    Participant

    Another usage, can we do something like this?

    Can we set a variable with const, let or var and reuse it? Ex:

    
    // Set a variable:
    
    let time = 100
    
     newTimer("timeout", time)
                .start()
    ,
      newText("text",<code>you have ${time} to answer that! run!</code>)
       .center()
    
    • This reply was modified 1 year, 5 months ago by Larissa_Cury. Reason: add another line of code
    • This reply was modified 1 year, 5 months ago by Larissa_Cury.
    #10546
    Jeremy
    Keymaster

    Hello,

    If you haven’t done so already, I invite you to read <the Core Concepts section in addition to the guide your reference, which also contains some pointers about the proper syntax and scope of PennController commands

    I’ll start with your second message. All PennController commands are javascript functions. When you do newTrial( /* ... */ ) whatever you write in place of /* ... */ are arguments to the function newTrial. It is illegal in javascript to use the let keyword to define a variable as part as an argument, so you cannot do things like newTrial( "myTrial", let time = 100 , newTimer("timeout", time) , /* ... */ ). However, you can do things like newTrial( "myTrial", time = 100 , newTimer("timeout", time) , /* ... */ ) because omitting let will make the expression time=100 return 100, which is a valid argument to pass to a function. Note that this would not set time as a local variable, as in “in the scope of newTrial“, because you simply are not in its scope (you’re just passing arguments)

    Now back to your first message. The files you upload to Resources are not just all thrown into the page when you open the experiment, otherwise it would be a real mess. What happens at the beginning of the experiment is your scripts get executed before body even gets populated, so any reference like document.querySelector(".form__btn--submit"); that you put at the root of your script will simply return null. However, Ibex with its Message and Form controllers, and PennController with newHtml (or newController + Message/Form) allow you to dynamically inject HTML files from the project’s Resources folder at some point during your experiment. The HTML files you upload to Resources can include CSS and javascript. However, the references in <link rel="stylesheet" href="style.css" /> and <script defer src="script.js"></script> will fail on the farm, because the project’s files are not simply exposed at the local path. So you might want to include CSS + javascript in the HTML document, as in:

    <html lang="en">
      <head>
        <meta charset="UTF-8" />
        <meta http-equiv="X-UA-Compatible" content="IE=edge" />
        <meta name="viewport" content="width=device-width, initial-scale=1.0" />
        <meta name="description" content="..." />
        <script>
            "use strict";
            // embed code in an async function so as to wait for the button element to be added to the page
            const runScript = async () => {
                /// SELECT BUTTON:
                const btnSubmit = await new Promise(function getBtn(r) {
                  const b = document.querySelector(".form__btn--submit");
                  if (b===null) window.requestAnimationFrame(()=>getBtn(r));
                  else r(b);
                });
            
                // SELECT INPUT:
                const inputSubmitName = document.querySelector(".form__input--name");
                const inputSubmitAge = document.querySelector(".form__input--age");
                 
                // SELECT BOX MESSAGE:
                 
                let welcomeMsg = document.querySelector(".welcome");
                 
                // SELECT FORM DIV
                const formDiv = document.querySelector(".operation--welcome");
                 
                // SELECT AND MANIPULATE CONTENT:
                btnSubmit.addEventListener("click", function (e) {
                  // Prevent default:
                  e.preventDefault();
                 
                  // Get name and age
                  const name = inputSubmitName.value;
                  const age = +inputSubmitAge.value; // transform string to a number
                 
                  // Make it disappear:
                 
                  formDiv.classList.add("welcome--hidden");
                 
                  // Display Welcome User Message:
                 
                  welcomeMsg.classList.remove("welcome--hidden");
                  welcomeMsg.textContent = `Hello, ${name}! You are ${age} years old. Welcome! 🤗`;  ////////////// HERE!!
                 
                  // log
                  console.log(age, name);
                });
            };
            runScript();
        </script>
        <style>
            /* general properties of document */
             
            * {
              margin: 0;
              padding: 0;
              box-sizing: inherit;
            }
             
            body {
              font-family: "Poppins", sans-serif;
              font-weight: 300;
              color: yellow; /* cor do texto */
              line-height: 1.9;
              background-color: #3616d9; /* cor do fundo */
            }
             
            .form--title {
              position: absolute;
              left: 400px;
              height: 350px;
              width: 550px;
              bottom: 90px;
            }
             
            .form--personal__info {
              position: absolute;
              left: 300px;
              height: 350px;
              width: 550px;
              bottom: 50px;
            }
             
            .welcome-message {
              background-color: aquamarine;
              text-align: center;
              font-size: 30px;
              width: 100%;
              position: absolute;
              height: 80px;
              bottom: 280px;
              color: red;
            }
             
            .welcome--hidden {
              opacity: 0;
              transform: translate(20px, 20px);
            }
        </style>
        <title>My first form</title>
      </head>
      <body>
         <div class="operation operation--welcome">
            <h2 class="form--title">Personal Info:</h2>
            <form class="form form--personal__info">
              <input type="text" 
                    class="form__input form__input--name" 
                    placeholder="Your Name here"/>
              <input type="number" 
                    class="form__input form__input--age" 
                    placeholder="Your Age Here"/>
              <button class="form__btn form__btn--submit">→</button>
              <label class="form__label">Submit your data 👈</label>
              <!-- <label class="form__label">your data 👈</label> -->
            </form>
         </div>
         <div class = "welcome welcome-message welcome--hidden">
            <h2 class="new--message">Welcome, user! 😀</h2>
         </div>
      </body>
    </html>
    

    Note that the CSS rules will come after those already in place by Ibex + PennController, so you will want to adapt them (in particular, the position:absolute; shifts your content outside the visible portion of the page)

    Then you can do something like this:

    newTrial(
        newHtml("my_file.html").print()
        ,
        newButton("Next")
            .print()
            .wait()
    )

    Jeremy

    #10551
    Larissa_Cury
    Participant

    Hi, Jeremy! Thank you very much! I’ll dig in into your answer, thanks! One more thing, I’d like to use a template literal to salute my participant. I thought thatr ‘var’ was a global variable, but I cannot do things such as

    newText('salute',hi, ${ID})

    Why is that? How can I ‘use’ the ID var?

    I was able to do sth as:

    
    let welcomeMsg = 'maria'
    
    // 👉 Instructions trial 
    newTrial("instructions",
    defaultText
            .center()
            .print()
    newText("instructions-1", <code>hi, ${welcomeMsg}</code>)
    )
    

    just a note: I’m adding the template literals between ` , but the forum is formatting into a block code 🙂

    • This reply was modified 1 year, 5 months ago by Larissa_Cury. Reason: editing my answer
    #10553
    Larissa_Cury
    Participant

    Link to the experiment with the ID-Var element: https://farm.pcibex.net/r/wPASJJ/

    #10559
    Jeremy
    Keymaster

    Hi,

    PennController elements do not correspond to any native javascript type, and in particular PennController Var elements do not correspond to javascript variables. As illustrated here, you can pass a Var element to the text command on a Text element to set its value dynamically. In your case, it would look something like this:

    newVar("hitext").set(getVar("ID")).set(v=>`hi, ${v}`),
    newText("instructions-1").text( getVar("hitext") )

    Jeremy

Viewing 6 posts - 1 through 6 (of 6 total)
  • You must be logged in to reply to this topic.