Converting sections of HTML page to image using JavaScript

I am trying to convert sections of an HTML page to images using JavaScript.
The sections I am trying to convert are in a div tag, and have nested contents.

I want to create a snapshot/screenshot of it, or convert the contents of the div tag into an image (jpeg or png or svng).
My div tag id is “mytest”.

And I have the below section –

However, when I run – the png file downloaded is empty.

          html2canvas(document.querySelector("#mytest")).then(canvas => {

            const a = document.createElement("a");
            a.href = canvas.toDataURL("image/png");
            a.download = "image.png";
            a.click(); 

          });

To download a PNG file with the contents of the div section

JS convert PDF into blob

function generatePDF() {
    var pdfObject = jsPDFInvoiceTemplate.default(props);
    var blob = pdfObject.OutputType(blob);
    var csrfToken = document.querySelector('meta[name="csrf-token"]').getAttribute('content');
    var formData = new FormData();
    formData.append('pdfData', blob);
    // Send PDF data to Laravel controller for saving
    $.ajax({
        url: '/save-pdf',
        type: 'POST',
        data: formData,
        contentType: false, // Don't set contentType manually, let jQuery handle it
        processData: false, // Don't process the data, let jQuery handle it
        headers: {
            'X-CSRF-TOKEN': csrfToken
        },
        success: function(response) {
            // Handle success response
            console.log('PDF saved successfully. PDF ID:', response.pdfId);
        },
        error: function(xhr, status, error) {
            // Handle error response
            console.error('Error saving PDF:', error);
        }
    });
    console.log(blob);
}

Error pdfObject.OutputType(blob) appear when using this javascript. I need to get the pdfObject (generated PDF) and send into the php where the file will be stored into database. When I debug the program, the issue is that the blob format is not generated hence no data is passed then the insert process error.

I tried the var blob ="testing data"; and everythings works fine and perfect

I created an express route to add reviews to my listings. It shows an error : Listing validation failed: title: Path `title` is required


const router = express.Router({mergeParams:true});
const wrapAsync = (fn)=>{
    return (req,res,next)=>{
        fn(req,res,next).catch(next);
    }
}
const validateReview = (req,res, next)=>{
    let {error} = reviewSchema.validate(req.body);
    if(error){
        let errMsg = error.details.map((el)=>el.message).join(",");
        throw new ExpressError(400, errMsg);
    }else{
        next();
    }
}
router.post("/", validateReview, wrapAsync(async(req,res)=>{
    let listing = await Listing.findById(req.params.id);
    let newReview = new Review(req.body.review);
    
    listing.reviews.push(newReview);
    
    await newReview.save();
    await listing.save();
    res.redirect(`/listings/${listing._id}`);
}));

This is the child express route to app.js

Listing validation failed: title: Path `title` is required.

now reviews contains only two fields, rating and comment, and has no title, I don’t understand where I can disable the title requirement from. The values in the form is not validating.

When I try to print the listing, req.params.id, req.body, newReview, its all working. There’s something wrong with validation requirement, which says there should be a valid title, but there’s no title field defined in the reviews object.

Checkbox is checked but returns false

I would like to use some JS to perform a function if a checkbox is checked. However, my input field checkbox keeps returning false when it’s checked and I can’t understand why.

Here’s the HTML:

<input id="option_service_desk" type="checkbox"/>

Here’s the JS:

if (document.getElementById('option_service_desk').checked)
 { 
 console.log('service 247 checked');
} else {
 console.log("service 247 not checked");
}

I’ve tried checking in the console and indeed, it’s returning as false, even though it is checked on the screen.

enter image description here

regex newline replace just by character n

I have this javascript regex:

let output = 'This role involves:n   - Steering the direction of universal expansion and resource allocation.';
console.log('before:', JSON.stringify(output));

output = output.replace(/[^a-zA-Z0-9 _-srnt]/gi, '');
console.log('after:', JSON.stringify(output));
// This role involvesn   - Steering the direction of universal expansion and resource allocation

It doesn’t leave in there n, but replaces it with just the n

Secondly, I would like to replace the - Steering to just one space, then the minus sign and then another space and then the word - Steering. But it seems that it’s not just a normal space. Or how do I debug that best?

SvelteKit wait for Firebase onAuthStateChanged before load function

I’m working with SvelteKit and Firebase to build a website. There’s a document in my Firestore that only logged in users can accces, I already set a rule for that. The problem that I’m facing is that the load function which fetchs data from the database is sending back a permission denied error as if the user is not logged in. The load function seems to run before the auth state if changed.

I tried using a simple store that stores the authenticated user to check if the user is signed in, but unfortunately the getDoc function can’t be awaited

