Service response with a 200 but console.log paint undefined

enter image description hereHi everyone and thanks in advance. I have a problem with the service on the picture. The service response with a 200 and as you see in the response window it’s a text but the console.log right after the call to the service response with an undefined and I don’t know why. Any help will be appreciated.

In theory res should have the text to use it in my component but I couldn’t find the way to do it.

Qualtrics Javascript not displaying visual code – d3 issue?

I am trying to program a drag-and-drop exercise in qualtrics, where participants drag and drop tokens along a number line. The code is printed below along with my survey flow.

However, when I test my survey, all I see is the manually written question text

Survey flow:
enter image description here

Javascript (which modifies the single question in the “distribution” block):

Qualtrics.SurveyEngine.addOnload(function()
{
    /*Place your JavaScript here to run when the page loads*/
    // Qualtrics.SurveyEngine.addOnload(function () //{jQuery.getScript("https://d3js.org/d3.v4.min.js");});
    
    // Hide next button
 this.hideNextButton();

// Stash location of question
var that = this;

// Get embedded variables
var Out_Party = Qualtrics.SurveyEngine.getEmbeddedData('Out_Party');
// alert(Out_Party);
    
// Set variables by party
if (Out_Party === 'Democrat') {
    // Colors
    var light_color = "#5e70fd"
    var dark_color = "#00108a"
} else {
     Colors
    var light_color = "#f96f67"
    var dark_color = "#850801"
}

    
// Create stash for coin-placement order
var coin_order = [];

// Set scale labels
    var left_label1 = 'Always';
    var left_label2 = 'liberal';
    var left_label3 = '';

    var right_label1 = 'Always';
    var right_label2 = 'conservative';
    var right_label3 = '';


// Define visual parameters
var plot_width = 800,
    plot_height = 600,
    margin = {top: 30, right: 30, bottom: 30, left: 110}, // Plot skews left
    width = plot_width - margin.left - margin.right,
    height = plot_height - margin.top - margin.bottom,
    v_space = 18,

    bins = 11,
    binWidth = (width / bins),
    binHeight = 250, // I think this is arbitrary
    tokens = 20,
    coinHeight = (binHeight) / tokens - 1,
    usedTokens = 0,

    dist_title_y = 15,
    dist_axis_text_y = dist_title_y + v_space + binHeight + v_space,

    submit_button_width = 100,
    button_height = 25,

    title_font_size = 20,
    axis_text_font_size = 18,

    dist_tracker = {};

var svg = d3.select('#dist_body')
    .append('svg')
    .attr("preserveAspectRatio", "xMinYMin meet")
    .attr("viewBox", "0 0 " + (plot_width * 1.1) + " " + (plot_height * 1.1))
    .style('display', 'inline-block')
    .style('position', 'absolute')
    .style('top', 0)
    .style('left', 0)
    .append('g')
    .attr('transform',"translate(" + margin.left + "," + margin.top + ")");

var coins = svg.append('g'),
    bars = svg.append('g');

// Add plot title
var plot_title = svg.append('text')
    .attr('y', dist_title_y)
    .attr('x', width / 2)
    .attr('text-anchor', 'middle')
    .text('Tokens left: ' + tokens)
    .style('user-select',' none')
    .style('font-size', title_font_size)
    .classed('texts', true);

// Add submit button
/// Container
var end_g = svg.append('g')
  .attr('opacity', 0);

/// Visible button
end_g.append('rect')
  .attr('x', (width / 2) - (submit_button_width / 2))
  .attr('width', submit_button_width)
  .attr('y', dist_axis_text_y + (v_space * 4) + button_height + v_space)
  .attr('height', button_height)
  .attr('rx', 10)
  .attr('fill', 'green');

/// Text
end_g.append('text')
  .attr('x', width / 2)
  .attr('y', dist_axis_text_y + (v_space * 4) + button_height + v_space + (button_height / 1.3))
  .attr('fill', 'white')
  .attr('text-anchor', 'middle')
  .style('user-select', 'none')
  .attr('font-size', title_font_size)
  .text('Submit');

/// Active invisible layer
var end_button = end_g.append('rect')
    .attr('x', (width / 2) - (submit_button_width / 2))
    .attr('width', submit_button_width)
    .attr('y', dist_axis_text_y + (v_space * 4) + button_height + v_space)
    .attr('height', button_height)
    .attr('rx', 10)
    .attr('opacity', 0)
    .on('click', return_data);

// Draw background and scale points
for (let i = 0; i < bins; i++){
    // Shaded regions denoting columns
    coins.append('rect')
        .attr('x', i * binWidth)
        .attr('width', binWidth - 1)
        .attr('y', dist_title_y + v_space)
        .attr('height', binHeight + (v_space * 1.2)) // Extend past text
        .attr('fill', 'grey')
        .attr('fill-opacity', i % 2 === 0 ? 0 : 0.1)
        .attr('id', 'bin-' + i)
        .attr('class', 'bin');

    // I think a container for coin placement?
    bars.append('rect')
        .attr('x', i * binWidth)
        .attr('width', binWidth - 1)
        .attr('y', dist_title_y + v_space)
        .attr('height', binHeight)
        .attr('fill-opacity', 0)
        .attr('id', 'bin-' + i)
        .attr('class', 'bin');

    // Scale points text
    bars.append('text')
      .attr('x',(i * binWidth) + (binWidth / 2))
      .attr('y', dist_axis_text_y)
      .attr('text-anchor', 'middle')
      .style('user-select', 'none')
      .style('font-size', axis_text_font_size)
      .text(i);

    // Remove buttons
    /// Text
    bars.append('text')
      .attr('x', (i * binWidth) + (binWidth / 2))
      .attr('y', dist_axis_text_y + (v_space * 4) + (button_height / 1.5))
      .attr('text-anchor', 'middle')
      .attr('font-size', axis_text_font_size - 4)
      .attr('stroke', 'red')
      .style('user-select', 'none')
      .text("remove");

    /// Button
    bars.append('rect')
        .attr('x', i * binWidth)
        .attr('width', binWidth)
        .attr('y', dist_axis_text_y + (v_space * 4))
        .attr('height', button_height)
        .attr('fill', 'white')
        .attr('fill-opacity', 0)
        .attr('stroke-width', '1')
        .attr('rx', 10)
        .attr('stroke', 'black')
        .attr('id', 'bminus-' + i)
        .attr('class', 'deleter');

    // Tracker
    dist_tracker['bin-'+i] = {'currentY':binHeight+coinHeight,'coins':[]}
}

// Add scale labels to perceived distribution
/// Left labels
bars.append('text')
      .attr('x', binWidth / 2)
      .attr('y', dist_axis_text_y + v_space)
      .attr('text-anchor', 'middle')
      .style('user-select', 'none')
      .style('font-size', axis_text_font_size)
      .text(left_label1)

bars.append('text')
      .attr('x', binWidth / 2)
      .attr('y', dist_axis_text_y + (v_space * 2))
      .attr('text-anchor', 'middle')
      .style('user-select', 'none')
      .style('font-size', axis_text_font_size)
      .text(left_label2)

bars.append('text')
      .attr('x', binWidth / 2)
      .attr('y', dist_axis_text_y + (v_space * 3))
      .attr('text-anchor', 'middle')
      .style('user-select', 'none')
      .style('font-size', axis_text_font_size)
      .text(left_label3)

/// Right labels
bars.append('text')
      .attr('x', (10 * binWidth) + binWidth / 2)
      .attr('y', dist_axis_text_y + v_space)
      .attr('text-anchor', 'middle')
      .style('user-select', 'none')
      .style('font-size', axis_text_font_size)
      .text(right_label1)

bars.append('text')
      .attr('x', (10 * binWidth) + binWidth / 2)
      .attr('y', dist_axis_text_y + (v_space * 2))
      .attr('text-anchor', 'middle')
      .style('user-select', 'none')
      .style('font-size', axis_text_font_size)
      .text(right_label2)

bars.append('text')
      .attr('x', (10 * binWidth) + binWidth / 2)
      .attr('y', dist_axis_text_y + (v_space * 3))
      .attr('text-anchor', 'middle')
      .style('user-select', 'none')
      .style('font-size', axis_text_font_size)
      .text(right_label3)

// Allow participant to add coins
d3.selectAll('.bin')
    .on('click',function(d){
        if (usedTokens < tokens){
            var Bin = d3.select(this);
            var count = dist_tracker[Bin.attr('id')].coins.length
            var bin_coin_id = 'cb-'+Bin.attr('id') + "-" + count;

            coins.append('rect')
                .attr('x',Bin.attr('x'))
                .attr('width', binWidth - 1)
                .attr('y', dist_tracker[Bin.attr('id')].currentY)
                .attr('height', coinHeight)
                .attr('fill', light_color)
                .attr('stroke-width', 0.5)
                .attr('stroke', 'black')
                .attr('rx', 6)
                .attr('id', bin_coin_id);

            dist_tracker[Bin.attr('id')].currentY -= coinHeight;
            dist_tracker[Bin.attr('id')].coins.push(bin_coin_id);
            
            // Add token addition to order
            coin_order.push("ADD" + Bin.attr('id'));
            
            // Increment tokens used
            usedTokens += 1

            // Update plot title
            plot_title.text('Tokens left: ' + (tokens - usedTokens))

            if (usedTokens === tokens){
              end_g.attr('opacity', 1);
            }
        }

    });

// Allow participant to delete coins
d3.selectAll('.deleter')
    .on('click',function(d){
        var Del = d3.select(this);
        var vals = dist_tracker["bin-"+Del.attr('id').split('-')[1]].coins;

        if (vals.length > 0){
            var lastcoin = vals[vals.length - 1];
            
            d3.select('#' + lastcoin).remove();

            dist_tracker["bin-"+Del.attr('id').split('-')[1]].coins.splice(-1, 1);
            dist_tracker["bin-"+Del.attr('id').split('-')[1]].currentY += coinHeight;
            
            // Add token deletion to order
            coin_order.push("DEL" + Del.attr('id'));
            
            // Increment tokens used
            usedTokens -= 1;

            // Update plot title
            plot_title.text('Tokens left: ' + (tokens - usedTokens))
        }

        if (usedTokens !== tokens){
          end_g.attr('opacity', 0);
        }

    })

// Define function for returning distribution data
function return_data(){
    if (usedTokens === tokens){
        // Create stash for tokens
        let arr = [];

        // Count tokens in each bin
        for (const [key, value] of Object.entries(dist_tracker)) {
            arr.push((key.split('-')[1], value['coins'].length));
        }

        // Record perceived distribution
        Qualtrics.SurveyEngine.setEmbeddedData('Out_dist_Q', arr.toString());
        
        // Record coin-placement order
        Qualtrics.SurveyEngine.setEmbeddedData('out_dist_order', coin_order.toString());

        // Advance to next page
        (function(){that.clickNextButton();}).delay(0.2);
    }
}


});

