Toggle card created in Elementor with a button inside the card

I normally do not use WordPress or Elementor but I have a project that requires it. The project requires card elements that toggle between two states, a “front” side with an image and a “back” side with text. This was very simple to set up in Elementor and works well as a hover effect on any device that has a mouse.

For reference, a testing environment that has this effect using Elementor:
https://project-001.com

The problem is when a user is on a mobile device. The cards will flip to the “back” side when they are tapped, but do NOT flip to the front side when they are tapped again. However, they will flip back when the user taps anywhere outside of the flipped card.

I’ve tried to implement buttons that can close the cards when clicked. At first, I seemed to have some success because I could get buttons outside the card to flip the card back to the “front” side. However, I could not get the button inside the card to flip the card. That’s when I realized the button outside the card was only working because it’s outside the card – it was functionally no different than tapping empty space outside the card.

My next thought was to attach an onClick event to the button (as a testing method – I’ll add an event listener later instead of onClick once this is resolved). I started with a basic alert() and was able to confirm that the button on the “back” of the card would fire. Next I added a few variations of scripts to toggle the card’s class and assigned some “transform: rotateY(180deg)” rules to the appended class.

This concept worked fine for a test card on a non-Elementor platform. For reference, see https://brukenet.com/test/index.php for a card flip that works fine by touch (this one doesn’t even use a button, tapping anywhere on the back of the card works).

