HTML + JavaScript custom player for multiple videos on a website page

I’m coding a portfolio website for myself using HTML, CSS and JS and I need to add multiple videos on a lot of pages. I followed some tutorials to learn how to customize the video player, but it only works for one specific video on the page. If I were to add more videos, I’d need to have one .js custom player file for each video and manually select them on the website. How can I apply this single .js custom video player to all of my videos using purely javascript? I have found similar topics about the subject here, but all of them uses jQuery and I’m struggling to make it work with javascript.

My HTML for the video player:

<section class="videoplayer">
<div class="c-video">
    <div id="video_player">
        <video src="./media/portfolio/videos/Show-Reel-2021.mp4" id="main-video"></video>
        <div class="progressAreaTime">00:00</div>
        <div class="controls">
            <div class="progress-area">
                <div class="progress-bar">
                    <span></span>
                </div>
                <div class="buffered-progress-bar"></div>
            </div>
            <div class="controls-list">
                <div class="controls-left">
                    <span class="icon">
                        <i class="material-icons fast-rewind" title="Retroceder 10 segundos">first_page</i>
                    </span>
                    <span class="icon">
                        <i class="material-icons play_pause" title="Reproduzir">play_arrow</i>
                    </span>
                    <span class="icon">
                        <i class="material-icons fast-forward" title="Avançar 10 segundos">last_page</i>
                    </span>
                    <span class="icon">
                        <i class="material-icons volume" title="Sem áudio">volume_up</i>
                        <input type="range" min="0" max="100" class="volume_range">
                    </span>
                    <div class="timer">
                        <span class="current">00:00</span> / <span class="duration">0:00</span>
                    </div>
                </div>
                <div class="controls-right">
                    <span class="icon">
                        <i class="material-icons auto-play" title="A repetição automática está desativada"></i>
                    </span>
                    <span class="icon">
                        <i class="material-icons settingsBtn" title="Detalhes">settings</i>
                    </span>
                    <span class="icon">
                        <i class="material-icons picture_in_picture" title="Miniplayer">picture_in_picture_alt</i>
                    </span>
                    <span class="icon">
                        <i class="material-icons fullscreen" title="Tela inteira">fullscreen</i>
                    </span>
                </div>
            </div>
        </div>
        <div id="settings">
            <div class="playback">
                <span>Velocidade da Reprodução</span>
                <ul>
                    <li data-speed="0.25">0.25</li>
                    <li data-speed="0.5">0.5</li>
                    <li data-speed="0.75">0.75</li>
                    <li data-speed="1" class="active">Normal</li>
                    <li data-speed="1.25">1.25</li>
                    <li data-speed="1.5">1.5</li>
                    <li data-speed="1.75">1.75</li>
                    <li data-speed="2">2</li>
                </ul>
            </div>
        </div>
    </div>
</div>

My JavaScript for the video player:

// Select elements
const vidsrc = document.querySelector('#main-video').src;
const video_player = document.querySelector('#video_player'),
mainVideo = video_player.querySelector('#main-video'),
progressAreaTime = video_player.querySelector('.progressAreaTime'),
controls = video_player.querySelector('.controls'),
progressArea = video_player.querySelector('.progress-area'),
progress_Bar = video_player.querySelector('.progress-bar'),
buffered_Bar = video_player.querySelector('.buffered-progress-bar'),
fast_rewind = video_player.querySelector('.fast-rewind'),
play_pause = video_player.querySelector('.play_pause'),
fast_forward = video_player.querySelector('.fast-forward'),
volume = video_player.querySelector('.volume'),
volume_range = video_player.querySelector('.volume_range'),
current = video_player.querySelector('.current'),
totalDuration = video_player.querySelector('.duration'),
auto_play = video_player.querySelector('.auto-play'),
settingsBtn = video_player.querySelector('.settingsBtn'),
picture_in_picture = video_player.querySelector('.picture_in_picture'),
fullscreen = video_player.querySelector('.fullscreen'),
settings = video_player.querySelector('#settings'),
playback = video_player.querySelectorAll('.playback li');

