Can someone help me how to end setTimeout and running function when event triggered

I’m trying to create a multiple div animation where they all move when scrolled, when I wheel up it doesn’t trigger the else if actions and doesn’t cancel the running setTimeout function. Please help I’m new when it comes to Javascript animation

HTML

<body>
    <section class="login">
        <div class="login-background">
            <div class="login-background__plus" data-animate-speed="2" data-animate-distance="60" style="height: 200px; width: 200px; top: 30px; left: 60px; background-color: #ccc;">
                <span></span>
                <span></span>
            </div>
            <div class="login-background__plus" data-animate-speed="1" data-animate-distance="80" style="height: 100px; width: 100px;top: 600px;left: 80px;background-color: #ccc;">
                <span></span>
                <span></span>
            </div>
            <div class="login-background__plus" data-animate-speed="3" data-animate-distance="800" style="height: 300px;width: 300px;top: 80px;left: 800px;background-color: #ccc;">
                <span></span>
                <span></span>
            </div>
            <div class="login-background__plus" data-animate-speed="0.5" data-animate-distance="500" style="height: 80px; width: 80px; top: 90px; left: 500px; background-color: #ccc;">
                <span></span>
                <span></span>
            </div>
            <div class="login-background__plus" data-animate-speed="1" data-animate-distance="300" style="height: 100px; width: 100px; top: 400px; left: 300px; background-color: #ccc;">
                <span></span>
                <span></span>
            </div>
        </div>
        <div class="login__wrapper">
            <h2 class="login__title">Login</h2>
        
            <label for="customer_email">Email Address</label>
            <input type="email" name="customer[email]" />
        
            <label for="customer_password">Password</label>
            <input type="password" name="customer[password]" />
        
            <input type="submit" value="Sign In" />
        </div>
    </section>
    <script>
        const animate = new Animation();
    </script>
</body>

JS

class Animation{
    constructor(){
        document.addEventListener('DOMContentLoaded', () => {
            document.addEventListener("wheel", this.wheelHandler);
        });
        this.callFunction = [];
        this.timer = [];
    }

    wheelHandler = (event) => {
        if(event.target.matches('.login-background')){
            const parser = new DOMParser();
            const loginElbg = document.querySelectorAll('.login-background')[0].innerHTML;
            const parseHTML = parser.parseFromString(loginElbg,'text/html');
            const plusEls = Array.from(parseHTML.querySelectorAll('.login-background__plus')).map((element) => element);
            plusEls.forEach((plusEl, index) => {
                let el = document.querySelectorAll('.login-background__plus')[index];
                let speed = parseFloat(el.getAttribute('data-animate-speed'));
                let x_axis = el.getBoundingClientRect();
                let x_axis_left = parseFloat(x_axis.left);
                let z_distance = (x_axis_left + (speed*5));
                let bodyRect = document.body.getBoundingClientRect();
                let that = this;
                let movement = event.deltaY;
                if(this.callFunction[index] !== "undefined"){
                    this.callFunction[index] = function(){
                        that.animateObjects(el,speed,z_distance,x_axis_left,movement,index);
                    }
                    this.timer[index] = setTimeout(this.callFunction[index],100);
                }
                if(this.callFunction[index] === "function"){
                    clearTimeout(this.timer[index]);
                    this.callFunction[index] = function(){
                        that.animateObjects(el,speed,z_distance,x_axis_left,movement,index);
                    }
                    this.timer[index] = setTimeout(this.callFunction[index],100);
                }
            });
        }
    }

    animateObjects = (el,speed,z_distance,x_axis,movement,index) => {
        let newX_axis = x_axis;
        let targetEl = el;
        let that = this;
        this.callFunction[index] = function(){
            that.animateObjects(el,speed,z_distance,newX_axis,movement);
        }
        console.log(movement);
        if(movement > 0){
            newX_axis += (speed*2);
            el.style.transform = `translate3d(${newX_axis}px, 0, 0)`;
            if(newX_axis < z_distance){
                // console.log(newX_axis + " != " + z_distance, newX_axis < z_distance);
                setTimeout(this.callFunction[index],100);
            }else{
                // console.log(newX_axis + " != " + z_distance, newX_axis < z_distance);
                return;
            }
        }else if(movement < 0){
            newX_axis -= (speed*2);
            el.style.transform = `translate3d(${newX_axis}px, 0, 0)`;
            if(newX_axis > z_distance){
                // console.log(newX_axis + " != " + z_distance, newX_axis < z_distance);
                setTimeout(this.callFunction[index],100);
            }else{
                // console.log(newX_axis + " != " + z_distance, newX_axis < z_distance);
                return;
            }
        }else{
            return;
        }
    }
}

Smooth transition and the divs don’t jump and where able to move left and right smoothly with the event listener

Best way to passing react props through three components

I have this kind of components tree in my react app. My header component includes the navbar component which in turn includes dialog1 and dialog2.
So, I was wondering what is the best way to pass the props [opened1, opened2, handleDialog1, handleDialog2] to the dialog components from header (passing via navbar). Can you tell me the optimal solution?

     header
       |
     navbar
   |        |
dialog1  dialog2

header.js

import React, { useState } from "react";
import { Button, Stack } from "@mui/material";
import Navbar from "components/Navbar";

export default function Header() {
  const [opened1, setOpened1] = useState(false);
  const [opened2, setOpened2] = useState(false);

  const handleDialog1 = () => {
    setOpened1(!opened1);
  };
  const handleDialog2 = () => {
    setOpened2(!opened2);
  };

  return (
    <Stack>
      <Button onClick={handleDialog1}>my first button</Button>
      <Button onClick={handleDialog2}>my second button</Button>
      <Navbar />
    </Stack>
  );
}

navbar.js

import React from "react";
import { Typography, Stack } from "@mui/material";
import Dialog1 from "components/Dialog1";
import Dialog2 from "components/Dialog2";

export default function Navbar() {
  return (
    <Stack>
      <Typography>lorem ipsum</Typography>
      <Typography>lorem ipsum</Typography>
      <Typography>lorem ipsum</Typography>
      <Dialog1 />
      <Dialog2 />
    </Stack>
  );
}

dialog1.js (dialog2.js is an equal component but with different numbers)

import React from "react";
import { Typography, IconButton, Dialog, DialogTitle } from "@mui/material";

export default function Dialog1() {
  return (
    <Dialog open={opened1} onClose={handleDialog1}>
      <DialogTitle>
        <Typography>my first dialog</Typography>
        <IconButton onClick={handleDialog1} />
      </DialogTitle>
    </Dialog>
  );
}

Contract revert when try to send a flashbots bundle

I have a solidity contract with this fragment:

if iszero(eq(caller(), memUser)) { revert(3, 3) }

When I try to send a bundle to flashbots, it reverts.