But the only thing that displays when I look at the survey is the manually written question text, none of what I’m trying to create visually with Javascript.

What I’ve done already:
I’ve tested whether the code is accurately grabbing the embedded data variable, Out_Party, using the alert() command, and it is. I’ve also tried manually calling d3.js, in case that’s the issue (display doesn’t change either way, so you’ll see that line commented out.) I’m just struggling to debug why the tokens and line isn’t displaying.

I’m relatively new to both Qualtrics and Javascript, so any and all help is greatly appreciated. Happy to provide a .qsf file, too.

Convert file of consts to string and save it in fs

I’m newbie with electronjs so i tried to save my file as a TXT file via fs like this:

simple consts in
data.ts file:

export const users = [{ id: 1, name: 'a', classId: 1 }]

export const classes = [
  { id: 1, name: 'A', booksId: [1, 2] },
]

export const books = [
  { id: 1, name: 'math' },
  { id: 2, name: 'physic' },
]

export const usersScore = [
  {
    userId: 1,
    scores: [
      { bookId: 1, score: 20 },
      { bookId: 2, score: 20 },
    ]
  }
]

After that I create an ipc in main.js to save file from App.tsx file

main.js file:

ipcMain.on('saveFile', (e, data) => {
  // Convert the data to a JSON string
  const jsonData = JSON.stringify(data, null, 2)

  dialog
    .showSaveDialog({
      title: 'Select the File Path to save',
      defaultPath: path.join(__dirname, '../assets/students.txt'),
      // defaultPath: path.join(__dirname, '../assets/'),
      buttonLabel: 'Save',
      // Restricting the user to only Text Files.
      filters: [
        {
          name: 'Text Files',
          extensions: ['txt', 'docx']
        }
      ],
      properties: []
    })
    .then((file) => {
      if (!file.canceled) {

        // Creating and Writing to the sample.txt file
        fs.writeFile(file.filePath.toString(), jsonData, (err) => {
          if (err) throw err
          console.log('Saved!')
        })
      }
    })
    .catch((err) => {
      console.log('err', err)
    })
})