mainVideo.addEventListener('loadeddata',()=>{
    setInterval(() => {
        let bufferedTime = mainVideo.buffered.end(0);
        let duration = mainVideo.duration;
        let width = (bufferedTime / duration) * 100;
        buffered_Bar.style.width = `${width}%`
    }, 500);
})

// Play
function playVideo() {
    play_pause.innerHTML = "pause";
    play_pause.title = "Pausar";
    video_player.classList.add('paused')
    mainVideo.play();
}

// Pause
function pauseVideo() {
    play_pause.innerHTML = "play_arrow";
    play_pause.title = "Reproduzir";
    video_player.classList.remove('paused')
    mainVideo.pause();
}

play_pause.addEventListener('click',()=>{
    const isVideoPaused = video_player.classList.contains('paused');
    isVideoPaused ? pauseVideo() : playVideo();
})

mainVideo.addEventListener('play',()=>{
    playVideo();
})

mainVideo.addEventListener('pause',()=>{
    pauseVideo();
})

// Rewind
fast_rewind.addEventListener('click',()=>{
    mainVideo.currentTime -= 10;
})

// Forward
fast_forward.addEventListener('click',()=>{
    mainVideo.currentTime += 10;
})

// Total duration
mainVideo.addEventListener("loadeddata",(e)=>{
    let videoDuration = e.target.duration;
    let totalMin = Math.floor(videoDuration / 60);
    let totalSec = Math.floor(videoDuration % 60);

    // Complete with zero at beggining
    totalSec < 10 ? totalSec = "0"+totalSec:totalSec;
    totalMin < 10 ? totalMin = "0"+totalMin:totalMin;
    totalDuration.innerHTML = `${totalMin}:${totalSec}`;
})

// [ Continues... ]

i need help please array of functions [duplicate]

i got the data from this array but when i add it to the loop to show all the arrays it only show me only one array
help pleaseeee

this is the problem :
https://i.imgur.com/huAv70U.png

the function to get data from api ( the problem isnt here this works fine )

function Movie(id){
fetch(`https://api.themoviedb.org/3/movie/${id}?api_key=${apikey}`)
    .then((res) => res.json())
    .then((data) => {
    name = data.original_title;
    img = data.poster_path;
    link = name.replace(/[^a-zA-Zs/ ]/g, "")
    var MyArray = {'name':`${name}`, 'img':`${img}`, 'link':`/movies/${link}.html`}
    console.log(MyArray)
    })
    .catch(err => {
        console.error(err);
    });
}

The Array :

var MyMovies = [
    Movie(238),
    Movie(899082),
    Movie(899),
]

the function to display all arrays (the problem is here i think)

function LoadMovies(){
    buildTable(MyMovies)
    function buildTable(data){
        var table = document.querySelector('#movies')
    
        for (var i = 0; i < data.length; i++){
            var row = `<img id="img" src="${"https://image.tmdb.org/t/p/w342/" + img}" alt="${name}" class="thumb" onclick="location.href='${link}';">`
            table.innerHTML += row
        }
    }
}

the console.log show this :
Uncaught TypeError: Cannot read properties of undefined (reading 'img')

Should I nest screens within the navigator function?

I’m currently developing an App in which multiple screens use the same data. Rather than declaring multiple loose functions and passing the same props everytime, I’ve nested them all in the same function that returns the navigator, which contains all data I need to use between the screens.

CODE BEGIN:

`imports…

const Drawer = createDrawerNavigator();

const HomeNav = ({route, navigation }) => {

... states, variables, and functions



const Scr1 = ({ navigation }) => {
        ... stuff with states and data above
    );
}

const Scr2 = ({ navigation }) => {
        ... other stuff 
    );
}


return (
    <Drawer.Navigator screenOptions={{drawerStyle:{backgroundColor:'#000000'}, drawerActiveTintColor:'#ffffff', drawerInactiveTintColor:'#DADADA'}} 
    initialRouteName="Casa" 
    drawerContent={(props) => <CustomDrawerContent {...props} />}>
        ... drawers
    </Drawer.Navigator>
)`