Using:
eth_callBundle

Im signing the bundle with the wallet that created the contract.

I think that the problem arises due to the fact that Flashbots transactions are executed by a miner address, not the original sender, before they are included in a block. So, when interacts with contract, its the miner address, that’s right?

Any help is appreciated

Compiling the contract and send a bundle transaction to flashbots

How to add a different type of quiz for quizdown?

I am trying to add one additional feature to a semi-popular JavaScript-Markdown program to create quizzes called Quizdown, that being is free response questions, in which all you would have is a single input bar to for a user to type into and will check if that string passed matches the string I specify to be the answer however I am not sure how to update the code to do so as far I have already done. I created a new type of question called ‘FreeResponse’ and added a class for it using the existing code that was already provided. Then in Parser I simply added it to the parseQuestion() function and am not sure where to go from here. I know that I have to update the determineQuestionType() function in order to determine if the question type is free response and that I will most likely have to update App.svelte to include a new text bar component. I will provide both files here:
quiz.ts:

import { writable, get, Writable } from 'svelte/store';
import autoBind from 'auto-bind';
import type { Config } from './config.js';

//Modify this file to support a FreeResponse question type

function isEqual(a1: Array<number>, a2: Array<number>): boolean {
    return JSON.stringify(a1) === JSON.stringify(a2);
}

function shuffle(array: Array<any>, n: number | undefined): Array<any> {
    // https://stackoverflow.com/questions/2450954/how-to-randomize-shuffle-a-javascript-array
    let currentIndex = array.length,
        temporaryValue,
        randomIndex;

    // While there remain elements to shuffle...
    while (0 !== currentIndex) {
        // Pick a remaining element...
        randomIndex = Math.floor(Math.random() * currentIndex);
        currentIndex -= 1;
        // And swap it with the current element.
        temporaryValue = array[currentIndex];
        array[currentIndex] = array[randomIndex];
        array[randomIndex] = temporaryValue;
    }
    return array.slice(0, n);
}

// we need to reference the classes in the svelte app despite minifaction of class names
export type QuestionType = 'MultipleChoice' | 'SingleChoice' | 'Sequence' | 'FreeResponse';

export abstract class BaseQuestion {
    readonly text: string;
    answers: Array<Answer>;
    readonly explanation: string;
    selected: Array<number>;
    solved: boolean;
    readonly hint: string;
    readonly questionType: QuestionType;
    readonly options: Config;
    showHint: Writable<boolean>;
    visited: boolean;

    constructor(
        text: string,
        explanation: string,
        hint: string,
        answers: Array<Answer>,
        questionType: QuestionType,
        options: Config
    ) {
        if (answers.length === 0) {
            throw 'no answers for question provided';
        }
        this.text = text;
        this.explanation = explanation;
        this.hint = hint;
        this.solved = false;
        this.showHint = writable(false);
        this.options = options;
        this.answers = answers;
        this.questionType = questionType;
        this.visited = false;
        autoBind(this);
        this.reset();
    }

    enableHint() {
        this.showHint.update((val) => true);
    }

    reset() {
        this.selected = [];
        this.solved = false;
        this.visited = false;
        this.showHint.set(false);
        if (this.options.shuffleAnswers) {
            this.answers = shuffle(this.answers, this.answers.length);
        }
    }
    abstract isCorrect(): boolean;
}

class Blanks extends BaseQuestion {
    isCorrect() {
        this.solved = false;
        return this.solved;
    }
}

class Pairs extends BaseQuestion {
    isCorrect() {
        this.solved = false;
        return this.solved;
    }
}

export class Sequence extends BaseQuestion {
    constructor(
        text: string,
        explanation: string,
        hint: string,
        answers: Array<Answer>,
        options: Config
    ) {
        // always enable shuffling for sequence questions
        options.shuffleAnswers = true;
        super(text, explanation, hint, answers, 'Sequence', options);
    }

    isCorrect() {
        // extract answer ids from answers
        let trueAnswerIds = this.answers.map((answer) => answer.id);
        this.solved = isEqual(trueAnswerIds.sort(), this.selected);
        return this.solved;
    }
}
//Create a FreeResponse class that extends BaseQuestion
class FreeResponse extends BaseQuestion {
    constructor(
        text: string,
        explanation: string,
        hint: string,
        answers: Array<Answer>,
        options: Config
    ) {
        super(text, explanation, hint, answers, 'FreeResponse', options);

    }
    isCorrect() {
        let trueAnswerIds = this.answers
            .filter((answer) => answer.correct)
            .map((answer) => answer.id);
        let selectedAnswerIds = this.selected.map((i) => this.answers[i].id);
        this.solved = isEqual(trueAnswerIds.sort(), selectedAnswerIds.sort());
        return this.solved;
    }
}


class Choice extends BaseQuestion {
    isCorrect() {
        let trueAnswerIds = this.answers
            .filter((answer) => answer.correct)
            .map((answer) => answer.id);
        let selectedAnswerIds = this.selected.map((i) => this.answers[i].id);
        this.solved = isEqual(trueAnswerIds.sort(), selectedAnswerIds.sort());
        return this.solved;
    }
}

export class MultipleChoice extends Choice {
    constructor(
        text: string,
        explanation: string,
        hint: string,
        answers: Array<Answer>,
        options: Config
    ) {
        super(text, explanation, hint, answers, 'MultipleChoice', options);
    }
}

export class SingleChoice extends Choice {
    constructor(
        text: string,
        explanation: string,
        hint: string,
        answers: Array<Answer>,
        options: Config
    ) {
        super(text, explanation, hint, answers, 'SingleChoice', options);
        let nCorrect = this.answers.filter((answer) => answer.correct).length;
        if (nCorrect > 1) {
            throw 'Single Choice questions can not have more than one correct answer.';
        }
    }
}

export class Answer {
    html: string;
    correct: boolean;
    id: number;
    comment: string;

    constructor(id: number, html: string, correct: boolean, comment: string) {
        this.html = html;
        this.correct = correct;
        this.id = id;
        this.comment = comment;
        autoBind(this);
    }
}

export class Quiz {
    questions: Array<BaseQuestion>;
    active: Writable<BaseQuestion>;
    index: Writable<number>;
    config: Config;
    onLast: Writable<boolean>;
    onResults: Writable<boolean>;
    onFirst: Writable<boolean>;
    isEvaluated: Writable<boolean>;
    allVisited: Writable<boolean>;

