How Can I Display Images When Clicked?

I am trying to develop a card matching game. I watched a Youtube Tutorial about it. But the cards does not show up even if I write the exact code from the video. The aim is matching two same characters. The characters should show up when a portal is clicked. So what’s the problem here? Here is my JavaScript code:

document.addEventListener('DOMContentLoaded',()=>{

    const cardArray = [
        {   
            name: 'beth',
            img: 'images/beth.png'
        },  

        {   
            name: 'beth',
            img: 'images/beth.png'
        }, 

        {   
            name: 'jerry',
            img: 'images/jerry.png'
        },    

        {   
            name: 'jerry',
            img: 'images/jerry.png'
        }, 

        {   
            name: 'morty',
            img: 'images/morty.png'
        },    

        {   
            name: 'morty',
            img: 'images/morty.png'
        }, 

        {   
            name: 'mrpoopybutthole',
            img: 'images/mrpoopybutthole.png'
        }, 
    
        {   
            name: 'mrpoopybutthole',
            img: 'images/mrpoopybutthole.png'
        },  

        {   
            name: 'rick',
            img: 'images/rick.png'
        },    

        {   
            name: 'rick',
            img: 'images/rick.png'
        },

        {   
            name: 'summer',
            img: 'images/summer.png'
        }, 
        
        {   
            name: 'summer',
            img: 'images/summer.png'
        }  
    ]


cardArray.sort(()=> 0.5 - Math.random());

const grid = document.querySelector('.grid');
const resultDisplay = document.querySelector('#result');
var cardsChosen = [];
var cardChosenId = [];
var cardsWon = [];


function createBoard() {
    for(let i=0; i<cardArray.length; i++){
        var card = document.createElement('img');
        card.setAttribute('src','images/portal.png');
        card.setAttribute('data-id', i);
        card.addEventListener('click', flipCard);
        grid.appendChild(card);
    }
}

function checkForMatch(){
    var cards = document.querySelectorAll('img');
    const optionOneId = cardsChosenId[0];
    const optionTwoId = cardsChosenId[1];

    if (cardsChosen[0] === cardsChosen[1]) {
        alert('You found a match');
        cards[optionOneId].setAttribute('src', 'images/white.png');
        cards[optionTwoId].setAttribute('src', 'images/white.png');
        cardsWon.push(cardsChosen);
    }

   else {
       cards[optionOneId].setAttribute('src', 'images/portal.png');
       cards[optionTwoId].setAttribute('src', 'image/portal.png');
       alert('Sorry, try again');
   } 

   cardsChosen = [];
   cardChosenId= [];
   resultDisplay.textContent = cardsWon.length;

   if (cardsWon.length === cardArray.length/2){
        resultDisplay.textContent = 'Congratulations! You found them all!';
   }

}


function flipCard(){
    var cardId= this.getAttribute('data-id');
    cardsChosen.push(cardArray[cardId].name);
    cardsChosenId.push(cardId);
    this.setAttribute('src',cardArray[cardId].img);

    if(cardsChosen.length === 2){
        setTimeout(checkForMatch,500);
    }


}
createBoard();

});

Create a function that follows a moving text on a table

I found a function to move data between table cells but the functions never seem to stick to whatever tag is “attached” to the cell itself. I’m not sure if I was using ids wrong. I need help finding a way to “attach” a function to a tag that moves between cells.
Can you help me create a button to move a tag (unit 1) upwards and downwards through a table such that it stops at the end of the table?

Original code attached here

//Send to the "bottom"
function sendOS() {
  var node = document.getElementById("r1c1").lastChild;
  document.getElementById("r1c3").appendChild(node);
  /*
    var node = document.getElementById("r1c3").lastChild;
  document.getElementById("r1c2").appendChild(node);
  */
}

//Send to the "top"
function sendTop() {
  var node = document.getElementById("r1c2").lastChild;
  document.getElementById("r1c1").appendChild(node);
}
table,
th,
td {
  border: 1px solid black;
  width: 32px;
  height: 32px;
}
<table>
  <tr id="row1">
    <td id="r1c1">Unit1</th>
      <td id="r1c2">Unit2</th>
        <td id="r1c3">Unit3</th>
  </tr>
  <tr id="row2">
    <td id="r2c1">r1c2</td>
    <td id="r2c2">r2c2</td>
    <td id="r2c2">r2c3</td>
  </tr>
  <tr id="row3">
    <td id="r2c2">r3c1</td>
    <td id="r2c2">r3c2</td>
    <td id="r2c2">r3c3</td>
  </tr>