and in my renderer file

App.tsx file:

import { Link } from 'react-router-dom'
import * as data from './utils/constants'
// import bridge from './utils/bridge'

function App(): JSX.Element {
  const save = () => {
    // send the data to main 
    window.electron.ipcRenderer.send('saveFile', data)
  }

  return (
    <>
      <button onClick={save}>save</button>
    </>
  )
}

export default App

but i got this error when i clicked on save button

enter image description here

I checked the type of jsonData and it says string!

How to intercept routes from / page only in NextJS?

I’m trying to intercept the /portfolio/project/[slug] route from main page (/) ONLY. With the following structure I’ve already accomplished that (partially):

image

The issue is that other routes that lead to that specific route also get intercepted which I don’t want. For example, when I’m on /portfolio and click on one of the /portfolio/project/[slug] links, it gets intercepted and dialog window opens. Is there any native way to fix it? Thanks!

JQuery $(window).height() incorrect after window maximized then restored to original size

I have a function that uses window height to set a bootstrapTable’s height. In addition, I’m using a resize event listener to change the height of the table if the window is resized.

This is inside an electron project on a windows machine.

This is the first part of the code which is triggered when a button is clicked:

  var $table = $("#results-table");
  var $availableHeight =
    $(window).height() -
    $("#results-header").outerHeight(true) -
    $("#search-section").outerHeight(true) -
    50;

  $table
  .bootstrapTable("destroy")
  .bootstrapTable({ data: data, height: $availableHeight });