// $lib/stores/authStore.js
import { writable } from 'svelte/store';
import { auth } from '$lib/firebase';
import { onAuthStateChanged } from 'firebase/auth';
export function authStore(auth) {
    let unsubscribe;

    const { subscribe } = writable(auth.currentUser, (set) => {
        unsubscribe = onAuthStateChanged(auth, (user) => {
            set(user);
    });
    return () => unsubscribe;
    });

    return {
    subscribe
    };
}
// +page.server.js
import { authStore } from '$lib/stores/authStore.js';
import { doc, getDoc } from 'firebase/firestore';

export async function load() {
    let protectedDoc;
    authStore.subscribe((user) => {
        if (user) {
            const docRef = doc(db, 'myCollection/myDoc')
        await getDoc(docRef).then((snapshot) => {
                protectedDoc = snapshot.data();
            });
            return { protectedDoc }
        };
    })
}

I tried something similar to a few discussions, but had no success
SvelteKit async function load not working or Firebase onAuthStateChanged cannot be made blocking

Firebase split second authentication confirmation is messing with Sveltekit pages due to Firestore rules

Sveltekit: Wait for resolve in +layout.ts before load() in +page.ts

How should I write this load function in order to the read the firebase document only after user auth state is not null?

How can I reset an array in a React state after a successful fetch request?

So, I’m collecting cellphone numbers from a textarea: the values are held in state.
I will validate them and/or add a country prefix based on whether or not they already have the prefix. For each validated number I want to store it in an array.
After I submit the data in the array in a fetch call, I want the contents of the array to be reset to an empty array to get it ready to receive a fresh batch of numbers.

I have decomposed the problem into two functions. One for processing the numbers and the other for making the fetch call

.
.
.
const [phoneNos, setPhoneNos] = useState('') // values from the textbox
const [validatedPhoneNos, setValidatedPhoneNos] = useState([]); // array to hold validated numbers

function addPhoneNosToDB () {
        fetch(`end_point`, {
            method: 'POST',
            headers: {
                'Content-Type': 'application/json',
            },
            mode: 'cors',
            body: JSON.stringify({
                somefield: fieldValue,
                list: validatedPhoneNos
            }),
        }).then(r => {
            toast.success('Your list was added')
            setPhoneNos('');
            setValidatedPhoneNos([])    // ***
        }).catch(err => toast.warning(err)) 
    }

//function to validate and format numbers
function procPhoneNos () {
        if (phoneNos) {
            const countryCodePattern = /^(?:+?234|0)?(7d{8})$/;
            const phoneNumberPattern = /^(0|+?234)(d{10})$/;

            let list = phoneNos.split(',').map(phoneno => phoneno.trim());

            list.forEach(phoneNumber => {
                if (phoneNumber.match(countryCodePattern)) {
                    setValidatedPhoneNos(prev => [...prev, phoneNumber])
                } else if(phoneNumber.match(phoneNumberPattern)) {
                    setValidatedPhoneNos(prev => [...prev, phoneNumber.replace(phoneNumberPattern, '234$2')]);
                } else {
                    toast.warning("One or more phone numbers not properly formatted")
                    return
                }
            });
            
                        //call the function to submit formatted numbers to db
            addPhoneNosToDB()
        } else toast.warning("you need to enter at least one phone number")
    }

Testing this out, I get an empty array whenever addPhoneNosToDB was called. If I removed line *** I do get the numbers in the array but mostyly only after a second request. Also, all the previous phone numbers get retained in the array. How do I fix it so that the array elements only get cleared after a successful fetch request? Preferably without useEffect except if necessary.
Thanks

Prior SO answer didn’t work to read a URL into a string

In Javascript, I want to read from a URL into a string. I rearranged the answer from a previous SO answer (28828029), and it didn’t work. Below is my code.
When run, it shows the alert at 3.
Then the alert at 16 shows readyState=1 and status=0.
Then it shows the alert at 5.
Then [sic] the alert at 18 shows readyState=4 and status still=0, instead of the desired 200.
No other alerts were shown.
I thought that maybe the original URL had disappeared in the interim, so I also tried it with https://finance.yahoo.com/quote/SPY, but got the same result.

How can I debug this further?

<script>
// rearranged from SO question 28828029 html-read-txt-file-from-url-location-in-javascript
alert("at 3");
    var outer_text = getText();
alert("at 5");
    var lot = outer_text.length;
alert("at 7: lot=" + lot);
outer_text = outer_text.split('n');    
alert("at 9" + outer_text);

