How to enable the user to change the size of the embedded video in CKEditor 5 (safe for the server and other users)?

The goal is to enable CKEditor 5 to resize the embedded video (safely).
(Media embed: https://ckeditor.com/docs/ckeditor5/latest/features/media-embed.html)

  1. Is it possible to make your own tool that would simply change the size of the embedded video (inserted via an external link), as it is done there with the image?

  2. As far as I understand, the video (via an external link) can be embedded in CKEditor as an IFrame by allowing the Source button in the toolbar. But then with such a tool, the user can insert any JS script () into the text, which is completely unsafe.

Add a YouTube Video (CK Editor)
https://360psg.helpscoutdocs.com/article/265-add-a-youtube-video-ck-editor

  1. Is it even necessary to check the text in CKEdotor fields (div or textfield) on the server before writing it to the database for the presence of JS scripts ( tag), because malicious code can be inserted into the code itself using F12, even if CKEditor tools do not provide such an opportunity (there is no Source button).

I found topics where people are asking for a simple tool in CKEditor, which I mention in paragraph 1. but it looks like no one is going to implement it? Is there any separate plugin for this feature at all?
https://github.com/ckeditor/ckeditor5/issues/6593
https://github.com/ckeditor/ckeditor5/issues/8204

Thanks!

react-native-video showing white Screen for 1 min then playing video

I am using this package to show video which I am getting fro pubnub message block , the require ment is once the video push from pubnub it will save locally
but video is playing first time push but after killing app and opening again it showing blank white screen for long time and then shows the video i tried to managed by states but unable to handle this issue

import React, { useEffect, useState,useRef } from 'react';
import { View, Text, StyleSheet, Dimensions, Image, ActivityIndicator, } from 'react-native';
import PubNub from 'pubnub';
import Video from 'react-native-video';
import AsyncStorage from '@react-native-async-storage/async-storage';
import RNFetchBlob from 'rn-fetch-blob';
import NetInfo from '@react-native-community/netinfo';

const HomeScreen = () => {
  const videoRef = useRef(null);
  const [mediaUrl, setMediaUrl] = useState('');
  const [displayID, setDisplayID] = useState('loading');
  const [mediaType, setMediaType] = useState('');
  const [progress, setProgress] = useState(0);
  const [loading, setLoading] = useState(false);

  const pubnub = new PubNub({
    // demokeys
    publishKey: 'pub-c-52eb18de-968d-4d2e-8e24-da7d49aac36d',
    subscribeKey: 'sub-c-863ea605-1972-4d02-be58-f9a4bce768fd',
    // productionKeys
    // publishKey: "pub-c-1edcf878-9b9d-4577-a260-21ec35fa5f09",
    // subscribeKey:"sub-c-59a0b640-b45b-4197-8cec-d20851980a5b",
    userId: displayID,
  });

  useEffect(() => {
    const loadDataAndSubscribe = async () => {
      let storedShortUuid = await AsyncStorage.getItem('shortUuid');
      let storedMediaUrl = await AsyncStorage.getItem('mediaUrl');
      let storedMediaType = await AsyncStorage.getItem('mediaType');
      if(storedMediaType && storedMediaUrl){
         setMediaUrl(storedMediaUrl);
        setMediaType(storedMediaType);
      }else{
        let downloadedMedia = await AsyncStorage.getItem("localMediaUrl")
        setMediaUrl(downloadedMedia)
      }
     
      if (!storedShortUuid) {
        storedShortUuid = Math.random().toString(36).substring(7);
        await AsyncStorage.setItem('shortUuid', storedShortUuid);
      }

      setDisplayID(storedShortUuid);
      subscribeToChannel(storedShortUuid);
     
    };

    loadDataAndSubscribe();
  }, []);

  const downloadMedia = async (mediaUrl, mediaType) => {
    setLoading(true);
    try {
      // Check if the device is online
      const netInfoState = await NetInfo.fetch();
      const isOnline = netInfoState.isConnected;
      
      // If the device is offline, attempt to load the media from local storage
      if (!isOnline) {
        const localMediaUrl = await AsyncStorage.getItem('localMediaUrl');
        if (localMediaUrl) {
          setLoading(false);
          setMediaUrl(localMediaUrl); // Set the media URL in state
          return localMediaUrl;
        }
      }
  
      const response = await RNFetchBlob.config({
        fileCache: true,
      }).fetch('GET', mediaUrl)
        .progress((received, total) => {
          const progress = (received / total) * 100;
          setProgress(progress);
        });
      
      const localPath = response.path();
      
      // Save the media to local storage for offline access
      await AsyncStorage.setItem('localMediaUrl', localPath);
  
      setLoading(false);
      setMediaUrl(localPath); // Set the media URL in state
      return localPath;
    } catch (error) {
      setLoading(false);
      console.error('Error downloading media:', error);
      return null;
    }
  };

  const handleMediaPlayback = async (message) => {
    const { mediaUrl, mediaType, downloadLocal } = message;
  
    if (downloadLocal) {
      // Download media locally if required
      const localPath = await downloadMedia(mediaUrl, mediaType);
  
      if (localPath) {
        setMediaUrl(localPath);
        setMediaType(mediaType);
      } else {
        console.error('Media download failed');
      }
    } else {
      // Directly set media URL for playback from remote source
      setMediaUrl(mediaUrl);
      setMediaType(mediaType);
    }
  };

  const subscribeToChannel = (shortUuid) => {
    pubnub.addListener({
      message: async (message) => {
        try {
          if (message && message.message) {
            const messageContent = JSON.parse(message.message);
            handleMediaPlayback(messageContent);
            await AsyncStorage.setItem('mediaUrl', messageContent.mediaUrl);
            await AsyncStorage.setItem('mediaType', messageContent.mediaType);
          } else {
            console.warn('Received message with missing message property:', message);
          }
        } catch (error) {
          console.error('Error parsing message:', error);
        }
      },
    });

    pubnub.subscribe({ channels: [`screenvu_${shortUuid}`] });
  };
console.log("problem he ",mediaUrl)
console.log("problem2  he ",mediaType)
console.log("ref",videoRef.current)
  return (
    <View style={styles.container}>
    {loading ? (
      <>
      <Text style={styles.progressText}>{Math.round(progress)}%</Text>
      </>
   
    ) : mediaUrl ? (
      mediaType === 'VIDEO' ? (
        <Video
         ref={videoRef}
          source={{ uri: mediaUrl }}
          style={styles.media}
          controls={false}
          resizeMode="contain"
          repeat={true}
          autoplay={true}
        />
        // <Text style={{color:'red'}}>{mediaUrl}{mediaType}</Text>
      ) : (
        <Image source={{ uri: mediaUrl }} style={styles.media} />
      )
    ) : (
      <React.Fragment>
        <Image source={require('./assets/logo.png')} style={styles.logo} />
        <View style={{ height: 30 }}></View>
        <View style={{ backgroundColor: 'white', justifyContent: 'center', alignItems: 'center', paddingHorizontal: 35, paddingVertical: 4 }}>
          <Text style={{ color: '#1846b1', fontWeight: 'bold', fontSize: 16 }}>{displayID}</Text>
        </View>
      </React.Fragment>
    )}
  </View>
);
  
};

const styles = StyleSheet.create({
  container: {
    flex: 1,
    justifyContent: 'center',
    alignItems: 'center',
  },
  mediaContainer: {
    width: Dimensions.get('window').width,
    height: Dimensions.get('window').height,
    backgroundColor: '#f6f6f6',
  },
  media: {
    flex: 1,
    width: '100%',
    height: '100%',
  },
  button: {
    marginTop: 20,
    padding: 10,
    backgroundColor: 'blue',
    borderRadius: 5,
  },
  buttonText: {
    color: 'white',
    fontSize: 16,
  },
  logo: {
    height: 100,
    width: 100,
  },
  loaderContainer: {
    justifyContent: 'center',
    alignItems: 'center',
  },
  progressText: {
    fontSize: 16,
    color:"blue",
    alignSelf:'center',
    justifyContent:'center'
  },
});

export default HomeScreen;

I tried to handle by useRef
tried set State is useEffect

Why does it redraw all the figures and not just one? Three.js

need to redraw one figure, not all
need to redraw one figure, not all
need to redraw one figure, not all
need to redraw one figure, not all
need to redraw one figure, not all
need to redraw one figure, not all
need to redraw one figure, not all
need to redraw one figure, not all
need to redraw one figure, not all
need to redraw one figure, not all
need to redraw one figure, not all
need to redraw one figure, not all
need to redraw one figure, not all

//////SCENE
const scene = new THREE.Scene();

const sizes = {
    width: window.innerWidth,
    height: window.innerHeight,
};

//////CAMERA
const camera = new THREE.PerspectiveCamera(75, sizes.width / sizes.height);

camera.position.z = 15

////// RENDERER

const renderer = new THREE.WebGLRenderer({
    // alpha: true, 
    antialias: true 
})

const container = document.querySelector('.canvas');

container.appendChild(renderer.domElement);
renderer.setPixelRatio(window.devicePixelRatio);
renderer.setSize(sizes.width, window.innerHeight);

////// LIGHT
const aLight = new THREE.AmbientLight(0x404040, 1.2);
scene.add(aLight);


////// Group
const group = new THREE.Group();

const geometry = new THREE.BoxGeometry();
const material = new THREE.MeshPhongMaterial({
    color: 0x00ff00,
    wireframe: true,
});

for (let x = -5; x <= 5; x += 5) {
    for (let y = -5; y <= 5; y += 5) {
        const cube = new THREE.Mesh(geometry, material);
        cube.position.set(x, y, 0)
        group.add(cube)
    }
}

scene.add(group)
////// OrbitControls
const controls = new OrbitControls(camera, renderer.domElement);



////// ANIME
function animate() {
    controls.update();
    requestAnimationFrame(animate);
    renderer.render(scene, camera); 
}

animate();

////// HANLERCLICK 

const raycaster = new THREE.Raycaster();
const pointer = new THREE.Vector2();

function onPointerMove(event) {

    pointer.x = (event.clientX / window.innerWidth) * 2 - 1;
    pointer.y = - (event.clientY / window.innerHeight) * 2 + 1;

    raycaster.setFromCamera(pointer, camera)


    const intersects = raycaster.intersectObjects(group.children)

    group.children.forEach(child => {
        child.material.color.set(0xffffff);
    });

    for (let i = 0; i < intersects.length; i++) {
        const intersectedObject = intersects[i].object;
        intersectedObject.material.color.set(0xff0000);
        console.log(intersectedObject.uuid);
    }

}

window.addEventListener('click', onPointerMove)



////// RESIZE



window.addEventListener('resize', () => {


    sizes.width = window.innerWidth;

    sizes.height = window.innerHeight;




    camera.aspect = sizes.width / sizes.height;

    camera.updateProjectionMatrix();




    renderer.setSize(sizes.width, sizes.height);

    renderer.setPixelRatio(Math.min(window.devicePixelRatio, 2));

    renderer.render(scene, camera);
});

Component not rerendering when global state changes. React Redux Toolkit

I’m working on Mafia application for automatizion the gamemaster’s work. I have a UserPanel component, that shows all players, their number and fouls they have.
UserPanel

I have also an AdminPanel component which consists of ControlPanel component, MiddlePanel component and VotingPanel component. Here’s the screen of AdminPanel componentAdminPanel

And the problem I have is that when I’m setting foul on the AdminPanel. It shows here, but it doesn’t on the UserPanel. I should notice that I’m using react-router-dom and UserPanel is on the localhost:3000 and AdminPanel is on the localhost:3000/admin. I don’t know why is it so, because the UserPanel and the MiddlePanel are subscribed to the gameSlice global state. Here’s UserPanel component code:

import React from "react";
import Player from "./Player";
import Timer from "./Timer";
import { useSelector } from "react-redux";

export default function UserPanel() {
    
    const players = useSelector((state) => state.gameReducer.players);

    return (
        <div className="user-panel">
            <div className="container">
                <h1>Mafia NUZP</h1>
                <div className="players-container">
                    {players.map(player => {
                        return <Player number={player.number} fouls={player.fouls} chosen={player.chosen}/>
                    })}
                </div>
                <Timer />
            </div>
        </div>
    )
}

MiddlePanel code:

import React from "react";
import Player from "../../Player";
import Role from "../../Role";
import Timer from "../../Timer";
import TimerControls from "./TimerControls";
import { useSelector } from "react-redux";

export default function MiddlePanel(props) {
    const players = useSelector((state) => state.gameReducer.players);
    let chosenPlayer = players.findIndex(player => player.chosen === true);

    return(
        <div className="middle-panel">
        <div className="chosen-player-container">
            <h1>Player {chosenPlayer + 1}</h1>
        </div>
        <div className="players-container">
            {players.map(player => {
              return <Player number={player.number} role={<Role role={player.role}/>} fouls={player.fouls} chosen={player.chosen}/>  
            })}
        </div>
        <div className="timer-container">
            <Timer />
            <TimerControls />
        </div>
    </div>
    )
}

ControlPanel code:

import React from "react";
import { setFoul, setRole } from "../../features/game/gameSlice";
import { useDispatch } from "react-redux";

export default function ControlPanel() {
    
    const dispatch = useDispatch();

    return(
        <div className="control-panel">
        <button className="btn btn-dark" onClick={() => dispatch(setRole({role: "Д"}))}>Сделать доном</button>
        <button className="btn btn-secondary" onClick={() => dispatch(setRole({role: "М"}))}>Сделать мафией</button>
        <button className="btn btn-warning" onClick={() => dispatch(setRole({role: "Ш"}))}>Сделать шерифом</button>
        <button className="btn btn-danger" onClick={() => dispatch(setRole({role: "К"}))}>Сделать мирным</button>
        <button className="btn btn-light" onClick={() => dispatch(setFoul())}>Поставить фол</button>
        <button className="btn btn-primary">Выставить на голосование</button>
        <button className="btn btn-danger">Изгнать</button>
        <button className="btn btn-info">Следующий игрок</button>
        <button className="btn btn-info">Предыдущий игрок</button>
    </div>
    )
}

And gameSlice code:

import { createSlice } from "@reduxjs/toolkit";

let players = [
    {number: 1, fouls: [null, null, null, null], role: null, chosen: false},
    {number: 2, fouls: [null, null, null, null], role: null, chosen: false},
    {number: 3, fouls: [null, null, null, null], role: null, chosen: false},
    {number: 4, fouls: [null, null, null, null], role: null, chosen: false},
    {number: 5, fouls: [null, null, null, null], role: null, chosen: false},
    {number: 6, fouls: [null, null, null, null], role: null, chosen: true},
    {number: 7, fouls: [null, null, null, null], role: null, chosen: false},
    {number: 8, fouls: [null, null, null, null], role: null, chosen: false},
    {number: 9, fouls: [null, null, null, null], role: null, chosen: false},
    {number: 10, fouls: [null, null, null, null], role: null, chosen: false}]

let admin = {

}

const initialState = {
    players: players,
    adminPanel: admin
}

const gameSlice = createSlice({
    name: "game",
    initialState,
    reducers: {
        setRole(state, action) {
            let {role} = action.payload
            let chosenIndex = state.players.findIndex(player => player.chosen === true);
            state.players[chosenIndex].role = role;
        },

        setFoul(state, action) {
            let chosenIndex = state.players.findIndex(player => player.chosen === true);
            
            let foulIndex = state.players[chosenIndex].fouls.findIndex(foul => foul === null);

            state.players[chosenIndex].fouls[foulIndex] = "F";
        },
    }
})

export const {setFoul, setRole} = gameSlice.actions

export default gameSlice.reducer

Vue3 Transitions: Control slide-fade in and slide-fade out independently of each other

I am trying to implement a comment section in my project. Each comment has its own quill editor to answer. The reason behind this on my mobile version I want to display the quill editor fixed to the bottom and on my desktop version I want to display a quill editor right below the comment which the user wants to answer.

However, I am facing one problem with my transition. When you press the comment answer button, you can see how the quill editor pops up from the bottom. When you press anywhere on the screen (except another comment answer button), the editor slides and fades out again.

However, when I press another comment answer button, you can already see the problem. One editor slides and fades out, and the editor of the comment where you pressed the comment answer button slides and fades in. This is what I am trying to solve here.

I need to control the slide-fade in and slide-fade out independently of each other in order to have no slide-fade out animation for the present editor and no slide-fade in animation for the editor of the comment where I pressed the answer button.

When the user clicks somewhere else, the animation should be as usual.

Here is a working example: click!

I appreciate any kind of help!
Kind regards

Trouble in API Calling [closed]

// Initialize and add the map
function initMap() {
    // Map options
    var mapOptions = {
        center: { lat: 28.618846, lng: 77.284942 },
        zoom: 12
    };

    // Create a map object
    var map = new google.maps.Map(document.getElementById("map"), mapOptions);

     // Fetch the coordinates and addresses from the API
     fetch("http://inventorysoftware.co.in/api/Users/FetchtrackingbyDate")
    .then(response => response.json())
    .then(data => {
        const locations = data.locations; // Assuming the API response contains an array of locations

        // Iterate over each location
        locations.forEach(location => {
            // Create marker for each location
            var marker = new google.maps.Marker({
                position: { lat: location.lat, lng: location.lng },
                map: map,
                title: location.title
            });

            // Create info window content
            var infoWindowContent = '<div><strong>' + location.User + '</strong><br>' +    

            location.address + '</div>';

            // Create info window
            var infoWindow = new google.maps.InfoWindow({
                content: infoWindowContent
            });

            // Add click event listener to open info window when marker is clicked
            marker.addListener('click', function () {
                infoWindow.open(map, marker);
            });
        });

        // Extract coordinates for route polyline
        var routeCoordinates = locations.map(location => ({
            lat: location.lat,
            lng: location.lng
        }));

        // Create a Polyline to represent the route
        var routePath = new google.maps.Polyline({
            path: routeCoordinates,
            geodesic: true,
            strokeColor: "#87CEEB",
            strokeOpacity: 1.0,
            strokeWeight: 2
        });

        // Set the Polyline on the map
        routePath.setMap(map);

        // Set the map bounds to include all route coordinates
        var bounds = new google.maps.LatLngBounds();
        routeCoordinates.forEach(coord => {
            bounds.extend(coord);
        });
        map.fitBounds(bounds);
    })
    .catch(error => console.error('Error fetching data from API:', error));
}

I tried to show the Employee location on map. But API is not working. No Get Method. Implemented the POST Method where when you POST enter date and companyid in json format, it will return data.

Typescript error when mapping optional field of an object

I’m using mongodb and planning to have a generic util function that maps the _id field to id.

const mapId = <T extends { _id?: string }>(item: T) => {
  const { _id, ...rest } = item;
  if (_id === undefined) {
    return rest;
  }

  return { ...rest, id: _id };
}

The rationale is that Mongodb queries have projection, hence the _id field might or might not be present. If it exists, then map it to id.

However, when I invoked this function, I got a typescript error

const city = { _id: 'new-york', name: 'New York' };
const mappedCity = mapId(city);
console.log(mappedCity.id); // has typescript error

The typescript error says Property 'id' does not exist on type 'Omit<{ _id: string; name: string; }, "_id">'.

I also checked that mapId somehow has the following type,

const mapId: <T extends {
  _id?: string | undefined;
}>(item: T) => Omit<T, "_id">

which does not incorporate the id field created in the mapId function. Why does it behave this way? How should I write the util function typings?

WordPress Use Javascript click on button does not work

I have a form to set a CSS between 2 options, I add another php files for create a banner, when I click on the button switch I can change the css, the problem is that when WordPress option is selected in the form the button to switch works perfectly but when I select on the form Wooster it doesn’t work anymore :

    <?php
/**
 * Class used to manage the display of the content of the settings
 */
class WoosterPartnerSettings
{
    /**
     * Hook to display the contents of the 'Settings' menu if the license is valid
     */
    public function __construct()
    {
        if (get_option('partner_license') && get_option('partner_license') != '') {
            add_action('tab_content_settings', array($this, 'wooster_partner_settings'));
            add_action('admin_init', array($this, 'display_style'));
            add_action('admin_enqueue_scripts', array($this, 'enqueue_style'));
        }
    }

    /**
     * Allows you to display the form to choose the style sheet to display
     *
     * @return void
     */
    public function wooster_partner_settings()
    {
?>
        <div class="wrap">
            <h1><?php echo __('Réglages Wooster', 'wooster-partner'); ?></h1>
            <hr class="line">

            <form method="post" action="options.php">
                <?php settings_fields('wooster-settings-group'); ?>
                <?php do_settings_sections('wooster-settings-group'); ?>

                <p class="parag"><?php echo __('Le plugin Compagnon propose deux styles d’affichage :', 'wooster-partner'); ?></p>

                <label for="style_wordpress">
                    <input type="radio" id="style_wordpress" name="wooster_style" value="compagnon-wp.css" <?php checked(get_option('wooster_style'), 'compagnon-wp.css'); ?>>
                    <?php echo __('Style WordPress', 'wooster-partner'); ?>
                </label>

                <label for="style_wooster">
                    <input type="radio" id="style_wooster" name="wooster_style" value="compagnon-wooster.css" <?php checked(get_option('wooster_style'), 'compagnon-wooster.css'); ?>>
                    <?php echo __('Style Wooster', 'wooster-partner'); ?>
                </label><br>

                <input type="submit" class="wooster-button" value="<?php echo __('Enregistrer les modifications', 'wooster-partner') ?>">
            </form>
        </div>
<?php
    }


    /**
     * Registers the setting for the Wooster plugin style
     *
     * @return void
     */
    public function display_style()
    {
        register_setting('wooster-settings-group', 'wooster_style');
    }

    /**
     * Enqueues the selected style for Wooster plugin settings page
     *
     * @return void
     */
    public function enqueue_style()
    {
        if (is_admin()) {
            if (isset($_GET['page']) && strpos($_GET['page'], 'wooster') === 0) {
                $selected_style = get_option('wooster_style', 'compagnon-wp.css'); // default style
                wp_enqueue_style('wooster-custom-style', plugins_url('wooster-partner/assets/css/' . $selected_style));
            }
        }
    }
    }
new WoosterPartnerSettings();
<?php

/**
 * WoosterBanner class
 * It creates  a banner for the Wooster plugin
 *
 * @package Wooster
 */
class WoosterBanner
{
    public function __construct()
    {
        if (isset($_GET['page']) && in_array($_GET['page'], ['wooster', 'wooster-followup', 'wooster-licences', 'wooster-compagnon', 'wooster-customers', 'wooster-partner', 'wooster-settings', 'wooster-setup']) && is_admin()) {
            add_action('admin_enqueue_scripts', array($this, 'enqueue_styles'));
            //add_action('wp_enqueue_scripts', array($this, 'enqueue_styles'));
            add_action('in_admin_header', array($this, 'wooster_header_section'));
            add_action('admin_footer', array($this, 'add_switch_style_button'));
        }
        add_action('wp_enqueue_scripts', array($this, 'enqueue_styles')); // for the front page

    }
    /**
     * Adds the banner to the top of the Wooster plugin settings page
     *
     * @return void
     */
    public function wooster_header_section()
    {
?>
        <div id="top-bar-banner">
            <div class="wooster-banner">
                <div class="logo">
                    <img src="<?php echo plugins_url('assets/img/logo.png', __DIR__); ?>" alt="Logo">
                </div>
                <div class="actions">
                <div id="wooster-activity-panel" class="wooster-layout__activity-panel" aria-labelledby="activity-panel-header_73">

                <div role="tablist" aria-orientation="horizontal" class="wooster-layout__activity-panel-tabs">

                    <button type="button" aria-selected="false" aria-controls="activity-panel-previewStore" id="switch-style" class="components-button wooster-layout__activity-panel-tab"><svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 512 512"><!--!Font Awesome Free 6.5.2 by @fontawesome - https://fontawesome.com License - https://fontawesome.com/license/free Copyright 2024 Fonticons, Inc.-->
                            <path d="M0 224c0 17.7 14.3 32 32 32s32-14.3 32-32c0-53 43-96 96-96H320v32c0 12.9 7.8 24.6 19.8 29.6s25.7 2.2 34.9-6.9l64-64c12.5-12.5 12.5-32.8 0-45.3l-64-64c-9.2-9.2-22.9-11.9-34.9-6.9S320 19.1 320 32V64H160C71.6 64 0 135.6 0 224zm512 64c0-17.7-14.3-32-32-32s-32 14.3-32 32c0 53-43 96-96 96H192V352c0-12.9-7.8-24.6-19.8-29.6s-25.7-2.2-34.9 6.9l-64 64c-12.5 12.5-12.5 32.8 0 45.3l64 64c9.2 9.2 22.9 11.9 34.9 6.9s19.8-16.6 19.8-29.6V448H352c88.4 0 160-71.6 160-160z" />
                        </svg>
                    </button>
                    <button type="button" aria-selected="false" aria-controls="activity-panel-previewStore" id="user-icon" class="components-button wooster-layout__activity-panel-tab"><svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 448 512"><!--!Font Awesome Free 6.5.2 by @fontawesome - https://fontawesome.com License - https://fontawesome.com/license/free Copyright 2024 Fonticons, Inc.-->
                            <path d="M304 128a80 80 0 1 0 -160 0 80 80 0 1 0 160 0zM96 128a128 128 0 1 1 256 0A128 128 0 1 1 96 128zM49.3 464H398.7c-8.9-63.3-63.3-112-129-112H178.3c-65.7 0-120.1 48.7-129 112zM0 482.3C0 383.8 79.8 304 178.3 304h91.4C368.2 304 448 383.8 448 482.3c0 16.4-13.3 29.7-29.7 29.7H29.7C13.3 512 0 498.7 0 482.3z" />
                        </svg>
                    </button>
                    <button type="button" aria-selected="false" aria-controls="activity-panel-help" id="help-icon" class="components-button wooster-layout__activity-panel-tab"><svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24" width="24" height="24" aria-hidden="true" focusable="false">
                            <path d="M12 4.75a7.25 7.25 0 100 14.5 7.25 7.25 0 000-14.5zM3.25 12a8.75 8.75 0 1117.5 0 8.75 8.75 0 01-17.5 0zM12 8.75a1.5 1.5 0 01.167 2.99c-.465.052-.917.44-.917 1.01V14h1.5v-.845A3 3 0 109 10.25h1.5a1.5 1.5 0 011.5-1.5zM11.25 15v1.5h1.5V15h-1.5z"></path>
                        </svg>
                    </button>
    </div>
                    </div>

                </div>
            </div>
        </div>
    <?php
    }
    /**
     * Registers the setting for the Wooster plugin style switch button
     *
     * @return void
     */

    public function add_switch_style_button()
    {
    ?>
        <script>
            document.addEventListener('DOMContentLoaded', function() {
            var toggleStyleBtn = document.getElementById('switch-style');
            var currentStyle = localStorage.getItem('wooster_style') || '<?php echo get_option('wooster_style', 'compagnon-wp.css'); ?>';
            //console.log('Style récupéré depuis localStorage :', currentStyle); // Instruction de débogage
            toggleStyleBtn.addEventListener('click', function() {
                currentStyle = currentStyle === 'compagnon-wp.css' ? 'compagnon-wooster.css' : 'compagnon-wp.css';
                changeStyle(currentStyle);
            });


            function changeStyle(styleName) {
                var styleElement = document.getElementById('wooster-custom-style');
                if (!styleElement) {
                    styleElement = document.createElement('link');
                    styleElement.id = 'wooster-custom-style';
                    styleElement.rel = 'stylesheet';
                    document.head.appendChild(styleElement);
                }
                styleElement.href = '<?php echo plugins_url('wooster-partner/assets/css/'); ?>' + styleName;
                localStorage.setItem('wooster_style', styleName);
                //console.log('Style défini dans localStorage :', styleName); // Instruction de débogage
            }

            // Charger le style initial
            changeStyle(currentStyle);


            });
        </script>
<?php
    }


    /**
     * Enqueues the selected style for Wooster plugin settings page
     *
     * @return void
     */




     public function enqueue_styles()
     {
         $selected_style = get_option('wooster_style', 'compagnon-wp.css'); // Style par défaut

         wp_enqueue_style('wooster-custom-style', plugins_url('wooster-partner/assets/css/' . $selected_style));

         // Enfiler d'autres styles nécessaires
         wp_enqueue_style('wooster-banner', plugins_url('assets/css/banner.css', __DIR__));
         wp_enqueue_style('font-awesome', 'https://cdnjs.cloudflare.com/ajax/libs/font-awesome/5.15.4/css/all.min.css', array(), '5.15.4');
         wp_enqueue_script('jquery'); // Bibliothèque JavaScript

         // Localiser votre script
         wp_localize_script('switch-style', 'switch_style_vars', array(
             'wooster_style_url' => plugins_url("wooster-partner/assets/css/compagnon-wooster.css"),
             'wp_style_url' => plugins_url("wooster-partner/assets/css/compagnon-wp.css"),
         ));

         // Enfiler votre script
         wp_enqueue_script('switch-style');
     }



}

new WoosterBanner();

I tried to enqueue dequeue but as I already put a condition in the script , it should not be necessary. I can’t also enqueue and dequeue as the same time

In Matter.js, using SVG objects created “fromVertices” I can’t “applyForce” or setVelocity on those bodies

When adding convex SVGs to a matter.js canvas (using the polyfills so they look fine) the movement of these bodies when forces are applied is not correct. I can barely move the bodies at all even when applying forces or setting velocity directly.

I have a matter.js canvas, and I am adding SVGs like this:
(code is a bit out of context, but hopefully this is enough to get the idea)

let svgBody = Bodies.fromVertices(
  (ltr.x * matterContainer.clientWidth),
  SVG_STARTING_Y_AS_PRCNT * matterContainer.clientHeight,
  [vertices],
  {
  //   friction: 3,
  //   frictionAir: 0.00001,
  restitution: 0.8,
  //   density: 0.42,
  label: "Letter",
  render: {
    fillStyle: "#00cc00",
    strokeStyle: "#00cc00",
    lineWidth: 1
    }
  }
);

As you can see, I’m playing with adding removing friction and other properties because when these objects collide with other objects they don’t move much at all.

Within a collision when I do:

Body.setVelocity(b, { x: 0, y: -10 });
Body.setAngularVelocity( b, 0.5 );

(b is the svg body)

nothing happens.

I even tried “reversing” gravity by adding the body to a collection (antiGravs) that is getting this code applied :

Events.on(engine, 'beforeUpdate', function() {
                        var gravity = engine.world.gravity;
          
                        antiGravs.forEach((bdy) => {
                            Body.applyForce(bdy, bdy.position, {
                                x: -gravity.x * gravity.scale * bdy.mass,
                                y: -gravity.y * gravity.scale * bdy.mass
                            });
                        })
                    });

When I add other bodies to that collection — I can throw them around with my mouse and they defy gravity, but not the SVG ones.

In the browser, here is what one of the SVG bodies looks like property wise:

angle: 0
anglePrev: -0.5
angularSpeed: 0.5
angularVelocity: 0.5
area: 704.3456252241083
axes: (2) [{…}, {…}]
bounds: {min: {…}, max: {…}}
chamfer: null
circleRadius: 0
collisionFilter: {category: 1, mask: 4294967295, group: 0}
constraintImpulse: {x: 0, y: 0, angle: 0}
density: 0
events: null
force: {x: 0, y: 0}
friction: 0.01
frictionAir: 0.01
frictionStatic: 0.5
id: 165
inertia: NaN
inverseInertia: NaN
inverseMass: Infinity
isSensor: false
isSleeping: false
isStatic: false
label: "Letter"
mass: 0
motion: 0
parent: {id: 167, type: 'body', label: 'Letter', parts: Array(3), plugin: {…}, …}
parts: [{…}]
plugin: {}
position: {x: 430.4627809892338, y: 195.48627853966926}
positionImpulse: {x: 0, y: 0}
positionPrev: {x: 430.0888761241821, y: 205.808158019019}
render: {visible: true, opacity: 1, strokeStyle: '#00cc00', fillStyle: '#00cc00', lineWidth: 1, …}
restitution: 0.9
sleepCounter: 0
sleepThreshold: 60
slop: 0.05
speed: 10
timeScale: 1
torque: 0
totalContacts: 0
type: "body"
velocity: {x: 0, y: -10}
vertices: (4) [{…}, {…}, {…}, {…}]
_original: null

Replacing words in a paragraph vue js

I am trying to replace specific words (that exists in table glossary)in a post content, the word that exists in the glossary should be replaced with itself wrapped in a glossary_container class, next to it is a plus sign that can be clicked to view the glossary description it has a glossary_description class, my code is working fine, except one thing.

**this is an example to explain my problem
**
tree description is hello I am a tree and a branch and I am green
flower description is hello I am flower
branch description is hello I am branch

the post content is “tree has many things, such as a flower,a branch”
there should be a plus sign next to tree, flower, branch to open their description box, instead, there is a a string added after tree that says “branch” with a plus sign next to it and the required classes
**so it looks like this in html **
tree<span class=”plus-sign” data-index=”0″ data-title=”hello I am a tree and a<span class=” glossary_container”=””> branch+ and I am green” style=”cursor:pointer”>+

**so it looks like this in page **
hello I am a tree branch + and I am green

Explanation of the problem: instead of adding the three description boxes, it scans the post content and sees “branch” in tree description (the first word) and adds the description next to it thinking that it is the word that needs a box, I want it to add it next to the post content so in the last word of the post content.

So it should not see post content with the added description boxes, it should only see the original post content and adds the plus sign, description box there.

//this is the code that I am using in vue js and returning to html

            const content = this.isRtl ? this.post.content_ar : this.post.content_en
            let modifiedContent = content.replaceAll(/<br(s*/)?>/gi, '<br /><br />');

            // Loop through each glossary term
            this.glossaries.forEach((glossary, index) => {
            const title = this.isRtl ? glossary.title_ar : glossary.title_en
            const desc = this.isRtl ? glossary.desc_ar : glossary.desc_en
            let filteredDesc = desc.replaceAll(/["']/g, '');
                // Check if the glossary term exists in the content
                if (content.includes(title)) {
                    console.log('content');
                    // Replace the glossary term with a span containing the term and plus sign
                    modifiedContent = modifiedContent.replace(
                        title,
                        `<span class="glossary_container"><span>${title}</span><span class="plus-sign" data-index="${index}" data-title="${filteredDesc}" style="cursor:pointer">+</span></span>`
                    );
                }
            });
            return modifiedContent;

How to make a HTML input be possible to change by a slider and manual input (keyboard)

I want to make an input that can be changed by a slider and by manual input, just like a regular <input type="number">. It has to be the same input because of JavaScript.

For example, here is the code I wrote:

const mph_in = document.getElementById("mph");
const dec_in = document.getElementById("dec");
const t_in = document.getElementById("t");
const out = document.getElementById("out");

mph_in.addEventListener('input', main);
dec_in.addEventListener('input', main);
t_in.addEventListener('input', main);


console.log(mph);

function m2mi(metre){
    return metre/1609.344;

}

function main(){

    // mph = 75.0;
    // dec = 0.9;
    // t = 1.0;


    mph = parseFloat(mph_in.value);
    dec = parseFloat(dec_in.value);
    t = parseFloat(t_in.value);

    v = mph*(1609.344/3600);

    reaction = t * v;

    braking = (v*v)/(2*dec);

    s = reaction + braking;

    console.log("main loaded");
    console.log("reaction distance: "+reaction);

    out.innerHTML = "Reaction distance: "+m2mi(reaction)+" mi<br> Braking distance: "+m2mi(braking)+" mi <br> <b>Stopping distance: "+m2mi(s)+" mi </b>";

}

function test(){
    console.log(m2mi(2000));

    // console.log("v = "+v);
}
<!-- 
  Train speed [mph]: 
  <input type="number" name="mph" id="mph" placeholder="75" value="75">
  <br> 
-->

Train speed [mph]: 
<input type="range" id="mph" name="mph" min="0" max="125" value="75" oninput="this.nextElementSibling.value = this.value"/>
<output></output>

<br>

Deceleration [m/s<sup>2</sup>]: 
<input type="number" name="dec" id="dec" placeholder="0.9" value="0.9">

<br>

Reaction time [s]: <input type="number" name="t" id="t" placeholder="3" value="3">
<br>
    
<button onclick="main()">Calculate</button><br>
<button onclick="test()">Debug</button><br>
<span id="out" >[output]</span>

The code works as intended, except the fact that the speed can only be controlled by a slider (and I would want to make it controllable by manual input too, just like the other inputs) and the deceleration and reaction time also controllable by a slider (not only by manual input). Is there any way to do this?

When I try to launch the html address of the app it does not got triggered in the browser while on the terminal it does

I was working an app on the visual studio code. But don’t know suddenly when I try to run the code it works fine on the terminal but in the case of the browser it just did not triggered. I even tried to uninstall and install the VScode but nothing happened. Can somebody help me regarding this. I have been trying this for the last few days

enter image description here
This is what I am getting on the browser side

How to make the page stay still when clicking on the Pause/Unpause Video button?

Look at this code

<!DOCTYPE html>
<html>
<head>
<style>
table, th, td {
  border: 1px solid black;
}
td:hover {
  background-color: lightgreen;
  color: #000000;
}

</style>
<script>
var video=document.getElementById("myVideo");

function pauseVideo(){
  video.pause();
}

function unpauseVideo(){
  video.play();
}

</script>

</head>
<body>
<video id="myVideo" width="200" height="200" controls autoplay loop>

  Your browser does not support the video tag.
</video>

<br>
<br>
<br>
<br><br>
<br><br><br><br><br><br>
<br><br><br><br><br><br>
<br><br><br><br><br><br>
<br><br><br><br><br><br>
<br><br><br><br><br><br>
<br><br><br><br><br><br>

<table>
<tr>
<td>
<a href="#" onclick="pauseVideo()" style="font-size: 35px; text-decoration: none" > Pause Video</a>
</td>
<td>
<a href="#" onclick="unpauseVideo()" style="font-size: 35px; text-decoration: none" > Unpause Video</a>
</td>
</tr>
</table>
<br><br><br><br><br><br>
<br><br><br><br><br><br>
<br><br><br><br><br><br>
<br><br><br><br><br><br>
<br><br><br><br><br><br>
<br><br><br><br><br><br>
<p>End Line</p>


</body>
</html>

When I click on the Pause Video / Unpause Video button, the page jumps to the top. That is not what I want. I would like the page to stay still now when I click these buttons.

I don’t understand why it keeps jumping up to the top whenever I click them.

How do I change that?

Issues with displaying tables in a report when clicking on sidebar buttons

I am working on creating a report with a sidebar that is intended to display a specific table when a button in the sidebar is clicked. However, the current implementation is causing an accumulation of tables, where each click on a sidebar button results in a new table being displayed below the previous ones. The desired behavior is to have only one table displayed at a time, corresponding to the button clicked. The issue seems to be related to how the tables are being handled upon button clicks, and I’m looking for guidance on how to ensure that only one table is displayed for each button click.

   <script>
        function showContent(fileName) {
            // hide
            var reportContents = document.querySelectorAll('.report-content');
            reportContents.forEach(function(content) {
                content.classList.add('visible');
            });
            //show
            var selectedContent = document.getElementById('content_' + fileName.replace('.', '_'));
            if (selectedContent) {
                selectedContent.classList.remove('hidden');
            }
        }
    </script>         

This is the code that I have been using so far.

Page to update data that has Filepond with a database image, but does not send anything

I have a page to update the MySQL database registration, it is a Blog, because if the user types something wrong or adds a wrong photo, they can use this page to bring the completed data, as well as the image that was previously sent as standard on Filepond.
So when the user opens this page it comes with all the information filled in, including the image field using Filepond.
This way, once the user wants to add new images, as there are multiple images, they can do so.
For example, the user can add up to 4 images, but I can only send one. Later I can update the data and send one more, leaving the one that is already there.
So, if I have a default image, which came from the database, and I want to add 1 more, this default image cannot be sent. When creating a message, it brings the blob information, I will give an example below:

HTML

<div class="mb-3">
    <label class="form-label fs-14 text-dark" for="Imagem">Imagem</label><span class="font-size__0-85rem font-weight__900 text-danger"><sup><i class="ti ti-asterisk"></i></sup></span>
    <div class="filepond--div"><input type="file" class="multiple-filepond" id="Imagem[]" name="Imagem[]" accept="image/jpeg, image/png, image/webp" data-allow-reorder="true" data-max-files="4" data-max-file-size="3MB" multiple></div>
</div>

SCRIPT

/*-- ** - - FILEPOND - - ** --*/
const Str__Filepond_Multiple = document.querySelector('.multiple-filepond');
const Str__Filepond = FilePond.create(Str__Filepond_Multiple,{
    instantUpload: false,
    "server": {
        "load": "../Image/Blog/Upload/1920x1080/",
    },
    "files": [
        {
            "source": "<?php echo $qRecord["Image_1"]; ?>",
            "options": {"type":"local"}
        },
        {
            "source": "<?php echo $qRecord["Image_2"]; ?>",
            "options": {"type":"local"}
        },
        {
            "source": "<?php echo $qRecord["Image_3"]; ?>",
            "options": {"type":"local"}
        },
        {
            "source": "<?php echo $qRecord["Image_4"]; ?>",
            "options": {"type":"local"}
        }
    ],
    labelButtonAbortItemLoad: "Abortar…",
    labelButtonAbortItemProcessing: "Cancelar…",
    labelButtonProcessItem: "Enviar…",
    labelButtonRemoveItem: "Remover…",
    labelButtonRetryItemLoad: "Tentar novamente…",
    labelButtonRetryItemProcessing: "Tentar novamente…",
    labelButtonUndoItemProcessing: "Desfazer…",
    labelFileLoadError: "Erro durante carregamento…",
    labelFileLoading: "Carregando",
    labelFileProcessing: "Enviando",
    labelFileProcessingAborted: "Carregamento cancelado…",
    labelFileProcessingComplete: "Carregamento completo…",
    labelFileProcessingError: "Erro durante carregamento…",
    labelFileProcessingRevertError: "Erro durante reversão…",
    labelFileRemoveError: "Erro durante remoção…",
    labelFileSizeNotAvailable: "Tamanho não disponível…",
    labelFileWaitingForSize: "Aguardando tamanho…",
    labelIdle: "Arraste e solte sua imagem aqui ou <span class="filepond--label-action">navegue</span>…",
    labelInvalidField: "O campo contém arquivos inválidos…",
    labelTapToCancel: "Toque para cancelar…",
    labelTapToRetry: "Toque para tentar novamente…",
    labelTapToUndo: "Toque para desfazer…",
    imageCropAspectRatio: 1,
    imageResizeMode: 'contain',
    imageResizeTargetWidth: 256,
    storeAsFile: true
});

Image that cames when I open the update Blog page:
Image 1

Inserted the new image, the I will send the form with the old and the new image:
Image 2

Page to update data that has Filepond with a database image, but does not send anything

Here we can see that the old image is the second one, the first one is the new (10.webp).
Then I puit a message error to check the result when I try to send:
Image 3

Here we have saying:

  • Erro (2): 2 images
  • 1-10.webp: Image 1, recognized the image that I
    put as a new one
  • 2-blob: Image Old, that was in the database and I
    want to maintain

The problem is exactly here. How do I add a new image, leaving the previous one if I want, using Filepond?
I tried everything but I couldn’t, I read and re-read several topics, without success. I’m not experienced with JS.