How to write JavaScript for an image gallery that pops out to show a large image with left and right arrows using repeater fields for the images

I’ve searched around the internet and most lighthouse image modals or pop out image galleries use JavaScript to go up and down by 1 to a different image source (ex: img1.jpg-> img2.jpg -> img3.jpg).

I’m building an image gallery module in Hubspot using Hubl with repeating fields so these solutions won’t work.

What JavaScript could I use when the source of the image will use non linear names (in other words- each image source could vary from www.name/flower.jpg to. www.name/pizza.jpg). Would a solution be adding numbers to the div containing the repeating image source?

Here is one possible image gallery solution using Hubl repeater image fields for the image source:

const images = [...document.querySelectorAll('.gallery-image img')];

// popup

const popup = document.querySelector('.popup');
const closeBtn = document.querySelector('.close-btn');
const imageName = document.querySelector('.image-name');
const largeImage = document.querySelector('.large-image img');
const imageIndex = document.querySelector('.index');
const leftArrow = document.querySelector('.left-arrow');
const rightArrow = document.querySelector('.right-arrow');

let index = 0; // will track our current image;

images.forEach((item, i) => {
    item.addEventListener('click', () => {
        updateImage(i);
        popup.classList.toggle('active');
    })
})

const updateImage = (i) => {
    let path = `img/img${i+1}.png`;
    largeImage.src = path;
    imageName.innerHTML = path;
    imageIndex.innerHTML = `0${i+1}`;
    index = i;
}

closeBtn.addEventListener('click', () => {
    popup.classList.toggle('active');
})

leftArrow.addEventListener('click', () => {
    if(index > 0){
        updateImage(index - 1);
    }
})

rightArrow.addEventListener('click', () => {
    if(index < images.length - 1){
        updateImage(index + 1);
    }
})
*{
    margin: 0;
    padding: 0;
    box-sizing: border-box;
}

*:focus{
    outline: none;
}

body{
    width: 100%;
    height: 100vh;
    display: flex;
    justify-content: center;
    align-items: center;
    background: #ff7a2d;
    font-family: 'roboto', sans-serif;
}

.gallery{
    width: 80%;
    height: 90vh;
    max-width: 1600px;
    max-height: 800px;
    display: flex;
    flex-wrap: wrap;
    justify-content: center;
    align-items: center;
}

.gallery-image{
    width: 30%;
    height: calc(50% - 20px);
    min-width: 300px;
    min-height: 200px;
    margin: 10px;
    overflow: hidden;
}

.image{
    width: 100%;
    height: 100%;
    object-fit: cover;
    transition: 1s;
}

/* popup */

.popup{
    position: fixed;
    top: 50%;
    left: 50%;
    transform: translate(-50%, -50%) scale(0);
    width: 80%;
    max-width: 1600px;
    height: 90vh;
    max-height: 800px;
    border-radius: 20px;
    background: rgba(0, 0, 0, 0.75);
    display: flex;
    justify-content: center;
    align-items: center;
    z-index: 5;
    overflow: hidden;
    transition: 1s;
    opacity: 0;
}

.popup.active{
    transform: translate(-50%, -50%) scale(1);
    opacity: 1;
}

.popup.active .close-btn,
.popup.active .image-name,
.popup.active .index,
.popup.active .large-image,
.popup.active .arrow-btn{
    opacity: 1;
    transition: opacity .5s;
    transition-delay: 1s;
}

.top-bar{
    position: absolute;
    top: 0;
    left: 0;
    width: 100%;
    height: 50px;
    background: #000;
    color: #fff;
    text-align: center;
    line-height: 50px;
    font-weight: 300;
}

.image-name{
    opacity: 0;
}

.close-btn{
    opacity: 0;
    position: absolute;
    top: 15px;
    right: 20px;
    width: 20px;
    height: 20px;
    border-radius: 50%;
    background: #f00;
    cursor: pointer;
}

.arrow-btn{
    opacity: 0;
    position: absolute;
    top: 50%;
    transform: translateY(-50%);
    padding: 10px;
    border-radius: 50%;
    border: none;
    background: none;
    cursor: pointer;
}

.left-arrow{
    left: 10px;
}

.right-arrow{
    right: 10px;
    transform: translateY(-50%) rotate(180deg);
}