</table>
<!--Table ends -->
<!-------------------------------------------------------------->


<button onclick="sendOS()">move to the other side</button>
<button onclick="sendTop()">move to the right</button>

AJAX: Posts are sent empty

I am using AJAX for the first time and try to send data to my PHP controller with an XMLHttpRequest. Unfortunately, the data arrives empty there.

           request.onload = () => {
                let responseObject = null;

                try {
                    responseObject = JSON.parse(request.responseText);
                } catch (e) {
                    console.error('Could not parse JSON!');
                }

                if (responseObject) {
                    handleResponse(responseObject);
                }
            };

            const requestData = `title=${this._title.value}&reference=${this._reference.value}&area=${this._area.value}`;

            request.open('post', 'checknews');
            request.setRequestHeader('Content-type', 'application/x-www-form-urlencoded');
            request.send(requestData);

Whats wrong ?

p5.js: Why can’t I use my ‘brush’ while background() is called in the draw() function?

I’m creating a painting app using the p5.js editor, and I want to be able to customise both the background and draw using various brushes etc.

The problem is, when I include background(variable) into the draw() function, I can only change the background, but cannot draw.

When I remove it so that it is only included in the setup, I can draw once again, but cannot change the background colour.

Is there a way to include both, perhaps in different functions?

Any help would be greatly appreciated as I’ve been stuck on this for days!!

Here is my code:

let whiteB;
let redB;
let yellowB;
let blueB;
let blackB;
let greenB;
let pinkB;
let brownB;
let bucket;

let brushSize;

let rSlide, gSlide, bSlide;
let r, g, b;

let imgLego;
let imgPalette;
let fontHead;
let fontMid;
let fontSub;
let x;

let legohead;
let lucky;


function preload() {
  imgLego = loadImage("images/lego.png");
  imgBucket = loadImage("images/bucket.png");
  fontHead = loadFont("fonts/shizuru.ttf");
  fontMid = loadFont("fonts/concertOne.ttf");
  fontSub = loadFont("fonts/gloria.ttf");
  
}// close preload function

function setup() {
  
  background(255);
  createCanvas(1000, 600);
  noStroke();

  x = 10;
  
  // create the slider for the brush size
  brushSize = createSlider(1, 100, 20);

  // create the sliders for red, gree, blue values
  rSlide = createSlider(0, 255, 0);
  gSlide = createSlider(0, 255, 0);
  bSlide = createSlider(0, 255, 0);

  // position the sliders
  rSlide.position(x, x * 20);
  gSlide.position(x, x * 22);
  bSlide.position(x, x * 24);
  brushSize.position(x, x * 26);

  // variables to hold the colour (background)
  r = 255;
  g = 255;
  b = 255;
  
  // variables to hold the colour (random button)
  r1 = random(0,255);
  g1 = random(0,255);
  b1 = random(0,255);
  
  // color variables for fill bucket
  whiteB = color(255);
  redB = color(255,0,0);
  yellowB = color(246, 236, 54);
  blueB = color(0,0,255);
  blackB = color(0);
  greenB = color(0,170,35);
  pinkB = color(255,53,184);
  brownB = color(155,103,60);
  bucket = whiteB;

}