    constructor(questions: Array<BaseQuestion>, config: Config) {
        this.index = writable(0);
        this.questions = questions;
        this.config = config;
        if (this.config.shuffleQuestions) {
            this.questions = shuffle(this.questions, this.config.nQuestions);
        }
        if (this.questions.length == 0) {
            throw 'No questions for quiz provided';
        }
        // setup first question
        this.active = writable(this.questions[0]);
        this.questions[0].visited = true;
        this.onLast = writable(this.questions.length == 1);
        this.onResults = writable(false);
        this.onFirst = writable(true);
        this.allVisited = writable(this.questions.length == 1);
        this.isEvaluated = writable(false);
        autoBind(this);
    }

    private setActive() {
        let idx = get(this.index);
        this.active.update((act) => this.questions[idx]);
        this.questions[idx].visited = true;
    }

    private checkAllVisited(): boolean {
        for (let question of this.questions) {
            if (!question.visited) {
                return false;
            }
        }
        return true;
    }

    jump(index: number): boolean {
        if (index <= this.questions.length - 1 && index >= 0) {
            // on a question
            this.index.set(index);
            this.setActive();
            this.allVisited.set(this.checkAllVisited());
            this.onResults.set(false);
            this.onLast.set(index == this.questions.length - 1);
            this.onFirst.set(index == 0);
            return true;
        } else if (index == this.questions.length) {
            // on results page
            this.onResults.set(true);
            this.onLast.set(false);
            this.index.set(index);
            return true;
        } else {
            return false;
        }
    }

    next(): boolean {
        return this.jump(get(this.index) + 1);
    }

    previous(): boolean {
        return this.jump(get(this.index) - 1);
    }

    reset(): Boolean {
        this.onLast.set(false);
        this.onResults.set(false);
        this.allVisited.set(false);
        this.isEvaluated.set(false);

        this.questions.forEach((q) => q.reset());
        return this.jump(0);
    }

    evaluate(): number {
        var points = 0;
        for (var q of this.questions) {
            if (q.isCorrect()) {
                points += 1;
            }
        }
        this.isEvaluated.set(true);
        return points;
    }
}
//Export the FreeResponse class
export { FreeResponse };

parser.ts:

import DOMPurify from 'dompurify';
import stripIndent from 'strip-indent';
import {
    Quiz,
    BaseQuestion,
    MultipleChoice,
    SingleChoice,
    FreeResponse,
    Sequence,
    Answer,
    QuestionType,
} from './quiz';
import { Config, mergeAttributes } from './config';
import marked from './customizedMarked';

function parseQuizdown(rawQuizdown: string, globalConfig: Config): Quiz {
    let tokens = tokenize(rawQuizdown);
    // globalConfig < quizConfig < questionConfig
    let quizConfig = new Config(globalConfig);

    if (hasQuizOptions(tokens)) {
        quizConfig = parseOptions(tokens, quizConfig);
    }
    let firstHeadingIdx = findFirstHeadingIdx(tokens);
    let questions = extractQuestions(tokens.slice(firstHeadingIdx), quizConfig);
    return new Quiz(questions, quizConfig);
}

function tokenize(rawQuizdown: string): marked.TokensList {
    return marked.lexer(htmlDecode(stripIndent(rawQuizdown)));
}

function hasQuizOptions(tokens: marked.TokensList) {
    // type definition does not allow custom token types
    // @ts-ignore
    let optionsIdx = tokens.findIndex((token) => token['type'] == 'options');
    let headingIdx = tokens.findIndex((token) => token['type'] == 'heading');
    // quiz options appear at the top before the first heading
    return optionsIdx !== -1 && headingIdx > optionsIdx;
}

function parseOptions(tokens: marked.Token[], quizConfig: Config): Config {
    // type definition does not allow custom token types
    // @ts-ignore
    let options = tokens.find((token) => token.type == 'options');
    return mergeAttributes(quizConfig, options['data']);
}

function extractQuestions(tokens: marked.Token[], config: Config) {
    let questions: BaseQuestion[] = [];
    let nextQuestion = 0;

    while (tokens.length !== 0) {
        nextQuestion = findFirstHeadingIdx(tokens.slice(1));
        if (nextQuestion === -1) {
            // no next question on last question
            nextQuestion = tokens.length;
        }
        let question = parseQuestion(
            tokens.splice(0, nextQuestion + 1),
            config
        );
        questions.push(question);
    }
    return questions;
}

function parseQuestion(tokens: marked.Token[], config: Config): BaseQuestion {
    let explanation = parseExplanation(tokens);
    let hint = parseHint(tokens);
    let heading = parseHeading(tokens);
    let answers = parseAnswers(tokens);
    let questionType = determineQuestionType(tokens);
    let questionConfig = new Config(config);
    const args = [heading, explanation, hint, answers, questionConfig] as const;
    switch (questionType) {
        case 'SingleChoice':
            return new SingleChoice(...args);
        case 'MultipleChoice':
            return new MultipleChoice(...args);
        case 'Sequence':
            return new Sequence(...args);
        case 'FreeResponse':
            return new FreeResponse(...args);
    }
}

function findFirstHeadingIdx(tokens: marked.Token[]): number {
    return tokens.findIndex((token) => token['type'] == 'heading');
}

function parseHint(tokens: marked.Token[]): string {
    let blockquotes = tokens.filter((token) => token['type'] == 'blockquote');
    return parseTokens(blockquotes);
}

function parseExplanation(tokens: marked.Token[]): string {
    let explanations = tokens.filter(
        (token) => token['type'] == 'paragraph' || token['type'] == 'code'
    );
    return parseTokens(explanations);
}

function parseHeading(tokens: marked.Token[]): string {
    let headings = tokens.filter((token) => token['type'] == 'heading');
    return parseTokens(headings);
}

function parseAnswers(tokens: marked.Token[]): Array<Answer> {
    let list = tokens.find(
        (token) => token.type == 'list'
    ) as marked.Tokens.List;
    let answers: Array<Answer> = [];
    list.items.forEach(function (item, i) {
        let answer = parseAnswer(item);
        answers.push(
            new Answer(i, answer['text'], item['checked'], answer['comment'])
        );
    });
    return answers;
}

function parseAnswer(item: marked.Tokens.ListItem) {
    let comments = item['tokens'].filter((token) => token.type == 'blockquote');
    let texts = item['tokens'].filter((token) => token.type != 'blockquote');
    return { text: parseTokens(texts), comment: parseTokens(comments) };
}

//Modify this function to check for FreeResponse
function determineQuestionType(tokens: marked.Token[]): QuestionType {
    let list = tokens.find(
        (token) => token.type == 'list'
    ) as marked.Tokens.List;
    if (list.ordered) {
        if (list.items[0].task) {
            return 'SingleChoice';
        } else {
            return 'Sequence';
        }
    } else {
        return 'MultipleChoice';
    }
}

function parseTokens(tokens: marked.Token[]): string {
    return DOMPurify.sanitize(marked.parser(tokens as marked.TokensList));
}

