Set element width based on a string that is not in the element

I have a React component that can render one string or another.

const MyComponent = (props: {
    readonly textA: string;
    readonly textB: string;
    readonly renderB: boolean;
}) => {
    return <>{props.renderB ? props.textB : props.textA}</>;
};

The problem is when I use this and I toggle renderB on and off, the width of the component can change based on which string is rendered. I want the component width to fit the longer of the two strings.

How can I take the max length of textA and textB and use that to determine the width of my component?

For example, it could look something like this:

const MyComponent = (props: {
    readonly textA: string;
    readonly textB: string;
    readonly renderB: boolean;
}) => {
    const widthA = /* compute the width of props.textA */;
    const widthB = /* compute the width of props.textB */;

    return (
        <div style={{ width: `${Math.max(widthA, widthB)}px` }}>
            {props.renderB ? props.textB : props.textA}
        </div>
    );
};

Passing function with arguments as a prop and invoking it internally in React

I got a Badge component in my React app. The badge can be painted in different colors. In order to make it more universal i’ve decided to add a prop called getBadgeColor. The idea is to implement different functions for different needs. For example, in one scenario i need badges for loading statuses. So i implement the function getStatusBadgeColor that looks like this:

enum BadgeColors {
    RED = 'red',
    YELLOW = 'yellow',
    GREEN = 'green',
    BLUE = 'blue',
    INDIGO = 'indigo',
    PURPLE = 'purple',
    PINK = 'pink',
}

export type BadgeColor = typeof BadgeColors[keyof typeof BadgeColors];

export type getBadgeColor<T> = (value: T) => BadgeColor;

export const getStatusBadgeColor: getBadgeColor<TStatus> = (status: TStatus) => {
    switch (status) {
        case Statuses.STATUS_SUCCESS:
            return BadgeColors.GREEN;
        case Statuses.STATUS_ERROR:
            return BadgeColors.INDIGO;
        default:
            return BadgeColors.BLUE;
    }
}

My Badge component looks like this.

interface BadgeProps<T> {
    label: string;
    color?: BadgeColor;
    getBadgeColor?: getBadgeColor<T>;
    value?: T
}

export const Badge = <T,>({ label, color, getBadgeColor}: BadgeProps<T>) => {

    const colorValue = getBadgeColor ? getBadgeColor() : color

    return (
        <span className="...">
            <svg className={cn('h-1.5', 'w-1.5', `fill-${colorValue}-500`)} viewBox="0 0 6 6" aria-hidden="true">
                <circle cx={3} cy={3} r={3} />
            </svg>
            {label}
        </span>
    )
}

I pass the function like this

<Badge label={record.status} getBadgeColor={() => getStatusBadgeColor(record.status)}  />

So the problem is basically that i can’t invoke a function inside the Badge component without calling it with arguments. Is there is a way i can do it? I would appreciate any help

how can i make a random number that is either 1 or 2 [duplicate]

i’m making a very simple game and i wanted an input that could do two different things randomly. my first thought was to make a variable that switches between 1 and 2 randomly (or a boolean) but i don’t know how to make a random number yet. this all would drive a pair of if statements. i would also like to change it randomly either when player input happens or on a setInterval. i’m very new to html javascript, so try to be thorough with an explanation. thanks!

woops, i made the question rong. this is also my first question on this sight.

Javascript ; loading data from url into object variable before running remaining code

I’m struggling to wrap my head around the javascript async/sync concepts.

I’ve subclassed an openlayers Layer class for some custom rendering in a map. After instantiating an object of the class, I want to load data (a png file from an url) and save the data into a class variable before I go on and do some custom webgl rendering based on the data. I’ve tried all sorts of stuff now with awaits and thens, but unable to get something to work. I was hoping someone could give me some pointers on how I should structure code to achieve this.

I’m able to do it when I load the data outside the class, but then only with a fixed url, and I need to be able to change the url on certain events.

Code for instantiating object and trying to run the function that sets the data in a class variable:

function update_map(time_change_event) {
    const new_url = 'www.example.com/' + time_change_event.detail.key
    const canvasLayer = new CanvasLayer({})
    canvasLayer.getData(new_url)
    map.addLayer(canvasLayer)
    map.removeLayer(*oldlayer*)
}

Code for custom class:

export class CanvasLayer extends Layer {

    data = null;

    getData(url){

        async data_promise = new Promise((resolve, reject) => {
            const image = new Image();
            image.onload = () => {
                const canvas = document.createElement('canvas');
                canvas.width = image.width;
                canvas.height = image.height;
                const context = canvas.getContext('2d');
                context.drawImage(image, 0, 0);
                const data = context.getImageData(0, 0, width, height);
                resolve(data);
            
            };
            image.onerror = () => {
                reject(new Error('failed to load'));
            };

            image.src = url;
        })
    
        this.data = await data_promise;

    }

    render(frameState, target){
        // This is called when layer is added to map
        // Doing stuff with this.data does not work because it is null
        console.log(this.data) returns null
    }
}

JS how to clear the page cache of a pdf document object pdf.js or how not to save it