that’s a cut down version of my code, to explain better. My screens, Scr1 and Scr2, are in the same function as the navigator.

Things work most of the time. I can easily share data between screens, but I’m having a LOT of problems with undefined objects and useless rerenders. I created a hook with the data that’s getting loaded as the state, so whenever it efectively loads, the screen gets rerendered. But I have multiple data variables, so the hook gets called as each one finishes loading. And if I remove those hooks, I lose my defined objects.
Anyway, bottom line, my question is if what I’m doing could give me problems in the future, if it’s the ‘right’ way to do things as to not complicate further down the road. If so, I find a way to deal with the rerenders, otherwise I change my code while I’m still beggining.

Full Homenav.js on github

That’s the complete file, if it helps
pretty messy, but I’m learning react so I’m just going at it
Thanks in advance!

change select element color to another when open

New to Material ui, i have this select element, i want to change the color of that input in the image to same as that ‘None’ section when select is clicked, so when user is able to see ‘None’ section then that input above it should have same background color as ‘None’ section and then when drop down is closed that input should change to gray

https://codesandbox.io/s/material-demo-forked-6hs9mm?file=/demo.js

code:

import React from 'react';
import { makeStyles } from '@material-ui/core/styles';
import InputLabel from '@material-ui/core/InputLabel';
import MenuItem from '@material-ui/core/MenuItem';
import FormControl from '@material-ui/core/FormControl';
import Select from '@material-ui/core/Select';
import Button from '@material-ui/core/Button';

const useStyles = makeStyles((theme) => ({
  button: {
    display: 'block',
    marginTop: theme.spacing(2),
  },
  formControl: {
    margin: theme.spacing(1),
    minWidth: 120,
  },
  select: {
    borderBottom: 'opx',
    '& ul': {
      paddingTop: '0px',
      paddingBottom: '0px',
    },
    '& ul:hover': {
      backgroundColor: '#1E2328',
    },
   
    '& .Mui-selected': {
      backgroundColor: '#1E2328',
      color: '#E9ECEC',
      fontWeight: '400, regular',
    },
    '& .Mui-selected:hover': {
      backgroundColor: '#1E2328',
    },
  },
  menuItemm: {
    display: 'flex',
    width: '225px',
    height: '56px',
    justifyContent: 'space-between',
    // border: '1px solid gray',
    backgroundColor: '#0B0B0B',
    color: 'white',
  },
  placeholder: {
    color: '#E9ECEC',
  },
}));

export default function ControlledOpenSelect() {
  const classes = useStyles();
  const [age, setAge] = React.useState('');
  const [open, setOpen] = React.useState(false);

  const handleChange = (event) => {
    setAge(event.target.value);
  };

  const handleClose = () => {
    setOpen(false);
  };

  const handleOpen = () => {
    setOpen(true);
  };

  return (
    <div>
 
      <FormControl className={classes.formControl}>
        <InputLabel  style={{backgroundColor:"gray",color:"white"}} id="demo-controlled-open-select-label">Age</InputLabel>
        <Select
          labelId="demo-controlled-open-select-label"
          id="demo-controlled-open-select"
          style={{backgroundColor:"gray",color:"white"}}
          open={open}
          MenuProps={{
            classes: { paper: classes.select },
            anchorOrigin: {
              vertical: 'bottom',
              horizontal: 'left',
            },
            transformOrigin: {
              vertical: 'top',
              horizontal: 'left',
            },
            getContentAnchorEl: null,
          }}
          onClose={handleClose}
          onOpen={handleOpen}
          value={age}
         
          onChange={handleChange}
        >
          <MenuItem value="">
            <em>None</em>
          </MenuItem>
          <MenuItem                           className={classes.menuItemm}
 value={10}>Ten</MenuItem>
          <MenuItem                           className={classes.menuItemm}
 value={20}>Twenty</MenuItem>
          <MenuItem                           className={classes.menuItemm}
 value={30}>Thirty</MenuItem>
        </Select>
      </FormControl>
    </div>
  );
}