.arrow-btn:hover{
    background: rgba(0, 0, 0, 0.5);
}

.index{
    position: absolute;
    bottom: 10px;
    right: 10px;
    font-size: 80px;
    font-weight: 100;
    color: rgba(255, 255, 255, 0.4);
    opacity: 0;
}

.large-image{
    margin-top: 5%;
    width: 80%;
    height: 80%;
    object-fit: contain;
    opacity: 0;
}
<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>Image Popup</title>

    <link rel="stylesheet" href="style.css">

</head>
<body>

    <!-- popup -->
    <div class="popup">
        <!-- top bar -->
        <div class="top-bar">
            <p class="image-name">Image Name</p>
            <span class="close-btn"></span>
        </div>
        <!-- arrows -->
        <button class="arrow-btn left-arrow"><img src="img/arrow.png" alt=""></button>
        <button class="arrow-btn right-arrow"><img src="img/arrow.png" alt=""></button>
        <!-- image -->
            {% for item in module.image_1 %}
        <div class="large-image">
                    
            
    {% if item.src %}
        {% set sizeAttrs = 'width="{{ item.width }}" height="{{ item.height }}"' %}
        {% if item.size_type == 'auto' %}
            {% set sizeAttrs = 'width="{{ item.width }}" height="{{ item.height }}" style="max-width: 100%; height: auto;"' %}
        {% elif item.size_type == 'auto_custom_max' %}
            {% set sizeAttrs = 'width="{{ item.max_width }}" height="{{ item.max_height }}" style="max-width: 100%; height: auto;"' %}
        {% endif %}
         {% set loadingAttr = item.loading != 'disabled' ? 'loading="{{ item.loading }}"' : '' %}
        <img src="{{ item.src }}" alt="{{ item.alt }}" {{ loadingAttr }} {{ sizeAttrs }}>
    {% endif %}
                                </div>
{% endfor %}

        <!-- image-index -->
        <h1 class="index">01</h1>
    </div>

    <div class="gallery">
                    {% for item in module.image_1 %}
        <div class="gallery-image">
    {% if item.src %}
        {% set sizeAttrs = 'width="{{ item.width }}" height="{{ item.height }}"' %}
        {% if item.size_type == 'auto' %}
            {% set sizeAttrs = 'width="{{ item.width }}" height="{{ item.height }}" style="max-width: 100%; height: auto;"' %}
        {% elif item.size_type == 'auto_custom_max' %}
            {% set sizeAttrs = 'width="{{ item.max_width }}" height="{{ item.max_height }}" style="max-width: 100%; height: auto;"' %}
        {% endif %}
         {% set loadingAttr = item.loading != 'disabled' ? 'loading="{{ item.loading }}"' : '' %}
        <img src="{{ item.src }}" alt="{{ item.alt }}" {{ loadingAttr }} {{ sizeAttrs }}>
    {% endif %}

        </div>
            {% endfor %}
        
    </div>

    <script src="app.js"></script>
    
</body>
</html>

The issue is I need the pop up image to only pop up to the selected image, not every image in the repeater field. I also need a way to specify what image is being navigated to using arrow icons when the image is popped out.

I understand that this JS is based around the assumption that images will be named in sequential order from 1 and on (but it won’t work for a repeater field):

 const updateImage = (i) => {

    let path = `img/img${i+1}.png`;
    largeImage.src = path;
    imageName.innerHTML = path;
    imageIndex.innerHTML = `0${i+1}`;
    index = i;
}

Any help appreciated.

Single Vs Double Quote in console.log [duplicate]

const bill = 40;
const tip = bill >= 50 && bill <= 300 ? bill * 0.15 : bill * 0.20;
console.log(`The bill was ${bill}, the tip was ${tip}, and the total value ${bill + tip}`);

const bill = 40;
const tip = bill >= 50 && bill <= 300 ? bill * 0.15 : bill * 0.20;
console.log("The bill was ${bill}, the tip was ${tip}, and the total value ${bill + tip}");

Can someone help explain to me why console.log(“”) doesn’t work in the case below? It only works with console.log(“)? I’ve always used (“”) when using console.log and never had an issue until I came across the problem below.

Knex tries to use sqlite3 when already using mysql2