When I take a page (page = doc.getPage), render it and then clean it (page.cleanup()), the page cache remains in the document object (doc), which accumulates and quickly clogs memory.

Tell me, please, is there any way to clear this cache or turn it off, other than just closing the document and opening it again (but it’s slow)? PDF version.js v3.11.174

doc._transport.#pageCache and doc._transport.#pagePromises are private and methods for their I did not find any cleaning (doc.cleanup() and doc._transport.startCleanup() does not help, but doc.destroy() clears the entire document object and it is not an option to continue working with it).

Making metaballs from compound path / Paper.js

I have the following code:

const data = [
  { text: "Forage" },
  { text: "Fourndollar" },
  // { text: 'Interiorndesign' },
  // { text: 'Salviannormcore' },
  // { text: 'Typewriter' },
  // { text: 'Bicyclenrights' },
  // { text: 'Try-hardnenamel' },
  // { text: 'Grailed' },
  // { text: 'Fingerstache' },
];

const canvas = document.getElementById("metaballs__canvas");
let circles = [];
let blob = null;

const random = (min, max) => Math.random() * (max - min) + min;

const orbitRadius = random(8, 16);
const orbitSpeed = random(0.001, 0.005);

paper.setup(canvas);
paper.view.autoUpdate = true;

blob = new paper.CompoundPath({
  children: [],
  strokeColor: "white"
});

const createCircles = (content, position) => {
  const text = new paper.PointText({
    point: position,
    content: content,
    fontFamily: "Instrument Sans",
    fontWeight: "400",
    fontSize: 24,
    justification: "center",
    fillColor: "white"
  });

  const circle = new paper.Path.Circle({
    center: position,
    radius: text.bounds.width / 2 + 48,
    fillColor: "transparent"
  });

  const group = new paper.Group([text, circle]);

  group.onMouseDrag = (event) => {
    group.position = group.position.add(event.delta);
  };

  circles.push({
    group: group,
    circle: circle,
    text: text,
    angle: random(0, 360),
    center: position,
    orbitRadius: orbitRadius,
    orbitSpeed: orbitSpeed
  });
};

const createBlob = () => {
  blob.removeChildren();

  const unitedPath = circles.reduce((acc, {
    circle
  }) => {
    if (acc) return acc.unite(circle);
    else return circle;
  }, null);

  if (unitedPath) blob.addChild(unitedPath);
};

const animateCircles = () => {
  circles.forEach(
    ({
        group,
        circle,
        text,
        angle,
        center,
        orbitRadius,
        orbitSpeed
      },
      index
    ) => {
      angle += orbitSpeed;

      const x = center.x + orbitRadius * Math.cos(angle);
      const y = center.y + orbitRadius * Math.sin(angle);

      circle.position = new paper.Point(x, y);
      text.position = new paper.Point(x, y);

      group.position = new paper.Point(x, y);

      circles[index].angle = angle;
    }
  );
};

data.forEach((item) => {
  createCircles(
    item.text,
    new paper.Point(
      random(0, paper.view.bounds.width),
      random(0, paper.view.bounds.height)
    )
  );
});

paper.view.onFrame = (event) => {
  createBlob();
  // animateCircles();
};

paper.view.update();
@import url("https://fonts.googleapis.com/css2?family=Instrument+Sans:ital,wght@0,400..700;1,400..700&display=swap");
#metaballs {
  padding: 32px;
}

#metaballs__canvas {
  position: relative;
  border-radius: 8px;
  width: 640px;
  aspect-ratio: 16 / 9;
  overflow: hidden;
  background-color: hsla(0, 0%, 0%, 1);
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/paper.js/0.12.18/paper-full.min.js"></script>

<div id="metaballs">
  <canvas id="metaballs__canvas"></canvas>
</div>

With 2 items, it works fine. However, whenever I uncomment more items, I encounter performance issues, probably caused by the compound path creation on every frame. Is there a more sophisticated solution for this?

I also want to smooth out the connections of the circles. I found a plugin called paperjs-round-corners, but it’s really buggy when applied to the segments. An example of what I’m aiming for is the option in Adobe Illustrator where you unite two circles, select the path, and apply a corner radius operation.

Corner Radius applied on compound path in Illustrator

Generating deterministic ECDSA keys based on seed and salt using zero-dependencies JavaScript and SubtleCrypto

Given seed and salt how do I produce a set of deterministic ECDSA keys using zero-dependencies JavaScript and SubtleCrypto?
This is a continuation of this question, which I was advised to form as a new question. Therefore I publish no sample code, my understanding is that there’re 2 major ways to go about it:

  1. Generate the key material and then somehow import it as ECDSA keys.
  2. Generate x & y required to generate ECDSA keys (I’m not sure how, given the generateKey call accepting just named curve, maybe via jwk(?))

I’d like the solution to rely as much as possibly on SubtleCrypto API with as little custom code as possible.

Generate deterministic ECDSA keys based on seed and salt using zero-dependencies JavaScript and SubtleCrypto