these two should have same color when drop down is open:

enter image description here

and then when drop down is closed that input should change to gray color (backgroundColor).

i tried using usestate but then it changes color after dropdown is closed and not when opened

English is not my mother language so could be mistakes

How to charts js to be responsive on a mobile phone

I have try this code. It works on my computer but not responsive on mobile phone

<?php
       
        foreach($visitor as $result){
            $month[] = $result->date; //for month
            $value[] = (float) $result->count; //for count
        }
       
  ?>

 <div class="col-md-12">
                          <canvas id="canvas" width="560" height="280"></canvas>
                  </div>

<script>

        var lineChartData = {
            labels : <?php echo json_encode($month);?>,
            datasets : [

                {
                    fillColor: "rgba(60,141,188,0.9)",
                    strokeColor: "rgba(60,141,188,0.8)",
                    pointColor: "#3b8bba",
                    pointStrokeColor: "#fff",
                    pointHighlightFill: "#fff",
                    pointHighlightStroke: "rgba(152,235,239,1)",
                    data : <?php echo json_encode($value);?>
                }

            ]

        }

        var myLine = new Chart(document.getElementById("canvas").getContext("2d")).Line(lineChartData);

        var canvas = new Chart(myLine).Line(lineChartData, {
            scaleShowGridLines : true,
            scaleGridLineColor : "rgba(0,0,0,.005)",
            scaleGridLineWidth : 0,
            scaleShowHorizontalLines: true,
            scaleShowVerticalLines: true,
            bezierCurve : true,
            bezierCurveTension : 0.4,
            pointDot : true,
            pointDotRadius : 4,
            pointDotStrokeWidth : 1,
            pointHitDetectionRadius : 2,
            datasetStroke : true,
            tooltipCornerRadius: 2,
            datasetStrokeWidth : 2,
            datasetFill : true,
            legendTemplate : "<ul class="<%=name.toLowerCase()%>-legend"><% for (var i=0; i<datasets.length; i++){%><li><span style="background-color:<%=datasets[i].strokeColor%>"></span><%if(datasets[i].label){%><%=datasets[i].label%><%}%></li><%}%></ul>",
            responsive: true
        });

</script>

I’m trying to figure out how I can get my charts to be responsive on a mobile phone. I want them to go underneath each other when on a small screen.

Why does my variable return null instead of the defined value

Does anyone know why my “Carry” variable in the code returns NAN instead of 0

var addBinary = function(a, b) {
  let i = a.length - 1
  let j = b.length - 1

  let result = []
  var carry = 0;
  while (i >= 0 || j >= 0) {
    if (i == 0) {
      console.log(carry)
    }

    let sum = carry

    if (i >= 0) {
      sum = sum + parseInt(a[i])
    }

    if (j >= 0) {
      sum += parseInt(b[i])
    }

    result.unshift(parseInt(sum) % 2)
    carry = parseInt(sum) / 2
    i--
    j--
  }

  if (carry > 0) {
    result.unshift(1)
  }
  // console.log(result)
  return result.toString()
};

abbBinary('11', '1')

console.log(carry) should return 0 and not NAN. I can’t seem to find the issue, sure I am missing something

Redirect after a successful logn not working

I’m trying to make it so you get redirected back to the home page after a successful login, but i don’t quite know how to make that. Login works I just don’t know how to make it so it redirects you. i’m using React@18 btw .Can someone please help?

Login.jsx