I’m trying to run some operations on a Node Typescript project with knex. It is already configured and when using knex-cli to create or run migrations (just as an example) it works perfectly fine.
The problem comes when I try to execute a normal operation e.g. insert, when I try to run, it throws an error:

Knex: runn$ npm install sqlite3 --savenCannot find module 'sqlite3'

And that’s pretty weird because the knexfile.ts is already configured.

Here I show the files:

knexfile.ts

import type { Knex } from "knex";

const config: { [key: string]: Knex.Config } = {
  development: {
    client: 'mysql2',
        connection: {
            host: 'localhost',
            database:  'test',
            user: 'root',
            password: 'root',
            port: 6033,
        },
        migrations: {
            directory: './src/infrastructure/repositories/mysql/migrations',
        },
        seeds: {
            directory: './src/infrastructure/repositories/mysql/seeds',
        }
  },
};

module.exports = config;

The part that is not working:

root.ts

import { FastifyPluginAsync } from 'fastify'
import knex from 'knex'


const root: FastifyPluginAsync = async (fastify, opts): Promise<void> => {
  
  fastify.post('/create', async(request, reply) => {

    // const knexapp = knex({
    //   client: 'mysql2',
    //       connection: {
    //           host: 'localhost',
    //           database:  'test',
    //           user: 'root',
    //           password: 'root',
    //           port: 6033,
    //       },
    //       migrations: {
    //           directory: './src/infrastructure/repositories/mysql/migrations',
    //       },
    //       seeds: {
    //           directory: './src/infrastructure/repositories/mysql/seeds',
    //       }
    // })

    await knex('users').insert(request.body)    
    return {message: request.body}
  })
}

export default root;

The code commented is because of another answer I got here that stated using a knex local variable would work and indeed it worked, but I don’t think that should be the best idea to solve this.

Javascript : make imagemap , but with zoomable / scrollable image

i want to let the user of a simple webpage create an imagemap, but since the image is very large ( with small items ), he needs to be able to zoom in before creating the clickable blocks.
I have found this : https://www.maschek.hu/imagemap/
And this works fine untill I noticed that you can not scroll the image around when you have zoomed in.
Is there anybody who knows another plugin which can do this? Or how to fix this?
Thank you.

I have looked online for other tools, but so far no success.

Using Hybridauth to get Yahoo email

I am trying to use hybridauth for a “Continue with Yahoo” button. I create the app on Yahoo, and implemented the code on a similar way I have been using it for the other social networks. But the response of yahoo ony have the property “sub”. I does not have name or email, or anything else.

Here is my code:

$configYahoo = [
    // Location where to redirect users once they authenticate with Yahoo
    // For this example we choose to come back to this same script
    'callback' => '**',

    "enabled" => true,
    // Yahoo application credentials
    'keys' => [
        'id' => '**',
        'secret' => '**'
    ],
    "scope"   => ['sdct-r', 'fspt-r', 'mail-r', 'sdps-r', 'sdpp-w'],
];

$adapterYahoo = new HybridauthProviderYahoo($configYahoo);
<?php

error_reporting(E_ALL);
ini_set('display_errors', 1);

include 'controllers/utils-functions.php';

