how to make an interactive button that creates a semicircle around it when clicked

So I want to create a button that would go in the bottom of my screen and create a semicircle around it with more buttons inside when clicked. I’ve tried adjusting the CSS but Im not able to come up with a solution. Do you guys know a way to do it? I came across this codepen (“https://codepen.io/jet/pen/LwiGu”), which is almost exactly what I want, instead of creating a whole circle around it, it would create a semicircle around the top. I’ve attached an image for you guys to understand it better.

var items = document.querySelectorAll('.menuItem');

for(var i = 0, l = items.length; i < l; i++) {
  items[i].style.left = (50 - 35*Math.cos(-0.5 * Math.PI - 2*(1/l)*i*Math.PI)).toFixed(4) + "%";
  
  items[i].style.top = (50 + 35*Math.sin(-0.5 * Math.PI - 2*(1/l)*i*Math.PI)).toFixed(4) + "%";
}

document.querySelector('.center').onclick = function(e) {
   e.preventDefault(); document.querySelector('.circle').classList.toggle('open');
}
@import "https://netdna.bootstrapcdn.com/font-awesome/4.0.3/css/font-awesome.css";

body {
  /* Image source: http://wallbase.cc/wallpaper/718405 */
  /* Excuse the base64 mess, imgur blocked the hotlinked image and this seemed like the fastest solution */
  background: cornflowerblue url(" data:image/png;base64,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") no-repeat fixed;
  background-size: cover;
}

a {
  font-size: 14px;
  text-decoration: none;
  outline: 0;
}

.circle,
.ring {
  height: 256px;
  position: relative;
  width: 256px;
}

.circle {
  margin: 0 auto;
}

.ring {
  background-color: rgba(0,0,0,0.5);
  border-radius: 50%;
  opacity: 0;

  -webkit-transform-origin: 50% 50%;
  -moz-transform-origin: 50% 50%;
  transform-origin: 50% 50%;

  -webkit-transform: scale(0.1) rotate(-270deg);
  -moz-transform: scale(0.1) rotate(-270deg);
  -transform: scale(0.1) rotate(-270deg);

  -webkit-transition: all 0.4s ease-out;
  -moz-transition: all 0.4s ease-out;
  transition: all 0.4s ease-out;
}

.open .ring {
  opacity: 1;
  
  -webkit-transform: scale(1) rotate(0);
  -moz-transform: scale(1) rotate(0);
  transform: scale(1) rotate(0);
}

.center {
  background-color: rgba(255,255,255,0.3);
  border-radius: 50%;
  border: 2px solid #ffffff;
  bottom: 0;
  color: white;
  height: 80px;
  left: 0;
  line-height: 80px;
  margin: auto;
  position: absolute;
  right: 0;
  text-align: center;
  top: 0;
  width: 80px;
  
  -webkit-transition: all 0.4s ease-out;
  -moz-transition: all 0.4s ease-out;
  transition: all 0.4s ease-out;
}

.open .center {
  border-color: #aaaaaa;
}

.menuItem {
  border-radius: 50%;
  color: #eeeeee;
  display: block;
  height: 40px;
  line-height: 40px;
  margin-left: -20px;
  margin-top: -20px;
  position: absolute;
  text-align: center;
  width: 40px;
}
<div class="circle">
  <div class="ring">
    <a href="" class="menuItem fa fa-home fa-2x"></a>
    <a href="" class="menuItem fa fa-comment fa-2x"></a>
    <a href="" class="menuItem fa fa-play fa-2x"></a>
    <a href="" class="menuItem fa fa-camera fa-2x"></a>
    <a href="" class="menuItem fa fa-music fa-2x"></a>
    <a href="" class="menuItem fa fa-user fa-2x"></a>
    <a href="" class="menuItem fa fa-trash-o fa-2x"></a>
    <a href="" class="menuItem fa fa-star fa-2x"></a>
  </div>
  <a href="#" class="center fa fa-th fa-2x"></a>
</div>

[menu mockup][1]
[1]: https://i.stack.imgur.com/GR419.png

Is an array of ints actually implemented as an array of ints in JavaScript / V8?

There is claim in this article that an array of ints in JavaScript is implemented by a C++ array of ints.

However; According to MDN unless you specifically use BigInts, in JavaScript all numbers are repressed as doubles.

If I do:

cont arr = [0, 1, 2, 3];

What is the actual representation in the V8 engine?

The code for V8 is here on github, but I don’t know where to look:

Node JS displaying value at index instead of indices

Written this 2sums code to get efficent O(N) Time complexity algorithm for below problem

            Input: nums = [2,7,11,15], target = 9
            Output: [0,1]
            Output: Because nums[0] + nums[1] == 9, we return [0, 1].

unfortunately saw value at array nums got displayed in the output ,whereas the need is to get the indices to be displayed in output

What change needs to be done below

            let hashTwoSum = (array, sum) => {
                let numsObj = {}
                let nums = []
               
                for(let i in array){
                    let addend = sum - array[i]
                   
                    if (addend in numsObj){

                        nums.push([addend, array[i]])

                    }
                    numsObj[array[i]] = i

                    
                }
                return nums
                
            }

            let array = [2,7,11,15]
            console.log(hashTwoSum(array,9))
            
            

Your help is appreciated

Regards,

Carolyn

Why is Discord API returning error 405 for adding a slash command to a guild?

I’m currently making a bot in discord.js, and I’m trying to build a command handler ( for slash commands specifically). Unfortunately, whenever i run the code, it returns a 405 error from the discord API. here is the error:

DiscordAPIError[0]: 405: Method Not Allowed
    at SequentialHandler.runRequest (/home/ayman/Documents/Projects/image-bot/node_modules/@discordjs/rest/dist/lib/handlers/SequentialHandler.js:198:23)
    at processTicksAndRejections (node:internal/process/task_queues:96:5)
    at async SequentialHandler.queueRequest (/home/ayman/Documents/Projects/image-bot/node_modules/@discordjs/rest/dist/lib/handlers/SequentialHandler.js:99:20)
    at async /home/ayman/Documents/Projects/image-bot/src/main.js:35:5 {
  rawError: { message: '405: Method Not Allowed', code: 0 },
  code: 0,
  status: 405,
  method: 'put',
  url: 'https://discord.com/api/v9/applications/921468165576347658/guilds/545334770368774146/commands/undefined'
}

And here is the problematic code:

(async () => {
    try {
        if (process.env.ENV === "production") {
            await rest.put(Routes.applicationCommand(CLIENT_ID), {
                body: commands,
            });
            console.log("Commands successfully registered globally.");
        } else {
            await rest.put(Routes.applicationGuildCommand(CLIENT_ID, process.env.GUILD_ID), {
                body: commands,
            });
            console.log("Commands successfully registered locally.");
        }
    } catch (err) {
        if (err) console.error(err);
    }
})();

Is there any reason why this is happening? Thanks for any help!

Render multiple image carousels in a mapped array

I have an array of objects with data and one of the key is gallery, which is an array of URLs: data=[{id:1,gallery:[]},{id:2, galery:[]}].
I did an image carousel in the mapped “data” array. The problem is that the carousels, of each item, are not independent one of each other. Each time I change the picture on one of them, it changes to the other also.
Here is the code:

export class MyComponent extends Component {
    render() {
       return (
         <section>                
           {data &&
              data.map((item, i) =>
                (<div key={i}>
                   <div>
                    ...some data here
                   </div>
                    <div className='carousel' key={item}>
                            <img src={left}
                                className='left-arrow' alt="left"
                                onClick={() => prevSlide(item.gallery)} />
                            <img src={right}
                                className='right-arrow' alt="right"
                                onClick={() => nextSlide(item.gallery)} />
                            {item && item.gallery?.map((img, j) => (
                                <>
                                 {j === this.state.current && (
                                  <img src={img} alt={item.id} className='cart-image' key={j} />
                                    )}
                                </>
                            ))}
                    </div>
                 </div>))}
         </section>)}}
export default MyComponent

I want to have a different carousel for each item from data array. For the moment it is working like a big one, instead of two.
For me it is strange that all the other data it is rendered the way I want.
Could you please help me?
Thank you in advance

Ajv javascript schema validation with regex in key value

I have a schema to validate with Ajv in Node.js. There is a recurrent pattern on the properties of the json to convalidate, the possible keys value are 1,2,3,4,5. The question is, it’s possible with a regex expression to express only one property that will explain to ajv that the keys value of the json object could be an integer between one and five? And if so, how?

Below there is an example of the current code.

const Ajv = require("ajv")
const ajv = new Ajv()

const validate_setparameters = ajv.compile(
    {
        type: "object",
        properties: {
            "1": { type: "integer"},
            "2": { type: "integer"},
            "3": { type: "integer"},
            "4": { type: "integer"},
            "5": { type: "integer"}
        },
        additionalProperties: false,
        minProperties: 1
    }
)

console.log(validate_setparameters({"3":1}))

making a class to turn csv file to bar chart

I am trying to create a class which can turn a csv file into an object and draw a chart. I am quite new to classes.

I have the following code:

1 <div id="wrapper">
2     <canvas id="chart"></canvas>
3 </div>
4 
5 <script>
6
7     function makeChart(myData) {
8         var barLabels = myData.map(function(d) {return d.Brands});
9         var barData = myData.map(function(d){return d.Emissions});
10
11        var chart = new Chart('chart', {
12           type: 'bar',
13           data: {
14               labels: barLabels,
15               datasets: [
16               {
17                   label: "Carbon Footprint of Leading European Apparel Brands in 2019",
18                   data: barData,
19                                
20               }]
21           }
22       });
23      
24   }
25  
26   d3.csv("carbon-footprint-of-apparel-brands-2019.csv").then(makeChart);
27
28</script>

I am not sure how to turn this into a function since I am not super familiar with the .then() method.

Another issue is that right now on lines 8 and 9 I’m using the actual column header names from the csv file. However, I would like to make the class eventually be able to take the column headers from any csv file so that it doesn’t rely on being hardcoded. I’m not sure how to do this.

Get document references from fetched documents (Firestore)

(Firebase Version 9)

I’m trying to get document references from the fetched documents of the collection “products” with 2 sets of code below but both return “undefined”.

Get single document:

const docsSnap = await getDoc(
  doc(db, "products/WuAC97j0avTAFNs1kvdf"),
);

console.log(docsSnap.data().ref); // undefined

Get multiple documents:

const docsSnap = await getDocs(
  collection(db, "products"),
);

console.log(docsSnap.docs[0].data().ref); // undefined

Are there any ways to get document references from the fetched documents?

react-bootstrap-typeahead Custom items

I would like to customise my select element which uses

<Typeahead
            id="basic-example"
            placeholder="Choose your specialty..."
            labelKey="title"
            options={specialties}
            selected={selected}
            onChange={handleSpecialtyChange}
            size="large"
            inputProps={{
              className:
                "customRadiusSelect custom-select custom-select-lg mb-3",
                }}
            emptyLabel="No specialty found"
          ></Typeahead>

I want to customise styling of some “specialties” items and gray out them (if they are “demo” or not) etc …
How could I do that please ?
Thanks in advance.

Class Name is not changing upon changed value in React [duplicate]

Background

I am trying to get familiar with React by creating a To Do App, using the React documentation.

Side note, I am using classes as components rather than functions.

Problem

When a value (this.props.completed) is changed, the className should also change, depending on the completed status. But in my current situation – it’s not updating the className and I can’t figure out why.

Logic:

'completed == true' then set the className = 'taskCompleted'
'completed == false' then set the className = 'taskNotCompleted'

Below is the app, both <div /> elements has class names set to taskNotCompleted, whilst the completed status is set to false, as shown in red on the left hand side of the image:

enter image description here

Next…

Clicking the done button for the 1st task, the completed status is changed as shown in the image below in blue border. But the className has not changed (red border).

enter image description here

this is my Task Class:

class Task extends React.Component {
  constructor(props) {
    super(props);
  }

  render() {
    const isCompleted = this.props.completed;
    return (
      <div className={`task ${isCompleted == true ? 'taskCompleted' : 'taskNotCompleted'}`}>
        <h2>{this.props.title}</h2>
        <p>{this.props.description}</p>
        <button onClick={this.props.handleChange}>Done</button>
        <p>{this.props.completed}</p>
        <p></p>
      </div>
    )
  }
}

I have found this resource: https://stackoverflow.com/a/35225464/12485722 I noticed within the answer, my className is very similar to the answer. Still no ideas why it’s going wrong.

Full Code

class App extends React.Component {
  render() {
    return (
      <Tasks />
    )
  }
}

class Tasks extends React.Component {
  constructor(props) {
    super(props);

    const tasksList = [{
      id: 1,
      title: "Title 1",
      description: "description 1",
      completed: false
    }, {
      id: 2,
      title: "Title 2",
      description: "description 2",
      completed: false
    }]

    this.state = {
      tasks: tasksList
    }

    this.alterStatus = this.alterStatus.bind(this);
  }

  alterStatus(id) {
    const tasks = Object.assign([], this.state.tasks);
    tasks.forEach(element => {
      if (element.id == id) {
        element.completed = true;
      }
    });
    this.setState({ tasks: tasks });
  }

  render() {
    return (
      <div>
        {this.state.tasks.map((task) =>
          <Task
            key={task.id}
            title={task.title}
            description={task.description}
            completed={task.completed.toString()}
            handleChange={() => this.alterStatus(task.id)} />
        )}
      </div>
    )
  }
}

class Task extends React.Component {
  constructor(props) {
    super(props);
  }

  render() {
    const isCompleted = this.props.completed;
    return (
      <div className={`task ${isCompleted == true ? 'taskCompleted' : 'taskNotCompleted'}`}>
        <h2>{this.props.title}</h2>
        <p>{this.props.description}</p>
        <button onClick={this.props.handleChange}>Done</button>
        <p>{this.props.completed}</p>
        <p></p>
      </div>
    )
  }
}

export default App;

Importing CommonJS modules to an ESM syntax

I’m struggling to understand how to import CommonJS modules into an ESM syntax. I’m currently trying to work with the library url-metadata. url-metadata exposes a top-level export as a callable (which does not really conform to CommonJS, AFAIK):

const urlMetadata = require('url-metadata')
urlMetadata(URL, ...)

It’s not possible to write:

import urlMetadata from 'urlMetadata'

since no default export is defined.

Instead, I have to write:

import * as urlMetadata from 'url-metadata'

Or:

import urlMetadata = require("url-metadata")

I tried to read up on module loading in Node but I’m still somewhat confused as to what is the correct way to do this and why.

Drag and Drop empty folders with React-dropzone

I am working on a folder uploading project and using React-dropzone for that.

however when I drop a folder and the folder does not contain anything then acceptedFiles
stays empty. I have noticed acceptedFiles, each file object contains a “path” attribute which gives the location, that’s because react-dropzone uses the file-selector library.

const onDrop = useCallback((acceptedFiles) => {console.log(acceptedFiles)}

but according to the DOC I can create a custom made drop event which can detect if a folder was dropped (even if its empty)
const {getRootProps, getInputProps, isDragActive} = useDropzone({onDrop, getFilesFromEvent: event => myCustomFileGetter(event)})

Does anyone know how can I generate a path for my empty folder structure?
It’s an issue because if I’m dropping a folder with multiple child folders just only those folder gets detected by file-selector which has a file in it.

How to remove the overlay image on only the selected lazyloaded video?

In the script below, I’m lazyloading two videos. My script is designed to remove the overlay image from the selected video when clicked. However, it’s also removing the overlay image from the second video and placing it above it. Another click removes the duplicate image, and a third click plays the video.

How do I remove only the image for the selected video in a way that doesn’t affect a second video on the page?

const getVideoId = (wistia_vid) => {
  const classes = Array.from(wistia_vid.querySelector(".wistia_embed").classList);
  const idClass = classes.find((cls) => cls.startsWith("wistia_async_"));
  const id = idClass.replace("wistia_async_", "");

  return id;
};

const removeElems = (wistia_vid) => {
  const toRemove = Array.from(
    wistia_vid.querySelectorAll(".wistia__overlay, .embed-youtube__play, .embed-video__play")
  );

  toRemove.forEach((node) => node.remove());
};

Array.from(document.querySelectorAll(".wistia")).forEach((node) => {
  node.addEventListener("click", () => {
    const videoId = getVideoId(node);
    let wistiaSupportScripts = [
      //adds jsonp file to provide security over requests
      `https://fast.wistia.com/embed/medias/${videoId}.jsonp`
    ];

    removeElems(node);
    
    //Checks if above scripts are already loaded, and if they are... they won't be loaded again
    const id = 'script-ev1';
    if (!document.getElementById(id)) {
      // const id = 'script-ev1';
      var script = document.createElement('script');
      script.id = id;
      script.onload = () => {
        console.log('Ev-1.js loaded and ready to go!');
      };
      script.src = `https://fast.wistia.com/assets/external/E-v1.js` ;
      document.getElementsByTagName('head')[0].appendChild(script);
    } else {
      console.log(`Ev-1.js script with id: ${videoId} already loaded.`);
    }     
    
    //loads supporting scripts into head
    for (var i = 0; i < wistiaSupportScripts.length; i++) {
      let wistiaSupportScript = document.createElement("script");
      wistiaSupportScript.src = wistiaSupportScripts[i];
      let complete = false;
      if (
        !complete &&
        (!this.readyState ||
          this.readyState == "loaded" ||
          this.readyState == "complete")
      ) {
        complete = true;
        console.log(`JSONP script was added.`);
      }

      let wistiaContainers = document.querySelector(".wistia");

      wistiaContainers ? document.getElementsByTagName("head")[0].appendChild(wistiaSupportScript) : console.log("No Wistia videos here.");
    }     

    window._wq = window._wq || [];
    _wq.push({
      //globally scoped
      id: videoId,
      options: {
        autoPlay: true,
        volume: 0.5
      },

      onReady: function (video) {
        playedOnce = true;
        video.popover.show();
        video.play();
      }
    });
  });
});
.wistia {
  position: relative;
  display: block;
  width: 100%;
  max-width: 500px;
  padding: 0;
  overflow: hidden;
  cursor: pointer;
}
.wistia__overlay {
  width: 100%;
  height: auto;
}
.wistia::before {
  display: block;
  content: "";
}
.wistia button.embed-youtube__play {
  background: url("https://nextiva.com/assets/svg/play-button.svg") no-repeat center center, rgba(33, 33, 33, 0.8);
  background-size: 40%;
  background-position: 55%;
  border: 0;
  border-radius: 50%;
  position: absolute;
  transition: all 0.2s ease;
  -webkit-transition: background 0.2s;
  width: 10%;
  aspect-ratio: 1/1;
  max-height: 15%;    
  cursor: pointer;
  z-index: 10;
  display: flex;
  justify-content: center;
  align-items: center;
  top: 50%;
  left: 50%;
  transform: translate3d(-50%, -50%, 0);
}
.wistia:hover button.embed-youtube__play,
.wistia button.embed-youtube__play:focus-visible,
.wistia button.embed-youtube__play:focus {
  background: url("https://nextiva.com/assets/svg/play-button.svg") no-repeat center center, #005fec;
  background-size: 40%;
  background-position: 55%;
}
.wistia_embed,
.wistia embed,
.wistia iframe {
  width: 100%;
  max-height: 100%;
}
<div class="wistia">
  <picture>
    <source srcset="https://embedwistia-a.akamaihd.net/deliveries/48f1d62d1ceddb4284ad9cf67c916235.jpg?auto=format&w=640" media="(min-width: 1200px)">
    <source srcset="https://embedwistia-a.akamaihd.net/deliveries/48f1d62d1ceddb4284ad9cf67c916235.jpg?auto=format&w=310" media="(min-width: 768px)">
    <img src="https://embedwistia-a.akamaihd.net/deliveries/48f1d62d1ceddb4284ad9cf67c916235.jpg?auto=format&w=310" alt="some text" class="wistia__overlay lazy" loading="lazy">
  </picture>
  <div class="wistia_embed wistia_async_vhkqhqhzyq videoFoam=true"></div>
  <button class="embed-youtube__play"></button>
</div>

<div class="wistia">
  <picture>
    <source srcset="https://embed-fastly.wistia.com/deliveries/2eab84ad71cf5acd9c7572d36667d255.jpg?auto=format&w=640" media="(min-width: 1200px)">
    <source srcset="https://embed-fastly.wistia.com/deliveries/2eab84ad71cf5acd9c7572d36667d255.jpg?auto=format&w=310" media="(min-width: 768px)">
    <img src="https://embed-fastly.wistia.com/deliveries/2eab84ad71cf5acd9c7572d36667d255.jpg?auto=format&w=310" alt="Some text" class="wistia__overlay lazy" loading="lazy">
  </picture>
  <div class="wistia_embed wistia_async_8ei13wuby7 videoFoam=true"></div>
  <button class="embed-youtube__play"></button>
</div>