function draw() {
  
  background(bucket);
  noStroke();
  
  // yellow rectangle acting as margin
  fill(yellowB);
  rect(0, 0, 250, height)
  
  // poisition the text & value of slider
  textAlign(LEFT, TOP);
  fill(255);
  textFont(fontMid);
  textSize(15);
  text("red : " + rSlide.value(), x*2 + rSlide.width, x*20);
  text("green : " + gSlide.value(), x*2 + gSlide.width, x*22);
  text("blue : " + bSlide.value(), x*2 + bSlide.width, x*24);
  text("brush : " + brushSize.value(), x*2 + brushSize.width, x*26);

  // read the value of the slider and store it in a variable
  r = rSlide.value();
  g = gSlide.value();
  b = bSlide.value();
  
  // customise "background" text
  fill(0);
  textSize(20);
  text("BRUSH COLOR", 20, 175);
  
  // red "navbar"
  fill(redB)
  rect(0,0,1000,120,0,0,50,0);
  
  // customse "sketch" text
  fill(255)
  textFont(fontHead);
  textSize(40);
  text("SKETCH", 180, 10)
  
  // customse "random" text
  fill(0)
  textFont(fontSub);
  textSize(25);
  text("random", 850, 550);
  
  
  // images
  image(imgBucket, 930, 40, 40, 40);
  image(imgLego, 20, 15, 160, 90);
  
  //**lego block top right corner**//
  stroke(0);
  strokeWeight(3)
  // yellow block
  fill(246, 236, 54);
  rect(748,18,164,84,5)
  
  
  // paint buttons
  
  ellipseMode(CENTER);
  
  // white button
  fill(whiteB);
  ellipse(770,40,30);
  if (mouseX > 750 && mouseX < 790 && mouseY > 20 && mouseY < 60 && mouseIsPressed) { 
  bucket = whiteB;
  }
    
  // red button
  fill(redB);
  ellipse(810,40,30);
  if (mouseX > 790 && mouseX < 830 && mouseY > 20 && mouseY < 60 && mouseIsPressed) { 
  bucket = redB;
  }
    
  // yellow button
  fill(yellowB);
  ellipse(850,40,30);
  if (mouseX > 830 && mouseX < 870 && mouseY > 20 && mouseY < 60 && mouseIsPressed) { 
  bucket = yellowB;
  }
  
  // blue button
  fill(blueB);
  ellipse(890,40,30);
  if (mouseX > 870 && mouseX < 910 && mouseY > 20 && mouseY < 60 && mouseIsPressed) { 
  bucket = blueB;
  }
  
  // black button
  fill(blackB);
  ellipse(770,80,30);
  if (mouseX > 750 && mouseX < 790 && mouseY > 60 && mouseY < 100 && mouseIsPressed) { 
  bucket = blackB;
  }
  
  // green button
  fill(greenB);
  ellipse(810,80,30);
  if (mouseX > 790 && mouseX < 830 && mouseY > 60 && mouseY < 100 && mouseIsPressed) { 
  bucket = greenB;
  }
  
  // pink button
  fill(pinkB);
  ellipse(850,80,30);
  if (mouseX > 830 && mouseX < 870 && mouseY > 60 && mouseY < 100 && mouseIsPressed) { 
  bucket = pinkB;
  }
  
  // brown button
  fill(brownB);
  ellipse(890,80,30);
  if (mouseX > 870 && mouseX < 910 && mouseY > 60 && mouseY < 100 && mouseIsPressed) { 
  bucket = brownB;
  } 
  
} // close draw function


function mouseDragged() {
  stroke(r,g,b);
  strokeWeight(brushSize.value())
  line(mouseX, mouseY, pmouseX, pmouseY)
  
} // close mouseDragged function

Get nested button id in header

So I’m trying to reference my button (which is nested inside my header/nav), to make an event onclick, but I cant seem to get it to work. Tried nesting getElementByName with getelementbyid tried some queryselector and querySelectorAll been watching a lot of videos and tutorials don’t know if I’m just doing them wrong thanks.

Tried:

var x = document.getElementsByClassName('hdr');
var y= x.querySelector('hdrBtns');
z = y.getElementById('singUp');

Tried:

const brt = document.querySelectorAll('.hdr .hdrBtns');
const dac = brt.getElementById('signUp');

Code Underneath:

 <body>
        <header class="hdr">
            <div class="hLogo">
                <h1>
                    Test
                </h1>               
            </div>

            <nav class="hdrBtns">
                <button id="singUp">Sign Up</button>
                <button id="singIN">Sign In</button> 
                
            </nav>
        </header>
     <script src="./script.js"></script>
    </body>

Find JSON values return as strings [duplicate]

I am trying to read the JSON data to find how many instances each trait_type’s value appears for each nth edition and send the value to the HTML table as a string with the trait_type value’s ID. The filter function currently returns 0 for each value.

var data = [
  {
    edition: 1,
    attributes: [
      {
        trait_type: "hair",
        value: "mullet"
      },
      {
        trait_type: "hat",
        value: "cap"
      }
    ]
  }
];
var mullet = data.filter(function (d) {
    return d.value === "mullet";
  }).length,
  cap = data.filter(function (d) {
    return d.value === "cap";
  }).length;

document.getElementById("mullet").innerText = mullet;
document.getElementById("cap").innerText = cap;
<dl>
  <dt>Hair?</dt>
  <dd id="mullet"></dd>
  <dt>Hat?</dt>
  <dd id="cap"></dd>
</dl>