If I log the window height to console I get a window height of 835px which is correct and the table is sized as I expect.

This is the same code within a window resize event listener:

window.addEventListener("resize", function (event) {
  var $table = $("#results-table");
  var $tableData = $table.bootstrapTable("getData");
  var $availableHeight =
    $(window).height() -
    $("#results-header").outerHeight(true) -
    $("#search-section").outerHeight(true) -
    50;

  $table
    .bootstrapTable("destroy")
    .bootstrapTable({ data: $tableData, height: $availableHeight });
});

If I maximize the window the table resizes correctly. Unfortunately when I restore the window back to its original size (by clicking the min/max button again) and log window height to console it now shows as 818px even though the window size has not actually changed (it is still has a height of 835px). This causes my table to be slightly shorter than it was originally.

I haven’t been able to figure out why this is happening.

“Redundant ‘await’ for a non-promise type” warning in WebStorm for async function

I’m working on a Node.js project with WebStorm, and I’m getting a warning when hovering over a line of code that uses await to call an asynchronous function.

Context:

The code itself works perfectly, but WebStorm displays this warning:

Redundant 'await' for a non-promise type

This occurs when I use await with an asynchronous function that I defined myself. However, if I remove the await, the code breaks, but stops indicating the warning.

Here’s a simplified example of the code (sensitive information has been removed):