Given seed and salt how do I produce a set of deterministic ECDSA keys using zero-dependencies JavaScript and SubtleCrypto?
This is a continuation of this question, which I was advised to form as a new question. Therefore I publish no sample code, my understanding is that there’re 2 major ways to go about it:

  1. Generate the key material and then somehow import it as ECDSA keys.
  2. Generate x & y required to generate ECDSA keys (I’m not sure how, given the generateKey call accepting just named curve, maybe via jwk(?))

I’d like the solution to rely as much as possibly on SubtleCrypto API with as little custom code as possible.

highcharts in react customization with plotlines and custom marker only on new data point

I am using highcharts and highcharts-react-official to create chart for eth Realtime price. I also show user currentround details that i am getting in startedRoundData from partent component and it render like this (image attached) also added plotlines for startTime and endTime. as you can see plotline text is corpped.
enter image description here

This is the exact chart I want to copy with all details and functionality.
enter image description here

Here is my code

import React, { useEffect, useState } from "react";
import Highcharts from "highcharts";
import HighchartsReact from "highcharts-react-official";
import moment from "moment";

const Chart = ({ data, startedRoundData }) => {
  const [chartOptions, setChartOptions] = useState({});

  useEffect(() => {
    const pricesData = data?.prices || [];
    const chartData = pricesData
      .slice(0, -1)
      .map((item) => [item.timestamp * 1000, parseFloat(item.price)]);

    const lastTimestamp = chartData[chartData.length - 1]?.[0] || 0;
    const futureTimestamp = lastTimestamp + 10000; // 10 seconds in the future

    const options = {
      chart: {
        type: "spline",
        backgroundColor: "#131722",
        height: "400px",
        marginRight: 10,
        marginLeft: 0,
        marginBottom: 30,
        marginTop: 10,
        animation: Highcharts.svg,
      },
      title: null,
      xAxis: {
        type: "datetime",
        lineColor: "#2a2e39",
        tickColor: "#2a2e39",
        labels: {
          style: { color: "#787b86", fontSize: "10px" },
          y: 20,
          formatter: function () {
            return moment(this.value).format("HH:mm:ss");
          },
        },
        tickLength: 0,
        minPadding: 0,
        maxPadding: 0,
        gridLineWidth: 1,
        gridLineColor: "#2a2e39",
        tickInterval: 10000, // 10 seconds interval
        tickAmount: 6,
        min: lastTimestamp - 50000, // Show 50 seconds of past data
        max: futureTimestamp, // Extend to 10 seconds in the future
        plotLines: [
          {
            color: "#ff9800",
            width: 1,
            value: startedRoundData?.startTime
              ? moment(startedRoundData?.startTime).utc().valueOf()
              : null, // Convert to UTC
            dashStyle: "dash",
            zIndex: 5,
            label: {
              useHTML: true, // Allows for custom HTML
              align: "center",
              y: 0,
              x: 0,
              formatter: function () {
                return `
                      <div class="custom-plotline-label">
                        <span class="label-text">Current</span>
                      </div>
                    `;
              },
            },
            events: {
              render: function () {
                // Access and style after rendering
                const plotLineLabel = this.plotLinesAndBands[0].label.element;
                plotLineLabel.style.transform = "rotate(270deg)";
                plotLineLabel.style.transformOrigin = "100% 12px";
                plotLineLabel.style.position = "absolute";
                plotLineLabel.style.left = "150px";
                plotLineLabel.style.top = "10px";
              },
            },
          },

          {
            color: "#ff9800",
            width: 1,
            value: startedRoundData?.lockTime
              ? moment(startedRoundData?.lockTime).utc().valueOf()
              : null, // Convert to UTC
            dashStyle: "dash",
            zIndex: 5,
            label: {
              text: "End",
              align: "center",
              style: { color: "#ffffff", fontSize: "12px" },
              y: 15,
            },
          },
        ],
      },
      yAxis: {
        title: null,
        labels: {
          align: "right",
          x: 45,
          style: { color: "#787b86", fontSize: "10px" },
          formatter: function () {
            return this.value.toFixed(2);
          },
        },
        gridLineColor: "#2a2e39",
        gridLineWidth: 1,
        tickAmount: 5,
        opposite: true,
        plotLines: [
          {
            color: "#ff9800",
            width: 1,
            value: startedRoundData?.startTime
              ? moment(startedRoundData?.startTime).utc().valueOf()
              : null, // Convert to UTC
            dashStyle: "dash",
            zIndex: 5,
            label: {
              text: startedRoundData?.startPrice
                ? startedRoundData?.startPrice
                : null,
              align: "center",
              style: {
                color: "#ffffff",
                fontSize: "12px",
                whiteSpace: "nowrap", // To ensure the text doesn't break
              },
              y: 15,
            },
          },
        ],
      },
      legend: { enabled: false },
      series: [
        {
          name: "Price",
          data: chartData,
          color: "#00ff00",
          lineWidth: 2,
          marker: {
            enabled: false,
          },
        },
      ],
      tooltip: {
        enabled: false,
      },
      credits: { enabled: false },
      plotOptions: {
        spline: {
          animation: {
            duration: 1000,
            easing: "easeOutQuart",
          },
        },
      },
    };

    setChartOptions(options);
  }, [data]);

  useEffect(() => {
    if (chartOptions.series) {
      const chart = Highcharts.charts[0];
      if (chart) {
        const series = chart.series[0];
        const lastPoint = series.data[series.data.length - 1];
        if (lastPoint) {
          lastPoint.update(
            {
              marker: {
                enabled: true,
                radius: 5,
                symbol: "circle",
                fillColor: "#00ff00",
                lineColor: "#00ff00",
                lineWidth: 2,
                states: {
                  hover: {
                    enabled: true,
                    radius: 5,
                    fillColor: "#00ff00",
                    lineColor: "#00ff00",
                    lineWidth: 2,
                  },
                },
              },
            },
            false
          );
          chart.redraw();
        }
      }
    }
  }, [chartOptions]);

  return (
    <div className="bg-[#131722] p-4 rounded-lg h-[485px]">
      <HighchartsReact highcharts={Highcharts} options={chartOptions} />
    </div>
  );
};