const Login = () => {
  const [username, setUsername] = useState("");
  const [password, setPassword] = useState("");
  const dispatch = useDispatch();
  const { isFetching, error } = useSelector((state) => state.user);

  const handleClick = (e) => {
    e.preventDefault();
    login(dispatch, { username, password });
  };
  return (
    <Container>
      <Wrapper>
        <Title>SIGN IN</Title>
        <Form>
          <Input
            placeholder="username"
            onChange={(e) => setUsername(e.target.value)}
          />
          <Input
            placeholder="password"
            type="password"
            onChange={(e) => setPassword(e.target.value)}
          />
          <Button onClick={handleClick} disabled={isFetching}>
            LOGIN
          </Button>
          {error && <Error>Something went wrong...</Error>}
          <Link>YOU DON'T REMEMBER YOUR PASSWORD?</Link>
          <Link>CREATE A NEW ACCOUNT</Link>
        </Form>
      </Wrapper>
    </Container>
  );
};

apiCallsjs

import { publicRequest } from "../requestMethods";
import { loginFailure, loginStart, loginSuccess } from "./userRedux";

export const login = async (dispatch, user) => {
  dispatch(loginStart());
  try {
    const res = await publicRequest.post("/auth/login", user);
    dispatch(loginSuccess(res.data));
  } catch (err) {
    dispatch(loginFailure());
  }
};

userReduxjs

import { createSlice } from "@reduxjs/toolkit";

const userSlice = createSlice({
  name: "user",
  initialState: {
    currentUse: null,
    isFetching: false,
    error: false,
  },
  reducers: {
    loginStart: (state) => {
      state.isFetching = true;
    },
    loginSuccess: (state, action) => {
      state.isFetching = false;
      state.currentUser = action.payload;
    },
    loginFailure: (state) => {
      state.isFetching = false;
      state.error = true;
    },
  },
});

export const { loginStart, loginSuccess, loginFailure } = userSlice.actions;
export default userSlice.reducer;

App.jsx

const App = () => {

  const user = useSelector((state)=>state.user.currentUser);
  const navigate = useNavigate()

  return (
    <Router>
      <Routes>
        <Route exact path="/" element={<Home/>} />
        <Route path="/products/:category" element={<ProductList/>} />
        <Route path="/product/:id" element={<Product/>} />
        <Route path="/cart" element={<Cart/>} />
        <Route path="/success" element={<Success/>} />
        {/* <Route path="/login">{user ? <Navigate to="/" /> : <Login />}</Route> */}
        <Route path="/login">{user ? navigate("/") : <Login/>}</Route>
        <Route path="/login" element={<Login/>}/>
        <Route path="/register" element={<Register/>} />
      </Routes>
    </Router>
  );
};

export default App;

I’ve tried using the navigate hook, but it redirects you even if you’ve failed the login.

How to use Vite HMR API with Pixi.js

I’m trying to use the Vite HMR API to create a Pixi.js app that hot reloads without resetting its state. The high-level idea:

  • main.js initializes Pixi.js so an imported function update() is run every tick.
  • The imported update() is passed an object with the state so changes can be made in main.js context.

I got update.js to hot update, but the app doesn’t reflect the modified function:

// update.js
if (import.meta.hot) {
    import.meta.hot.accept()
}
export default function update(delta, state) {
    state.bunny.rotation += 0.1 * delta;
}

I think it’s because Pixi is still using the old update():

// main.js
app.ticker.add((delta) => { update(delta, state) });

So I tried to accept updates in main.js when update.js was updated:

// main.js
import update from './update.js';

if (import.meta.hot) {
    import.meta.hot.accept('./update.js', (newUpdate) => {
    console.log('Update ticker here.');
  })
}

However this callback is not called when update.js is hot updated. Why is the callback not getting called?


I have tried some other things, like porting this Snowpack HMR example to Vite. I had problems/errors setting the module state (module.setState(import.meta.hot.data)), but I don’t think I need to do this.

Using CSS to float forms and images

I currently have a dropdown box that when the user selects one of the eight images, it displays on the webpage. However, just now the image goes directly above the dropbox and I would like it so the image is displayed on the left and the dropbox on the right. I am just not sure how to code the css as the two are connected so I don’t know if div classes would work.