function getText()
{   // read text from URL location
    var request = new XMLHttpRequest();
    request.open('GET', 'http://www.puzzlers.org/pub/wordlists/pocket.txt', true);
    request.send(null);
    alert("at 16: request.readyState="+request.readyState+", request.status="+request.status);
    request.onreadystatechange = function () 
    {   alert("at 18: request.readyState="+request.readyState+", request.status="+request.status);
        if (request.readyState === 4 && request.status === 200) 
        {   var type = request.getResponseHeader('Content-Type');
            alert("at 21: type = " + type + "request.responseText="+request.responseText);
            if (type.indexOf("text") !== 1) 
            {   return request.responseText;
}   }   }   }
</script>
</body></html>```

Placing noUiSliders beside each other

I am trying to place 2 noUiSliders to the right of 3 other sliders since having multiple sliders takes up too much vertical space. My HTML page has 4 main tabs, and this all within a single tab, where I have one main collapsible header (Filters), which has further collapsible headers based on the type of filter ( Filters -> Phenotypic Data Filters)

I have 5 sliders in the Phenotypic Data Filters header which has an additional div called .slidercontainer because I wanted to restrict the width of the slider. Additionally each input header is linked to the Help tab which is what the href and onclick() functions are for.

I have tried setting up 2 different div for the slider (one with 3 and one with 2), with the purpose of trying to move the div with 2 sliders to the right, but I tried many ways and nothing seems to have worked.

My code is messy so please excuse that and it is below for reference:

Relevant CSS:

.collapsible {
            background-color: #777;
            color: white;
            cursor: pointer;
            padding: 12px;
            width: auto;
            border: 1px solid ;
            text-align: left;
            outline: none;
            font-size: 15px;
            display: flex;
            align-items: center;
        }
        .collapsible.active, .collapsible:hover {
            background-color: #555;
        }
        .collapsible::before {
            content: "25BA";
            margin-right: 10px;
        }
        .active.collapsible::before {
            content: "25BC";
        }
        .content {
            padding: 0 18px;
            display: none;
            border: 1px solid ;
            overflow: hidden;
            background-color: #f1f1f1;
            box-shadow: 0 8px 8px rgba(0, 0, 0, 0.2);
        }
.slidecontainer {
            width: 50%;
            margin-left: 10px;
        }

HTML:

<div class="collapsible">Phenotypic Data Filters</div>
                <div class="content">
                    <button id="reset_all_sliders" class="reset-all-button">Reset ALL Sliders</button>
                    <br>
                        <a href="#" onclick="openTab(event, 'help', 'help_year')" style = "margin-left:10px;" id="year_help"> Year: </a>&nbsp;&nbsp;<input type="checkbox" name="year" value="2015" checked> 2015
                        <input type="checkbox" name="year" value="2016"> 2016
                        <input type="checkbox" name="year" value="2017"> 2017
                        <input type="checkbox" name="year" value="2018"> 2018
                        <br><br>

                        <a href="#" onclick="openTab(event, 'help', 'help_location')" style = "margin-left:10px;" id="location_help">Location: </a>&nbsp;&nbsp;<input type="checkbox" name="location" value="Channel-North"> Channel-North
                        <input type="checkbox" name="location" value="Channel-South"> Channel-South
                        <input type="checkbox" name="location" value="Creek-West"> Creek-West
                        <input type="checkbox"  name="location" value="Creek-East"> Creek-East
                        <br><br>

                        <a href="#" onclick="openTab(event, 'help', 'help_mortality')" style = "margin-left:10px;" id="mortality_help">Mortality: </a>&nbsp;&nbsp;<input type="checkbox" name="mortality" value="Alive"> Alive
                        <input type="checkbox" name="mortality" value="Missing"> Missing
                        <input type="checkbox" name="mortality" value="Dead"> Dead
                        <input type="checkbox" name="mortality" value="New"> New
                        <br><br>
                        
                        <div class="slidecontainer">
                        <a href="#" onclick="openTab(event, 'help', 'help_eco_vol')" id="eco_vol_help">Ecological Volume (units):</a>
                        <button id="eco_vol_reset" class="reset-button">Reset slider</button>
                        <div id="eco_vol_value" class="hover-value"></div><br><br><br><br>
                        <div id="eco_vol"></div>
                        <br><br><br>

                        <a href="#" onclick="openTab(event, 'help', 'help_ln_eco_vol')" id="ln_eco_vol_help">Natural Log of Ecological Volume (units):</a>
                        <button id="ln_eco_vol_reset" class="reset-button">Reset slider</button>
                        <div id="ln_eco_vol_value" class="hover-value"></div><br><br><br><br>
                        <div id="ln_eco_vol"></div>
                        <br><br><br>

                        <a href="#" onclick="openTab(event, 'help', 'help_length')" id="length_help">Length (cm):</a>
                        <button id="length_reset" class="reset-button">Reset slider</button>
                        <div id="length_value" class="hover-value"></div><br><br><br><br>
                        <div id="length"></div>
                        <br><br><br>
                        
                        <a href="#" onclick="openTab(event, 'help', 'help_width')" id="width_help">Width (cm):</a>
                        <button id="width_reset" class="reset-button">Reset slider</button>
                        <div id="width_value" class="hover-value"></div><br><br><br><br>
                        <div id="width"></div>
                        <br><br><br>
                        
                        <a href="#" onclick="openTab(event, 'help', 'help_height')" id="height_help">Height (cm):</a>
                        <button id="height_reset" class="reset-button">Reset slider</button>
                        <div id="height_value" class="hover-value"></div><br><br><br><br>
                        <div id="height"></div>
                        <br><br><br>
                    </div>
                </div>

noUiSlider code:

// Sliders
        var ecoVolSlider = document.getElementById('eco_vol');
        var ecoVol_field = document.getElementById('eco_vol_value');
        var lnEcoVolSlider = document.getElementById('ln_eco_vol');
        var lnVol_field = document.getElementById('ln_eco_vol_value');
        var alleleFreqSlider = document.getElementById('allele_freq');
        var allele_field = document.getElementById('allele_freq_value');
        var lengthSlider = document.getElementById('length');
        var length_field = document.getElementById('length_value');
        var widthSlider = document.getElementById('width');
        var width_field = document.getElementById('width_value');
        var heightSlider = document.getElementById('height');
        var height_field = document.getElementById('height_value');

        noUiSlider.create(ecoVolSlider, {
            start: [0],
            tooltips: true,
            connect: 'lower',
            behaviour: 'hover-snap',
            range: {
                'min': 0,
                'max': 35000
            },
            pips: {
                mode: 'values',
                values: [0, 10000, 20000, 30000, 35000],
                density: 4
            }
        });
        ecoVolSlider.noUiSlider.on('update', function (values, handle) {
            ecoVol_field.innerHTML = values[handle];
            ecoVol_field.style.display = 'none';
        });
        
        noUiSlider.create(lnEcoVolSlider, {
            start: [0],
            tooltips: true,
            connect: 'lower',
            behaviour: 'hover-snap',
            range: {
                'min': -4,
                'max': 12
            },
            pips: {
                mode: 'values',
                values: [-4, 0, 4, 8, 12],
                density: 4
            }
        });
        lnEcoVolSlider.noUiSlider.on('update', function (values, handle) {
            lnVol_field.innerHTML = values[handle];
            lnVol_field.style.display = 'none';
        });

        noUiSlider.create(lengthSlider, {
            start: [0],
            tooltips: true,
            connect: 'lower',
            behaviour: 'hover-snap',
            range: {
                'min': 0,
                'max': 50
            },
            pips: {
                mode: 'values',
                values: [0, 10, 20, 30, 40, 50],
                density: 4
            }
        });
        lengthSlider.noUiSlider.on('update', function (values, handle) {
            length_field.innerHTML = values[handle];
            length_field.style.display = 'none';
        });
        
        noUiSlider.create(widthSlider, {
            start: [0],
            tooltips: true,
            connect: 'lower',
            behaviour: 'hover-snap',
            range: {
                'min': 0,
                'max': 50
            },
            pips: {
                mode: 'values',
                values: [0, 10, 20, 30, 40, 50],
                density: 4
            }
        });
        widthSlider.noUiSlider.on('update', function (values, handle) {
            width_field.innerHTML = values[handle];
            width_field.style.display = 'none';
        });
        
        noUiSlider.create(heightSlider, {
            start: [0],
            tooltips: true,
            connect: 'lower',
            behaviour: 'hover-snap',
            range: {
                'min': 0,
                'max': 25
            },
            pips: {
                mode: 'values',
                values: [0, 5, 10, 15, 20, 25],
                density: 4
            }
        });
        heightSlider.noUiSlider.on('update', function (values, handle) {
            height_field.innerHTML = values[handle];
            height_field.style.display = 'none';
        });

Thank you in advance for your help and I appreciate any input!

Adding and removing a class by using a click event listener

I am making an overlay using CSS but need an onclick event to change the content of the class.

I made a sign Up form to be under the sign in form. At the click of the sign Up, the sign Up form class should be added to the container while also at the click of the sign in button, I want the sign Up form to be removed and the sign In id to replace the container.

I have tried using JavaScript to create a variable for the container, sign Up and sign In unique id to select their respective area in the DOM. I also made event listeners to add and remove the class that won’t display at first (since the sign in form would display first, that would mean that it’ll be the sign up form that would need to be added and removed).

BELOW IS THE CODE I ATTEMPTED.

// ACCOUNTS Overlay
const container = document.getElementById('container');
const signIpButton = document.getElementById('signIn');
const signUpButton = document.getElementById('signUp');

    // Add the classname to container
signUpButton.addEventListener('click', () => 
    container.classList.add('right-panel-active')
);

    // Remove the classname from container
signUpButton.addEventListener('click', () => 
    container.classList.remove('right-panel-active')
);

Mysql2 messing with routing

I am trying to use mysql2 in the backend but it seems to messing with my routes when I use it in production.

My server file looks like this:

const express = require('express')
const app = express()
const PORT = process.env.PORT || 5001
const path = require('path')

const cors = require('cors')
const bodyParser = require('body-parser')

// const mysql = require('mysql2')

app.use(cors())
app.use(bodyParser.json())


app.get('/test', (req, res) => {
    res.send({message: 'Working Again'})
})

app.get('/budgettracker/pull', (req, res) => {
    res.send({message: '/budgettracker/pull hit'})
})

app.post('/budgettracker/push', (req, res) => {
    console.log(req.body)
    res.send(req.body)
})

app.get('*', (req, res) => {                       
    res.sendFile(path.resolve(__dirname, '../public_html','index.html'));                               
  });


app.listen(PORT, () => {
    console.log(`Listening on port http://localhost:${PORT}`) 
})