export default Chart;
<script src="https://cdnjs.cloudflare.com/ajax/libs/react/18.2.0/umd/react.production.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/react-dom/18.2.0/umd/react-dom.production.min.js"></script>

Event working but class not reacting to the event

In my website, when you click in an element, an nav list open just above. This list closes when the user clicks in another part of the page (body), scroll the page (body) and when clicks again in the element named “Produtos”.

I did the body part and with the last one it isn’t working!

let listaProdutos = document.querySelector(".lista-produtos");
let checkBoxProdutos = document.querySelector("#menu");
let produtos = document.getElementById("link-produtos");

checkBoxProdutos.addEventListener("change", function () {
  x = window.matchMedia("(max-width: 849px)");
  if (x.matches) {
    if (this.checked) {
      listaProdutos.classList.add("visivel");
      listaProdutos.classList.remove("invisivel");

      // Para fechar a lista:
      let body = document.querySelector("body");
      body.addEventListener("click", function () {
        listaProdutos.classList.add("invisivel");
        listaProdutos.classList.remove("visivel");
        checkBoxProdutos.checked = true;
      });
      body.addEventListener("mousewheel", function () {
        listaProdutos.classList.add("invisivel");
        listaProdutos.classList.remove("visivel");
      });

      produtos.addEventListener("click", function () {
        alert("ola");
        listaProdutos.classList.add("invisivel");
        listaProdutos.classList.remove("visivel");
      });
    } else {
      listaProdutos.classList.add("invisivel");
      listaProdutos.classList.remove("visivel");
    }
  }
});
.visivel {
  display: block;
}

.invisivel {
  display: none;
}
<div class="cabecalho-lista">
  <ul class="cabecalho__lista">
    <li class="cabecalho__item">
      <a class="cabecalho__item__link" href="index.html">Home</a>
    </li>
    <div class="cabecalho__item-produtos">
      <li class="cabecalho__item cabecalho__item__produtos">
        <input class="produtos-celular" type="checkbox" id="menu" />
        <label for="menu">
          <a
            class="cabecalho__item__link"
            id="link-produtos"
            href="produtos.html"
            >Produtos</a
          >
        </label>

        <ul class="lista-produtos invisivel">
          <li class="lista-produtos__item">
            <a href="produtos.html#ignite">Linha Ignite</a>
          </li>
          <li class="lista-produtos__item">
            <a href="produtos.html#elfbar">Linha Elfbar</a>
          </li>
          <li class="lista-produtos__item">
            <a href="produtos.html#oxbar">Linha Oxbar</a>
          </li>
          <li class="lista-produtos__item">
            <a href="produtos.html#lost">Linha Lost Mary</a>
          </li>
        </ul>
      </li>
    </div>
    <li class="cabecalho__item">
      <a class="cabecalho__item__link" href="contato.html">FAQ</a>
    </li>
  </ul>
</div>

When the listener are listening click in “produtos”, the alert works well but the class that cleans the nav list simple doesnt work!

The list only disappear when the user scrool or click the body.

GROQ query to Sanity returns undefined for whyChoseExamples field (Next.js 14 + Sanity)

I’m working with Sanity.io and using a GROQ query to fetch data for my application. I’m trying to retrieve the whyChoseExamples field from my main document type, but it’s returning undefined.

schema.ts