firebase functions, cant resolve module?

Im having an annoying problem which i’ve spent most of my day trying to solve without any luck – Also tried searching for a solution here and on Google, but without any luck, or at least all solution tried out didn’t work.

When running my function, the firebase function log is telling me:

Cannot find module 'mailgun.js'

I have no idea why it won’t resolve the module as it exist in the package.json file.

From the package.json:

"dependencies": {
    "cors": "^2.8.5",
    "firebase-admin": "^9.8.0",
    "firebase-functions": "^3.14.1",
    "form-data": "^4.0.0",
    "mailgun.js": "^4.1.4"
  },

I’ve have done a npm install inside the functions folder, and it deploys without problems, so the problem is when calling the function…

The code is:

import * as functions from "firebase-functions";
import Mailgun from "mailgun.js";
// eslint-disable-next-line @typescript-eslint/no-var-requires
const formData = require("form-data");

const domain = "https://app.mailgun.com/app/sending/domains/sandboxae7cd087b3854d25a6933f1fe489b5e3.mailgun.org";
const mgClient = new Mailgun(formData);

const mg = mgClient.client({
  key: "mykey",
  username: "api",
  public_key: "mypublickey",
});

export const sendWelcomeEmailToClient = functions.https.onCall(
    async (email: string) => {
      return mg.messages.create(domain, {
        from: "Task System",
        to: email,
        subject: "Testing",
        html: "Dette er en test",
      });
    }
);

Please note, i’ve also tried doing a require instead of import on mailgun.js like so, but didn’t work either:

const Mailgun = require("mailgun.js");

How to iterate over array elements inside objects in javascript

I have a graphData array and I would like to push the close price array values of this response data I got from finhub into the x key of the graphData and the timestamps into the y key of the graphData array.

so it would be like this: graphData[{x:timestamp, y:closing price}]

So essentially I want to have the x values of graphData to be the timestamp each stock and the y values of graphData to be the closing price of each stock so that I can graph it

This is the Line Graph I am using from chartjs:

return (
<div className="linegraph">
  <Line
    data={{
      datasets: [
        {
          type: "line",
          backgroundColor: "black",
          borderColor: "#5AC53B",
          borderWidth: 2,
          pointBorderColor: "rgba(0, 0, 0, 0)",
          pointBackgroundColor: "rgba(0, 0, 0, 0)",
          pointHoverBackgroundColor: "#5AC53B",
          pointHoverBorderColor: "#000000",
          pointHoverBorderWidth: 4,
          pointHoverRadius: 6,
          data: graphData,
        },
      ],
    }}
    options={{
      maintainAspectRatio: false,
      legend: {
        display: false,
      },
      tooltips: {
        mode: "index",
        intersect: false,
      },
      scales: {
        yAxes: [
          {
            gridLines: {
              display: false,
            },
          },
        ],
      },
    }}
  />
</div>

);
}

Any kind of help will be appreciated. I am sorry if I could not word the question properly. English is not my first language and if you need any additional information to understand me properly please ask

How to find document’s array item by its “_id” field in MongoDB (Mongoose)?

I have the following schema (NestJS + Mongoose):

@Schema({ timestamps: true })
export class Listing {
  @Prop({
        type: [{
            bidderId: { type: Types.ObjectId, required: true, select: false, ref: User.name, index: true },
            amount: { type: Number, required: true },
            date: { type: Date, required: true }
        }],
        select: false
    })
        bids!: Bid[]
}

so basically every listing document has an array of bids.
now I notice that automatically mongoDB (or mongoose) creates _id field for every bid item I put into the bids array.

My question is, If I have a bid’s _id, how can I query it’s item from the listing’s bids array? something like:

  // Adding a new bid to the listing, and retrieving the updated listing
  const listingWithAddedBid = await this.listingModel.findByIdAndUpdate(listingId, {
    $push: {
        bids: {
            $each: [{
                amount: bidInfo.amount,
                bidderId: new Types.ObjectId(user.id),
                date: new Date()
            }],
            $sort: { amount: -1 }
        }
    }
}, { new: true })

  // Getting the new bid's _id from the array (it will be at index 0 because we sort buy amount)
  const newBidId = listingWithAddedBid.bids[0]._id

  // here how can I query the entire bid item from the array with 'newBidId'? this won't work
  this.listingModel.findById(newBidId) // returns null

Export or import trouble with jsx files