// authUtils.js
const axios = require("axios");

exports.getAccessToken = async (provider, clientId, clientSecret, code, redirectUri) => {
    if (provider === "github") {
        const response = await axios.post(
            'https://github.com/login/oauth/access_token',
            { client_id: clientId, client_secret: clientSecret, code },
            { headers: { Accept: 'application/json' } }
        );
        return response.data.access_token;
    } else if (provider === "linkedin") {
        const response = await axios.post(
            'https://www.linkedin.com/oauth/v2/accessToken',
            null,
            {
                params: {
                    grant_type: 'authorization_code',
                    code,
                    redirect_uri: redirectUri,
                    client_id: clientId,
                    client_secret: clientSecret,
                },
                headers: { 'Content-Type': 'application/x-www-form-urlencoded' },
            }
        );
        return response.data.access_token;
    }
};

Then, in my controller:

const { getAccessToken } = require('./authUtils');

exports.githubCallback = async (req, res) => {
    const { code } = req.query;
    try {
        const accessToken = await getAccessToken("github", clientId, clientSecret, code, redirectUri);
        // Other stuff here...
    } catch (err) {
        console.error("Error during callback:", err);
        return res.status(500).json({ message: "Internal error" });
    }
};

What I’ve tried:

  • If I remove await in const accessToken = await getAccessToken(...), the code breaks, indicating that await is required.
  • I’ve confirmed that getAccessToken is declared with async and uses await internally for HTTP calls, so it should indeed return a promise.

Question:
Why does WebStorm show this “Redundant ‘await’ for a non-promise type” warning? Is there a way to resolve this warning without removing await, which is definitely needed here?

adding same eventListener type on the same element

I know there might be similar question asked before but in my situation I am using promises , basically I have a modal that opens after clicking button , there are many and each one open depends on the buttons className which was clicked, this modal has overlay behind it basically when u click it it will hide the modal and overlay , my main problem is that I can’t remove the event listeners from the other two btns after one is clicked and after confirmResult function is returned , I would appreciate any help with this problem

  • also I would like to know if what I am doing is good practice or not , is it ok to use
const openModal = function (className) {
  if (currentModal) currentModal.classList.add("hidden");
  const modal = document.querySelector(`.modal--${className}`);
  modal.classList.remove("hidden");
  overlay.classList.remove("hidden");
  return modal;
};

const hideModal = function () {
  currentModal.classList.add("hidden");
  overlay.classList.add("hidden");
  confirmOverlay.classList.add("hidden");
};

const confirmResult = function () {
  return new Promise(function (resolve, _) {
    btnWarning.addEventListener(
      "click",
      function () {
        resolve(true);
      },
      { once: true }
    );

    btnBack.addEventListener(
      "click",
      function () {
        resolve(false);
        console.log("false promise btn (not consumed)");
      },
      { once: true }
    );

    confirmOverlay.addEventListener(
      "click",
      function () {
        resolve(false);
        console.log("false promise overlay");
      },
      { once: true }
    );
  });
};

overlay.addEventListener("click", function () {
  hideModal();
});

membersList.addEventListener("click", async function (e) {
  try {
    const btn = e.target.closest(".btn--members");

    if (!btn) return;

    if (btn.classList.contains("btn--kick")) {
      currentModal = openModal(btn.dataset.btnModal);

      const confirmation = await confirmResult();

      if (confirmation) {
        console.log("true");

        // hide the modal at end
      } else {
        hideModal();
      }

      console.log(confirmation);
    }

    if (btn.classList.contains("btn--promote")) {
      currentModal = openModal(btn.dataset.btnModal);
    }
  } catch (err) {
    console.log(err);
  }
});