function htmlDecode(text: string) {
    return text
        .replace(/&lt;/g, '<')
        .replace(/&gt;/g, '>')
        .replace(/&amp;/g, '&');
}

export default parseQuizdown;

App.svelte:

<script lang="ts">
    import type { Quiz } from './quiz';
    import ProgressBar from './components/ProgressBar.svelte';
    import { onMount } from 'svelte';
    import registerLanguages from './languages/i18n';
    import Card from './components/Card.svelte';
    import Credits from './components/Credits.svelte';
    import SmoothResize from './components/SmoothResize.svelte';
    import QuestionView from './components/QuestionView.svelte';
    import Row from './components/Row.svelte';
    import Button from './components/Button.svelte';
    import { _ } from 'svelte-i18n';
    import ResultsView from './components/ResultsView.svelte';
    // import { Linear, CheckFirst } from './progressModes.js';
    import Animated from './components/Animated.svelte';
    import registerIcons from './registerIcons.js';
    import Icon from './components/Icon.svelte';
    import Hint from './components/Hint.svelte';
    import { fly } from 'svelte/transition';
    import Container from './components/Container.svelte';
    import Loading from './components/Loading.svelte';
    // import Modal from './components/Modal.svelte';

    export let quiz: Quiz;
    // https://github.com/sveltejs/svelte/issues/4079
    $: question = quiz.active;
    $: showHint = $question.showHint;
    $: index = quiz.index;
    $: onLast = quiz.onLast;
    $: onFirst = quiz.onFirst;
    $: onResults = quiz.onResults;
    $: isEvaluated = quiz.isEvaluated;
    $: allVisited = quiz.allVisited;

    //let game = new Linear(quiz);

    registerLanguages(quiz.config.locale);
    registerIcons();

    let node: HTMLElement;
    let minHeight = 150;
    let reloaded = false;
    // let showModal = false;

    // set global options
    onMount(async () => {
        let primaryColor: string = quiz.config.primaryColor;
        let secondaryColor: string = quiz.config.secondaryColor;
        let textColor: string = quiz.config.textColor;

        node.style.setProperty('--quizdown-color-primary', primaryColor);
        node.style.setProperty('--quizdown-color-secondary', secondaryColor);
        node.style.setProperty('--quizdown-color-text', textColor);
        node.style.minHeight = `${minHeight}px`;
    });
</script>

<div class="quizdown-content" bind:this="{node}">
    <Card>
        <ProgressBar value="{$index}" max="{quiz.questions.length - 1}" />
        <Loading update="{reloaded}" ms="{800}" minHeight="{minHeight}">
            <Container>
                <SmoothResize minHeight="{minHeight}">
                    <Animated update="{$index}">
                        {#if $onResults}
                            <ResultsView quiz="{quiz}" />
                        {:else}
                            <QuestionView
                                question="{$question}"
                                n="{$index + 1}"
                            />
                            <Hint hint="{$question.hint}" show="{$showHint}" />
                        {/if}
                    </Animated>
                </SmoothResize>

                <!-- <Modal show="{showModal}">Are you sure?</Modal> -->

                <Row>
                    <Button
                        slot="left"
                        title="{$_('hint')}"
                        disabled="{!$question.hint || $showHint || $onResults}"
                        buttonAction="{$question.enableHint}"
                        ><Icon name="lightbulb" solid="{false}" /></Button
                    >
                    <svelte:fragment slot="center">
                        <Button
                            title="{$_('previous')}"
                            disabled="{$onFirst || $onResults || $isEvaluated}"
                            buttonAction="{quiz.previous}"
                            ><Icon name="arrow-left" size="lg" /></Button
                        >

                        <Button
                            disabled="{$onLast || $onResults || $isEvaluated}"
                            buttonAction="{quiz.next}"
                            title="{$_('next')}"
                            ><Icon name="arrow-right" size="lg" /></Button
                        >

                        {#if $onLast || $allVisited}
                            <div in:fly="{{ x: 200, duration: 500 }}">
                                <Button
                                    disabled="{!($onLast || $allVisited) ||
                                        $onResults}"
                                    title="{$_('evaluate')}"
                                    buttonAction="{() =>
                                        quiz.jump(quiz.questions.length)}"
                                    ><Icon
                                        name="check-double"
                                        size="lg"
                                    /></Button
                                >
                            </div>
                        {/if}
                    </svelte:fragment>

                    <Button
                        slot="right"
                        title="{$_('reset')}"
                        buttonAction="{() => {
                            reloaded = !reloaded;
                            quiz.reset();
                        }}"><Icon name="redo" /></Button
                    >
                </Row>

                <Credits />
            </Container>
        </Loading>
    </Card>
</div>

<!-- global styles applied to all elements in the app -->
<style type="text/scss" global>
    @import 'highlight.js/styles/github';
    @import 'katex/dist/katex';
    @import '@fortawesome/fontawesome-svg-core/styles';

    img {
        max-height: 400px;
        border-radius: 4px;
        max-width: 100%;
        height: auto;
    }

    code {
        padding: 0 0.4rem;
        font-size: 85%;
        color: #333;
        white-space: pre-wrap;
        border-radius: 4px;
        padding: 0.2em 0.4em;
        background-color: #f8f8f8;
        font-family: Consolas, Monaco, monospace;
    }

    a {
        color: var(--quizdown-color-primary);
    }

    .quizdown-content {
        padding: 1rem;
        max-width: 900px;
        margin: auto;
    }
</style>

Any assistance in working towards my feature update for Quizdown.

import javascript module: The requested module X does not provide an export named Y

I am having a problem to import a JavaScript module. Here is the code (test.js) that I am trying (I have seen it being used in many projects that import IPFS):

import IPFS from 'ipfs'

When I run it with node, this throws the following error:

import IPFS from 'ipfs'
       ^^^^
SyntaxError: The requested module 'ipfs' does not provide an export named 'default'
    at ModuleJob._instantiate (node:internal/modules/esm/module_job:127:21)
    at async ModuleJob.run (node:internal/modules/esm/module_job:193:5)
    at async Promise.all (index 0)
    at async ESMLoader.import (node:internal/modules/esm/loader:337:24)
    at async loadESM (node:internal/process/esm_loader:88:5)
    at async handleMainPromise (node:internal/modules/run_main:61:12)

Process finished with exit code 1

I tried to find out what is wrong here. So I ctrl-clicked on ipfs and it takes me to the following index.d.ts:

/**
 * @typedef {import('ipfs-core-types').IPFS} IPFS
 */