I am using react router to handles routes in the front end, and res.sendFile on my node server to serve index.html for unspecified routes.

When I include the “require mysql2” line, I get a 503 error when refreshing the page on child routes.
When I leave it commented out, the routing works as intended. I don’t understand what the problem is, and I have half a mind to just switch to sequelize and see if that works.

Any suggestions would be appreciated.

I tried reinstalling mysql2 on the server, but that doesn’t seem to change anything. I’m not sure if there should be a specific order when declaring the routes and database stuff.

Element type is invalid: expected a string – but the import implementation seems correct

frontendsrccomponentsCronJobTable.js:

import React, { useState } from 'react';
import { Table, Button, Form, InputGroup, Col } from 'react-bootstrap';

function CronJobTable() {
  const [cronJobs, setCronJobs] = useState([]);
  const [newCronJob, setNewCronJob] = useState({
    minute: '',
    hour: '',
    day: '',
    month: '',
    weekday: '',
    command: '',
  });

  const [validationErrors, setValidationErrors] = useState({});

  const handleInputChange = (e) => {
    setNewCronJob({ ...newCronJob, [e.target.name]: e.target.value });
    setValidationErrors({ ...validationErrors, [e.target.name]: '' }); // Clear error on change
  };

  const validateCronExpression = (expression, fieldName) => {
    // You can implement a more robust validation using a cron parsing library here
    // For now, let's do a basic check for allowed characters and ranges
    const allowedChars = /[*,/-0-9]/;
    if (!allowedChars.test(expression)) {
      setValidationErrors({ ...validationErrors, [fieldName]: 'Invalid characters' });
      return false;
    }
    return true;
  };

  const addCronJob = () => {
    const isValidMinute = validateCronExpression(newCronJob.minute, 'minute');
    const isValidHour = validateCronExpression(newCronJob.hour, 'hour');
    const isValidDay = validateCronExpression(newCronJob.day, 'day');
    const isValidMonth = validateCronExpression(newCronJob.month, 'month');
    const isValidWeekday = validateCronExpression(newCronJob.weekday, 'weekday');

    if (isValidMinute && isValidHour && isValidDay && isValidMonth && isValidWeekday) {
      setCronJobs([...cronJobs, newCronJob]);
      setNewCronJob({
        minute: '',
        hour: '',
        day: '',
        month: '',
        weekday: '',
        command: '',
      });
      setValidationErrors({}); // Clear all errors
    }
  };

  const deleteCronJob = (index) => {
    setCronJobs(cronJobs.filter((_, i) => i !== index));
  };

  return (
    <div>
      <h2>Add New Cron Job</h2>
      <Form>
        <Form.Row>
          <Form.Group as={Col}>
            <Form.Label>Minute:</Form.Label>
            <Form.Control
              type="text"
              name="minute"
              value={newCronJob.minute}
              onChange={handleInputChange}
              isInvalid={!!validationErrors.minute}
            />
            <Form.Control.Feedback type="invalid">
              {validationErrors.minute}
            </Form.Control.Feedback>
          </Form.Group>
          <Form.Group as={Col}>
            <Form.Label>Hour:</Form.Label>
            <Form.Control
              type="text"
              name="hour"
              value={newCronJob.hour}
              onChange={handleInputChange}
              isInvalid={!!validationErrors.hour}
            />
            <Form.Control.Feedback type="invalid">
              {validationErrors.hour}
            </Form.Control.Feedback>
          </Form.Group>
        </Form.Row>
        <Form.Row>
          <Form.Group as={Col}>
            <Form.Label>Day:</Form.Label>
            <Form.Control
              type="text"
              name="day"
              value={newCronJob.day}
              onChange={handleInputChange}
              isInvalid={!!validationErrors.day}
            />
            <Form.Control.Feedback type="invalid">
              {validationErrors.day}
            </Form.Control.Feedback>
          </Form.Group>
          <Form.Group as={Col}>
            <Form.Label>Month:</Form.Label>
            <Form.Control
              type="text"
              name="month"
              value={newCronJob.month}
              onChange={handleInputChange}
              isInvalid={!!validationErrors.month}
            />
            <Form.Control.Feedback type="invalid">
              {validationErrors.month}
            </Form.Control.Feedback>
          </Form.Group>
          <Form.Group as={Col}>
            <Form.Label>Weekday:</Form.Label>
            <Form.Control
              type="text"
              name="weekday"
              value={newCronJob.weekday}
              onChange={handleInputChange}
              isInvalid={!!validationErrors.weekday}
            />
            <Form.Control.Feedback type="invalid">
              {validationErrors.weekday}
            </Form.Control.Feedback>
          </Form.Group>
        </Form.Row>
        <Form.Group>
          <Form.Label>Command:</Form.Label>
          <Form.Control 
            type="text" 
            name="command" 
            value={newCronJob.command} 
            onChange={handleInputChange} 
          />
        </Form.Group>
        <Button variant="primary" onClick={addCronJob}>
          Add New Cron Job
        </Button>
      </Form>

      <br />

      <h2>Current Cron Jobs</h2>
      <Table striped bordered hover>
        <thead>
          <tr>
            <th>Minute</th>
            <th>Hour</th>
            <th>Day</th>
            <th>Month</th>
            <th>Weekday</th>
            <th>Command</th>
            <th>Actions</th>
          </tr>
        </thead>
        <tbody>
          {cronJobs.map((cronJob, index) => (
            <tr key={index}>
              <td>{cronJob.minute}</td>
              <td>{cronJob.hour}</td>
              <td>{cronJob.day}</td>
              <td>{cronJob.month}</td>
              <td>{cronJob.weekday}</td>
              <td>{cronJob.command}</td>
              <td>
                <Button variant="danger" onClick={() => deleteCronJob(index)}>
                  Delete
                </Button>
              </td>
            </tr>
          ))}
        </tbody>
      </Table>
    </div>
  );
}