export const mainPage = {
  name: 'main',
  title: 'Strona główna',
  type: 'document',
  fields: [
    {
      name: 'header',
      title: 'Nagłówek',
      type: 'string',
    },
    {
      name: 'subheader',
      title: 'Podtytuł',
      type: 'string',
    },
    {
      name: 'buttonText',
      title: 'Text na przycisku',
      type: 'string',
    },
    {
      name: 'backgroundImage',
      title: 'Obraz tła',
      type: 'image',
      options: { hotspot: true },
      fields: [{ name: 'alt', title: 'Tekst alternatywny (SEO)', type: 'string' }],
    },
    {
      name: 'whyChose',
      title: 'Dlaczego warto nas wybrać',
      type: 'string',
    },
    {
      name: 'whyChoseTitle',
      title: 'Dlaczego warto nas wybrać - Tytuł',
      type: 'string',
    },
    {
      name: 'whyChoseSubtitle',
      title: 'Dlaczego warto nas wybrać - Podtytuł',
      type: 'string',
    },
    {
      name: 'whyChoseExamples',
      title: 'Dlaczego warto nas wybrać - Zalety współpracy',
      type: 'array',
      of: [
        {
          type: 'object',
          name: 'textWithImage',
          title: 'Karta zalet',
          fields: [
            {
              name: 'header',
              title: 'Tytuł',
              type: 'string',
            },
            {
              name: 'subHeader',
              title: 'Podtytuł',
              type: 'string',
            },
            {
              name: 'image',
              title: 'Image',
              type: 'image',
              options: {
                hotspot: true,
              },
              fields: [
                {
                  name: 'alt',
                  title: 'Tekst alternatywny (SEO)',
                  type: 'string',
                },
              ],
            },
          ],
        },
      ],
    },
  ],
};

groq query

export const getMainPageContent = async (): Promise<MainPage[]> => {
  const client = createClient({
    projectId: 'myprojectId',
    dataset: 'production',
    apiVersion: '2024-09-17',
  });

  return client.fetch(groq`
  *[_type == "main"]{
  header,
  subheader,
  buttonText,
  backgroundImage {
    asset->{
      _id,
      url
    },
    alt,
  },
  whyChose,
  whyChoseTitle,
  whyChoseSubtitle,
  whyChoseExamples{
    header,
    subHeader,
    image {
      asset->{
        _id,
        url
      },
      alt,
    }
  },
}
`);
};

When I run this query and try to access whyChoseExamples, it comes back as undefined.

What I’ve Tried:

Checked Field Names:

Ensured that all field names in my query match those in my Sanity schema exactly.
Verified that it’s whyChoseExamples, not whyChooseExamples.
Confirmed Data Entry:

In Sanity Studio, the whyChoseExamples field is populated with data in my main document.

Used Sanity’s Vision Tool:

Ran the query in the Vision tool within Sanity Studio.
The whyChoseExamples field does appear in the results.

Additional Information:

Other fields like header, subheader, and whyChose are being returned correctly.
There are no conditional fields or permissions set that would hide whyChoseExamples.
I’m using the latest versions of the Sanity and Next.js

What could be causing the whyChoseExamples field to return undefined in my GROQ query, even though it’s populated in the Sanity Studio and correctly defined in the schema? How can I modify my query or schema to successfully retrieve this field?

Any help would be greatly appreciated!

Simulating IN clause for NoSQL database

So I want to simulate a SELECT * FROM TABLE WHERE ID IN {LIST_OF_IDS} query, I know Im using a NoSQL database (dynamoDB) but I have an index on the field for which I want to execute this query. So mainly I want to get all the posts from a user where the userID (index column) is the given list.

I am using Amplify as my managed backend and using graphql as my API. I know there is no IN keyword to use for graphql (at least nog APPSYNC). I have tried creating a custom resolver from a template provided by AWS like the following

import { util } from '@aws-appsync/utils';

/**
 * Gets items from the DynamoDB tables in batches with the provided `id` keys
 * @param {import('@aws-appsync/utils').Context} ctx the context
 * @returns {import('@aws-appsync/utils').DynamoDBBatchGetItemRequest} the request
 */
export function request(ctx) {
    return {
        operation: 'BatchGetItem',
        tables: {
            Posts: {
                keys: ctx.args.ids.map((id) => util.dynamodb.toMapValues({ id })),
                consistentRead: true,
            },
        },
    };
}

/**
 * Returns the BatchGetItem table items
 * @param {import('@aws-appsync/utils').Context} ctx the context
 * @returns {[*]} the items
 */
export function response(ctx) {
    if (ctx.error) {
        util.error(ctx.error.message, ctx.error.type);
    }
    return ctx.result.data.Posts;
}

But this doesnt seem to work. I would also like to avoid to run a query for each user in the list to retrieve the posts. All help is greatly appreciated, also if you have another architectural solution/proposal to solve this issue I am all ears!

how do i manipulate my object with its own properties

Currently learning JS, im a beginner.
I created an object to tinker with, and i want to give it some properties that are dependent on th previous properties of the same object.

I have managed to solve it by working about it yet, i know, i am sure there is a way to do it with in the object definition.

please help me, as a beginner i don’t know what key words to used when googling so this is my best bet.

By doing this :


airMax1 = {
    price : 200,
    appreciation : 8,
    taxRate : 0.2,
    realPrice : ((this.price+this.appreciation)*this.taxRate)+this.price+this.appreciation,
}
console.log(airMax1)

console.log(airMax1.realPrice)

i was expecting this output :

{ price: 200, appreciation: 8, taxRate: 0.2, realPrice: 249.6 } 249.6

yet what i get is this :

{ price: 200, appreciation: 8, taxRate: 0.2, realPrice: NaN }
NaN

but when i do it differently like this :

airMax1 = {
    price : 200,
    appreciation : 8,
    taxRate : 0.2,
}