I try to import some components into my App.js file from index2.js(export .jsx collection) where I can import only one component to see something on website – when I want import more, the page is white / empty, but if I import only Navbar.jsx component that’s work.

File structure:

__node_modules

__public

__src
____components
_______Cryptocurrencies.jsx
_______Cryptodetails.jsx
_______index2.js
_______Exchanges.jsx
_______Homepage.jsx
_______Navbar.jsx
_______News.jsx
___App.css
___App.js
___index.js

__.gitignore
__package-lock.json
__package.json

index.js:

import react from "react";
import reactDom from "react-dom";
import { BrowserRouter as Router } from "react-router-dom";
import App from "./App"
import 'antd/dist/antd.min.css';
reactDom.render(
    <Router>
        <App />
    </Router>, 
    document.getElementById('root')
)

App.js

import React from 'react'
import { Routes, Route, Link } from 'react-router-dom'
import { Layout, Typography, Space } from 'antd'
import { Cryptocurrencies, Cryptodetails, Exchanges, Homepage, Navbar, News } from './components'
import './App.css';

const App = () => {
    return (
        
            <div className='app'>
                <div className='navbar'>
                    <Navbar />
                </div>
                <div className='main'>
                <Layout>
                    <div className='routes'>
                        <Routes>
                            <Route path='/'>
                                <Homepage />
                            </Route>
                            <Route path='/exchanges'>
                                <Exchanges />
                            </Route>
                            <Route path='/cryptocurrencies'>
                                <Cryptocurrencies />
                            </Route>
                            <Route path='/crypto:coinId'>
                                <Cryptodetails />
                            </Route>
                            <Route path='/news'>
                                <News />
                            </Route>
                        </Routes>
                    </div>
                </Layout>
            </div>
                <div className='footer'>

                </div>
            </div>
        
    )
}

export default App

index2.js

export { default as Cryptocurrencies } from './Cryptocurrencies'
export { default as Cryptodetails } from './Cryptodetails'
export { default as Exchanges } from './Exchanges'
export { default as Homepage } from './Homepage'
export { default as Navbar } from './Navbar'
export { default as News } from './News'

The .jsx files are created by using default rafce.

Not working code (App.js):

...
import { Cryptocurrencies, Cryptodetails, Exchanges, Homepage, Navbar, News } from './components'
...
uncommented code with Layout part in div ``main`` class
...

Working code (App.js):

...
import { Navbar } from './components'
...
//commented code with Layout part in div ``main`` class
...

Please, explain me where have make an error. Thanks!

Is it possible to have nested enum in Typescript?

Having those enums:

export enum First {
  TEST_1 = 'test_1',
  TEST_2 = 'test_2'
}

export enum Second {
  TEST_3 = 'test_3',
  TEST_4 = 'test_4'
}

is it possible to combine them into a single one?

Something like:

export enum Main {
  First {
    TEST_1 = 'test_1',
    TEST_2 = 'test_2'
  },
  Second {
    TEST_3 = 'test_3',
    TEST_4 = 'test_4'
  }
}

React – Sending uploaded images as url to an API

I am sending multiple images to an API but the way I do it sends it as an object but I need to send it as a URL.

State:

const [files, setFiles] = useState([]);

Image uploader:

 const fileSelectHandler = (e) => {
        setFiles([...files, ...e.target.files]);
      };

<input
  type="file"
  className="form-control"
  id="customFile"
  multiple
  onChange={fileSelectHandler}
/>

Expected sending package:

"pic": [
            {
                "url": "760634d2-f8ec-4caa-9a2d-14a8828cfb5dpetplace.jpg"
            },
            {
                "url": "760634d2-f8ec-4caa-9a2d-14a8828cfb5dpetplace.jpg"
            }
       ]

Why is my WebRTC peer-to-peer application failing to work properly?

it’s been quite a long time since I’ve posted here. Just wanted to bounce this off of you as it has been making my brain hurt. So, I have been developing a real time video chat app with WebRTC. Now, I know that the obligatory “it’s somewhere in the network stack (NAT)” answer always applies.

As is always the case it seems with WebRTC, it works perfectly in my browser and on my laptop between tabs or between Safari/Chrome. However, over the internet on HTTPS on a site I’ve created, it is shotty at best. It can accept and display the media stream from my iPhone but it cannot receive the media stream from my laptop. It just shows a black square on the iPhone for the remote video.

Any pointers would be most appreciate though as I’ve been going crazy. I know that TURN servers are an inevitable aspect of WebRTC but I’m trying to avoid employing that.