However, what works outside of Elementor does not seem to work inside the Elementor site. I’ve tried to look at the events that are firing, and I’ve looked at the hooks available to Elementor (c.f. https://developers.elementor.com/docs/hooks/js/ ) but quite frankly I’ve had a hard time because there’s so much going on that I can’t separate the wheat from the chaff, so to speak.

Anyone have a good suggestion for how to get a button (or the entire card for that matter) to toggle back to the “front” in Elementor in response to a tap event?

Thanks.

JavaScript popup calling different images onclick

I have created an image popup which uses javaScript to call different images onClick.

HTML Code snippet for the same as below.

<img onmouseover="imgload();" src="11.jpg">
<img onmouseover="imgbarb();" src="13.jpg">

I use the below javaScript to load the onmouseover function

JavaScript code for 11.jpg

function imgload() {
  var imgContainers   = document.querySelectorAll('.img-container');
  var tooltipElements = document.querySelectorAll('.tooltip');
  var popup           = document.getElementById('imagePopup1');
  var popupOverlay    = document.getElementById('imagePopupOverlay1');
  var popupImage      = document.getElementById('popupImage1');
  var closePopupBtn   = document.getElementById('closeImagePopupBtn1');
  // Show tooltip on hover
  imgContainers.forEach((container, index) => {
    var tooltip = container.querySelector('.tooltip');
    var image   = container.querySelector('img');
    container.addEventListener('mouseenter', function() {
      tooltip.style.display = 'block';
    });
    container.addEventListener('mouseleave', function() {
      tooltip.style.display = 'none';
    });
    // Open full-size image popup when image is clicked
    image.addEventListener('click', function() {
      var imageSrc               = "11-new.jpg";
      popupImage.src             = imageSrc;
      popup.style.display        = 'block';
      popupOverlay.style.display = 'block';
    });
  });
  // Close the image popup when clicking the close button
  closePopupBtn.addEventListener('click', function() {
    popup.style.display        = 'none';
    popupOverlay.style.display = 'none';
  });
  // Close the image popup when clicking the overlay
  popupOverlay.addEventListener('click', function() {
    popup.style.display        = 'none';
    popupOverlay.style.display = 'none';
  });
}

JavaScript code for 13.jpg

function imgbarb() {
  var imgContainers   = document.querySelectorAll('.img-container');
  var tooltipElements = document.querySelectorAll('.tooltip');
  var popup           = document.getElementById('imagePopup1');
  var popupOverlay    = document.getElementById('imagePopupOverlay1');
  var popupImage      = document.getElementById('popupImage1');
  var closePopupBtn   = document.getElementById('closeImagePopupBtn1');
  // Show tooltip on hover
  imgContainers.forEach((container, index) => {
    var tooltip = container.querySelector('.tooltip');
    var image   = container.querySelector('img');
    container.addEventListener('mouseenter', function() {
      tooltip.style.display = 'block';
    });
    container.addEventListener('mouseleave', function() {
      tooltip.style.display = 'none';
    });
    // Open full-size image popup when image is clicked
    image.addEventListener('click', function() {
      var imageSrc               = "13-new.jpg";
      popupImage.src             = imageSrc;
      popup.style.display        = 'block';
      popupOverlay.style.display = 'block';
    });
  });
  // Close the image popup when clicking the close button
  closePopupBtn.addEventListener('click', function() {
    popup.style.display        = 'none';
    popupOverlay.style.display = 'none';
  });
  // Close the image popup when clicking the overlay
  popupOverlay.addEventListener('click', function() {
    popup.style.display        = 'none';
    popupOverlay.style.display = 'none';
  });
}

I have around 30+ images. So each time when I wish to create a popup image for a new image, I have to create a new function and then call onmouseover everytime.

I feel it is very cumbersome to manage as it also increases the code.
Is there a simple way to this so I do not have to create a new function every time when I add a new image for popup?

I tried if and else, arrays and other stuff, but it did not work.

How to have multiple vidstack players on one page?

I need to set up vidstack player this way

<zzVideo class="zzVideo" data-src="youtube/ssvK18GSsEA"></zzVideo>

Now I am trying to figure out how to intialize multiple player on one page. I came up with this code. I am sure that real programmers would correct me.

var players = [];

[...document.getElementsByTagName("zzVideo")].forEach((element, i) => {
//    console.log(element.dataset.src + ' - '+i);
    element.id = "zzVid"+i;
   
players[i] = VidstackPlayer.create({
         target: '#zzVid'+i,
         title: 'Video #'+1,
         src: element.dataset.src,
      //    poster: 'https://files.vidstack.io/sprite-fight/poster.webp',
         layout: new VidstackPlayerLayout({
      //      thumbnails: 'https://files.vidstack.io/sprite-fight/thumbnails.vtt',
         }),
       });
  });

Can you please help me to have better solution? Working jsfiddle is here https://jsfiddle.net/radek/o9bs7qv5/55/

Firefox rendering issue for ellipses

In Firefox browser , truncation of string is not working, when typing into the input box at first time truncation is not working, but when focusing out and typing once again it start working , seems its rendering problem which is not working at first time.

Above code will give the different result in firefox and the the chrome browser.

in chrome it will work at first time , means once user will start the typing into the input box , it will start showing the ellipses once text overflow will happen.
but in Firefox it will not work like this, at first time when user will start the typing it will not show ellipses although text exceeds the boundary of input box , but when user focus out from the input box and start once again start typing into the input box ellipses will be shown. this behavior is creating confusion.

Kindly provide the solution for the same
I am using 128.5.2 esr firfox version

input.b {
  white-space: nowrap;
  width: 50px;
  overflow: hidden;
  text-overflow: ellipsis;
  border: 1px solid #000000;
}

div.c {
  white-space: nowrap;
  width: 50px;
  overflow: hidden;
  text-overflow: "----";
  border: 1px solid #000000;
}
<h2>text-overflow: ellipsis:</h2> 
<input class="b" />

Updating the primary entry for a google contact using the people API without deleting previous primary entry

I am working on a Google Apps Script project that integrates with the Google People API. My goal is to update a field designated as primary (e.g., primary address). However, I haven’t found a way to directly change the primary field by modifying the metadata of the array’s entries.

For example, adding ‘primary’: true to the metadata for the new primary entry and removing it from other entries does not override the existing primary designation.

Current Approach:

The only method I’ve found to achieve this is as follows:

Remove all entries in the array except the one that should be primary.
Update the contact.
Add back the other entries, removing their metadata to avoid conflicts.
Here’s a snippet of the function where I apply the changes, including handling the primary address update (there are quite a few class objects that I have created that perform operations in the api but aren’t part of the API so apologies if that confuses the matter but it’s the methodology I’m concerned about since this seems like an opportunity for disaster, so I don’t want to build a backup in the event of an error while information isn’t saved unless I have to):

_applyChanges(person, changes) {
  if (!person || !Array.isArray(changes)) {
    throw new Error('Valid contact and changes array required');
  }
  
  try {
    let primaryAddressChanges = [];
    let removals = [];
    
    changes.forEach(change => {
      if (change.apiFieldInfo?.arrayField === 'addresses' && change.isPrimary) {
        primaryAddressChanges.push(change);
      }
    });

    if (person.addresses && primaryAddressChanges.length > 0 && person.addresses.length > 1) {
      let primaryAddress = {};
      let otherAddresses = [];
      
      person.addresses.forEach(address => {
        if (address.metadata?.primary) {
          primaryAddress = address;
        } else {
          otherAddresses.push(address);
        }
      });

      if (primaryAddress) {
        // Reorder and update addresses to make the desired one primary
        let finalAddressArray = [primaryAddress].concat(otherAddresses);
        let googlePerson = new GooglePerson(person);
        try {
          googlePerson.updateAddresses([primaryAddress]); // Only update the primary address
          googlePerson.update();
          googlePerson.updateAddresses(finalAddressArray); // Add back the other addresses
          person = googlePerson.person;
        } catch (error) {
          Logger.log(`Error updating primary address: ${error.message}`);
        }
      }
    }

    return person;
  } catch (error) {
    Logger.log(`Error applying changes: ${error.message}`);
    throw error;
  }
}

Key Problem:

Why doesn’t directly adding ‘primary’: true to the metadata of the new primary entry and removing it from the others work? Is there a better or more direct approach to achieve this?

Additional Information:
The updateAddresses method in the code above is a utility method to modify the addresses of a GooglePerson instance.
The process involves updating the primary address and then re-adding the other addresses after clearing their metadata.
I’d appreciate any insights or alternative approaches. Am I missing something in the API documentation or functionality?

If you want me to refine this further, let me know!

I’m trying to implement the Web Share Api functionality on my web app but when i test it on my iphone 14 on chrome, is not working

Has anyone else ran into this issue? I’m implementing the Web Share API and it works when i tested it using my desktop but when i tested it using my iphone 14 it works on safari but when i use chrome, the first couple of times i click on the share button it does not work ,some times it works and some times it does not so i need to spam click it hoping it works one of those times , what is also wierd is that when i used an online virtual machine and tested it on iphone12 it worked fine so i don’t know if it is a compatibility problem ?

handleCopyOpen = async (socialHandle) => {
      if (this.sharingInProgress) {
        console.log('Sharing is already in progress.');
        return;
      }
      this.sharingInProgress = true;
    
      try {
        const targetElement = document.querySelector('.milestone-popup');
        if (!targetElement) throw new Error('Target element not found.');
    
        // Get the Blob from the prepareScreenshot function
        const blob = await this.prepareScreenshot(targetElement);
    
        if (navigator.canShare && navigator.canShare({ files: [new File([blob], 'screenshot.png', { type: 'image/png' })] })) {
          const file = new File([blob], 'screenshot.png', { type: 'image/png' });
    
          await navigator.share({
            title: 'Achievement on Fanstories',
            text: 'Check out my latest achievement!',
            files: [file],
          });
          console.log('Shared successfully using Web Share API');
        } else {
          console.warn('Web Share API not supported. Showing fallback.');
          const url = URL.createObjectURL(blob);
          window.open(url, '_blank');
        }
      } catch (error) {
        if (error.name === 'AbortError') {
          console.log('User canceled the share operation.');
        } else {
          console.error('Error during sharing:', error);
          alert('Failed to share. Please try again.');
        }
      } finally {
        this.sharingInProgress = false;
      }
    };
    
    prepareScreenshot = async (targetElement) => {
      // Define cloneContainer outside the try block for broader scope
      let cloneContainer;
    
      try {
        // Clone the target element to avoid modifying the original DOM
        cloneContainer = document.createElement('div');
        cloneContainer.style.cssText = `
          position: fixed;
          top: 0;
          left: 0;
          width: 100vw;
          height: 100vh;
          z-index: -1; /* Keeps the clone invisible */
          opacity: 0; /* Ensures it's not visible to users */
        `;
        document.body.appendChild(cloneContainer);
    
        const clonedElement = targetElement.cloneNode(true);
        cloneContainer.appendChild(clonedElement);
    
        // Adjust cloned content for capturing
        const footerElement = clonedElement.querySelector('.share-footer');
        const closeButtonElement = clonedElement.querySelector('.close-button');
        const confettiCanvas = clonedElement.querySelector('canvas');
    
        if (footerElement) footerElement.style.display = 'none';
        if (closeButtonElement) closeButtonElement.style.display = 'none';
        if (confettiCanvas) confettiCanvas.style.display = 'none';
    
        // Allow DOM changes to reflect
        await new Promise((resolve) => setTimeout(resolve, 100));
    
        // Capture the screenshot
        const canvas = await html2canvas(clonedElement, {
          backgroundColor: null,
          useCORS: true,
          scale: 2, // High resolution
        });
    
        // Convert canvas to Blob
        return new Promise((resolve, reject) => {
          canvas.toBlob(
            (blob) => {
              if (blob) {
                resolve(blob); // Return the Blob directly
              } else {
                reject(new Error('Failed to convert canvas to Blob.'));
      

        }
        },
        'image/png', // MIME type
        1.0 // Image quality (1.0 = best)
      );
    });
  } catch (error) {
    console.error('Error during screenshot preparation:', error);
    throw error;
  } finally {
    // Ensure cloneContainer is cleaned up
    if (cloneContainer) {
      document.body.removeChild(cloneContainer);
    }
  }
};

Vue: returning non-reactive values from a composable

Is it okay to return non-reactive values from a composable?

E.g., like so:

// useNavLink.js

import { toValue } from 'vue'
import { useRouter } from 'vue-router'

export default function useNavLink(link) {
  const router = useRouter()

  const handleLinkClick = (ev) => {
    ev.preventDefault()

    router.push(toValue(link))
  }

  return { handleLinkClick }
}
// NavLink.vue

<template>
  <a :href="link" @click="handleLinkClick">{{ label }}</a>
</template>

<script setup>
import useNavLink from '@/composables/useNavLink'

const { link, label } = defineProps(['link', 'label'])

const { handleLinkClick } = useNavLink(() => link)
</script>

The docs say the following,

The recommended convention is for composables to always return a plain, non-reactive object containing multiple refs.

but they don’t explicitly say that one shouldn’t return non-reactive values.

How to correctly enable/disable a parent section based on child selection?

I have a scenario where I am dynamically creating child buttons for a parent section, and I need to manage the state of the parent based on whether the child sections are selected or unselected. The parent should only be enabled when all child buttons are unselected. However, my current approach is not working as expected: when I unselect one child, the parent remains disabled, even though other children are still unselected.

below is code:

if (childItem) { 
const childButton = $('<div/>', {
    text: childItem.section_name,
    'id': childItem.id,
    'class': 'button-location-style child-section',
    click: function() {
        var index = ids.indexOf(childItem.id);

        if (index > -1) {
            // Unselect the child
            ids.splice(index, 1);  
            $(this).removeClass("changedBackground"); 

            // Enable the parent section when the child is unselected
            $(`#${parentId}`).removeClass('disabled'); 

        } else {
            // Select the child
            ids.push(childItem.id); 
            $(this).addClass("changedBackground"); 

            // Disable the parent section when the child is selected
            $(`#${parentId}`).addClass('disabled'); 
        }

        // Update the section ID input field with the selected IDs
        $('#SectionId').attr('value', ids.join(','));
    }
});

// Append the child button to the container
childContainer.append(childButton);

}

Problem:

  • The parent section should be enabled only when all child sections are
    unselected.
  • The parent is not behaving as expected. After selecting multiple
    children and unselecting one, the parent remains disabled even though
    all child sections should not be selected.

What I have tried:

  • I have checked the ids array when a child is selected or unselected,
    but the parent is still not enabled when all children are unselected.

How can I modify my code so that the parent section only gets enabled when all child sections are unselected, and stays disabled when any child section is selected?

PWA Payload and JSON

First time here, I have a problem with PWA push notifications.
It’s a chatting page made with PHP.
My push notifications are sent OK (on the phone and on the web). I have a push notification.

But there is a problem with the format of the received notification.

I received a notification text formatted like that :

{“title”:”Nouveau message de Maman”,”body”:”Test”,”icon”:”/icons/icone-app-72.png”,”url”:”/messagerie.php”}

I want to receive :

Nouveau message de maman

Test

Icons of the app and link on the click on the notification

It’s seems to be a parsing problem ? but no ideads where is problem and how to resolve it.

Payload seems to be the problem because when i try juste to send the function and do no pass informations with payload it’s OK.

Can anyone help me ?

Thanks a lot 🙂

$stmt = $pdo->prepare("SELECT endpoint, p256dh, auth FROM subscriptions WHERE user_id = ?");
        $stmt->execute([$destinataire_id]);
        $subscriptionData = $stmt->fetch(PDO::FETCH_ASSOC);

        if ($subscriptionData) {
            $subscription = Subscription::create([
                'endpoint' => $subscriptionData['endpoint'],
                'keys' => [
                    'p256dh' => $subscriptionData['p256dh'],
                    'auth' => $subscriptionData['auth'],
                ],
            ]);
        
            $webPush = new WebPush([
                'VAPID' => [
                    'subject' => 'mailto:[email protected]',
                    'publicKey' => VAPID_PUBLIC_KEY,
                    'privateKey' => VAPID_PRIVATE_KEY,
                ],
            ]);
        
            // Payload spécifique pour la messagerie
            $payload = json_encode([
                'body' => 'Vous avez un nouveau message de ' . htmlspecialchars($_SESSION['nom']),
                'icon' => '/icons/icone-app-72.png',
                'url' => '/messagerie.php?utilisateur_id=' . $_SESSION['user_id'],
            ]);
        
            $webPush->queueNotification($subscription, $payload);
        
            foreach ($webPush->flush() as $report) {
                if (!$report->isSuccess()) {
                    error_log("Erreur d'envoi (messagerie) : " . $report->getReason());
                }
            }
        }

And here is my sw.js (services workers)

self.addEventListener('push', (event) => {
  console.log('Notification reçue.');

  let data = {
    body: 'Tu as une nouvelle notification.',
    icon: '/icons/icone-app-72.png',
    url: '/notifications.php', // URL par défaut pour redirection
  };

  try {
    // Extraire les données envoyées par le serveur (si présentes)
    if (event.data) {
      const payload = event.data.json();
      data = {
        body: payload.body || data.body,
        icon: payload.icon || data.icon,
        url: payload.url || data.url,
      };
    }
  } catch (error) {
    console.error('Erreur lors du traitement du payload:', error);
  }

  const options = {
    body: data.body,
    icon: data.icon,
    data: { url: data.url },
  };

  event.waitUntil(self.registration.showNotification('Notification', options));
});

self.addEventListener('notificationclick', (event) => {
  event.notification.close();

  if (event.notification.data && event.notification.data.url) {
    event.waitUntil(clients.openWindow(event.notification.data.url));
  }
});

Firebase Security Rules: Unable to Read Custom Token Claims in request.auth.token

I am having trouble with reading Firebase custom token in my security rules; it was working fine previously, but idk why now, I am unable to read tokens and due to this, all of my security rules are not being false.

SECURITY RULES (sample):

match /TUTORS/{docID} {
  allow read: if isSignedIn() && isTutor();
}

Now I always get false from isTutor function:

function isTutor() {
  return request.auth.token.role == "tutor";
}

I am setting custom token like this using Firebase Admin SDK using this same service account. I am doing other operations as well which are successful.

const additionalClaims = {
    role: "tutor",
};
const auth = admin.auth();

try {
       await auth.setCustomUserClaims(uid, additionalClaims);

    const customToken = await auth.createCustomToken(uid, additionalClaims);
    return {
        type: "success",
        token: customToken,
    };
} catch (error) {
    console.error("Error creating custom token:", error);
    return {
        type: "error",
        token: null,
    };
}

I am getting the token as well like this:

“ey**”

This was working fine a few days back but i can’t figure out the reason why it is not working now. If i remove the roles checking func from security rules, the rules start to work, so i am pretty sure that issue lies in custom tokens.

also I did this:

const user = await admin.auth().getUser(uid);
console.log('User custom claims:', user.customClaims);

and got:

User custom claims:

{role: "tutor"}
  1. Verified custom claims are set (getUser(uid) shows { role: “tutor” }).
  2. Refreshed the ID token on the client using user.getIdToken(true).
  3. Simulated requests in Firestore Security Rules Simulator, but request.auth.token does not include role .

calling json 2nd dimension array in php [duplicate]

I had trouble to call the 2nd dimension data of the array, I have an array like this

(13) [{…}, {…}, {…}, {…}, {…}, {…}, {…}, {…}, {…}, {…}, {…}, {…}, {…}]
0: {azimuth: 1.9834929332749562, altitude: -0.0009456257895690352, zenith: 1.5717419525844656, azimuthDegrees: 113.6457737706788, altitudeDegrees: -0.05418036674103183, …}
1: {azimuth: 1.9625993875035166, altitude: 0.2381641039831701, zenith: 1.3326322228117264, azimuthDegrees: 112.4486617789119, altitudeDegrees: 13.645797989750525, …}
2: {azimuth: 1.9670438426767658, altitude: 0.4781320008138626, zenith: 1.092664325981034, azimuthDegrees: 112.70331030257417, altitudeDegrees: 27.394945696779967, …}
3: {azimuth: 2.0056409208258157, altitude: 0.716028155591109, zenith: 0.8547681712037876, azimuthDegrees: 114.91475998205134, altitudeDegrees: 41.02539132790719, …}
4: {azimuth: 2.106117875144968, altitude: 0.9464893499017506, zenith: 0.624306976893146, azimuthDegrees: 120.67166540286752, altitudeDegrees: 54.229845103451325, …}
5: {azimuth: 2.352774172235539, altitude: 1.1542514926942995, zenith: 0.41654483410059706, azimuthDegrees: 134.8040302164822, altitudeDegrees: 66.13373902805874, …}
6: {azimuth: 2.9582193797984337, altitude: 1.2825445688422454, zenith: 0.2882517579526511, azimuthDegrees: 169.4934853362582, altitudeDegrees: 73.48439083208653, …}
7: {azimuth: 3.727387198651306, altitude: 1.2258827648993766, zenith: 0.3449135618955199, azimuthDegrees: 213.5635550938108, altitudeDegrees: 70.23790860656241, …}
8: {azimuth: 4.097477963055694, altitude: 1.040743662815431, zenith: 0.5300526639794656, azimuthDegrees: 234.76819393095275, altitudeDegrees: 59.630219434310625, …}
9: {azimuth: 4.244625795743045, altitude: 0.8170110513103618, zenith: 0.7537852754845348, azimuthDegrees: 243.19914370843512, altitudeDegrees: 46.81128505563008, …}
10: {azimuth: 4.304659041507528, altitude: 0.5813792398726065, zenith: 0.98941708692229, azimuthDegrees: 246.6387953212116, altitudeDegrees: 33.31057674122426, …}
11: {azimuth: 4.322058816246406, altitude: 0.34187533384813323, zenith: 1.2289209929467633, azimuthDegrees: 247.63572897822766, altitudeDegrees: 19.588013749124052, …}
12: {azimuth: 4.311693172055207, altitude: 0.1020810862683183, zenith: 1.4687152405265782, azimuthDegrees: 247.04182131413768, altitudeDegrees: 5.848815411285501, …}length: 13[[Prototype]]: Array(0)

I got it from Ajax call using JSON.stringify like below

var sunarray = [];
for(){
doSomething();
sunarray.push();
}
var solararray = JSON.stringify(sunarray);
sendDatathroughtAJAX();

in the server, I was able to call the first dimension by

$sun = json_decode($_POST['arrayraw']);
$data = pg_escape_string(anotherdata]);
echo json_encode($sun[1]);