export const create: typeof import("ipfs-core/src/components").create;
export const crypto: typeof import("libp2p-crypto");
export const isIPFS: typeof import("is-ipfs");
export const CID: typeof import("multiformats").CID;
export const multiaddr: typeof import("multiaddr").Multiaddr;
export const PeerId: typeof import("peer-id");
export const globSource: typeof import("ipfs-utils/src/files/glob-source");
export const urlSource: typeof import("ipfs-utils/src/files/url-source");
export const path: typeof pathImport;
export type IPFS = import('ipfs-core-types').IPFS;
import { path as pathImport } from "./path.js";
//# sourceMappingURL=index.d.ts.map

It looks to me like IPFS is exported by a named export. So I tried to change my code to named import, like this:

import {IPFS} from 'ipfs'

This throws the following error:

import {IPFS} from 'ipfs'
        ^^^^
SyntaxError: The requested module 'ipfs' does not provide an export named 'IPFS'
    at ModuleJob._instantiate (node:internal/modules/esm/module_job:127:21)
    at async ModuleJob.run (node:internal/modules/esm/module_job:193:5)
    at async Promise.all (index 0)
    at async ESMLoader.import (node:internal/modules/esm/loader:337:24)
    at async loadESM (node:internal/process/esm_loader:88:5)
    at async handleMainPromise (node:internal/modules/run_main:61:12)

Process finished with exit code 1

So how can I solve this problem?

Here is the package.json:

{
  "name": "ipfs-test",
  "version": "1.0.0",
  "description": "",
  "main": "index.js",
  "scripts": {
    "test": "echo "Error: no test specified" && exit 1"
  },
  "author": "",
  "license": "ISC",  
  "type": "module"
}

I should mention that I wrote the code in Intellij, and it did not show a compilation error, which it usually does when it cannot locate imports. So that’s also weird.

CSS Background Gradient Not Covering the Whole Page Including Scrollable Content

I’m experiencing a problem with a CSS background gradient in my HTML document. I have designed a page that uses a linear gradient as a background, and I’ve set it on the body element. The issue I’m facing is that the gradient seems to end where the screen ends initially, even though there’s more content to scroll through. As a result, when you scroll down, a second instance of the gradient appears to start over again.

Here’s my current CSS (SCSS) code:

@import url('https://fonts.googleapis.com/css2?family=Poppins:wght@400;500;700&display=swap');


body {
    min-height: 100vh;
    background: linear-gradient(to bottom, rgb(10, 25, 47), rgb(44, 83, 100));
    color: whitesmoke;
    font-family: 'Poppins', sans-serif;
}


img {
    max-width: 28%;
    border-radius: 50%;
}

.container {
    height: auto;
    width: 100vw;
    height: 100vh;
    display: grid;
    grid-template-columns: repeat(2, 1fr);
    grid-template-rows: 1fr 0.25fr 3fr;
    gap: 3%;
    padding: 3%;
    box-sizing: border-box;
}

.content-left, .content-right {
    display: flex;
    align-items: center;
    justify-content: center;
}

.slogan {
    grid-column: span 2;
    font-size: 1.5em;
    display: flex;
    align-items: top;
    justify-content: center;
    text-transform: uppercase;
    letter-spacing: 2px;
}
.container-form {
    height: auto;
    grid-column: span 2;
    display: flex;
    flex-direction: column;
    align-items: center;
    justify-content: center;
    margin-bottom: 30px; // Add space at the bottom
}


input, textarea, select {
    border: 2px solid whitesmoke;
    background-color: rgba(255, 255, 255, 0.1);
    color: whitesmoke;
}

input:invalid:not(:placeholder-shown), textarea:invalid:not(:placeholder-shown) {
    border: 2px solid red;
}

input:invalid:focus:not(:placeholder-shown), textarea:invalid:focus:not(:placeholder-shown) {
    outline: none;
}

input:invalid:not(:placeholder-shown)::placeholder, textarea:invalid:not(:placeholder-shown)::placeholder {
    color: red;
}

#register-form:invalid:not(:placeholder-shown) ~ #popup {
    display: block;
}

button, input[type=submit] {
    margin-top: 20px;
    padding: 10px 20px;
    font-size: 1em;
    transition: background-color 0.3s ease;
}

button:hover, input[type=submit]:hover {
    background-color: rgba(255, 255, 255, 0.1);
}

.form-container {
    background: rgba(255, 255, 255, 0.1);
    border-radius: 15px;
    padding: 20px;
    width: 100%;
    max-width: 400px;
    box-sizing: border-box;
}

.form-control {
    background-color: transparent !important;
    color: whitesmoke !important;
    border-color: whitesmoke;
}

.form-control::placeholder {
    color: rgba(255, 255, 255, 0.7);
}

.button-container {
    display: flex;
    justify-content: space-between;
    gap: 10px;
    width: 100%;
}

#login-button {
    background-color: transparent;
    border: 2px solid whitesmoke;
    color: whitesmoke;
}

#login-button:hover {
    background-color: rgba(255, 255, 255, 0.1);
}

The expected behavior is for the gradient to always cover the whole screen, including the content that is not initially visible because it has to be scrolled to. I would like to avoid having two instances of the gradient. Essentially, the gradient should adapt to the height of the screen, even the scrolled height.

I’ve tried using different CSS properties and values such as height: auto; and min-height: 100%; but these didn’t seem to work. I also tried no-repeat but what this does is to show a write rectangle instead. Any help would be appreciated!
Here’s the HTML in case you need it to replicate the error:

<!DOCTYPE html>
<html lang="en">
<head>
    <title>Register</title>

    <!-- Required meta tags -->
    <meta charset="utf-8">
    <meta name="viewport" content="width=device-width, initial-scale=1, shrink-to-fit=no">
    <link rel="icon" type="image/png" href="../assets/icons/social.png"/>

    <!-- Bootstrap CSS v5.2.1 -->
    <link href="https://cdn.jsdelivr.net/npm/[email protected]/dist/css/bootstrap.min.css" rel="stylesheet"
        integrity="sha384-iYQeCzEYFbKjA/T2uDLTpkwGzCiq6soy8tYaI1GyVh/UjpbCx/TYkiZhlZB6+fzT" crossorigin="anonymous">
    <link href="https://fonts.googleapis.com/css2?family=Poppins:wght@400;500;700&display=swap" rel="stylesheet">
    <link rel="stylesheet" href="../css/register.css">