So, here is my Session class which handles essentially all the WebRTC related client side session logic:

(The publish method is just an inherited member that emulates EventTarget/EventEmitter functionality and the p2p config is just for Google’s public STUN servers)

class Session extends Notifier {
    constructor(app) {
        super()

        this.app = app

        this.client = this.app.client

        this.clientSocket = this.client.socket

        this.p2p = new RTCPeerConnection(this.app.config.p2pConfig)

        this.closed = false

        this.initialize()
    }

    log(message) {
        if (this.closed) return

        console.log(`[${Date.now()}] {Session} ${message}`)
    }

    logEvent(event, message) {
        let output = event
        if (message) output += `: ${message}`
        this.log(output)
    }

    signal(family, data) {
        if (this.closed) return
        
        if (! data) return

        let msg = {}
        msg[family] = data
        
        this.clientSocket.emit("signal", msg)
    }

    initialize() {
        this.p2p.addEventListener("track", async event => {
            if (this.closed) return
            try {
                const [remoteStream] = event.streams
                this.app.mediaManager.remoteVideoElement.srcObject = remoteStream
            } catch (e) {
                this.logEvent("Failed adding track", `${e}`)
                this.close()
            }
        })

        this.p2p.addEventListener("icecandidate", event => {
            if (this.closed) return 
            if (! event.candidate) return
            this.signal("candidate", event.candidate)
            this.logEvent("Candidate", "Sent")
        })

        this.p2p.addEventListener("connectionstatechange", event => {
            if (this.closed) return
            switch (this.p2p.connectionState) {
                case "connected":
                    this.publish("opened")
                    this.logEvent("Opened")
                    break
            
                // A fail safe to ensure that faulty connections 
                // are terminated abruptly
                case "disconnected":
                case "closed":
                case "failed":
                    this.close()
                    break

                default:
                    break
            }
        })

        this.clientSocket.on("initiate", async () => {
            if (this.closed) return
            try {
                const offer = await this.p2p.createOffer()
                await this.p2p.setLocalDescription(offer)
                this.signal("offer", offer)
                this.logEvent("Offer", "Sent")
            } catch (e) {
                this.logEvent("Uninitiated", `${e}`)
                this.close()
            }

        })

        this.clientSocket.on("signal", async data => {
            if (this.closed) return
            try {
                if (data.offer) {
                    this.p2p.setRemoteDescription(new RTCSessionDescription(data.offer))
                    this.logEvent("Offer", "Received")
                    const answer = await this.p2p.createAnswer()
                    await this.p2p.setLocalDescription(answer)
                    this.signal("answer", answer)
                    this.logEvent("Answer", "Sent")
                }

                if (data.answer) {
                    const remoteDescription = new RTCSessionDescription(data.answer)
                    await this.p2p.setRemoteDescription(remoteDescription)
                    this.logEvent("Answer", "Received")
                }

                if (data.candidate) {
                    try {
                        await this.p2p.addIceCandidate(data.candidate)
                        this.logEvent("Candidate", "Added")
                    } catch (e) {
                        this.logEvent("Candidate", `Failed => ${e}`)
                    }
                }
            } catch (e) {
                this.logEvent("Signal Failed", `${e}`)
                this.close()
            }
        })

        this.app.mediaManager.localStream.getTracks().forEach(track => {
            this.p2p.addTrack(track, this.app.mediaManager.localStream)
        })
    }

    close() {
        if (this.closed) return

        this.p2p.close()
        this.app.client.unmatch()
        this.logEvent("Closed")
        
        this.closed = true
    }
}

VueJS: JSON objects are not showing in my code

I have API that stores JSON data as shown in JSON body below… I wanted to show the data amount stored in installments but it didn’t work good because its showing me each amount value two times and I couldn’t figure out the problem here.