export default CronJobTable;

Then in the calling file frontendsrcpagesmainApp.js I do:

import CronJobTable from "../components/CronJobTable";

And I get the error on the React frontend:

Element type is invalid: expected a string (for built-in components)
or a class/function (for composite components) but got: undefined. You
likely forgot to export your component from the file it’s defined in,
or you might have mixed up default and named imports.

Check the render method of `CronJobTable`.
Error: Element type is invalid: expected a string (for built-in components) or a class/function (for composite components) but got: undefined. You likely forgot to export your component from the file it's defined in, or you might have mixed up default and named imports.

Check the render method of `CronJobTable`.
    at createFiberFromTypeAndProps (http://192.168.1.34:3000/static/js/bundle.js:76423:21)
    at createFiberFromElement (http://192.168.1.34:3000/static/js/bundle.js:76444:19)
    at createChild (http://192.168.1.34:3000/static/js/bundle.js:65013:32)
    at reconcileChildrenArray (http://192.168.1.34:3000/static/js/bundle.js:65253:29)
    at reconcileChildFibers (http://192.168.1.34:3000/static/js/bundle.js:65595:20)
    at reconcileChildren (http://192.168.1.34:3000/static/js/bundle.js:68527:32)
    at updateHostComponent (http://192.168.1.34:3000/static/js/bundle.js:69171:7)
    at beginWork (http://192.168.1.34:3000/static/js/bundle.js:70616:18)
    at HTMLUnknownElement.callCallback (http://192.168.1.34:3000/static/js/bundle.js:55602:18)
    at Object.invokeGuardedCallbackDev (http://192.168.1.34:3000/static/js/bundle.js:55646:20)

Complex column sorting in tanstack table (Solid) issues

In a Solid JS app, I am attempting to utilize the Sort feature of a Tanstack Table (V8). I’m also using Webpack5 and Module Federation, if that could potentially cause an issue.

I have a column that utilizes values from multiple data fields/columns to format progress on a task. It needs to be able to be sorted:

{ cell: ({row}) =>
        <span
            class={`${row.original.commit_dt === row.original.trend_dt ? 'text-blue-100' : row.original.commit_dt < row.original.trend_dt ? 'text-red-400' : 'text-green-500'} font-bold`}
            title={`${row.original.commit_dt === row.original.trend_dt ? 'On track...' :
                `${row.original.commit_dt < row.original.trend_dt ? 'Behind by ' + wkDayDiff(row.original.commit_dt, row.original.trend_dt, true) : 'Ahead by ' + wkDayDiff(row.original.trend_dt, row.original.commit_dt)} working day(s)...`}`}>
                {row.original.trend_dt}
                </span>
        , header: 'Trend Date', size: 100, enableSorting: true, sortType: trendSort }

As you can see, I have created a sort function that should handle this, but for whatever reason it is failing. I believe I’m using the correct format, as documented for Tanstack Table V8 for Solid JS:

const trendSort = (rowA, rowB, id) => {
        const a = new Date(rowA.values[id]), b = new Date(rowB.values[id]);
        return a > b ? 1 : b > a ? -1 : 0;
    };

My header definition in the table is a bit complex, too, as it utilizes Solid-Icons and also contains a column resizer:

<thead class='uppercase bg-gray-700 display'>
    <For each={table.getHeaderGroups()}>
        {(headerGroup) => (
            <tr>
                <For each={headerGroup.headers}>
                    {(header) =>
                        <th key={header.id} style={{ width: `${header.getSize()}px` }} class={`p-1 text-xs`}>
                            {header.isPlaceholder ? null :
                                <>
                                    <span class={`${header.column.getCanSort() && 'cursor-pointer'} inline-flex`} onClick={header.column.getToggleSortingHandler()}>
                                        {flexRender(header.column.columnDef.header, header.getContext())}
                                    </span>
                                    <button class='inline float-right hover:bg-darkprimary hover:border-primary border-2 border-gray-600 p-0 resizing' onMouseDown={header.getResizeHandler()} onDoubleClick={header.column.resetSize()}>&#177;</button>
                                    {{asc: <AiOutlineCaretUp size={15} class="float-right text-secondary" />, desc: <AiOutlineCaretDown size={15} class="float-right text-secondary" />}[header.column.getIsSorted()?? null]}
                                </>
                            }
                        </th>
                    }
                </For>
            </tr>
        )}
    </For>
</thead>

Let me know if you need more code, as I have a large quantity of it for this purpose.

How to create a basic search bar in javascript

I pretty much copied a vary basic search bar that is functional using HTML, CSS and Javascript.

When you type something in the search bar it does show up in the console.

The results are supposed to go from the home index.html to a different page: searchresults.html and display on the page.

I do not understand what part of the function is not working and why it will not display on the second page at all.

Inspiration: https://codepen.io/simplyramaken/pen/dyqVPBz

My code:

https://codepen.io/sarahprogram/pen/abxQydz

<!DOCTYPE html>

<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Finance Blog</title>

<link rel="stylesheet" href="style.css">
<link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/font-        awesome/4.7.0/css/font-awesome.min.css">
<link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/font-awesome/4.7.0/css/font-awesome.min.css">
</head>

<body>
<header>
<h1>Finance Blog</h1>

    <div class="search-div">
      <form action="searchresults.html" method="get" onclick="searchResult ()">
     <button type="submit" class="search-button" id="search-b"><i class="fa fa-search" style="font-size:24px"></i></button>
      <input type="text" class="search" id="search-i" placeholder="search...">
    </form>
    </div>

  <nav>
  <ul>
  <li>
   <a href="deals.html" class="nav-bar" id="deals">Deals</a>
  </li>
  <li>
  <a href="free.html" class="nav-bar" id="free">Free</a>
  <li>
    <a href="savingmoney.html" class="nav-bar" id="savingmoney">Saving Money</a>
  </li>
  <li>
    <a href="investing.html" class="nav-bar" id="investing">Investing</a>
  </li>
  <li>
    <a href="makemoney.html" class="nav-bar" id="makemoney">Make Money</a>
  </li>
  <li>
    <a href="recipies.html" class="nav-bar" id="recipes">Recipies</a>
  </li>
</ul>
</nav>
</header>

<main>
<section class="blog"> 

<div class="BlogContainer">
  <a href="#">
  <img src="" alt="" class="blog-img">
    <h2 class="blog-title">FREE Workouts: My Favorite Fun Youtube Workout Channel</h2>
  <p class="blog-copy"></p>
  <span class="time"></span>
</a>
</div>

<div class="BlogContainer">
<a href="#" class="bloglink">
 <img src="" alt="" class="blog-img">
<h2 class="blog-title">How to Get FREE Coffee Grounds from Starbucks for Your Garden!
  </h2>
  <p class="blog-copy"></p>
  <span class="time"></span>
  </a>
</div>

<div class="BlogContainer">
  <a href="#">
  <img src="" alt="" class="blog-img">
  <h2 class="blog-title">My Favorite Simple and Easy Credit Card 
  </h2>
  <p class="blog-copy"></p>
  <span class="time"></span>
</a>
</div>

</section>


<div class="sidebar">
<aside>
<div><img src="pig.image" alt="pig photo" class="aside-img"></div>

<br>

<div>
  <p class="aside-p">Sign up to never miss a post!</p>
  <br>
  <form method="post">
  <input type="text" class="aside-input" placeholder="YOUR EMAIL ADDRESS" pattern="[email protected]" required>
  <br>
  <button class="button-submit">SIGN UP</button>
  </form>
</div>

<br>

<div class="social">
<a href="#" class="fa fa-pinterest"></a>
<a href="#" class="fa fa-youtube"></a>
<a href="#" class="fa fa-tiktok"></a>
<a href="#" class="fa fa-instagram"></a>
</div>


</aside>
</div>
</main>


<div class="container-pagination">
<div class="pagination">
    <ul>
    <li><a href="" class="pagination-previous">Previous</a></li>
    <li><a href="">1</a></li>
    <li><a href="">2</a></li>
    <li><a href="">3</a></li>
    <li><a href="" class="pagination-next">Next</a></li>
    </ul>
</div>
</div>





<footer>

<div class="social-footer">
<a href="#" class="fa fa-pinterest"></a>
<a href="#" class="fa fa-youtube"></a>
<a href="#" class="fa fa-tiktok"></a>
<a href="#" class="fa fa-instagram"></a>
</div>

<div class="footer-content">
<p><a href="about.html" class="footer-p" id="about">About</a></p>
<br>
<p><a href="contact.html" class="footer-p" id="contact">Contact</a></p>
<br>
<p><a href="privacy.html" class="footer-p" id="privacy">Privacy Policy</a></p>
<br>
<p><a href="terms.html" class="footer-p" id="terms">Terms</a></p>
</div>

</footer>

<p class="footer-copyright" id="date"></p>

<script src="js.js"></script>

</body>
</html>


<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<link rel="stylesheet" href="searchresults.css">
<title>Search Results</title>
</head>
<body>
<div>
<ul id="search-results"></ul>
</div>
<script src="js.js"> 
</script>
</body>
</html>



* {
margin: 0;
padding: 0;
}

html body { 
overflow: auto; 
height: 100%;
}

header {
display: flex;
}

body {
height: 100%;
}

h1 {
color: #FB6F92;
margin-top: 82px;
margin-left: 40px;
margin-bottom: 10px;
}

.search-div {
position: absolute;
right: 25px;
margin-top: 82px;
display: flex;
}

.search-button {
color:#FB6F92;
margin: 5px;
border: none;
background: none;
padding: 0;

}

.search {
position: relative;
border-color:#FB6F92;
width: 250px;
border-style: solid;
padding: 6px;
border-radius: 25px;
font-size: 16px;
}

nav {
position: fixed;
top: 0px;
width: 100%;
height: 50px;
background-color: #fbe5e5;
font-family: arial;
display: flex;
align-items: center;
justify-content: center;
z-index: 1;
}

nav a {
  text-align: center;
  display: inline-block;
}

nav ul li a {
color: #FB6F92;
text-decoration: none;
}

li {
display: inline;
margin: 20px;
}

.nav-bar:hover {
color: gray;
}

main {
display: flex;
}

.blog {
display: flex;
justify-content: center;
flex-wrap: wrap;
margin-top: 0px;
width: 80%;
}

.BlogContainer {
display: grid;
grid-template-rows: repeat(3, 1fr);
grid-template-columns: auto auto auto;
grid-auto-rows: 0px;
overflow: hidden;
width: 25%;
margin: 15px;
}

.blog-title {
color: black;
font-family: 'Times New Roman', Times, serif;
font-size: 20px;
overflow: wrap;
}

.BlogContainer a h2:hover {
color: gray;
}

.BlogContainer a {
text-decoration: none;
}

.blog-img {
display: flex;
justify-content: center;
margin-bottom: 20px;
}

.next-page {
font-family: Arial;
position: relative;
display: flex;
justify-content: center;
}

.next-page a {
text-decoration: none;
color: black;
display: flex;
justify-content: center;
position: absolute;
bottom: 0;
}

.sidebar {
position: relative;
display: flex;
flex-grow: 1;
justify-content: center;
margin-top: 35px;
}

aside {
color: black;
font-family: arial;
position: sticky;
display: flex;
flex-direction: column;
overflow: auto;

}

.aside-img {
width: 200px;
height: 200px;
margin-bottom: 30px;
margin-left: 9px;
}

.aside-p {
font-weight: bold;
font-size: 16px;
}

.aside-input {
margin-bottom: 5px;
width: 209px;
color: black;
border-style: solid;
padding: 5px;
border-color: black;
font-size: 14px;
}

.aside-span {
font-weight: bold;
font-size: 22px;
}

.button-submit {
font-weight: bold;
font-size: 14px;
margin-bottom: 30px;
padding: 6px;
color:#FB6F92;
background-color: #fbe5e5;
width: 223px;
border-style: none;

}

.social a {
 color: black;
 text-decoration: none;
 }


.container-pagination {
text-align: center;
margin-bottom: 50px;
}

.container-pagination a {
color: black;
text-decoration: none;
}

footer {
width: 100%;
height: 298px;
font-family: arial;
background-color: #fbe5e5;
display: grid;
grid-template-columns: 1fr 1fr 1fr 1fr;
}

.social-footer {
margin-top: 20px;
margin-left: 25px;
}

.social-footer a {
color: black;
text-decoration: none;
}

.footer-content {
grid: 2/4fr;
margin-top: 20px;
}

.footer-copyright {
width: 100%;
text-align: center;
font-size: 14px;
color: black;
font-family: arial;
background-color: #fbe5e5;
display: block;
padding-bottom: 10px;
}

.footer-p {
color: black;
text-decoration: none;
}




const search = document.getElementById('search-i');
const links = document.getElementsByClassName('.blog-title');

function searchResult() {

search.addEventListener("click", searchResult);
const searchValue = search.value.toLowerCase();

for (let i = 0; i < links.length; i++) {
const text = links[i].textContent.toLowerCase();                                                 
  if (text.includes(searchValue)) {
document.getElementById('search-results').innnerHMTL;
    links[i].style.display = 'block';
  } else {
document.getElementById('search-results').innerHTML;
    links[i].style.display = 'none';
  }
}
console.log(searchValue);
};

console.log(searchResult);
}

I do not know why the javascript does not display the results on page