try {
    $adapterYahoo->authenticate();
    $userProfile = $adapterYahoo->getUserProfile();
    $isConnected = $adapterYahoo->isConnected();
    // var_dump($isConnected);
    // var_dump($userProfile);

    $adapterYahoo->disconnect();
    if ($userProfile->lastName) {
        $fullname = $userProfile->firstName . ' ' . $userProfile->lastName;
    } else {
        $fullname = $userProfile->firstName;
    }
?>

This is the response I get, I used var_dump to get it:

object(stdClass)#75 (1) { ["sub"]=> string(26) "******************" }

Please let me know if something like this happen to any of you guys, or if you notice what I am doing wrong, I don’t know what else to try.

.Remove() function not working for MongoDb

This is constantly giving me error that Contact.remove() is not a function. I want to delete a contact by passing id.

const DeleteContact = asyncHandler(async (req, res) => {

    const contact = await Contact.findById(req.params.id);
    if (!contact) {
       res.status(404)
       throw new Error("Contact not found");
    }
  
 
    await Contact.remove();
    res.status(200).json(contact);
});


javascript not run on some element

My javascript not running on some element, it should be hiding some classes i.e when image loaded it will remove skeleton and display the image and replacing image source when original image broken or 404. but sometimes the skeleton is still displaying, and the image not visible

var aimpImages = document.querySelectorAll('.aimp-img');

function removeClassesAfterLoad(imgElement) {
  imgElement.parentNode.classList.remove('skeleton');
  imgElement.classList.remove('hide');
}

aimpImages.forEach(function(aimpImg) {
  var imgElement = aimpImg.querySelector('.aimp-img');

  if (imgElement) {
    imgElement.addEventListener('load', function() {
      removeClassesAfterLoad(imgElement);
    });
  };
  aimpImg.addEventListener("error", function(replace) {
    replace.target.src = '/img/404.svg';
  });
});

var imgCards = document.querySelectorAll(".img-card");
imgCards.forEach(function(imgCard) {
  var imgElement = imgCard.querySelector(".img-card");

  if (imgElement) {
    imgElement.addEventListener("load", function() {
      removeClassesAfterLoad(imgElement);
    });
  };
  
  imgCard.addEventListener("error", function(replace) {
    replace.target.src = "/img/404.svg";
  });
});

var imgCarousels = document.querySelectorAll(".img-carousel");

imgCarousels.forEach(function(imgCarousel) {
  var imgElement = imgCarousel.querySelector(".img-carousel");

  if (imgElement) {
    imgElement.addEventListener("load", function() {
      removeClassesAfterLoad(imgElement);
    });
  };
  
  imgCarousel.addEventListener("error", function(replace) {
    replace.target.src = "/img/404.svg";
  });
});
<div class="sect-items">
  <div class=c ontainer>
    <div class=c ard>
      <div class=i mage>
        <div class="img-card skeleton">
          <img class="img-card hide" href="#" src="w7-thumbnail/Raphtalia.png" title="Raphtalia"></div>
        <h3 style="margin-top: 1rem;">Windowa 7 Themes</h3>
      </div>
      <div class=c ontent>
        <p>Custom themes for windows 7, bored with your default windows 7 themes? try our custom anime themes for windows 7</p>
        <a href="/themes/windows7/" type="button" class="btn btn-primary">More 7 Themes</a>
      </div>
    </div>
  </div>

or you can visit my page at github https://henrietta2243.github.io/Home-Page/

tried to move tag in first line of tag but the js won’t load and placed inside the js won’t load. It work fine in VScode live server

ReactJS – What’s the difference between using useRef and putting a variable outside of the component?

What’s the difference between this code:

function MyComponent(){
    const isPersistent = useRef(true)
    // some more code...
}

and this code:

let isPersistent = true
function MyComponent(){
    // some more code...
}

I know I would usually put useRef for these. I’d never actually do it the second way, I just wanna know why. what’s the difference between these? I know I can useRef to also put on an HTML element. but if that’s not the case, why isn’t the second one good practice?

How To Clerar Interval After Function Done with Its Work

So i am building a countdown timer, if timer is over it stops the clock at zero and print done on in console log.

my issue is, when clock reaches zero, it should print done only once and setInterval should be cleared

const endDate = document.getElementById('end').innerText;
const inputs = document.querySelectorAll("input")


const clock = () => {
    const end = new Date(endDate)
    const now = new Date()
    const diff =(end-now)/1000


    if (diff < 0){
        console.log("Done")
        return;

    }

    // COnvert In days
    inputs[0].value = (Math.floor(diff/3600/24))
    inputs[1].value = (Math.floor((diff/3600) % 24))
    inputs[2].value = (Math.floor(diff/ 60 % 60))
    inputs[3].value = (Math.floor(diff% 60))
    
}



clock();

const clearInt = setInterval(() => {
    clock()
}, 1000);


if (clock === 0){
clearInterval(clearInt);
}

Formatting a value with exactly two decimals in JavaScript


    <script type="text/javascript">
   $(document).ready(function() { 
  
  $('#btn-add').click(function(){
      $('#select-from option:selected').each( function() {
              $('#select-to').append("<option value='"+$(this).val()+"'>"+$(this).text()+"</option>");
          $("input[name='class']").val(parseFloat($(this).val()) + parseFloat($("input[name='class']").val()));
      });
  });
  $('#btn-remove').click(function(){
      $('#select-to option:selected').each( function() {
          $('#select-from').append("<option value='"+$(this).val()+"'>"+$(this).text()+"</option>");
          $(this).remove();
          $("input[name='class']").val(parseInt($("input[name='class']").val() - parseInt($(this).val())));
          total= $("input[name='class']").val(parseInt($("input[name='class']").val() - parseInt($(this).val())));
      });
  
  });
    
   });
    </script>

I would like to shorten the number after decimal numbers to 2. Does somebody has any idea

Dynamically Adding Object properties as false value when they are not available in the API Output not working?

I have data output from a GA4 API. Over here I am pulling data for all the events such as view_item, add_to_cart,begin_checkout, and purchase.

API Output from GA4 Account

In the below code, you will see that all events are being populated except purchase.

var data = [{
      dimensionValues : [{
        value : 'view_item'
      }],
      metricValues : [{
        value : 175029
      }]
    }, {
      dimensionValues : [{
        value : 'add_to_cart'
      }],
      metricValues : [{
        value : 10049
      }]
    }, {
      metricValues : [{
        value : 6326
      }],
      dimensionValues : [{
        value : 'begin_checkout'
      }]
    } 
  
  ]

Objective

If event data is not available such as purchase, then I want to add this as a false value.

Expected Result

{
  add_to_cart: 10049,
  begin_checkout: 6326,
  view_item: 175029
  purchase: false
}

This is what I have done so far

var eventArray1 = [];

for (var item in data1) {
      var dimensions = data1[item].dimensionValues;
      for (var i = 0; i < dimensions.length; i++) {
        eventArray1.push([dimensions[i].value, data1[item].metricValues[0].value]);
      }

    }


const obj = Object.fromEntries(eventArray1);

const viewItem = obj.view_item !== undefined;    
const addToCart = obj.add_to_cart !== undefined;
const beginCheckout = obj.begin_checkout !== undefined;
const p = obj.purchase !== undefined;

if (viewItem === false || addToCart === false || beginCheckout === false || p === false) {

obj.view_item = viewItem
obj.add_to_cart = addToCart
obj.begin_checkout = beginCheckout
obj.purchase = p

} else  {}

console.log(obj)

Console Log


{
  add_to_cart: true,
  begin_checkout: true,
  purchase: false,
  view_item: true
}

How can I get the expected results as shown above? I would like to add the missing events dynamically to the object. Missing purchase is an example, view item can also be missing if not configured.

How to call NodeJS script inside custom VSCode Extension?

In one of my projects I created a NodeJS script. Now I would like to create a VSCode extension.

How can I link this script to a command inside my custom made extension?

The script should be included in the extension package.

I tried running the script from the terminal, but it wouldn’t load the script from within my package.

const terminal = vscode.window.createTerminal( 'My Node Script' );
terminal.show();
terminal.sendText( 'npm run myscript', true );

How can I achieve this?

Determination on the first element in selector [closed]

How is the determination on the first element in selector whether it is the direct descendant or indefinite depth level of descendant, of the current object/node, e.g. in body node below:

var e = document.body.querySelectorAll('div')   

So the first element in selector; div will it be interpreted as the direct descendant or not, so how JS code to mean it as direct descendant if not ?

JavaScript POST 415 Unsupported Media Type JSON [closed]

Whenever i try and make a post request to an REST api, I seem to come across an error saying unsupported media type can anyone help. I am trying to submit a UUID and an integer,

let addItemCart = () => {
  let sumbitBtns = document.getElementsByClassName('Subbutton')

  for (let i = 0; sumbitBtns.length > i; i++) {
    sumbitBtns[i].addEventListener('click', (e) => {
      let Item = e.target.dataset.item
      let quantity = 1
      fetch('URL', {
          method: 'POST',
          Headers: {
            'Accept': 'application/json',
            'Content-Type': 'application/json;charset=utf-8',
          },
          body: JSON.stringify({
            'Items_id': Item,
            'quantity': quantity
          })
        })
        .then(response => response.json())
        .then(data => {
          console.log('Success:', data)
        })
    })
  }
}

Everything seems to be working fine except when i add the method, headers and body stuff is where the error seems to lie.