</head>
<body>
    <div class="container">
        <div class="content-left">
            <img src="../assets/images/logo.jpeg" alt="logo">
        </div>
        <div class="content-right">
            <h1>Stockify</h1>
        </div>
        <div class="slogan">
            <h2>The smart way</h2>
        </div>

        <div class="container-form">
            <form id="register-form" action="index.html" class="form-container">
                <div class="mb-3">
                    <label for="name" class="form-label">Name:</label>
                    <input type="text" id="name" name="name" class="form-control">
                </div>
                <div class="mb-3">
                    <label for="email" class="form-label">Email:</label>
                    <input type="email" id="email" name="email" class="form-control">
                </div>
                <div class="mb-3">
                    <label for="phone" class="form-label">Phone Number:</label>
                    <input type="tel" id="phone" name="phone" class="form-control">
                </div>
                <div class="mb-3">
                    <label for="subscription" class="form-label">Subscription Plan:</label>
                    <select id="subscription" name="subscription" class="form-control" required></select>
                </div>
                <div class="mb-3">
                    <label for="password" class="form-label">Password:</label>
                    <input type="password" id="password" name="password" class="form-control">
                </div>
                <div class="button-container">
                    <button id="login-button" class="btn btn-primary" type="button" onclick="redirectToLogin()">Login</button>
                    <input type="submit" value="Register" onclick=sendLoginRequest() class="btn btn-primary">
                </div>
                
            </form>
        </div>
    </div>

    <!-- Bootstrap JavaScript Libraries -->
    <script src="https://cdn.jsdelivr.net/npm/@popperjs/[email protected]/dist/umd/popper.min.js"
        integrity="sha384-oBqDVmMz9ATKxIep9tiCxS/Z9fNfEXiDAYTujMAeBAsjFuCZSmKbSSUnQlmh/jp3" crossorigin="anonymous">
    </script>
        <script src="https://cdn.jsdelivr.net/npm/[email protected]/dist/js/bootstrap.min.js"
        integrity="sha384-7VPbUDkoPSGFnVtYi0QogXtr74QeVeeIs99Qfg5YCF+TidwNdjvaKZX19NZ/e6oz" crossorigin="anonymous">
    </script>

    <script src="../javascript/register.js"></script>
    <script src="../javascript/cookie.js"></script>
</body>

</html>

Demo in snippet below:

@import url('https://fonts.googleapis.com/css2?family=Poppins:wght@400;500;700&display=swap');
body {
  min-height: 100vh;
  background: linear-gradient(to bottom, rgb(10, 25, 47), rgb(44, 83, 100));
  color: whitesmoke;
  font-family: 'Poppins', sans-serif;
}

img {
  max-width: 28%;
  border-radius: 50%;
}

.container {
  height: auto;
  width: 100vw;
  height: 100vh;
  display: grid;
  grid-template-columns: repeat(2, 1fr);
  grid-template-rows: 1fr 0.25fr 3fr;
  gap: 3%;
  padding: 3%;
  box-sizing: border-box;
}

.content-left,
.content-right {
  display: flex;
  align-items: center;
  justify-content: center;
}

.slogan {
  grid-column: span 2;
  font-size: 1.5em;
  display: flex;
  align-items: top;
  justify-content: center;
  text-transform: uppercase;
  letter-spacing: 2px;
}

.container-form {
  height: auto;
  grid-column: span 2;
  display: flex;
  flex-direction: column;
  align-items: center;
  justify-content: center;
  margin-bottom: 30px; // Add space at the bottom
}

input,
textarea,
select {
  border: 2px solid whitesmoke;
  background-color: rgba(255, 255, 255, 0.1);
  color: whitesmoke;
}

input:invalid:not(:placeholder-shown),
textarea:invalid:not(:placeholder-shown) {
  border: 2px solid red;
}

input:invalid:focus:not(:placeholder-shown),
textarea:invalid:focus:not(:placeholder-shown) {
  outline: none;
}

input:invalid:not(:placeholder-shown)::placeholder,
textarea:invalid:not(:placeholder-shown)::placeholder {
  color: red;
}

#register-form:invalid:not(:placeholder-shown)~#popup {
  display: block;
}

button,
input[type=submit] {
  margin-top: 20px;
  padding: 10px 20px;
  font-size: 1em;
  transition: background-color 0.3s ease;
}

button:hover,
input[type=submit]:hover {
  background-color: rgba(255, 255, 255, 0.1);
}

.form-container {
  background: rgba(255, 255, 255, 0.1);
  border-radius: 15px;
  padding: 20px;
  width: 100%;
  max-width: 400px;
  box-sizing: border-box;
}

.form-control {
  background-color: transparent !important;
  color: whitesmoke !important;
  border-color: whitesmoke;
}

.form-control::placeholder {
  color: rgba(255, 255, 255, 0.7);
}

.button-container {
  display: flex;
  justify-content: space-between;
  gap: 10px;
  width: 100%;
}

#login-button {
  background-color: transparent;
  border: 2px solid whitesmoke;
  color: whitesmoke;
}

#login-button:hover {
  background-color: rgba(255, 255, 255, 0.1);
}
<!-- Bootstrap CSS v5.2.1 -->
<link href="https://cdn.jsdelivr.net/npm/[email protected]/dist/css/bootstrap.min.css" rel="stylesheet" integrity="sha384-iYQeCzEYFbKjA/T2uDLTpkwGzCiq6soy8tYaI1GyVh/UjpbCx/TYkiZhlZB6+fzT" crossorigin="anonymous">
<link href="https://fonts.googleapis.com/css2?family=Poppins:wght@400;500;700&display=swap" rel="stylesheet">

<div class="container">
  <div class="content-left">
    <img src="../assets/images/logo.jpeg" alt="logo">
  </div>
  <div class="content-right">
    <h1>Stockify</h1>
  </div>
  <div class="slogan">
    <h2>The smart way</h2>
  </div>

  <div class="container-form">
    <form id="register-form" action="index.html" class="form-container">
      <div class="mb-3">
        <label for="name" class="form-label">Name:</label>
        <input type="text" id="name" name="name" class="form-control">
      </div>
      <div class="mb-3">
        <label for="email" class="form-label">Email:</label>
        <input type="email" id="email" name="email" class="form-control">
      </div>
      <div class="mb-3">
        <label for="phone" class="form-label">Phone Number:</label>
        <input type="tel" id="phone" name="phone" class="form-control">
      </div>
      <div class="mb-3">
        <label for="subscription" class="form-label">Subscription Plan:</label>
        <select id="subscription" name="subscription" class="form-control" required></select>
      </div>
      <div class="mb-3">
        <label for="password" class="form-label">Password:</label>
        <input type="password" id="password" name="password" class="form-control">
      </div>
      <div class="button-container">
        <button id="login-button" class="btn btn-primary" type="button" onclick="redirectToLogin()">Login</button>
        <input type="submit" value="Register" onclick=sendLoginRequest() class="btn btn-primary">
      </div>

    </form>
  </div>
</div>

<!-- Bootstrap JavaScript Libraries -->
<script src="https://cdn.jsdelivr.net/npm/@popperjs/[email protected]/dist/umd/popper.min.js" integrity="sha384-oBqDVmMz9ATKxIep9tiCxS/Z9fNfEXiDAYTujMAeBAsjFuCZSmKbSSUnQlmh/jp3" crossorigin="anonymous">
</script>
<script src="https://cdn.jsdelivr.net/npm/[email protected]/dist/js/bootstrap.min.js" integrity="sha384-7VPbUDkoPSGFnVtYi0QogXtr74QeVeeIs99Qfg5YCF+TidwNdjvaKZX19NZ/e6oz" crossorigin="anonymous">
</script>