//vv result in console.log vv 
:{
    "azimuth": 1.9625993875035166,
    "altitude": 0.2381641039831701,
    "zenith": 1.3326322228117264,
    "azimuthDegrees": 112.4486617789119,
    "altitudeDegrees": 13.645797989750525,
    "zenithDegrees": 76.35420201024948,
    "declination": -0.4090977792339249,
    "date": "2024-12-21T23:29:51.187Z"
}

I have trouble calling the 2nd dimension data by

echo json_encode($sun[1][azimuth]);
echo json_encode($sun[1]['azimuth']);

The only difference I got compared to the other people’s questions is that I don’t have any quotation marks for the key and value of the array.

Does anybody know how to call this 2nd dimension array data?

Dynamically change HTML column in Matrix based on row information in SurveyJS

I want to create a SurveyJS matrix with rows that contain a text & HTML element. Thus, the HTML content should change in each row. The Survey is a reasoning test that contains a text statement and a symbol pattern that I create by combining HTML code with some CSS. In the remaining columns it contains the response if the statement correctly describes the symbol pattern.

Below is an example of creating the matrix with the correct column types and row information. If I pass a static HTML to the HTML column it gets displayed correctly. But I am stuck at accessing the pattern property of each row to dynamically change the HTML.

const matrix_dynamic_html = {
    "elements": [
      {
        type: "matrixdropdown",
        name: "Test",
        title: "my_title",
        description: "my_pattern",
        columns: [
          {
            name: "pattern",
            title: "Pattern",
            cellType: "html",
            // here we have to access the HTML for each row 
            html: "{row.pattern}"
          },
          {
            name: "response",
            title: "response",
            cellType: "radiogroup",
            "choices": [
              {
                "value": 0,
                "text": "Incorrect"
              },
              {
                "value": 1,
                "text": "Correct"
              }
            ],
            "showInMultipleColumns": true,
            "colCount": 1
          }
        ],
        rows: [
          {
            value: "question_1",
            text: "This is question 1.",
            pattern: generate_html("ques_1"),
          },
          {
            value: "question_2",
            text: "This is question 2.",
            pattern: generate_html("ques_2"),
          },
          {
            value: "question_3",
            text: "This is question 3.",
            pattern: generate_html("ques_3"),
          },
          {
            value: "question_4",
            text: "This is question 4.",
            pattern: generate_html("ques_4"),
          }
        ],
        rowTitleWidth: "50%",
      }
    ],
    "showQuestionNumbers": false
  };