I have been trying to remove the eventListener after the promise is returned but it didn’t work for me , idk what’s wrong to be honest

Preventing Checkout if postcode out of area in WooCommerce

We have installed & tweaked the following widget that checks to see if postcodes are in our delivery areas, if not it auto redirects them to a page to register their interest.

<div id="deliverychecker-container" data-widget-id="166f5152dc8d7b"></div>
<script>
(function() {
    const i = setInterval(function() {
        const d = document.getElementById("deliverychecker-results");
        if (!d) {
            return;
        }
        const t = d.firstChild.firstChild.innerText.slice(0, 5);
        if (t == "Sorry") {
            clearInterval(i);
            setTimeout(function() {
                window.location = "/register-your-interest-261/";
            }, 3000)
        };
    }, 1000);
    var a = document.createElement("script");
    a.type = "text/javascript";
    a.async = !0;
    a.src = "https://cdn.deliverychecker.co/api/v1/js/166f5152dc8d7b.js";
    var b = document.getElementsByTagName("script")[0];
    b.parentNode.insertBefore(a, b);
    console.log(a);
    console.log(b);
}());
</script>

The API calls an external db that has the postcodes in (a subset of PAF)

I now need to do the same thing on the WooCommerce chekout page to prevent people adding a different postcode that is out of area, but I can’t work out how to do so.

Note that we are using WooCommerce classic checkout (shortcode).

Any pointers please, I am stuck as to where to start.

Scroll Position of a Div added Dynamically in Angular

I have a list that adds dynamic components that aren’t created until results are returned from the server. After everything is loaded and fetched…the scrollTop of the dynamically added divs are all 0. I assume the dom is unaware of the position of the newly added divs at the time I am trying to determine their position or if what I am trying to do is even possible.

<div class="item" *ngFor="let item of list$ | async">
    <my-component class="my-comp" [data]="item"></my-component>
<div>

Then in a function i call when scrolling… the component position always returns 0:

onScroll() {
    const elem = this.ref.nativeElement.querySelector('.my-comp');
    console.log(`ELEM: `, elem);
    console.log(`ELEM SCROLL TOP: `, elem.scrollTop); //Always 0
}

My use case is to have dynamically loaded video components where I have control the video play/pause states based on the users scrolling. Again…these components are not created or added until well after the view itself has been created. Any help is much appreciated.

Unexpected behaviour with JavaScript’s “onanimationend”

Please have a look at this code snippet:

const highlight = (element) => {
  element.classList.remove('highlight');
  setTimeout(() => {
    element.classList.add('highlight');
  }, 0);
  element.onanimationend = () => {
    element.classList.remove('highlight');
  }
}
document.querySelector('body').addEventListener('click', event => {
  if (event.target.hash) {
    event.preventDefault();
    const element = document.querySelector(event.target.hash);
    highlight(element);
  }
});
@keyframes highlight {
  from {
    background: red;
  }
  to {
    background: white;
  }
}
.highlight {
  animation: highlight 5s;
}
<ul>
  <li>
    <a href="#foo">Foo</a>
    <div>
      <ul>
        <li>
          <a href="#foo-1">Foo 1</a>
        </li>
        <li>
          <a href="#foo-2">Foo 2</a>
        </li>
        <li>
          <a href="#foo-3">Foo 3</a>
        </li>
      </ul>
    </div>
  </li>
  <li>
    <a href="#bar">Bar</a>
  </li>
  <li>
    <a href="#baz">Baz</a>
  </li>
</ul>

<hr>

<div id="foo">
  <h2>Foo</h2>
  <ul>
    <li id="foo-1">Foo 1</li>
    <li id="foo-2">Foo 2</li>
    <li id="foo-3">Foo 3</li>
  </ul>
</div>

<div id="bar">
  <h2>Bar</h2>
</div>