Setting Videotitel via useState in React native

I`m trying to create a dynamically generated video view in react native. I call the side Play with the parameters letter and mode. The selected video found out of an array is correct. See console log. But the videoTitel itself is always the video from the first side call. So it´s not updating when I call the side again. The title only changes if I change setVideoTitle, e.g. with a button onclick.

export default function Play ({ navigation, route}) {

let letter = route.params.Letter;
let mode = route.params.Mode;

const video = useRef(null);
const [selection, setSelection] = useState(0);

const Videos = require('../components/Videos');
const selectedVideo = Videos.Array.find(V => V.name === letter.toString());
console.log(selectedVideo)
console.log("Video: " + selectedVideo.Front[mode])
const [videoTitel, setVideoTitel] = useState(selectedVideo.Front[mode]);
console.log("VideoTitel: "+ videoTitel)
const [videoSpeed, setVideoSpeed] = useState(1.0);

enter image description here

How can I display a table’s results using a Go button rather than an automatic search?

I’m working on a page that contains drop-down menus for filtering datatables. Everything works properly.
But the issue is that the information in the search results is automatically displayed based on my selection.
Instead is it possible to add a button that reads “Go/Search Results” so that the user can click to see the results.The results should be displayed only when the user clicks on the button.

Here is the link to my code –

https://live.datatables.net/yamifera/16/edit

$(document).ready(function() {
  var table = $('#example').DataTable({
    responsive: true,
    searching: true,
    columnDefs: [
            {
                target: 6,
                visible: false,
                searchable: true,
            }
      ],
    dom: 'Bfrtip',
        buttons: [
            {
                extend: 'excelHtml5',
                exportOptions: {
                    columns: ':visible'
                }
            },
            {
                extend: 'pdfHtml5',
                orientation: 'landscape',
                exportOptions: {
                    columns: ':visible'
                     }
              },           
            {
                extend: 'print',
                exportOptions: {
                    columns: ':visible'
                }
               },
        //  'colvis'
        ],
  });

  buildSelect(table);
 
  table.on('draw', function() {
    buildSelect(table);
  });
  $('#test').on('click', function() {
    table.search('').columns().search('').draw();
  });
});

function buildSelect(table) {
  var counter = 0;
  table.columns([0, 1, 2]).every(function() {
    var column = table.column(this, {
      search: 'applied'
    });
    counter++;
    var select = $('<select><option value="">select me</option></select>')
      .appendTo($('#dropdown' + counter).empty())
      .on('change', function() {
        var val = $.fn.dataTable.util.escapeRegex(
          $(this).val()
        );

        column
          .search(val ? '^' + val + '$' : '', true, false)
          .draw();
      });

    if ( column.index() === 0 ) {
      var filteredNames = column.data().unique().toArray();
      ['Garrett', 'Test1', 'Ashton'].forEach((d) => {
        if (filteredNames.includes(d)) {
          select.append('<option value="' + d + '">' + d + '</option>');
        }
      });
    } else {
      column.data().unique().sort().each(function(d, j) {
        select.append('<option value="' + d + '">' + d + '</option>');
      });
    }

    // The rebuild will clear the exisiting select, so it needs to be repopulated
    var currSearch = column.search();
    if (currSearch) {
      // ** MY CHANGE **
      // Use RegEx to find the selected value from the unique values of the column.
      // This will use the Regular Expression returned from column.search to find the first matching item in column.data().unique
      select.val(column.data().unique().toArray().find((e) => e.match(new RegExp(currSearch))));
    }
  });
}
<!DOCTYPE html>
<html>
  <head>
    <link rel="stylesheet" type="text/css"  href="https://cdn.datatables.net/1.10.15/css/jquery.dataTables.min.css" />
<link rel="stylesheet" type="text/css"  href="https://cdn.datatables.net/buttons/1.4.0/css/buttons.dataTables.min.css" />

<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/jszip/3.1.3/jszip.min.js"></script>
<script src="https://cdn.rawgit.com/bpampuch/pdfmake/0.1.27/build/pdfmake.min.js"></script>
<script src="https://cdn.rawgit.com/bpampuch/pdfmake/0.1.27/build/vfs_fonts.js"></script>
<script src="https://cdn.datatables.net/1.10.15/js/jquery.dataTables.min.js"></script>
<script src="https://cdn.datatables.net/buttons/1.4.0/js/dataTables.buttons.min.js"></script>
<script src="https://cdn.datatables.net/buttons/1.4.0/js/buttons.flash.min.js"></script>
<script src="https://cdn.datatables.net/buttons/1.4.0/js/buttons.html5.min.js"></script>
<script src="https://cdn.datatables.net/buttons/1.4.0/js/buttons.print.min.js"></script>

    
    
    <meta charset=utf-8 />
    <title>DataTables - JS Bin</title>
  </head>
<div class="searchbox">
<p>Name: 
  
  <span id="dropdown1">
  </span>
</p>

<p>Postion: <span id="dropdown2">
  </span>
</p>

<p>Office: <span id="dropdown3">
</span>
</p>
  <button type="button" id="test">Clear Filters</button>
</div>
  <table id="example" class="cell-border row-border stripe dataTable no-footer dtr-inline" role="grid" style=" width: 100%; padding-top: 10px;"><thead>
<tr>

<th>&#160;</th>
<th>&#160;</th>
<th>&#160;</th>
<th colspan="3" style=" text-align: center;">Information</th>
  <th>&#160;</th>
</tr>


          <tr>
            <th>Name</th>
            <th>Position</th>
            <th>Office</th>
            <th>Age</th>
            <th>Start date</th>
            <th>Salary</th>
            <th>Hidden Column</th>
          </tr>
        </thead>
        
        <tbody>
          <tr>
            <td>
Test1</td>


            <td>test</td>
            <td>test3</td>
            <td>test4</td>
            <td>2011/04/25</td>
            <td>$3,120</td>
            <td>Sys Architect</td>
          </tr>
          <tr>
            <td>Garrett</td>
            <td>Director: fgghghjhjhjhkjkj</td>
            <td>Edinburgh</td>
            <td>63</td>
            <td>2011/07/25</td>
            <td>$5,300</td>
            <td>Director:</td>
          </tr>
          <tr>
            <td>Ashton</td>
            <td>Technical Authorjkjkjk fdfd h gjjjhjhk</td>
            <td>San Francisco</td>
            <td>66</td>
            <td>2009/01/12</td>
            <td>$4,800</td>
            <td>Tech author</td>
          </tr>
          
            
          </tr></tbody></table>
</div>

Form Data Not Sending on Safari/Firefox iOS

This works on everything but Safari/Firefox on iOS:

jQuery("#gform_1").one('submit', function(event) {
  const form = document.getElementById("gform_1");
  const firstName = document.getElementById('input_1_1').value;
  const lastName = document.getElementById('input_1_2').value;
  const phoneNumber = document.getElementById('input_1_3').value;
  const email = document.getElementById('input_1_4').value;

  const formData = {
    firstName: firstName,
    lastName: lastName,
    phoneNumber: phoneNumber,
    email: email
  };

  jQuery.ajax({
    url: 'https://www.example.com/submissions.php',
    type: 'POST',
    data: formData,
    success: function(response) {
      console.log("Success!", response);
    },
    error: function(xhr, status, error) {
      console.error("Error!", error);
      console.log(xhr.responseText);
    }
  });
});

console.error("Error!", error) is blank. It says “Error! ””. The console.log(xhr.responseText) is also blank. I don’t think it’s a CORs issue since the submissions.php is hosted on the same server/domain as the form.

Javascript Regex: get specific parts inside brackets without taking extra brackets

I am building a program that would simplify coding discord bots. I wanted to add inline functions, but seems like my regex selector is not the perfect match.

My program loops through every inline function and tests if it exists in the string. And replaces the inline function strings with the inline function returnings.

For example, {ping} is translated to 91. Or, {id author} is translated to id of the message author.

The problem is that if there are inline functions in an inline function. I managed to solve 1 inline function per 1, but as the number grow, my regex selector fails and just matches the wrong stuff.

what i want it to match:

{avatarurl {id {message}}}
           ^^^^^^^^^^^^^^

can even match this too:

{avatarurl {id {message}}}
               ^^^^^^^^^

this too:

{avatarurl {id {message}}}
^^^^^^^^^^^^^^^^^^^^^^^^^^

and so on.

it just needs to starts from {(function name) and end with }.

my regex selector fails at matching this part, it just matches extra brackets. I need a perfect regex selector that will match {blabla}, but still work when placed into another {blabla}.

this is the pattern that didnt work out: new RegExp(`{${func.name}([^}]+[^])*}`)

the func.name is the function name.
i also need the part that comes after “{funcname” and before “}”.

Passing data to a React component

I’m trying to pass the innerHTML of a div to a react component and use that data when rendering the component. I cannot figure out the correct way to pass/use this to the component.

Here is a simple example I’m working with. I’d like to be able to have multiple divs in the index.html file with varying content each one, and for each div with a certain class name such as “dynamic-box” or something similar, it’ll be rendered inside of the dynamic SVG box. But for now, I am stuck on pulling the content of the div and passing that to the React component.

How can i apply a smooth expand transition to this vue component?

The component below has a large amount of data and initially, this data is partially hidden. When the user clicks to expand, ‘dataExpanded’ property is set to true and ‘data-not-expanded’ class is removed, removing the overflow and limited height property. What i need is that, when removing the limited height, a smooth expand transition is displayed instead of abruptly changing the height of the component. How can i archieve it? I am using vue and vuetify but not sure if they can help since the transition isn’t based on a simple v-if or v-show.

<car-page-data
            :class="{
              'data-not-expanded': !dataExpanded,
            }"
            :car="car"
          />

Style:

.data-not-expanded {
  height: 400px;
  overflow: hidden;
}

A library to handle reporting bugs in the browser

I’m managing a small web application for my team, it’s a small react application with a flask backend.

I’m developing it with a colleague and, of course, our other colleagues using the applications often find weird bugs.

They often have troubles replicating them and explaining us what happened. I would like to create a button to “report bugs” that automatically makes a screenshot, dumps the console and network tab of the inspector and prepares an email ready to be sent with all the relevant info to replicate.

Is there any library that could work for us?

I’ve seen instabug, but due to company policy it has to be open sourced.

Updating text to match .length is always one behind

I have some fitlering being used on my site and I have a text block that I would like updated with the number of active filters so the user can always tell how many are applied even if the filters are closed.

The issue is, my count is always one behind either way. It’s taking one more click to get the correct number.

I would assume the number is updating with the CURRENT number as opposed to updating AFTER the click has occured, but I can’t wrap my brain around how to restructure to address that.

Here’s my code:

let countFilter = 0;

function updateFilterCount() {
  let countFilter = $(".is-active").length;
  $(".caps.count").text(countFilter);
  if (countFilter > 0) {
    $(".filtered-text").addClass("active");
    $(".caps.all.active").removeClass("active");
  } else {
    $(".filtered-text.active").removeClass("active");
    $(".caps.all").addClass("active");
  }
}

updateFilterCount();

$(".fltr, .fltr-label, .filter_drawer, .button.ghost.filter__button.active").on(
  "click",
  function () {
    updateFilterCount();
  }
);

Firebase functions not executing

I have a firebase project using node.js and I have a form that logs in and can sign up new users. I have recently wanted to make a welcome function that send a welcome email to the user when they sign up and when running the function no email is sent but no errors are thrown either.

I have a functions folder in my root directory and this is what the structure of that folder looks like:

enter image description here

The code for the index.js file is as follows:

const functions = require("firebase-functions");
const { sendEmail } = require('./sendEmail');

// Export the functions
exports.sendEmail = functions.auth.user().onCreate((user) => {
  sendEmail(user);
});

The config.js file:

const functions = require('firebase-functions');
const admin = require('firebase-admin');
const serviceAccount = require('./course-curve-firebase-adminsdk-ae6ht-411a2a0ae9.json');

admin.initializeApp({
  credential: admin.credential.cert(serviceAccount),
  databaseURL: serviceAccount.databaseURL
});

const getEmailConfig = async () => {
  const snapshot = await admin.firestore().collection('config').doc('email').get();
  return snapshot.data();
};

module.exports = getEmailConfig;

And lastly the send emails file:

const functions = require('firebase-functions');
const nodemailer = require('nodemailer');
const getEmailConfig = require('./config');

const transporter = nodemailer.createTransport({
  service: 'Gmail',
  auth: getEmailConfig,
});

const sendEmail = async (user) => {
  const emailConfig = await getEmailConfig();

  const mailOptions = {
    from: emailConfig.email_address,
    to: '[email protected]',
    subject: 'New User Registered',
    html: `<p>New user registered: ${user.email}</p>`,
  };

  try {
    await transporter.sendMail(mailOptions);
    console.log('Email sent successfully');
  } catch (error) {
    console.error('Error sending email:', error);
  }
};

module.exports = {sendEmail};

Any help on figuring out why my function isn’t working would be greatly appreciated. Have a blessed day.