I use the generate_html function to generate the HTML and have checked that this works properly.

I appreciate any input on how to access the pattern property or adapt the setup of the matrix to be able to dynamically change the HTML. Any help is welcome.

How to open a URL in a new tab and redirect the current tab without triggering mobile browser popup blockers?

I’m working on a feature where I send a request to a server and receive a response. The response may or may not include a URL. If a URL is present in the response:

  1. I need to open that URL in a new browser tab.
  2. Simultaneously, I want to redirect the current tab to another page.

However, I’m facing issues with mobile browsers blocking the new tab because the window.open action doesn’t occur as a direct result of the user’s interaction (e.g., a click).

Additionally, opening a tab ahead of time (before the response is received) isn’t an option. The request is triggered by a form button, which also switches steps in the form. Since the response may not always contain a URL, I can’t open a new tab in advance for every button click.

  1. Here’s what I’ve tried so far:
fetch('/api/some-endpoint')
  .then(response => response.json())
  .then(data => {
    if (data.url) {
      window.open(data.url, '_blank');
    }
    window.location.href = '/another-page';
  });
  • Expectation: Open the URL in a new tab and redirect the current tab.
  • Result: Works on desktop, but mobile browsers block the new tab.
  1. Creating a link dynamically and emulating a click:
const link = document.createElement('a');
link.href = data.url;
link.target = '_blank';
link.click();
  • Expectation: Avoid triggering popup blockers.
  • Result: Did not work; the new tab is still blocked.

Is there a reliable way to achieve this functionality, especially on mobile browsers? Or any alternative approaches to handle this scenario?

Go to definition does not work in Vscode for the components declared inside index.jsx

I have a component named Messages defined inside this path: components/src/components/common/messages/index.jsx like the below image
enter image description here

I imported the Messages component as shown below image
enter image description here

When I use Ctrl + click on the component name in the import statement, it goes to the place where it is used. In the place where it is used When I use Ctrl + click on the component name, it goes back to the import statement. Let’s see the image below

enter image description here

I added a jsconfig.json file into my project, this is its content:

{
    "compilerOptions": {
        "baseUrl": "./components/src",
        "module": "es6",
        "jsx": "react"
    },
    "include": [
        "./components/src"
    ]
}

I can use Ctrl + Click to go to the definition of the Messages component if I update the above import statement from src/components/common/messages to src/components/common/messages/index. But I don’t want to do it. This way of importing worked with this command npx webpack serve -c config/webpack.serve.js, but it doesn’t work with Go to definition command of vscode. Does anyone know how to configure the project to be able to use Go to definition command of vscode with this way of importing?