{
  "response": [{
        "floors": [{
              "flats": [{
                    "status": "sold",
                    "price": "150000",
                    "currency": "USD",
                    "end_date": "Not Set",
                    "buyer": "ella",
                    "buyer_phone_number": "002822128",
                    "receipt_number_field": "553108012022",
                    "size_unit": "M",
                    "_id": "61d9b61397e87e39832a5abb",
                    "flat_number": 1,
                    "description": "This is a newly created flat.",
                    "city": "NY",
                    "payment": {
                      "installment_payment": {
                        "installments": [{
                            "amount": "1344",
                            "date": "2022-01-13",
                            "is_paid": false
                          },
                          {
                            "amount": "444",
                            "date": "2022-01-24",
                            "is_paid": false
                          },
                          {
                            "amount": "44444",
                            "date": "2022-01-17",
                            "is_paid": false
                          }
                        ],
                        "remaining": "150000"
                      },
                      "paid_amount": "1234"
                    },
                    "floor": "61d9b61397e87e39832a5aba",
                    "building": "61d9b61397e87e39832a5ab9",
                    "size": "176.25",
                    "directions": " south",
                    "createdAt": "2022-01-08T16:04:43.557Z",
                    "updatedAt": "2022-01-08T16:22:29.220Z",
                    "__v": 0
                  },

my code:

<div v-for="(flat,index) in Flats" :key="index">
<div v-for="(find,indexT) in flat.payment" :key="indexT" >
<div v-if="flat.payment.installment_payment">
 <div v-for="(find,indexT) in  flat.payment.installment_payment.installments" :key="indexT">
                <div v-if="find.amount >0">

                 <p> {{find.amount}}$  amount </p>
                                         
                                      </div>
                                      </div>
                                    </div>
                                </div>
                                </div>

p.S: I stored my API data in array Flats

How to make images responsive on smaller screen sizes?

I am a beginner learning from tutorials and I am using the NASA APOD API to make an image gallery.

However, for some reason the images are not responsive when viewing on smaller screen sizes. The images goes off screen and I want it to be like a grid 3 column gallery.

Is using flex box the answer? or Perhaps using media queries is easier?

Apologies for the newbie question.

const resultsNav = document.getElementById("resultsNav");
const favoritesNav = document.getElementById("favoritesNav");
const imagesContainer = document.querySelector(".images-container");
const saveConfirmed = document.querySelector(".save-confirmed");
const loader = document.querySelector(".loader");

// NASA API
const count = 18;
const apiKey = 'DEMO_KEY';
const apiUrl = `https://api.nasa.gov/planetary/apod?api_key=${apiKey}&count=${count}`;

let resultsArray = [];
let favorites = {};

// Show Content
function showContent(page) {
  window.scrollTo({ top: 0, behavior: "instant" });
  if (page === "results") {
    resultsNav.classList.remove("hidden");
    favoritesNav.classList.add("hidden");
  } else {
    resultsNav.classList.add("hidden");
    favoritesNav.classList.remove("hidden");
  }
  loader.classList.add("hidden");
}

// Create DOM Nodes
function createDOMNodes(page) {
  const currentArray =
    page === "results" ? resultsArray : Object.values(favorites);
  currentArray.forEach((result) => {
    // Card Container
    const card = document.createElement("div");
    card.classList.add("card");

    // Link that wraps the image
    const link = document.createElement("a");
    link.href = result.hdurl;
    link.title = "View Full Image";
    link.target = "_blank";

    // Image
    const image = document.createElement("img");
    image.src = result.url;
    image.alt = "NASA Picture of the Day";
    image.loading = "lazy";
    image.classList.add("card-img-top");

    // Card Body
    const cardBody = document.createElement("div");
    cardBody.classList.add("card-body");

    // Card Title
    const cardTitle = document.createElement("h5");
    cardTitle.classList.add("card-title");
    cardTitle.textContent = result.title;

    // Save Text
    const saveText = document.createElement("p");
    saveText.classList.add("clickable");
    if (page === "results") {
      saveText.textContent = "Add To Favorites";
      saveText.setAttribute("onclick", `saveFavorite('${result.url}')`);
    } else {
      saveText.textContent = "Remove Favorite";
      saveText.setAttribute("onclick", `removeFavorite('${result.url}')`);
    }

    // Card Text
    const cardText = document.createElement("p");
    cardText.textContent = result.explanation;

    // Footer Conatiner
    const footer = document.createElement("small");
    footer.classList.add("text-muted");

    // Date
    const date = document.createElement("strong");
    date.textContent = result.date;

    // Copyright
    const copyrightResult =
      result.copyright === undefined ? "" : result.copyright;
    const copyright = document.createElement("span");
    copyright.textContent = ` ${copyrightResult}`;

    // Append everything together
    footer.append(date, copyright);
    // cardBody.append(cardTitle, saveText, cardText, footer); //hide to make image display
    link.appendChild(image);
    card.append(link);

    // Append to image container
    imagesContainer.appendChild(card);
  });
}

// Update the DOM
function updateDOM(page) {
  // Get favorites from local storage
  if (localStorage.getItem("nasaFavorites")) {
    favorites = JSON.parse(localStorage.getItem("nasaFavorites"));
  }
  imagesContainer.textContent = "";
  createDOMNodes(page);
  showContent(page);
}

// Get 10 images from NASA API
async function getNasaPictures() {
  // Show Loader
  loader.classList.remove("hidden");
  try {
    const response = await fetch(apiUrl);
    resultsArray = await response.json();
    updateDOM("results");
  } catch (error) {
    // Catch Error Here
  }
}

// Add result to favorites
function saveFavorite(itemUrl) {
  // Loop through the results array to seelct favorite
  resultsArray.forEach((item) => {
    if (item.url.includes(itemUrl) && !favorites[itemUrl]) {
      favorites[itemUrl] = item;
      // Show save confirmation for 2 seconds
      saveConfirmed.hidden = false;
      setTimeout(() => {
        saveConfirmed.hidden = true;
      }, 2000);
      // Set Favorites in Local Storage
      localStorage.setItem("nasaFavorites", JSON.stringify(favorites));
    }
  });
}

// Remove item from favorites
function removeFavorite(itemUrl) {
  if (favorites[itemUrl]) {
    delete favorites[itemUrl];
    localStorage.setItem("nasaFavorites", JSON.stringify(favorites));
    updateDOM("favorites");
  }
}

// On Load
getNasaPictures();
html {
  box-sizing: border-box;
}

body {
  margin: 0;
  background: whitesmoke;
  overflow-x: hidden;
  font-family: Verdana, sans-serif;
  font-size: 1rem;
  line-height: 1.8rem;
}

.container {
  position: relative;
  display: flex;
  flex-direction: column;
  align-items: center;
  margin-top: 5px;
  margin-bottom: 25px;
}

/* Navigation */
.navigation-container {
  position: fixed;
  top: 0;
}

.navigation-items {
  display: flex;
  justify-content: center;
}

.background {
  background: whitesmoke;
  position: fixed;
  right: 0;
  width: 100%;
  height: 60px;
  z-index: -1;
}

.clickable {
  color: #0b3d91;
  cursor: pointer;
  user-select: none;
}

.clickable:hover {
  color: #fc3d21;
}

/* Images Container */
.images-container {
  display: grid;
  grid-template-columns: repeat(3, 1fr);
  padding-top: 100px;
}

.column {
  margin-left: auto;
  margin-right: auto;
}

.card {
  margin: 10px 10px 20px;
  width: 300px;
  height: 300px;
}

.card-img-top {
  width: 300px;
  height: 300px;
  border-radius: 5px 5px 0 0;
  display: block;
  margin-left: auto;
  margin-right: auto;
}

.card-body {
  padding: 20px;
}

.card-title {
  margin: 10px auto;
  font-size: 24px;
}

/* Save Confirmation */
.save-confirmed {
  background: white;
  padding: 8px 16px;
  border-radius: 5px;
  box-shadow: 0 4px 8px 0 rgba(0, 0, 0, 0.2);
  transition: 0.3s;
  position: fixed;
  bottom: 25px;
  right: 50px;
  z-index: 500;
}

/* Hidden */
.hidden {
  display: none;
}
<div class="loader hidden">
    </div>

    <!-- Container -->
    <div class="container">
      <!-- Navigation -->
      <div class="navigation-container">
        <span class="background"></span>
        <!-- Results Nav -->
        <span class="navigation-items" id="resultsNav">
          <h3 class="clickable" onclick="updateDOM('favorites')">Favorites</h3>
          <h3>&nbsp;&nbsp;&nbsp;•&nbsp;&nbsp;&nbsp;</h3>
          <h3 class="clickable" onclick="getNasaPictures()">Load More</h3>
        </span>
        <!-- Favorites Nav -->
        <span class="navigation-items hidden" id="favoritesNav">
          <h3 class="clickable" onclick="getNasaPictures()">
            Load More NASA Images
          </h3>
        </span>
      </div>

      <!-- Images Container -->
      <div class="container-fluid">
        <div class="row">
          <div class="column">
            <div class="images-container"></div>
          </div>
        </div>
      </div>
    </div>

    <!-- Save Confirmation -->
    <div class="save-confirmed" hidden>
      <h1>ADDED!</h1>
    </div>