Here’s the code:

<img id="imageToSwap" src="kittens1.jpg"/>

<select id="kittenlist" onChange="swapImage()">
<option value="kittens1.jpg">Image 1</option>
<option value="kittens2.jpg">Image 2</option>
<option value="kittens3.jpg">Image 3</option>
<option value="kittens4.jpg">Image 4</option>
<option value="kittens5.jpg">Image 5</option>
<option value="kittens6.jpg">Image 6</option>
<option value="kittens7.jpg">Image 7</option>
<option value="kittens8.jpg">Image 8</option>
</select>

regex help for comma separated list with no special characters replace with dash

I’m trying to create an array of strings in JS on input change in React. This is all working fine. The end goal is to have a comma and space separated list of keywords in the input that has no special characters. Special characters including space need to be removed and replaced with -. I have the input working all is good except two scenarios. If the user doesn’t enter a space after the comma the word doesn’t separate. And a trailing - is left if a special character or space is entered. I want to then split input into array using .split(', ') to create an array of keywords. Is it better to do regex and then split?

Currently using

mods = mods.split(', ');
const formatted = mods.map(mod => {
    return mod.replace(/[^,A-Z0-9]+/ig, "-").toLowerCase();
});

example input/output

in = hello world&,anotHer, test8(
out = hello-world, another, test8

javascript event.target.match or event.target.closest does not work

In my project, I have a cart icon that when mouse clicks on the icon needs to unfold a dropdown list with two link options. When the mouse is clicking on somewhere else or in a blank space the dropdown list needs to dissapear.

Here is a snippet of my html template which shows upon clicking on the element with id shoppingCartIcon the javascript function cartIconClicked() is called.

<div class="container-fluid sticky-top" id="takeawayHeaderCartContainer">
    <div class="row">
        <div class="col-11" id="cartIconContent">
            <i class="fa dropbtn" id="shoppingCartIcon" onclick="cartIconClicked()">&#xf07a;</i> <!--this code codes for the shopping cart icon-->
            <span class='badge badge-warning' id='lblCartCount'> 
                {% if sessionValidity %}
                    {{totalCartItems}}
                {% else %}
                0 
                {% endif %}
            </span>
            <div id="myDropdown" class="dropdown-content">
                <a href="#">Option 1</a>
                <a href="#">Option 2</a>
            </div>
        </div>        
    </div>
</div>

In my css file I have this snippet.

/* Dropdown Content (Hidden by Default) */
.dropdown-content {
  display: none;
  position: absolute;
  background-color: #f1f1f1;
  min-width: 160px;
  box-shadow: 0px 8px 16px 0px rgba(0,0,0,0.2);
  z-index: 1;
}

/* Links inside the dropdown */
.dropdown-content a {
  color: black;
  padding: 12px 16px;
  text-decoration: none;
  display: block;
}

#takeawayHeaderCartContainer {
  justify-content: flex-end;
}

#shoppingCartIcon {
  font-size: 2rem;
  float: right;
  color: blue;
}

#lblCartCount {
    font-size: 16px;
    background: #ff0000;
    color: #fff;
    padding: 0 5px;
    vertical-align: top;
    float: right;
}

.badge {
  padding-left: 9px;
  padding-right: 9px;
  -webkit-border-radius: 9px;
  -moz-border-radius: 9px;
  border-radius: 9px;
}
.label-warning[href],
.badge-warning[href] {
  background-color: #c67605;
}