airMax1.realPrice=((airMax1.price+airMax1.appreciation)*airMax1.taxRate)+airMax1.price+airMax1.appreciation

console.log(airMax1)

console.log(airMax1.realPrice)

it works and gives me the disered output of

{ price: 200, appreciation: 8, taxRate: 0.2, realPrice: 249.6 }
249.6

how can the same math formula produce a number when its outside the object and not produce a number when its inside the object.

i have swapped the object name with the this. method and all

How to add a class and remove when clicked, or when clicked elsewhere?

I have a caret dropdown that is supposed to do an up and down animation on 4 different tabs. In general scheme of things, these tabs populate different content when clicked on. The problem here is that I successfully am able to add and remove a class active when I click (with the .toggle functionality). The problem here is it only does it when I have one, not when i add to all 4 tabs. I need to remove ‘active‘ when clicked again on the same one, but when a different tab is clicked, i need it to add it that tab as well, and remove it on the previous tab. Do I need to add a forEach and loop on each instance of the #caret-dropdown ?

//Tab toggle for full page modal
const workMarketToggle = document.querySelector("#tab-toggle--workmarket");
const wmButton = document.querySelector("button");
const tabs = document.querySelector(".wrapper");
const tabButton = document.querySelectorAll(
  ".tab-button, .toggle-text, .toggle-img"
);
const contents = document.querySelectorAll(".content");
tabs &&
  tabs.addEventListener("click", (e) => {
    const button = e.target.closest("button");
    if (!button) return;

    contents.forEach((content) => content.classList.remove("active"));
    tabButton.forEach((btn) => btn.classList.remove("active"));

    button.classList.add("active");
    const element = document.getElementById(button.dataset.id);
    element.classList.add("active");
  });

// Caret Dropdown for tab toggle in Full Page Modal
const caretDropdown = document.querySelector(
  "#dropdown-trigger .caret-dropdown"
);
if (caretDropdown) {
  console.log("hello caret is here");
}
caretDropdown.addEventListener("click", function (event) {
  event.preventDefault();
  caretDropdown.classList.toggle("active");
});
#tab-toggle--workmarket .container,
#tab-toggle--profservices .container {
  margin: 30px auto;
}

#tab-toggle--workmarket #tab1,
#tab-toggle--workmarket #tab2,
#tab-toggle--workmarket #tab3,
#tab-toggle--workmarket #tab4,
#tab-toggle--workmarket #tab5,
#tab-toggle--workmarket #tab6,
#tab-toggle--profservices #tab1,
#tab-toggle--profservices #tab2,
#tab-toggle--profservices #tab3,
#tab-toggle--profservices #tab4,
#tab-toggle--profservices #tab5,
#tab-toggle--profservices #tab6 {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  width: 100%;
  gap: 50px;
  padding-top: 50px;
}

#tab-toggle--workmarket .wrapper,
#tab-toggle--profservices .wrapper {
  max-width: 1330px;
  margin: auto;
  border-radius: 10px;
}

#tab-toggle--profservices .buttonWrapper {
  display: flex;
  flex-direction: row;
  justify-content: center;
  align-items: center;
  background-color: #20347d;
  border-radius: 10px;
  height: 81px;
  max-width: 848px;
  margin: 0 auto;
  position: relative;
  z-index: 12;
}

#tab-toggle--profservices .no-bg {
  background-color: #eff5ff;
  height: auto;
}

#tab-toggle--profservices .contentWrapper {
  max-width: 1220px;
  margin: 0 auto;
}

#tab-toggle--workmarket button.tab-button,
#tab-toggle--profservices button.tab-button {
  font-family: var(--font-family-base);
  color: #fff;
}

.tab-button.tab-button-img {
  background-color: #eff5ff !important;
  height: 100% !important;
}

#tab-toggle--profservices button.tab-button {
  border: none;
  padding: 10px;
  background-color: #20347d;
  color: #fff;
  font-size: 18px;
  cursor: pointer;
  transition: 0.5s;
  border-radius: 10px;
  width: 202px;
  height: 61px;
  margin: 0 20px;
}

#tab-toggle--workmarket button:hover,
#tab-toggle--profservices button:hover {
  background-color: #d5e3ff;
}

#tab-toggle--workmarket button.active,
#tab-toggle--profservices button.active {
  background-color: white;
  margin: 0 20px;
}

#tab-toggle--workmarket button:hover,
#tab-toggle--workmarket button.active,
#tab-toggle--profservices button:hover,
#tab-toggle--profservices button.active {
  color: #000;
}

#tab-toggle--profservices button:hover,
#tab-toggle--profservices button.active {
  width: 202px;
  color: #33478c;
}

#tab-toggle--workmarket .active,
#tab-toggle--profservices .active {
  background-color: #f3f4f6;
}

#tab-toggle--workmarket .content,
#tab-toggle--profservices .content {
  display: none;
  padding: 10px 20px;
}

#tab-toggle--profservices .content-regular.active {
  display: flex;
  justify-content: center;
  padding: 70px 20px;
  align-items: center;
  gap: 50px;
  background-color: #fff;
  border-radius: 10px;
  margin: 0px;
  box-shadow: rgba(0, 0, 0, 0.14) 0px 3px 15px;
}

