How to get mouse position with Rete.js

I am looking for a way to add a listener to my editor so that when I hover it with my mouse, I can get my the position of my mouse. I am hoping that by doing so it would give me the coordinate of my mouse with the referencial of the editor wich places the center (0,0) in the middle and therefore makes it possible to have negative coordinates.

I saw that it was possible with Rete.js v1 through with the mouseMove event and something about getting the mouse position through area.view but I cannot really find anything working for REte.js V2.

Change Cursoroverstyle for Bullets in Amcharts5 after clicking on button

I have created a MapPointSeries with bullets via

var pointSeries = chart.series.push(am5map.MapPointSeries.new(root, {
        latitudeField: "latitude",
        longitudeField: "longitude",
      }));
      pointSeries.bullets.push(function () {
        return am5.Bullet.new(root, {
          sprite: am5.Circle.new(root, {
            radius: 3,
            templateField: "bulletSettings"
          },bulletTemplate,
        });


var bulletTemplate = am5.Template.new({
      fill: am5.color(0x000000),
      cursorOverStyle: "pointer"
    });

This works fine. However, now I want to change this cursorOverStyle to default, when a button is clicked and I just cannot seem to make it work. I thought it must be the easiest way to iterate over the bullets in the pointSeries and change the cursorOverStyle attribute or attach a new template, but I fail to implement both solutions

Spritesheet and map not working in kaboom.js when building dist folder. Why does it not the files when I try to deploy?

I’m building a game in kaboom.js following the a freecodecamp video, but when I try to deploy it I get a ReferenceError: Can’t find variable: Co in the index.js file in the dist folder. I think the problem is that the loadSprite function doesn’t find the spritesheet and map in build and I’ve spent an entire day trying to resolve it, but nothing.enter image description here

I tried searching everywhere on google and on forum. I’ve tried hundreds of deploys on GitHub pages and netlify. And I’ve tried redoing the project and changing folders, but nothing.

A working searchbar on a github pages website

I am making a website that contains a searchbar. In that searchbar you can search the titles of the different pages on the website. The code below shows an example on how this works:

const f = document.getElementById('form');
const q = document.getElementById('query');
const site = 'http://localhost:3001/';

function submitted(event) {
  event.preventDefault();
  if (q.value.toLowerCase() === "home" ) {
    const winHome = window.open(site, '_blank');
    winHome.focus();
  } else { 
    const url = site + q.value.toLowerCase();
    const win = window.open(url, '_blank');
    win.focus();
  } 
}

let availableKeywords = {
  'this is an example title',
  'this is also an example title'
}

const resultsBox = document.querySelector(".result-box");
const inputBox = document.getElementById("query");
  
inputBox.onkeyup = search;
  
function display(result){
  const content = result.map((list)=>{
    return "<li onclick=selectInput(this)>" + list + "</li>";
  });

  resultsBox.innerHTML = "<ul>" + content.join('') + "</ul>";
}
  
function selectInput(list){
  inputBox.value = list.innerHTML;
  resultsBox.innerHTML = '';
}

function search(){
  let result = [];
  let input = inputBox.value;
  if(input.length){
    result = availableKeywords[chosenLanguage].filter((keyword)=>{
      return keyword.toLowerCase().includes(input.toLowerCase());
    });
    console.log(result);
  }
  display(result);

  if(!result.length){
    resultsBox.innerHTML = '';
  }
}
<form id="form" role="search">
           <input type="text" id="query" name="q" placeholder="Search Here..." aria-label="Search through site content" autocomplete="off">
           <button>
             <span class="icon">
                <ion-icon name="search-outline"></ion-icon>
             </span>
           </button>
         </form>
         <div class="result-box">
         </div>

Then in a file called “main.js”, that is outside the “public” folder, i made it so that the link that got searched after using the searchbar led to the desired page:

const express = require("express");
const app = express();
const port = 3001;
const path = require('path');

app.use(express.static(__dirname + '/public'));

app.get("/this%20is%20an%20example%20title", function (req, res) {
  res.sendFile("example.html",{ root: path.join(__dirname, './public/pages') });
});

app.get("/this%20is%20also%20an%20example%20title", function (req, res) {
  res.sendFile("anotherExample.html",{ root: path.join(__dirname, './public/pages') });
});

app.get('*', function(req, res){
  res.sendFile("error404.html",{ root: path.join(__dirname, './public/pages') });
});

I want to put the website online using github pages. The url then changes from “localHost:3001/this%20is%20an%20example%20title” to “https://[my github name].github.io/[name of project]/public/pages/this%20is%20an%20example%20title”

This url however, gives a 404 page. I have changed the const site from “http://localhost:3001/” to “https://[my github name].github.io/[name of project]/public/pages/” but that didnt seem to work. When i use the search bar it still searches the localHost url. How do i make it so the new url also sends the user to the desired html page?

LightningChart JS syncing 2 charts axis with mouse scroll, user trying to zoom in, and making the axis same oriantations

I am trying to create a component that sync between 2 types of charts, the first is a heatmap the second is a bar chart / segments chart / rectangle charts, will end up with the one that works the best.

I must make them look like this:
so that the Y axis will be aligned with the same values on the same line
the same grid

same when the user zoom in they should stay together because this resembels the depth of the data.

In order to show the same data for the same depth aligned together for both charts

enter image description here

when I tried to do it this is the result which is not good
enter image description here

  1. problem 1 the axis are not aligned because the lables oriantation are not the same
  2. problem 3 the values of the axises are not aligned they suppose to have the same depth but they dont even after using the sync function of the axis.
  3. For the right chart, the axises doesnt show the same nubmers as the left chart start from the same (0,0) point and I cant figure out how to fix this. the direction of the axis is bad because it grows towards down and not up like on the left chart.

I used this function to sync between the axises

    synchronizeAxisIntervals(axisPSD, axisRMS);

but it does not work properly,when the user want to scroll to zoom-in,it does not work.

code to regenerate in reactjs

createRMSGraph.ts

import React from 'react';
import { lc } from './lightningChartObject';
import { Axis, AxisScrollStrategies, ColorHEX, SolidFill, Themes } from '@arction/lcjs';

const createRMSGraph = (divRef: string): Axis => {
  const theme = Themes.light;
  const BackgroundFill = new SolidFill({
    color: ColorHEX('#ffffff'),
  });
  const chart = lc
    .ChartXY({
      container: divRef,
      theme: theme,
      defaultAxisY: {  opposite : true },
    })
    .setSeriesBackgroundFillStyle(BackgroundFill)
    .setTitle('');
  console.log(chart.getDefaultAxisX());
  chart.getDefaultAxisX().setTitle('X Axis');
  chart.getDefaultAxisY().setTitle('Y Axis');

  const segmentSeries = chart
    .addSegmentSeries()
    .setDefaultStyle((figure) => figure.setStrokeStyle((stroke) => stroke.setThickness(20)));

  const histogramData = [{ x: 25.01, y: 19.52317495 }];
  histogramData.forEach((point) => {
    segmentSeries.add({ startX: point.x, startY: 0, endX: point.x, endY: point.y });
  });

  return chart.getDefaultAxisX();
};

export { createRMSGraph };

createPSDGraph.ts

import React from 'react';
import { lc } from './lightningChartObject';
import { Axis, ColorHEX, SolidFill, Themes } from '@arction/lcjs';

const createPSDGraph = (divRef: string): Axis => {
  //init
  const theme = Themes.light;
  const BackgroundFill = new SolidFill({
    color: ColorHEX('#ffffff'),
  });
  const chart = lc
    .ChartXY({
      container: divRef,
      theme: theme,
    })
    .setSeriesBackgroundFillStyle(BackgroundFill)
    .setTitle('');

  chart.getDefaultAxisX().setTitle('X Axis');
  // chart.addAxisX({ type: 'logarithmic', base: 10 }).setTitle('X Axis');
  chart.getDefaultAxisY().setTitle('Y Axis');

  // add heatmap on top of
  chart.addHeatmapGridSeries({
    columns: 901,
    rows: 50,
  });
  return chart.getDefaultAxisY();
};

export { createPSDGraph };

MERGraphs.tsx

import { Box } from '@mui/system';
import React, { useEffect, useId, useState } from 'react';
import { createPSDGraph } from './utils/createPSDGraph';
import { createRMSGraph } from './utils/createRMSGraph';
import { synchronizeAxisIntervals } from '@arction/lcjs';

const MERGraphs = () => {
  const id = useId();
  useEffect(() => {
    const axisPSD = createPSDGraph(`${id}-PSD`);
    const axisRMS = createRMSGraph(`${id}-RMS`);
    synchronizeAxisIntervals(axisPSD, axisRMS);
  }, []);

  return (
    <Box sx={{ display: 'flex', width: '1000px', height: '500px' }}>
      <Box id={`${id}-PSD`} sx={{ width: '100%' }}></Box>
      <Box id={`${id}-RMS`} sx={{ width: '100%' , rotate: "90deg" }}></Box>
    </Box>
  );
};

export { MERGraphs };

React level select drop down menu with unknown key pair dynamic values

I want to make a select dropdown menu with every option being depedent from the previous one. The data I am retrieving from database have that kind of form

> {"category_1": 
{"sub_1":{"price":3},
"sub2":{"price":2}},
"category_2":{"sub_1":{"price":2}," sub2":{"price":2}}}

The problem is that the depth of the object is dynamic and I can’t figure out how to make the select dropdown with useState values because I can’t know from the beginning how many attributes the data will have. I use a recursive function to flatten the object but I am stuck how to use the data in a select menu after that. Here is my code with the form where I want to display my data. The data are the business props

import flattenObj from "../hooks/useRecursion";

const BusinessForm = ({business}) => {





const arr = flattenObj(business.options)

console.log(arr)
return ( 
    <div>
        <h5>
            this is a businessform for {business.business_name}
        </h5>
       
       
        {arr.map((o)=>(
            <p>{o[0]}</p>
        ))
        
        }
        
           
       
    </div>
 );
}



export default BusinessForm;

and here is my recursive function that returns an array

const flattenObj = (ob) => {
 
    // The object which contains the
    // final result
    let result = {};
    let arr = []                            
    
    
    for (const i in ob) {
    //    console.log(i)
       
      
        
        // We check the type of the i using
        // typeof() function and recursively
        // call the function again
        if ((typeof ob[i]) === 'object' && !Array.isArray(ob[i])) {
            const temp = flattenObj(ob[i]);
            
            // for (const j in temp) {
 
                // Store temp in result
                // result[i + '.' + j] = temp[j];  
                
                
                //{category_1:{sub_1:{"price":3},sub_2:{"price":2}},category_2:{sub_1:{"price":2},sub_2:{"price":3}}}
                arr.push([i,temp])
                
                // loop through the object "ob"
               
                   
                
               // }
        }
 
        // Else store ob[i] in result directly
        else {
            // result[i]=ob[i]
            arr.push(ob[i])
            
        }
    }
    
    return arr;
    
};
export default flattenObj;

Any thougths on how can this be done?

Javascript scroll bars on Legends that are too large

// The MIT License (MIT)

// Copyright (c) 2017 Zalando SE

// Permission is hereby granted, free of charge, to any person obtaining a copy
// of this software and associated documentation files (the "Software"), to deal
// in the Software without restriction, including without limitation the rights
// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
// copies of the Software, and to permit persons to whom the Software is
// furnished to do so, subject to the following conditions:

// The above copyright notice and this permission notice shall be included in
// all copies or substantial portions of the Software.

// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
// THE SOFTWARE.


function radar_visualization(config) {

  // custom random number generator, to make random sequence reproducible
  // source: https://stackoverflow.com/questions/521295
  var seed = 42;
  function random() {
    var x = Math.sin(seed++) * 10000;
    return x - Math.floor(x);
  }

  function random_between(min, max) {
    return min + random() * (max - min);
  }

  function normal_between(min, max) {
    return min + (random() + random()) * 0.5 * (max - min);
  }

  // radial_min / radial_max are multiples of PI
    const quadrants = [
    { radial_min: 0, radial_max: 0.5, factor_x: 1, factor_y: 1 },
    { radial_min: 0.5, radial_max: 1, factor_x: -1, factor_y: 1 },
    { radial_min: -1, radial_max: -0.5, factor_x: -1, factor_y: -1 },
    { radial_min: -0.5, radial_max: 0, factor_x: 1, factor_y: -1 }
  ];

  const rings = [
    { radius: 130 },
    { radius: 220 },
    { radius: 310 },
    { radius: 400 }
  ];

  const title_offset =
    { x: -675, y: -420 };

  const footer_offset =
    { x: -675, y: 420 };

  const legend_offset = [
    { x: 450, y: 90 },
    { x: -675, y: 90 },
    { x: -675, y: -310 },
    { x: 450, y: -310 }
  ];

  function polar(cartesian) {
    var x = cartesian.x;
    var y = cartesian.y;
    return {
      t: Math.atan2(y, x),
      r: Math.sqrt(x * x + y * y)
    }
  }

  function cartesian(polar) {
    return {
      x: polar.r * Math.cos(polar.t),
      y: polar.r * Math.sin(polar.t)
    }
  }

  function bounded_interval(value, min, max) {
    var low = Math.min(min, max);
    var high = Math.max(min, max);
    return Math.min(Math.max(value, low), high);
  }

  function bounded_ring(polar, r_min, r_max) {
    return {
      t: polar.t,
      r: bounded_interval(polar.r, r_min, r_max)
    }
  }

  function bounded_box(point, min, max) {
    return {
      x: bounded_interval(point.x, min.x, max.x),
      y: bounded_interval(point.y, min.y, max.y)
    }
  }

  function segment(quadrant, ring) {
    var polar_min = {
      t: quadrants[quadrant].radial_min * Math.PI,
      r: ring === 0 ? 30 : rings[ring - 1].radius
    };
    var polar_max = {
      t: quadrants[quadrant].radial_max * Math.PI,
      r: rings[ring].radius
    };
    var cartesian_min = {
      x: 15 * quadrants[quadrant].factor_x,
      y: 15 * quadrants[quadrant].factor_y
    };
    var cartesian_max = {
      x: rings[3].radius * quadrants[quadrant].factor_x,
      y: rings[3].radius * quadrants[quadrant].factor_y
    };
    return {
      clipx: function(d) {
        var c = bounded_box(d, cartesian_min, cartesian_max);
        var p = bounded_ring(polar(c), polar_min.r + 15, polar_max.r - 15);
        d.x = cartesian(p).x; // adjust data too!
        return d.x;
      },
      clipy: function(d) {
        var c = bounded_box(d, cartesian_min, cartesian_max);
        var p = bounded_ring(polar(c), polar_min.r + 15, polar_max.r - 15);
        d.y = cartesian(p).y; // adjust data too!
        return d.y;
      },
      random: function() {
        return cartesian({
          t: random_between(polar_min.t, polar_max.t),
          r: normal_between(polar_min.r, polar_max.r)
        });
      }
    }
  }

  // position each entry randomly in its segment
  for (var i = 0; i < config.entries.length; i++) {
    var entry = config.entries[i];
    entry.segment = segment(entry.quadrant, entry.ring);
    var point = entry.segment.random();
    entry.x = point.x;
    entry.y = point.y;
    entry.color = entry.active || config.print_layout ?
      config.rings[entry.ring].color : config.colors.inactive;
  }

  // partition entries according to segments
  var segmented = new Array(4);
  for (var quadrant = 0; quadrant < 4; quadrant++) {
    segmented[quadrant] = new Array(4);
    for (var ring = 0; ring < 4; ring++) {
      segmented[quadrant][ring] = [];
    }
  }
  for (var i=0; i<config.entries.length; i++) {
    var entry = config.entries[i];
    segmented[entry.quadrant][entry.ring].push(entry);
  }

  // assign unique sequential id to each entry
  var id = 1;
  for (var quadrant of [2,3,1,0]) {
    for (var ring = 0; ring < 4; ring++) {
      var entries = segmented[quadrant][ring];
      entries.sort(function(a,b) { return a.label.localeCompare(b.label); })
      for (var i=0; i<entries.length; i++) {
        entries[i].id = "" + id++;
      }
    }
  }

  function translate(x, y) {
    return "translate(" + x + "," + y + ")";
  }

  function viewbox(quadrant) {
    return [
      Math.max(0, quadrants[quadrant].factor_x * 400) - 420,
      Math.max(0, quadrants[quadrant].factor_y * 400) - 420,
      440,
      440
    ].join(" ");
  }

  var svg = d3.select("svg#" + config.svg_id)
    .style("background-color", config.colors.background)
    .attr("width", config.width)
    .attr("height", config.height);

  var radar = svg.append("g");
  if ("zoomed_quadrant" in config) {
    svg.attr("viewBox", viewbox(config.zoomed_quadrant));
  } else {
    radar.attr("transform", translate(config.width / 2, config.height / 2));
  }

  var grid = radar.append("g");

  // draw grid lines
  grid.append("line")
    .attr("x1", 0).attr("y1", -400)
    .attr("x2", 0).attr("y2", 400)
    .style("stroke", config.colors.grid)
    .style("stroke-width", 1);
  grid.append("line")
    .attr("x1", -400).attr("y1", 0)
    .attr("x2", 400).attr("y2", 0)
    .style("stroke", config.colors.grid)
    .style("stroke-width", 1);

  // background color. Usage `.attr("filter", "url(#solid)")`
  // SOURCE: https://stackoverflow.com/a/31013492/2609980
  var defs = grid.append("defs");
  var filter = defs.append("filter")
    .attr("x", 0)
    .attr("y", 0)
    .attr("width", 1)
    .attr("height", 1)
    .attr("id", "solid");
  filter.append("feFlood")
    .attr("flood-color", "rgb(0, 0, 0, 0.8)");
  filter.append("feComposite")
    .attr("in", "SourceGraphic");

  // draw rings
  for (var i = 0; i < rings.length; i++) {
    grid.append("circle")
      .attr("cx", 0)
      .attr("cy", 0)
      .attr("r", rings[i].radius)
      .style("fill", "none")
      .style("stroke", config.colors.grid)
      .style("stroke-width", 1);
    if (config.print_layout) {
      grid.append("text")
        .text(config.rings[i].name)
        .attr("y", -rings[i].radius + 62)
        .attr("text-anchor", "middle")
        .style("fill", config.rings[i].color)
        .style("opacity", 0.35)
        .style("font-family", "Arial, Helvetica")
        .style("font-size", "42px")
        .style("font-weight", "bold")
        .style("pointer-events", "none")
        .style("user-select", "none");
    }
  }

  function legend_transform(quadrant, ring, index=null) {
    var dx = ring < 2 ? 0 : 140;
    var dy = (index == null ? -16 : index * 12);
    if (ring % 2 === 1) {
      dy = dy + 36 + segmented[quadrant][ring-1].length * 12;
    }
    return translate(
      legend_offset[quadrant].x + dx,
      legend_offset[quadrant].y + dy
    );
  }

  // draw title and legend (only in print layout)
  if (config.print_layout) {

    // title
    radar.append("text")
      .attr("transform", translate(title_offset.x, title_offset.y))
      .text(config.title)
      .style("font-family", "Arial, Helvetica")
      .style("font-size", "30")
      .style("font-weight", "bold")

    // date
    radar
      .append("text")
      .attr("transform", translate(title_offset.x, title_offset.y + 20))
      .text(config.date || "")
      .style("font-family", "Arial, Helvetica")
      .style("font-size", "14")
      .style("fill", "#999")

    // legend
    var legend = radar.append("g");
    for (var quadrant = 0; quadrant < 4; quadrant++) {
      legend.append("text")
        .attr("transform", translate(
          legend_offset[quadrant].x,
          legend_offset[quadrant].y - 45
        ))
        .text(config.quadrants[quadrant].name)
        .style("font-family", "Arial, Helvetica")
        .style("font-size", "18px")
        .style("font-weight", "bold");
      for (var ring = 0; ring < 4; ring++) {
        legend.append("text")
          .attr("transform", legend_transform(quadrant, ring))
          .text(config.rings[ring].name)
          .style("font-family", "Arial, Helvetica")
          .style("font-size", "12px")
          .style("font-weight", "bold")
          .style("fill", config.rings[ring].color);
        legend.selectAll(".legend" + quadrant + ring)
          .data(segmented[quadrant][ring])
          .enter()
            .append("a")
              .attr("href", function (d, i) {
                 return d.link ? d.link : "#"; // stay on same page if no link was provided
              })
              // Add a target if (and only if) there is a link and we want new tabs
              .attr("target", function (d, i) {
                 return (d.link && config.links_in_new_tabs) ? "_blank" : null;
              })
            .append("text")
              .attr("transform", function(d, i) { return legend_transform(quadrant, ring, i); })
              .attr("class", "legend" + quadrant + ring)
              .attr("id", function(d, i) { return "legendItem" + d.id; })
              .text(function(d, i) { return d.id + ". " + d.label; })
              .style("font-family", "Arial, Helvetica")
              .style("font-size", "11px")
              .on("mouseover", function(d) { showBubble(d); highlightLegendItem(d); })
              .on("mouseout", function(d) { hideBubble(d); unhighlightLegendItem(d); });
      }
    }
  }

  // layer for entries
  var rink = radar.append("g")
    .attr("id", "rink");

  // rollover bubble (on top of everything else)
  var bubble = radar.append("g")
    .attr("id", "bubble")
    .attr("x", 0)
    .attr("y", 0)
    .style("opacity", 0)
    .style("pointer-events", "none")
    .style("user-select", "none");
  bubble.append("rect")
    .attr("rx", 4)
    .attr("ry", 4)
    .style("fill", "#333");
  bubble.append("text")
    .style("font-family", "sans-serif")
    .style("font-size", "10px")
    .style("fill", "#fff");
  bubble.append("path")
    .attr("d", "M 0,0 10,0 5,8 z")
    .style("fill", "#333");

  function showBubble(d) {
    if (d.active || config.print_layout) {
      var tooltip = d3.select("#bubble text")
        .text(d.label);
      var bbox = tooltip.node().getBBox();
      d3.select("#bubble")
        .attr("transform", translate(d.x - bbox.width / 2, d.y - 16))
        .style("opacity", 0.8);
      d3.select("#bubble rect")
        .attr("x", -5)
        .attr("y", -bbox.height)
        .attr("width", bbox.width + 10)
        .attr("height", bbox.height + 4);
      d3.select("#bubble path")
        .attr("transform", translate(bbox.width / 2 - 5, 3));
    }
  }

  function hideBubble(d) {
    var bubble = d3.select("#bubble")
      .attr("transform", translate(0,0))
      .style("opacity", 0);
  }

  function highlightLegendItem(d) {
    var legendItem = document.getElementById("legendItem" + d.id);
    legendItem.setAttribute("filter", "url(#solid)");
    legendItem.setAttribute("fill", "white");
  }

  function unhighlightLegendItem(d) {
    var legendItem = document.getElementById("legendItem" + d.id);
    legendItem.removeAttribute("filter");
    legendItem.removeAttribute("fill");
  }

  // draw blips on radar
  var blips = rink.selectAll(".blip")
    .data(config.entries)
    .enter()
      .append("g")
        .attr("class", "blip")
        .attr("transform", function(d, i) { return legend_transform(d.quadrant, d.ring, i); })
        .on("mouseover", function(d) { showBubble(d); highlightLegendItem(d); })
        .on("mouseout", function(d) { hideBubble(d); unhighlightLegendItem(d); });

  // configure each blip
  blips.each(function(d) {
    var blip = d3.select(this);

    // blip link
    if (d.active && Object.prototype.hasOwnProperty.call(d, "link") && d.link) {
      blip = blip.append("a")
        .attr("xlink:href", d.link);

      if (config.links_in_new_tabs) {
        blip.attr("target", "_blank");
      }
    }

    // blip shape
    if (d.moved > 0) {
      blip.append("path")
        .attr("d", "M -11,5 11,5 0,-13 z") // triangle pointing up
        .style("fill", d.color);
    } else if (d.moved < 0) {
      blip.append("path")
        .attr("d", "M -11,-5 11,-5 0,13 z") // triangle pointing down
        .style("fill", d.color);
    } else {
      blip.append("circle")
        .attr("r", 9)
        .attr("fill", d.color);
    }

    // blip text
    if (d.active || config.print_layout) {
      var blip_text = config.print_layout ? d.id : d.label.match(/[a-z]/i);
      blip.append("text")
        .text(blip_text)
        .attr("y", 3)
        .attr("text-anchor", "middle")
        .style("fill", "#fff")
        .style("font-family", "Arial, Helvetica")
        .style("font-size", function(d) { return blip_text.length > 2 ? "8px" : "9px"; })
        .style("pointer-events", "none")
        .style("user-select", "none");
    }
  });

  // make sure that blips stay inside their segment
  function ticked() {
    blips.attr("transform", function(d) {
      return translate(d.segment.clipx(d), d.segment.clipy(d));
    })
  }

  // distribute blips, while avoiding collisions
  d3.forceSimulation()
    .nodes(config.entries)
    .velocityDecay(0.19) // magic number (found by experimentation)
    .force("collision", d3.forceCollide().radius(12).strength(0.85))
    .on("tick", ticked);
}

So i’m using the basic opensource Zalando radar to display data. I have python knowledge so i have made changes to the python side of the code to make the radar accept my data format.

Where i’m struggling is the JavaScript. I have no JS knowledge so have only been following other guides / fixes but to no avail.

What i’m trying to do is stop the legends from expanding into one another (each quadrant has a legend showing each data point in the quadrant) some of my quadrants are quite expansive in data thus the legend ends up being too long and overlapping the legend below.

I was hoping i could limit the size of the legend and then add some scroll bars to those that exceed the given size.

for (var ring = 0; ring < 4; ring++) {
    legend.append("text")
        .attr("transform", legend_transform(quadrant, ring))
        .text(function(d, i) {
            return d.label; // Retain original label
        })
        .style("font-family", "Arial, Helvetica")
        .style("font-size", "12px")
        .style("font-weight", "bold")
        .style("fill", config.rings[ring].color)
        .style("max-height", "50px") // Adjust max-height as needed
        .style("overflow", "hidden")
        .style("text-overflow", "ellipsis")
        .style("line-height", "1em");

I have tried just limiting the size of the legend but that has not been successful
my attempts have either led to no change in the display, or the whole thing falling over dramatically and no information being displayed at all

How to interpret the property define in function in javascript?

In javascript, you can define a bunch of variable in a function,
1, How to check if there is a specific property in function in JavaScript?
2, What is the different between property define in a function and define by dot notation?

Here is an example in javascript
1, how do i know whether ‘age’ is in function(also an object in javascript) or not?
2, what’s the different between these 2 variable “age” and “say”?

    function Foo() {
        this.age = 18;
    }

    Foo.say = 'hi'

    console.log(Foo.prototype.hasOwnProperty('age')); // false
    console.log(Foo.prototype.hasOwnProperty('say')); // false
    console.log(Foo.hasOwnProperty('age')); // false
    console.log(Foo.hasOwnProperty('say')); // ture

    let o = new Foo();
    console.log(o.age, o.say); // 18 undefined

How can I make an interactive push notification in React Native?

at work I was given a task to make push notifications for our application more interactive. Application in react native. At first I did everything using the Notifee library, but there are just push buttons and two buttons, and now I need to make sure that the buttons can be styled, arranged in different ways, insert data into them, draw an additional interface and insert a progress bar from the back. As an example, they gave notifications from Yandex Go and we need to implement something similar here. Tell me how to do this, which direction to dig in, and whether this is generally feasible in react native. The main problem for me is that I don’t understand how to draw and style it.

I tried the notifee library. I expect a result approximately as in the photo enter image description here

How to save and load customized page in GrapeJS

I created a simple page builder by following GrapeJS Docs and it is working well.
I think there need to be 2 functions to save and load the generated page.
How can I do this?

const editor = grapesjs.init({
  // Indicate where to init the editor. You can also pass an HTMLElement
  container: '#gjs',
  // Get the content for the canvas directly from the element
  // As an alternative we could use: `components: '<h1>Hello World Component!</h1>'`,
  fromElement: true,
  // Size of the editor
  height: '300px',
  width: 'auto',
  // Disable the storage manager for the moment
  storageManager: false,
  // Avoid any default panel
  panels: { defaults: [] },
  blockManager: { },
  layerManager: { },
  deviceManager: { },
  selectorManager: { },
  styleManager: { },
  storageManager: { }
});

WordPress – swiper carousel cause unwanted horizontal scroll

I have an elementor website where I will need to insert some different carousels of images inside the post content. Initially I was using elementor and I’ve made a template for each carousle I will need. At the moment I’ve decided to switch to a shortcode that will use the included swiper of elementor and create a carousel. This is the code

function custom_carousel_shortcode($atts) {
    
    $atts = shortcode_atts(
        array(
            'ids' => '',
        ),
        $atts,
        'custom-carousel'
    );

    $image_ids = explode(',', $atts['ids']);

    $carousel_html = '';

    foreach ($image_ids as $image_id) {
        $image_url = wp_get_attachment_image_url($image_id, 'full');
        if ($image_url) {
            $carousel_html .= '<div class="swiper-slide"><img src="' . esc_url($image_url) . '" class="swiper-slide-img" /></div>';
        }
    }

    $output = '<div class="elementor-widget-container"><div class="elementor-element elementor-widget elementor-image-carousel"><div id="swiper_init" class="swiper-container"><div class="swiper-wrapper">' . $carousel_html . '</div><div class="swiper-pagination"></div><div class="swiper-button-prev"></div><div class="swiper-button-next"></div></div></div></div>';

    $output .= '<script>
    jQuery(document).ready(function($) {
        $(window).on("load", function() {
            console.log(elementorFrontend.utils);
            let mySwiper;
            const swiperElement = $(".swiper-container");
            const swiperConfig = {
                //centeredSlides: true,
                loop: false,
                pagination: {
                    el: ".swiper-pagination"
                },
                navigation: {
                    nextEl: ".swiper-button-next",
                    prevEl: ".swiper-button-prev"
                },
                //autoplay: {
                //  delay: 5000
                //},
                //slidesPerView: 1,
                //slidesPerGroup: 1,
            };
            //
            if (typeof elementorFrontend.utils.swiper === "function") {
                new elementorFrontend.utils.swiper(swiperElement, swiperConfig).then((newSwiperInstance) => {
                    
                    console.log("New Swiper instance is ready: ", newSwiperInstance);
                    mySwiper = newSwiperInstance;
                });
            } else if (typeof Swiper === "function") {
                console.log("Swiper global variable is ready, create a new instance: ", Swiper);
                mySwiper = new Swiper(".swiper-container", swiperConfig);
            } else {
                console.error("Swiper initialization failed.");
            }
        });
    });
    </script>';

    return $output;
}
add_shortcode('custom-carousel', 'custom_carousel_shortcode');

At the moment swiper will be loaded correctly where I’m testing it and is able to get the images using their id. My main problem at the moment is with the layout. I’ve noticed that I’m unable to have only a single slide displayed and other slides that are part of the carousel will be positioned on the left or right side of the screen, this will cause an horizontal scroll. How I can fix this and get a carousel that will work like the carousel widget of elementor? Do i need to adjust swiper settings or to use CSS?

Vite build project and widgets into separate bundles

I need your help/advice on how to configure Rollup in Vite the right way to produce the desired build bundles.

I already have an up-and-running Vite config which builds the Vue project.
Part of config is

  build: {
    rollupOptions: {
      output: {
        manualChunks: {
          mapboxGl: ['mapbox-gl']
        }
      }
    },

    sourcemap: 'hidden',
  },

  plugins: [
    vue(),
    svgLoader()
  ],

The project structure is simple ->

.
├── index.html
├── public
├── src/
│   ├── main.ts
│   └── components/
│       └── ... *.vue and ts files
└── ...

I have added folder widgets to src where will live standalone widgets.
I want to get in the dist folder separately builder bundles like:

.
└── dist/
    ├── index.html
    ├── assets/
    │   └── ...everything related to the project
    └── widgets/
        └── every widgets folder with built bundle + CSS

Currently, I have the result without widgets folder.
I have experimented a bit with rollupOptions and got this config:

 build: {
    rollupOptions: {
      input: {
        index: fileURLToPath(new URL('src/main.ts', import.meta.url)),
        ...Object.fromEntries(
            globSync('src/widgets/**/*.ts').map(file => [
              // This remove `src/` as well as the file extension from each
              // file, so e.g. src/nested/foo.js becomes nested/foo
              relative(
                  'src',
                  file.slice(0, file.length - extname(file).length)
              ),
              // This expands the relative paths to absolute paths, so e.g.
              // src/nested/foo becomes /project/src/nested/foo.js
              fileURLToPath(new URL(file, import.meta.url))
            ])
        ),
      },
      output: {
        manualChunks: {
          mapboxGl: ['mapbox-gl']
        }
      }
    },

    sourcemap: 'hidden',
  },

  plugins: [
    vue(),
    svgLoader()
  ],

Unfortunately, this config doesn’t produce index.html into dist folder for main project, and /widgets folder is added into the main project’s /assets folder.

Please help to achieve

.
└── dist/
    ├── index.html
    ├── assets/
    │   └── ...everything related to the project
    └── widgets/
        └── every widgets folder with built bundle + CSS

Thank you

A way of showing items from Pinia store

I am developing an recipe management app with Vue 3, Vuetify. I am using vue router and Pinia as a store. The app consists of two parts – search where user can search for a recipe trough an API and favorites section. Each user can add a recipe to favorites. Each part has it’s own view and route.
I have a problem regarding showing items from the store.
In HomeView.vue I am subscribing to the state and saving the favorite recipes in local storage.

const store = useRecipesStore();

store.$subscribe((mutation, state) => {
   localStorage.setItem('favoriteRecipes', JSON.stringify(state.favoriteRecipes));
});

In FavoritesView.vue I am trying to show them as in:

<template>
    <Recipes :recipes="recipes" />
</template>

<script setup>
    import { onMounted } from 'vue';
    import { useRecipesStore } from '@/stores/recipesStore.js';

    const store = useRecipesStore();

    const recipes = store.getFavoriteRecipes;

    onMounted(() => {
        const savedRecipes = localStorage.getItem('favoriteRecipes') 
            ? JSON.parse(localStorage.getItem('favoriteRecipes')) 
            : [];

        store.setFavoriteRecipes(savedRecipes);
    });
</script>

I have tested that items do save to local storage and also fills in store.

The store:

import { defineStore } from 'pinia';

export const useRecipesStore = defineStore('recipesStore', {
    state: () => ({
        recipes: [],
        favoriteRecipes: [],
        activeRecipe: null,
    }),
    getters: {
        getRecipes() {
            return this.recipes;
        },
        getFavoriteRecipes() {
            return this.favoriteRecipes;
        },
        canBeAddedToFavorites() {
            if (!this.activeRecipe) return false;

            return !this.favoriteRecipes.some(recipe => recipe.id === this.activeRecipe.id);
        },
    },
    actions: {
        addFavoriteRecipe(recipe) {
            this.$patch({
                favoriteRecipes: [...this.favoriteRecipes, recipe]
            });
        },
        setActiveRecipe(recipe) {
            this.$patch({
                activeRecipe: recipe
            });
        },
        setFavoriteRecipes(recipes) {
            this.$patch({
                favoriteRecipes: recipes
            });
        },
    },
});

The weirdest part is that on initial favorites page load the items do not show but when I visit home page and switch back they do show.

What could be the problem?