/* Change color of dropdown links on hover */
.dropdown-content a:hover {background-color: #ddd}

/* Show the dropdown menu (use JS to add this class to the .dropdown-content container when the user clicks on the dropdown button) */
.show {display:block;}

I am not sure if I fully graps the last line .show {display:block;} in above css style because we do not have a show class in the html template to begin with. I therefore guess it is meant for the javascript – see below. I got this script from this tutorial. Can someone explain to me what this line in particular classList.toggle("show") does? I guess it switches the class “show” on and off for the dropdown list? My biggest problem is though, this line if (!event.target.closest('.fa dropbtn')). This line gets fired every time both when I click on the cart icon and somewhere else, which is NOT the intension. It should get fired if the user clicks somewhere else than the cart icon, in which case a check will be performed to see if the drop down list has the “show” on and if so it should be removed, leading to drop down list dissapearing – see the link tutorial for full description.

function cartIconClicked() {
    document.getElementById("myDropdown").classList.toggle("show");
  }
  
  // Close the dropdown menu if the user clicks outside of it
  window.onclick = function(event) {
      console.log(event.target);
      if (!event.target.closest('.fa dropbtn')) 
      {
        console.log("we are here");
    }
} 

Why is URL.creatObjectURL(blob) giving a cross-origin frame error in NodeJS/React application

I have never had this happen before and am not sure why it’s happening.
I have a component written to display PDF files in an iFrame as part of a larger application. I am retrieving a BLOB stream from the server and attempting to create a URL for it to display in the iFrame but it keeps giving me a cross-origin error, which I though would not be possible since it is creating the URL out of data.

Here is my entire component:

import React, { useState, useEffect } from 'react'
import IFrameComponent from '../Elements/IFrameComponent';

const PDFPages = (props) => {
    let [file, setFile] = useState(null)
    let [notFound, show404]=useState(false)
    useEffect(() => {
        let id=props.site?.componentFile;
        fetch(`${process.env.REACT_APP_HOST}/documents/GetPDF`,
            {
                method: 'POST'
                , headers: {
                    'Content-Type': 'application/json'
                }
                , credentials: 'include'
                , body: JSON.stringify({file:id})
            })
            
            .then(async response => {
                let blob;
                try{
                    blob=await response.blob(); // <--- this functions correctly
                }
                catch(ex){
                    let b64=await response.json()
                    blob=Buffer.from(b64.fileData,'base64')
                }
                //Create a Blob from the PDF Stream
                //Build a URL from the file
                const str=`data:application/pdf;base64,${b64.fileData}`
                const url=URL.createObjectURL(blob) //<---  ERROR IS THROWN HERE
                setFile(url);
            })
            .catch(error => {
                show404(true)
            });
    }, []);

    if(!notFound){
    return <IFrameComponent src={file} title=''>
        Please enable iFrames in your browser for this page to function correctly        
    </IFrameComponent>
    }
    else {
        return (
            <>
            <h3> File {file} could not be found on server</h3>
            </>
        )
    }
}

export default PDFPages;

For completeness here is the GetPDF function from the server which is sending the file.

router.post('/GetPDF', async (req, res, next) => {
    const props = req.body;
    let fileName = props.file;
    try {
        fileName = fileName.replace(/%20/g, " ");
        let options = {};
        if (props.base64) options.encoding = 'base64'
        let data = await dataQuery.loadFile(`./data/documentation/${fileName}`, options);
        if (!props.base64) {
            res.attachment = "filename=" + fileName
            res.contentType = 'application/pdf'
            res.send(data);
        }
        else{
            res.send({fileData:data, fileName: fileName});
        }
    }
    catch (ex) {
        res.send({ error: true })
    }
});

I have done very little work in node sending files but am positive my client code is good. Where am I going wrong here?

Emulating lisp list operations in js

What would be the proper way to define the cons, car, and cdr functions if we were to use javascript and functional programming? So far I have:

// CAR = λxy.x
// CDR = λxy.y
// CONS = λxy => ?
const car = a => b => a;
const cdr = a => b => b;
const cons = f => a => b;

let pair = cons(3)(4);
console.log(pair(car));
console.log(pair(cdr));

But my issue is pair(car) seems like an odd way to invoke the function. It seems like car(pair) seems like a better way but I’m not sure how to save the pair so it can be passed like that. How would that be done?