#tab-toggle--profservices .content.active {
  display: flex;
  justify-content: center;
  padding: 70px 20px;
  align-items: center;
  gap: 50px;
  background-color: #fff;
  border-radius: 10px;
  margin: -30px;
  box-shadow: rgba(0, 0, 0, 0.14) 0px 3px 15px;
}
#dropdown-trigger {
  display: block;
}
.caret-dropdown {
  cursor: pointer;
  top: 50%;
  transform: translateY(-50%);
  display: inline-block;
  height: 10px;
  left: 15px;
  margin-top: 2px;
  position: relative;
  text-align: left;
  transition: 0.4s ease;
  transform: rotate(0);
  width: 13px;
}
.caret-dropdown:after,
.caret-dropdown:before {
  background-color: transparent;
  border-bottom: 11px solid #444;
  box-sizing: content-box;
  content: "";
  display: inline-block;
  height: 8px;
  left: 0;
  position: absolute;
  top: 0;
  transition: 0.4s ease;
  width: 3px;
}
.caret-dropdown:before {
  transform: rotate(-135deg);
}
.caret-dropdown:after {
  transform: rotate(135deg);
}
.caret-dropdown.active {
  transform: rotate(0);
  transform: translate(0, -6px);
}
.caret-dropdown.active:before {
  transform: rotate(-45deg);
}
.caret-dropdown.active:after {
  transform: rotate(45deg);
}
<!-------- TAB TOGGLE SECTION -------->
<div class="bg-lightblue">
  <div id="tab-toggle--profservices">
    <div class="wrapper">
      <div class="buttonWrapper no-bg gap-100">
        <button class="tab-button tab-button-img active" data-id="implementation">

          <img src="#" width="150" class="toggle-img" />
          <h3 class="blue toggle-text">Implementation</h3>
             <a href="#" id="dropdown-trigger"
                  ><span class="caret-dropdown"></span
                ></a>
        </button>
        <button class="tab-button tab-button-img" data-id="advisory">
   
          <img
            src="#" width="150" class="toggle-img" >
          <h3 class="blue toggle-text">Advisory</h3>
              <a href="#" id="dropdown-trigger"
                  ><span class="caret-dropdown"></span
                ></a>
        </button>
        <button class="tab-button tab-button-img" data-id="integration">
          
                <img
                  src="#"
                  width="150"
                  class="toggle-img"
                />
                <h3 class="blue toggle-text">Integration</h3>
                    <a href="#" id="dropdown-trigger"
                  ><span class="caret-dropdown"></span
                ></a>
              </button>
        <button class="tab-button tab-button-img" data-id="transformation">
      
                <img
                  src="#"
                  width="150"
                  class="toggle-img"
                />
                <h3 class="blue toggle-text">Transformation</h3>
                    <a href="#" id="dropdown-trigger"
                  ><span class="caret-dropdown"></span
                ></a>
              </button>
      </div>
      <div class="contentWrapper">
        <div class="content content-regular active" id="implementation">
          <div class="pf-two-col-1">
            <p class="deep-red wfn-caps bold pb-0 mb-0">Info 1</p>
            <h2 class="pt-0 mt-0">
              information here
            </h2>
            <ul class="profservices">
              <li>
                list 1
              </li>
              <li>list 2</li>
              <li>
                list 3
              </li>
            </ul>
          </div>
          <div class="pf-two-col-2">
            <img src="#" class="pf-img-col2" skiplazy="" />
          </div>
        </div>
        <div class="content" id="advisory">
          <div class="pf-two-col-1">
            <p class="deep-red wfn-caps bold pb-0 mb-0">info 2</p>
            <h2 class="pt-0 mt-0">
              information here
            </h2>
            <ul class="profservices">
              <li>
                list 1
              </li>
              <li>list 2</li>
              <li>
                list 3
              </li>
            </ul>
          </div>
          <div class="pf-two-col-2">
            <img src="#" class="pf-img-col2" skiplazy="" />
          </div>
        </div>
        <div class="content" id="integration">
          <div class="pf-two-col-1">
            <p class="deep-red wfn-caps bold pb-0 mb-0">info 3</p>
            <h2 class="pt-0 mt-0">
              information here
            </h2>
            <ul class="profservices">
              <li>
                info 1
              </li>
              <li>
                info 2
              </li>
              <li>
                info 3
              </li>
            </ul>
          </div>
          <div class="pf-two-col-2">
            <img src="#" class="pf-img-col2" skiplazy="" />
          </div>
        </div>
        <div class="content" id="transformation">
          <div class="pf-two-col-1">
            <p class="deep-red wfn-caps bold pb-0 mb-0">info 4</p>
            <h2 class="pt-0 mt-0">
              information here
            </h2>
            <ul class="profservices">
              <li>
                list 1
              </li>
              <li>list 2</li>
              <li>
                list 3
              </li>
            </ul>
          </div>
          <div class="pf-two-col-2">
            <img src="#" class="pf-img-col2" skiplazy="" />
          </div>
        </div>
      </div>
    </div>
  </div>