<div id="baz">
  <h2>Baz</h2>
</div>

Then please run the code snippet (preferably on full page) and try:

Click on “Foo”, wait a second or two, click on “Foo 1”, wait another second, click on “Foo 2”, wait a second, click on “Foo 2” again, wait a second, click on “Foo 3”. Everything works as expected.

Now click on “Foo 1” (or “Foo 2” or “Foo 3”), wait 3 seconds and then click on “Foo”. As you can see, the background color animation of “Foo” ends at the same time as the background color animation of “Foo 1” (or “Foo 2” or “Foo 3”). One could also say that the CSS class “highlight” is removed from “Foo” too early.

Why is that and how to fix this?

Trying to detect if img is overlapping cloned img

I’m trying to check if a img is hitting a cloned img but when testing it seems to be thinking its hitting the clone when it is not

 const moveInterval = setInterval(() => {
               const rect = clonedBullet.getBoundingClientRect();
               if (rect.right >= window.innerWidth) {
                   clearInterval(moveInterval); // Stop moving
                   document.body.removeChild(clonedBullet); // Delete the clone
               } else {
                   clonedBullet.style.left = (rect.left + 2) + "px"; // Move right  & detect hit
                   if (Player.y < clonedBullet.y + clonedBullet.height / 2 && Player.y > clonedBullet.y - clonedBullet.height / 2) {
                      if (Player.x < clonedBullet.x + clonedBullet.width / 2 && Player.x > clonedBullet.x - clonedBullet.width / 2) {
                          Hp = Hp - 1
                          document.getElementById("hpHeader").textContent = Hp;
                      }
                  }
             


               }
           }, 5);

I’ve tried to change the box where it’s checking I also tried to do meany things but I have not worked on this for a pretty long time so I can’t remember.

Understanding console.log() within functions vs. using return in JavaScript?

I’m learning about functions in JavaScript and I’m confused about the role of console.log() and return.

function reusableFunction() {
  console.log("Hi World");
}

reusableFunction(); 

I understand this function logs “Hi World” to the console. My questions are:

  1. Why doesn’t this function need a return statement? I’ve seen other functions that are used return to send values back. Is console.log() doing something similar?

  2. Why do we call the function with just reusableFunction(); instead of console.log(reusableFunction());? When would I use the second way of calling the function?

I’m trying to understand the fundamental difference between displaying something in the console console.log() and returning a value from a function. Can you explain this with clear examples and perhaps point me to some resources for further learning?

I tried reading Documents like MDN, JS, and Google Developer Docs. I even did a Google Search and kept getting the basics. It answered my question. I just simply want to know when you know to use a return statement in your functions and when to console.log() and then call the function, like this console.log(reusableFunction()) . I understand what console.log() is what the return statement is and the difference between both.

How to check attribute using playwright?

I’m using spectrum web components to show a checkbox. Here’s what I use

<sp-checkbox size="m" data-test-id="test" checked="" tabindex="0" dir="ltr"></sp-checkbox>

When sp-checkbox is not checked, I want to click on it using the click(). I do the following in playwright

  testBtn = () => this.page.getByTestId("test");

  await this.testBtn().click();

but it clicks on the checkbox regardless of whether it’s checked. I only want to click on the checkbox when it’s not checked.

How can I do this using playwright?

Vue 3/ Vuetify 3 V-stepper next button causes scroll to top of page

I’m using vue 3 / vuetify 3.

How do I stop the next button (or increasing a step in the nav header) from causing a scroll to top action?

For some reason whenever I click the next button (or click on a higher step in the navigation panel) the page scrolls to the top of the page window (not just the stepper), which is not ideal for the UI / UX. When I click previous (or a lower step in the nav panel) this does not happen.

I’ve tried everything, including using manual v-stepper-actions to prevent the default action etc and to manually set the scroll (I want it to scroll to top of stepper window). However, the skip to top of page always happens first before the subsequent scroll I set, which is messy.