</div>

Twilio.s Pitchshifting voice in Audiocall in audioContext.createMediaStreamSource(stream);

I’m banging my head up against this issue for hours missing something simple. I’m trying to implement a checkbox in my html page to toggle pitchshifting my microphone input for privacy and am working on combining Twilio.js with Pitchshifter located here:

Original Twilio-voice: [https://github.com/twilio/twilio-voice.js/releases](Twilio JS DIST github) (located in dist folder)

twilio-voice.js-2.12.1 located in the dist folder
Pitchshifter: [https://github.com/urtzurd/html-audio/blob/gh-pages/static/js/pitch-shifter.js](Pitchshifter on Github)

Upon answering a call, I see the console.log(s) being triggered, but no change in voice adjustment like the Pitchshift demo. I believe it has something to do with the way I am connecting the audio processor but after multi multi attempts the voice passing through is still unmodified.

I’ll worrie about adding the checkbox later to enable and disable the pitchshift once I get this part figured out.

Any pointers would be much appreciated as to why.

I attempted the modified code above and expected to hear my voice being modified and unrecognizable. I am doubtful but ultimately unsure if there is some post event that is overwriting the processor from taking effect.

var pitchShifterProcessor;
var initProcessor = function (audioContext) {
var validGranSizes = [256, 512, 1024, 2048, 4096, 8192];
var grainSize = validGranSizes[1];
var pitchRatio = 2.0;
var overlapRatio = 0.50;

console.log("1");
var hannWindow = function (length) {
    var window = new Float32Array(length);
    for (var i = 0; i < length; i++) {
        window[i] = 0.5 * (1 - Math.cos(2 * Math.PI * i / (length - 1)));
    }
    return window;
};

console.log("2");
var linearInterpolation = function (a, b, t) {
    return a + (b - a) * t;
};

console.log("3");
if (pitchShifterProcessor) {
    pitchShifterProcessor.disconnect();
}

console.log("4");
if (audioContext.createScriptProcessor) {
    pitchShifterProcessor = audioContext.createScriptProcessor(grainSize, 1, 1);
    console.log("audioContext.createScriptProcessor");
} else if (audioContext.createJavaScriptNode) {
    pitchShifterProcessor = audioContext.createJavaScriptNode(grainSize, 1, 1);
    console.log("audioContext.createJavaScriptNode");
}

console.log("5");
pitchShifterProcessor.buffer = new Float32Array(grainSize * 2);
pitchShifterProcessor.grainWindow = hannWindow(grainSize);
console.log("6");
pitchShifterProcessor.onaudioprocess = function (event) {
    var inputData = event.inputBuffer.getChannelData(0);
    var outputData = event.outputBuffer.getChannelData(0);

    for (i = 0; i < inputData.length; i++) {
        // Apply the window to the input buffer
        inputData[i] *= this.grainWindow[i];

        // Shift half of the buffer
        this.buffer[i] = this.buffer[i + grainSize];

        // Empty the buffer tail
        this.buffer[i + grainSize] = 0.0;
    }

    // Calculate the pitch shifted grain re-sampling and looping the input
    var grainData = new Float32Array(grainSize * 2);
    for (var i = 0, j = 0.0; i < grainSize; i++, j += pitchRatio) {
        var index = Math.floor(j) % grainSize;
        var a = inputData[index];
        var b = inputData[(index + 1) % grainSize];
        grainData[i] += linearInterpolation(a, b, j % 1.0) * this.grainWindow[i];
    }

    // Copy the grain multiple times overlapping it
    for (i = 0; i < grainSize; i += Math.round(grainSize * (1 - overlapRatio))) {
        for (j = 0; j <= grainSize; j++) {
            this.buffer[i + j] += grainData[j];
        }
    }

    // Output the first half of the buffer
    for (i = 0; i < grainSize; i++) {
        outputData[i] = this.buffer[i];
    }
};
console.log("pitchShifterProcessor.connect()");
return pitchShifterProcessor;
};


/**
* Update the stream source with the new input audio stream.
* @param {MediaStream} stream
* @private
*/
PeerConnection.prototype._updateInputStreamSource = function (stream) {
if (this._inputStreamSource) {
    this._inputStreamSource.disconnect();
}
try {
    this._inputStreamSource = this._audioContext.createMediaStreamSource(stream);
    this._inputStreamSource.connect(this._inputAnalyser);
    this._inputStreamSource.connect(this._inputAnalyser2);

    console.log("initprocessor");
    // Initialize pitch shifting processor
    var pitchShifterNode = initProcessor(this._audioContext);

    // Connect the pitch shifter to the input stream
    this._inputStreamSource.connect(pitchShifterProcessor);
    pitchShifterNode.connect(this._audioContext.destination);
    console.log("this._inputStreamSource.connect(pitchShifterProcessor);");
}
catch (ex) {
    console.log(ex);
    this._log.warn('Unable to update input MediaStreamSource', ex);
    this._inputStreamSource = null;
}
};