How do I render data matching the xAxis to create a table with react?

I want to create a grid (with yAxis being the years and months being the yAxis). How can I render the data along the xAxis? I kept searching for an answer, but cant find anything anywhere except ‘use library’. Sorry if its too beginner, but I just dont know how to do it. Thanks!

const data = [
  {
    year: 2024,
    months: [
      { monthName: "jan", value: "3%" },
      { monthName: "feb", value: "28%" },
      { monthName: "mar", value: "2%" },
      { monthName: "apr", value: "30%" },
      { monthName: "may", value: "26%" },
      { monthName: "jun", value: "20%" },
      { monthName: "dec", value: "40%" },
    ],
  },
  {
    year: 2023,
    months: [
      { monthName: "jan", value: "35%" },
      { monthName: "feb", value: "28%" },
      { monthName: "apr", value: "22%" },
    ],
  },
];

export const Grid = () => {
  return (
    <div>
      {monthsXAxis.map((month, i) => {
        return data?.map((item, i) => {
          return (
            <div>
              <div style={{ display: "flex", flexDirection: "row" }}>
                <div>
                  <h1>{item.year}</h1>
                </div>
                {item.months.map((keyVal, i) => {
                  console.log("fucking shit", keyVal);
                  return (
                    <div
                      style={{
                        backgroundColor: "pink",
                        border: "1px solid grey",
                        alignItems: "center",
                        width: 50,
                        height: 30,
                      }}
                    >
                      <p>{keyVal.value}</p>
                    </div>
                  );
                })}
              </div>
              <div style={{ display: "flex", flexDirection: "row" }}>
                <div
                  style={{ width: 50, height: 30, backgroundColor: "yellow" }}
                >
                  <Typography>{month}</Typography>
                </div>
              </div>
              ;
            </div>
          );
        });
      })}
    </div>
  );
};

EventListener not being removed

I’ve got some Javascript that works fine on the first load, but isn’t working on Postback. After doing some reading, it seems like I need to remove the EventListeners and rebind them. So I’ve got the following code. On first load, the alerts triggered are:

  • Add_Load
  • PageLoadStuff Start
  • PageLoadStuff Vars
  • PageLoadStuff Complete
  • PageLoadStuff Start
  • PageLoadStuff Vars
  • PageLoadStuff Complete

I type in my textbox and the counters count down as expected. I click a button which triggers a postback. After that, my alerts are:

  • It’s a Postback!
  • null

And the counters stop functioning completely. This is not inside an Update Panel. My assumption is that I remove the EventListeners and then add them back by running the PageLoadStuff function again, but I’m not even sure if that’s right.

Here’s my script:

<script type="text/javascript">

    function PageLoadStuff() {
        alert("PageLoadStuff Start");
        const textArea2 = document.getElementById('TextBox_Follow_Up_Answer2');
        const label1 = document.getElementById('Label_Answer_Char_Count');
        const label2 = document.getElementById('Label_Answer_Char_Count2');
        const labelRemaining1 = document.getElementById('Label_Answer_Char_Remaining');
        const labelRemaining2 = document.getElementById('Label_Answer_Char_Remaining2');
        alert("PageLoadStuff Vars");

        // Add input event listener for text area
        textArea2.addEventListener('input', IncrementCounters);

        function IncrementCounters() {
            textCounter(textArea2, 3000, label1, labelRemaining1);
            textCounter2(textArea2, 865, label2, labelRemaining2);
            //        alert("Event Listener - DOMContentLoaded");
        }
        alert("PageLoadStuff Complete");
    }

    var isPostBack = '<%= this.IsPostBack%>' == 'True';
    if (isPostBack) {
        alert("It's a PostBack!");
        const textArea2 = document.getElementById('TextBox_Follow_Up_Answer2');
        alert(textArea2);
        document.removeEventListener('DOMContentLoaded', PageLoadStuff);
        textArea2.removeEventListener('input', IncrementCounters);
        alert("EventListeners Removed");
        PageLoadStuff();

    }

    if (document.readyState == 'loading') {
        // still loading, wait for the event
        document.addEventListener('DOMContentLoaded', PageLoadStuff);
    } else {
        PageLoadStuff();
    }

    Sys.Application.add_load(function () {
        alert("Add_Load");
        PageLoadStuff();
    });

    function textCounter(field, maxlimit, label, label2) {
        if (field.value.length > maxlimit)
            field.value = field.value.substring(0, maxlimit);
        else {

            label.innerHTML = maxlimit - field.value.length;
        }
        if (field.value.length > maxlimit - 500) {
            label.style.color = "#FF0000";
            label2.style.color = "#FF0000";
        }
        else {
            label.style.color = "#000000";
            label2.style.color = "#000000";
        }
    //    alert("textCounter Fired");
    }

    function textCounter2(field, maxlimit, label, label2) {
        if (field.value.length > maxlimit)
        field.value = field.value;
        else {

            label.innerHTML = maxlimit - field.value.length;
        }
        if (field.value.length > maxlimit - 200) {
            label.style.color = "#FF0000";
            label2.style.color = "#FF0000";
        }
        else {
            label.style.color = "#000000";
            label2.style.color = "#000000";
        }
    //    alert("textCounter2 Fired");
    }

</script>

How do I avoid whitespace collapsing in Motion Canvas Text?

I am recently using Motion Canvas for my animations. I want to avoid whitespace collapsing in Txt component. I have looked for solution like change the style of whitespace to pre but this is not even an option. This is what I want to do.

interface TextNodeProps {
    text: string;
    color: string;
}

interface ColorNodeProps {
    text: string;
}


const Red = ({text}: ColorNodeProps) => <TextNode text={text} color='#ff0000'/>

const Green = ({text}: ColorNodeProps) => <TextNode text={text} color='#00ff00'/>

const TextNode = ({text, color}: TextNodeProps) => <Txt text={text} fill={color}/> 

When I use like this

<Red text='Hello    World'/>

It only renders

Hello World

*whitespace collapsed

Rather I want this

Hello    world

Any help is appreciated.

Firebase functions Error file is not defined

I’m currently building my first ever project on Firebase. I just deployed my project on it, and after few hours of debugging, I’m mostly lost, and have no more ideas on how to resolve it. I don’t know why when I’m uploading my file, I receive a 500 error. I’ve some errors in the consoel, which are:

[Here’s the link to the console][1], and here is my component:

export const GenerateNew = () => {
  const [image, setImage] = useState(null);
  const [style, setStyle] = useState('Gamer');
  const [loading, setLoading] = useState(false);
  const [isDropdownOpen, setIsDropdownOpen] = useState(false);
  const [credits, setCredits] = useState(0);
  const [showCreditAlert, setShowCreditAlert] = useState(false);
  
  const dropdownRef = useRef(null);
  const { currentUser } = useAuth();

  useEffect(() => {
    if (currentUser) {
      const userDocRef = doc(db, 'users', currentUser.uid);
      const unsubscribe = onSnapshot(userDocRef, (docSnapshot) => {
        if (docSnapshot.exists()) {
          const userData = docSnapshot.data();
          setCredits(userData.credits || 0);
        }
      });
      return () => unsubscribe();
    }
  }, [currentUser]);

  useEffect(() => {
    const handleClickOutside = (event) => {
      if (dropdownRef.current && !dropdownRef.current.contains(event.target)) {
        setIsDropdownOpen(false);
      }
    };
    document.addEventListener('mousedown', handleClickOutside);
    return () => document.removeEventListener('mousedown', handleClickOutside);
  }, []);

  const onDrop = useCallback((acceptedFiles) => {
    setImage(acceptedFiles[0]);
  }, []);

  const { getRootProps, getInputProps, isDragActive } = useDropzone({
    onDrop,
    accept: { 'image/*': ['.jpeg', '.jpg', '.png', '.gif', '.webp'] },
    maxFiles: 1,
    disabled: !!image
  });

  const handleSubmit = async (e) => {
    e.preventDefault();
    if (!image) {
      alert('Please select an image first.');
      return;
    }
    if (credits === 0) {
      setShowCreditAlert(true);
      return;
    }

    setLoading(true);

    try {
      const formData = new FormData();
      formData.append('image', image);
      formData.append('style', style);

      console.log('FormData content:');
      for (let [key, value] of formData.entries()) {
        console.log(key, value);
      }

      const response = await axios.post(`${API_URL}/generate`, formData, {
        headers: { 'Content-Type': 'multipart/form-data' },
      });

      const generatedImageUrl = response.data.output;

      // Sauvegarder les images dans Firebase Storage
      console.log('start save dans FBS');
      const originalImageRef = ref(storage, `original/${currentUser.uid}/${Date.now()}_${image.name}`);
      console.log('Saved dans FBS');
      await uploadBytes(originalImageRef, image);
      const originalImageUrl = await getDownloadURL(originalImageRef);

      const generatedImageResponse = await fetch(generatedImageUrl);
      const generatedImageBlob = await generatedImageResponse.blob();
      const generatedImageRef = ref(storage, `generated/${currentUser.uid}/${Date.now()}_generated.png`);
      await uploadBytes(generatedImageRef, generatedImageBlob);
      const firebaseGeneratedImageUrl = await getDownloadURL(generatedImageRef);

      // Sauvegarder les informations dans Firestore
      console.log('Save dans FBS');
      const setupsRef = collection(db, 'generatedImages');
      const setupsSnapshot = await getDocs(query(setupsRef, where('userId', '==', currentUser.uid)));
      const setupNumber = setupsSnapshot.size + 1;
      console.log('Saved dans FBS');

      await addDoc(setupsRef, {
        userId: currentUser.uid,
        originalImage: originalImageUrl,
        generatedImage: firebaseGeneratedImageUrl,
        style: style,
        title: `Setup #${setupNumber}`,
        createdAt: new Date()
      });

      // Mettre à jour les crédits de l'utilisateur
      const userRef = doc(db, 'users', currentUser.uid);
      await updateDoc(userRef, { credits: increment(-1) });

      setLoading(false);
      alert('Image generated and saved successfully!');
      
      setImage(null);
      setStyle('Gamer');
    } catch (error) {
      console.error('Error:', error.response ? error.response.data : error.message);
      setLoading(false);
      alert('An error occurred. Please try again.');
    }
  };

  const styles = ['Gamer', 'Aesthetic', 'RGB Free'];

And my index.js file, my firebase functions:

const functions = require('firebase-functions');
const express = require('express');
const multer = require('multer');
const Replicate = require('replicate');
const cors = require('cors');

const app = express();

// Configuration de Multer avec gestion d'erreurs
const upload = multer({
  storage: multer.memoryStorage(),
  limits: { fileSize: 10 * 1024 * 1024 }, // Limite à 10MB
}).single('image');

app.use(cors({ origin: true }));
app.use(express.json());
app.use(express.urlencoded({ extended: true }));

const replicate = new Replicate({
  auth: functions.config().replicate.api_token,
});

const styleDescriptions = {
  'Gamer': `Upgrade this setup to create a gaming setup, with aesthetic rgb lights...`,
  'Aesthetic': `Transform this setup into a minimalist and visually pleasing design...`,
  'RGB Free': `Enhance this setup to create a professional and sophisticated environment...`
};

app.post('/generate', (req, res) => {
  console.log('Received generate request');
  
  upload(req, res, async function(err) {
    console.log('On arrive ici');
    if (err) {
      console.error('Upload error:', err);
      return res.status(400).json({ error: 'File upload error', details: err.message });
    }

    console.log('File uploaded successfully');
    console.log('File details:', file ? { originalname: file.originalname, size: file.size } : 'No file');
    console.log('Selected style:', style);

    try {
      const { file } = req;
      const { style } = req.body;

      console.log('File details:', file ? { originalname: file.originalname, size: file.size } : 'No file');
      console.log('Selected style:', style);

      if (!file) {
        return res.status(400).json({ error: 'No image file provided' });
      }

      const styleDescription = styleDescriptions[style] || '';

      console.log('Preparing input for Replicate API');
      const input = {
        image: `data:${file.mimetype};base64,${file.buffer.toString('base64')}`,
        prompt: styleDescription,
        guidance: 3.5,
        num_outputs: 1,
        aspect_ratio: "1:1",
        output_format: "webp",
        output_quality: 80,
        prompt_strength: 0.80,
        num_inference_steps: 28
      };

      console.log('Sending request to Replicate API...');
      const output = await replicate.run(
        "black-forest-labs/flux-dev",
        { input }
      );

      console.log('Replicate API response received');
      res.json({ output: output[0] });
    } catch (error) {
      console.error('Error in generate function:', error);
      res.status(500).json({ error: 'An error occurred while generating the image', details: error.message });
    }
  });
});

// Export the Express app as a Firebase Cloud Function
exports.api = functions.https.onRequest(app);

It sounds like this for (let [key, value] of formData.entries()) {console.log(key, value);}

is the only console.log which is working. Nothing else sounds working.

Do you guys have any idea?

Appreciate it!
[1]: https://i.sstatic.net/nutf6I9P.png

Align images from carousel in React with outer components

I am using the library react-multi-carousel, however, I am having difficulties aligning the images so the left border from the first image aligns with the items in the outside, in this case an h2, like so:
enter image description here

And the right border from the last image aligns with the outer element, which in this case, is the “shop” button, like so:
enter image description here

This is the link to the CodeSanbox. Is this possible to do with that library?

Trying to use login-2FA and i am getting this error, Failed to load resource: the server responded with a status of 401 ()

Invalid OTP error when using front end, when I test API with swagger it works fine.

I am trying to implement asp.net 2FA authentication but i am getting error Invalid OTP when i try to use the front end, even though I received the email with the OTP. When i test the API using swagger i am able to get the JWT token and login.

OTPVerification.jsx

    function OTPVerification({ isOpen, onOpenChange, username, length = 6 }) {
    const { setIsLoading, isLoading, verifyOTP } = useAuth();

    const handleOtpSubmit = async (otp) => {
        setIsLoading(true);

        try {

            if (otp.length !== 6 || isNaN(otp)) {
                toast.error('Please enter a valid 6-digit OTP.');
                return;
            }
            console.log("Username: ", username);
            console.log("OTP: ", otp);
            const response = await verifyOTP(username,otp);
            console.log("Response: ", response);
            if (response.success) {
                toast.success('OTP Verified Successfully!');
                onOpenChange(false);
            } else {
                toast.error(response.message || 'OTP Verification Failed. Please try again.');
            }
        } catch (error) {
            console.error('Error during OTP verification:', error);
            const message = error.response?.data?.message || 'An error occurred during OTP      verification. Please try again.';
            toast.error(message);
        } finally {
            setIsLoading(false);
        }
    };

AuthContext,jsx

    async function verifyOTP(username, otp) {
    setIsLoading(true); // Start loading state
   
    try {
        const response = await axios.post('/api/Auth/login-2FA', {
            Username: username,
            OTP: otp
        });

        console.log('Sent OTP request:', { username, otp });

        if (response.data.Status === 'Success') {
            login(response.data.token, response.data.user);
            return { success: true, token: response.data.token, user: response.data.user };
        } else {
            return { success: false, message: response.data.Message };
        }
    } catch (error) {
        console.error('Error verifying OTP:', error);
        const message = error.response?.data?.message || 'An error occurred. Please try again.';
        return { success: false, message };
    } finally {
        setIsLoading(false); // Stop loading state
    }
}

AuthController.cs

    [HttpPost]
[Route("login-2FA")]
public async Task<IActionResult> LoginWithOTP([FromBody] OtpRequest request)
{
    // Validate the request
    if (request == null || string.IsNullOrEmpty(request.OTP) || string.IsNullOrEmpty(request.Username))
    {
        _logger.LogWarning("Invalid OTP request: Missing code or username.");
        return BadRequest(new { Status = "Error", Message = "Code and Username are required." });
    }

    // Find the user by username
    var user = await _userManager.FindByNameAsync(request.Username.ToLower());
    if (user == null)
    {
        _logger.LogWarning("OTP login attempt for non-existent user: {Username}", request.Username);
        return Unauthorized(new { Status = "Error", Message = "Invalid username or OTP ." });
    }
    if (await _userManager.IsLockedOutAsync(user))
    {
        _logger.LogWarning("User is locked out: {Username}", user.UserName);
        return Unauthorized(new { Status = "Error", Message = "User account is locked out." });
    }

    // Verify the OTP token
    var signInResult = await _signInManager.TwoFactorSignInAsync("Email", request.OTP, rememberClient: false, isPersistent: false);

        if (signInResult.Succeeded)
        {
        // Generate JWT token
        var authClaims = new List<Claim>
        {
            new Claim(ClaimTypes.Name, user.UserName),
            new Claim(JwtRegisteredClaimNames.Jti, Guid.NewGuid().ToString())
        };

        // Add user roles to claims
        var userRoles = await _userManager.GetRolesAsync(user);
        foreach (var role in userRoles)
        {
            authClaims.Add(new Claim(ClaimTypes.Role, role));
        }

        // Generate token string using claims
        var jwtToken = GenerateTokenString(authClaims);

        _logger.LogInformation("2FA login successful for user: {Username}", user.UserName);

        return Ok(new
        {
            token = jwtToken,
            expiration = new JwtSecurityTokenHandler().ReadJwtToken(jwtToken).ValidTo
        });
    }

    _logger.LogWarning("Invalid OTP provided for user: {Username}.", request.Username);
    return Unauthorized(new { Status = "Error", Message = "Invalid OTP." });
}

Why my 3d model keeps placing text not in the middle of y coordinates but a little below it?

I’ve spent two days going back and forth, and it’s still the same. The text engraving depth varies on my curved 3D ring model—one side of the letter is deep, while the other side is not. I’m trying to use my .glb ring model, change its texture to silver, and add text that appears in the middle and looks engraved. I also want to be able to use x and y sliders to move the text. I could really use some help with this.

Main problem is: 1. wrong text alignment after i input text (its not in the middle of y axis.
2. Text looks not evenly deep.

{% assign model_found = false %} 

{% for media in product.media %}
  {% if media.media_type == 'model' %}
    {% assign model_url = media.sources[0].url %}
    
    <!-- 3D Model Container -->
    <div id="3d-container" style="width: 100%; height: 0; padding-bottom: 75%; position: relative;"></div>

    <!-- Text Input for Engraving -->
    <div style="margin-top: 20px; text-align: center;">
      <input type="text" id="engraveText" placeholder="Type your text here" style="padding: 10px; font-size: 16px; width: 60%; max-width: 300px;">
      <input type="color" id="textColor" value="#000000" style="padding: 10px; margin-left: 10px;">
    </div>

    <!-- Text Size and Position Sliders with Real-Time Value Display -->
    <div style="margin-top: 20px; text-align: center;">
      <label for="textSize">Text Size: <span id="textSizeValue">100</span></label>
      <input type="range" id="textSize" min="10" max="200" value="100" style="width: 50%; max-width: 300px;">
      <br>
      <label for="textPosX">Position X: <span id="textPosXValue">50</span></label>
      <input type="range" id="textPosX" min="0" max="100" value="50" style="width: 50%; max-width: 300px;">
      <label for="textPosY">Position Y: <span id="textPosYValue">50</span></label>
      <input type="range" id="textPosY" min="0" max="100" value="50" style="width: 80%; max-width: 300px;">
    </div>

    <!-- Invert and Mirror Text Buttons -->
    <div style="margin-top: 20px; text-align: center;">
      <button id="invertText" style="padding: 10px; font-size: 16px;">Invert Text</button>
      <button id="mirrorText" style="padding: 10px; font-size: 16px; margin-left: 10px;">Mirror Text</button>
    </div>

    <!-- Material Selection -->
    <div style="margin-top: 20px; text-align: center;">
      <label for="materialSelect">Choose Material:</label>
      <select id="materialSelect" style="padding: 10px; font-size: 16px;">
        <option value="metal">Metal</option>
        <option value="silver">Silver</option>
        <option value="gold">Gold</option>
      </select>
    </div>

    <!-- Engraving Depth Slider -->
    <div style="margin-top: 20px; text-align: center;">
      <label for="engravingDepth">Engraving Depth: <span id="engravingDepthValue">0.05</span></label>
      <input type="range" id="engravingDepth" min="0.01" max="0.2" step="0.01" value="0.05" style="width: 80%; max-width: 300px;">
    </div>

    <!-- Hidden input to store engraving data for order processing -->
    <input type="hidden" id="engravingDataInput" name="engravingData" value="">

    <!-- Include Three.js -->
    <script src="https://cdnjs.cloudflare.com/ajax/libs/three.js/r128/three.min.js"></script>

    <!-- Include GLTFLoader for loading 3D models -->
    <script src="https://cdn.jsdelivr.net/npm/[email protected]/examples/js/loaders/GLTFLoader.js"></script>

    <!-- Include OrbitControls -->
    <script src="https://cdn.jsdelivr.net/npm/[email protected]/examples/js/controls/OrbitControls.js"></script>

    <!-- Include RGBELoader for HDRI -->
    <script src="https://cdn.jsdelivr.net/npm/[email protected]/examples/js/loaders/RGBELoader.js"></script>

    <script>
      document.addEventListener('DOMContentLoaded', function() {
        const container = document.getElementById('3d-container');
        const containerWidth = container.clientWidth;
        const containerHeight = container.clientHeight;

        // Initialize Three.js Scene
        const scene = new THREE.Scene();

        // Load HDRI environment
        const rgbeLoader = new THREE.RGBELoader();
        rgbeLoader.load('https://dl.polyhaven.org/file/ph-assets/HDRIs/hdr/1k/brown_photostudio_02_1k.hdr', function (texture) {
          texture.mapping = THREE.EquirectangularReflectionMapping;
          scene.environment = texture;
          scene.background = texture; 
        });

        // Initialize Camera
        const camera = new THREE.PerspectiveCamera(75, containerWidth / containerHeight, 0.1, 1000);
        camera.position.set(0, 2, 5);

        // Initialize Renderer
        const renderer = new THREE.WebGLRenderer({ antialias: true });
        renderer.setPixelRatio(window.devicePixelRatio);
        renderer.setSize(containerWidth, containerHeight);
        renderer.physicallyCorrectLights = true;

        renderer.toneMapping = THREE.ACESFilmicToneMapping;
        renderer.toneMappingExposure = 2.0;  

        container.appendChild(renderer.domElement);

        // Add Ambient and Directional Lighting
        const ambientLight = new THREE.AmbientLight(0xffffff, 2);
        scene.add(ambientLight);

        const directionalLight = new THREE.DirectionalLight(0xffffff, 2);
        directionalLight.position.set(5, 10, 7.5).normalize();
        scene.add(directionalLight);

        // Initialize OrbitControls
        const controls = new THREE.OrbitControls(camera, renderer.domElement);
        controls.enableDamping = true;
        controls.dampingFactor = 0.05;
        controls.enablePan = false;

        let isTextInverted = false;
        let isTextMirrored = false;

        // Load the 3D Model
        const gltfLoader = new THREE.GLTFLoader();
        const modelUrl = "{{ model_url | escape }}";
        gltfLoader.load(modelUrl, function(gltf) {
          const model = gltf.scene;
          scene.add(model);
          model.position.set(0, 0, 0);

          const box = new THREE.Box3().setFromObject(model);
          const center = box.getCenter(new THREE.Vector3());
          model.position.sub(center);

          function updateTextInRealTime() {
            const text = document.getElementById('engraveText').value.trim();
            const color = document.getElementById('textColor').value;
            const textSize = document.getElementById('textSize').value;
            const posX = document.getElementById('textPosX').value;
            const posY = document.getElementById('textPosY').value;
            const material = document.getElementById('materialSelect').value;
            const engravingDepth = document.getElementById('engravingDepth').value;

            document.getElementById('textSizeValue').textContent = textSize;
            document.getElementById('textPosXValue').textContent = posX;
            document.getElementById('textPosYValue').textContent = posY;
            document.getElementById('engravingDepthValue').textContent = engravingDepth;

            const canvas = document.createElement('canvas');
            const context = canvas.getContext('2d');

            const canvasWidth = 1024;
            const canvasHeight = 1024;
            canvas.width = canvasWidth;
            canvas.height = canvasHeight;

            context.clearRect(0, 0, canvasWidth, canvasHeight);
            context.fillStyle = '#ffffff';
            context.fillRect(0, 0, canvasWidth, canvasHeight);

            context.font = `Bold ${textSize}px Arial`;
            context.textAlign = 'center';
            context.textBaseline = 'middle';
            context.fillStyle = color;

            // Adjust the Y-coordinate calculation
            const adjustedPosX = (canvasWidth * posX) / 100;
            const adjustedPosY = (canvasHeight * (100 - posY)) / 100; // Invert Y-axis

            if (isTextInverted) {
              context.scale(-1, 1);
              context.translate(-canvasWidth, 0);
            }

            if (isTextMirrored) {
              context.save();
              context.scale(1, -1);
              context.translate(0, -canvasHeight);
              context.fillText(text, adjustedPosX, canvasHeight - adjustedPosY);
              context.restore();
            } else {
              context.fillText(text, adjustedPosX, adjustedPosY);
            }

            const newTexture = new THREE.CanvasTexture(canvas);
            newTexture.needsUpdate = true;

            const bumpTexture = new THREE.CanvasTexture(canvas);
            bumpTexture.needsUpdate = true;

            const displacementTexture = new THREE.CanvasTexture(canvas);
            displacementTexture.needsUpdate = true;

            model.traverse(function(child) {
              if (child.isMesh) {
                let metalness = 1.0;
                let roughness = 0.15;
                let color = new THREE.Color(0xffffff);

                if (material === 'silver') {
                  roughness = 0.05;
                  color.setHex(0xC0C0C0);
                } else if (material === 'gold') {
                  roughness = 0.15;
                  color.setHex(0xD4AF37);
                } else {
                  roughness = 0.25;
                }

                const textMaterial = new THREE.MeshPhysicalMaterial({
                  map: newTexture,
                  bumpMap: bumpTexture,
                  bumpScale: 0.15,
                  displacementMap: displacementTexture,
                  displacementScale: parseFloat(engravingDepth),
                  roughness: roughness,
                  metalness: metalness,
                  clearcoat: 1.0,
                  envMap: scene.environment,
                  reflectivity: 1.0,
                  transparent: true,
                  color: color,
                  side: THREE.DoubleSide,
                });

                child.material = textMaterial;
                child.material.needsUpdate = true;
              }
            });

            const engravingData = {
              text: text,
              color: color,
              textSize: textSize,
              posX: posX,
              posY: posY,
              isTextInverted: isTextInverted,
              isTextMirrored: isTextMirrored,
              material: material,
              engravingDepth: engravingDepth
            };

            document.getElementById('engravingDataInput').value = JSON.stringify(engravingData);
          }

          document.getElementById('engraveText').addEventListener('input', updateTextInRealTime);
          document.getElementById('textSize').addEventListener('input', updateTextInRealTime);
          document.getElementById('textPosX').addEventListener('input', updateTextInRealTime);
          document.getElementById('textPosY').addEventListener('input', updateTextInRealTime);
          document.getElementById('textColor').addEventListener('input', updateTextInRealTime);
          document.getElementById('materialSelect').addEventListener('change', updateTextInRealTime);
          document.getElementById('engravingDepth').addEventListener('input', updateTextInRealTime);
          document.getElementById('invertText').addEventListener('click', function() {
            isTextInverted = !isTextInverted;
            updateTextInRealTime();
          });
          document.getElementById('mirrorText').addEventListener('click', function() {
            isTextMirrored = !isTextMirrored;
            updateTextInRealTime();
          });

          updateTextInRealTime();

          function animate() {
            requestAnimationFrame(animate);
            controls.update();
            renderer.render(scene, camera);
          }
          animate();
        });
      });
    </script>
  {% endif %}
{% endfor %}

OrbitControls in ThreeJS not working with import map

I’m trying to get a simple ThreeJs with OrbitControls for pan and zoom. I was able to get a working example with an older version (128), but I’m having trouble with the newer r168.

In the example, I’m trying to write the js code directly into an html page, and importing the threejs dependencies using cdn, instead of a local source.

<body>
    <script type="importmap">
        {
            "imports": {
                "three": "https://unpkg.com/[email protected]/build/three.module.js",
                "three/examples/jsm/controls/OrbitControls": "https://unpkg.com/[email protected]/examples/jsm/controls/OrbitControls.js"
            }
        }
    </script>
    <script type="module">
        import * as THREE from 'three';
        import { OrbitControls } from 'three/examples/jsm/controls/OrbitControls.js';

        // Scene setup
        const scene = new THREE.Scene();
        const camera = new THREE.PerspectiveCamera(75, window.innerWidth / window.innerHeight, 0.1, 1000);
        
        // Renderer setup
        const renderer = new THREE.WebGLRenderer();
        renderer.setSize(window.innerWidth, window.innerHeight);
        renderer.setClearColor(0x000000); // Set background color to black
        document.body.appendChild(renderer.domElement);

        // Create a cube
        const geometry = new THREE.BoxGeometry();
        const material = new THREE.MeshBasicMaterial({ color: 0x00ff00 });
        const cube = new THREE.Mesh(geometry, material);
        scene.add(cube);

        // Position the camera
        camera.position.z = 5;

        // OrbitControls setup
        const controls = new OrbitControls(camera, renderer.domElement);
        controls.enableDamping = true; // Enable smooth damping
        controls.dampingFactor = 0.25; // Adjust the damping factor for smoothness
        controls.enableZoom = true;    // Enable zoom
        controls.enablePan = true;     // Enable panning

        // Animation loop
        function animate() {
            requestAnimationFrame(animate);
            controls.update(); // Required if damping is enabled
            renderer.render(scene, camera);
        }
        animate();

        // Adjust canvas on window resize
        window.addEventListener('resize', () => {
            camera.aspect = window.innerWidth / window.innerHeight;
            camera.updateProjectionMatrix();
            renderer.setSize(window.innerWidth, window.innerHeight);
        });
    </script>
</body>

The code seems to get an error right at the start, in the import { OrbitControls } from 'three/examples/jsm/controls/OrbitControls.js';.

Any help on what might be going on and how to fix this?

Is my translate between two language(JS and Java) correct?

Please someone tell me what’s wrong with my code.
I translate the code from JavaScript to Java, but I think there must be something problem in it, because it doesn’t work as expected.
BTW, I am not good at JavaScript, if you can tell me what’s wrong with my code in Java,
that’s awesome

Tips: the code following is a certain encrypt method

//...
info = JSON.stringify(info);

                function encode(str, key) {
                    if (str === '') return '';
                    var v = s(str, true);
                    var k = s(key, false);
                    if (k.length < 4) k.length = 4;
                    var n = v.length - 1,
                        z = v[n],
                        y = v[0],
                        c = 0x86014019 | 0x183639A0,
                        m,
                        e,
                        p,
                        q = Math.floor(6 + 52 / (n + 1)),
                        d = 0;

                    while (0 < q--) {
                        d = d + c & (0x8CE0D9BF | 0x731F2640);
                        e = d >>> 2 & 3;

                        for (p = 0; p < n; p++) {
                            y = v[p + 1];
                            m = z >>> 5 ^ y << 2;
                            m += y >>> 3 ^ z << 4 ^ (d ^ y);
                            m += k[p & 3 ^ e] ^ z;
                            z = v[p] = v[p] + m & (0xEFB8D130 | 0x10472ECF);
                        }

                        y = v[0];
                        m = z >>> 5 ^ y << 2;
                        m += y >>> 3 ^ z << 4 ^ (d ^ y);
                        m += k[p & 3 ^ e] ^ z;
                        z = v[n] = v[n] + m & (0xBB390742 | 0x44C6F8BD);
                    }

                    return l(v, false);
                }

                function s(a, b) {
                    var c = a.length;
                    var v = [];

                    for (var i = 0; i < c; i += 4) {
                        v[i >> 2] = a.charCodeAt(i) | a.charCodeAt(i + 1) << 8 | a.charCodeAt(i + 2) << 16 | a.charCodeAt(i + 3) << 24;
                    }

                    if (b) v[v.length] = c;
                    return v;
                }

                function l(a, b) {
                    var d = a.length;
                    var c = d - 1 << 2;

                    if (b) {
                        var m = a[d - 1];
                        if (m < c - 3 || m > c) return null;
                        c = m;
                    }

                    for (var i = 0; i < d; i++) {
                        a[i] = String.fromCharCode(a[i] & 0xff, a[i] >>> 8 & 0xff, a[i] >>> 16 & 0xff, a[i] >>> 24 & 0xff);
                    }

                    return b ? a.join('').substring(0, c) : a.join('');
                }

                return '{SRBX1}' + base64.encode(encode(info, token));
//...
//...
private static String encode(String str,String key) {
        if(str==null||key==null)
            throw new RuntimeException("null is not allowed!");
        if (str == "") return "";
        var v = s(str, true);
        var k = s(key, false);
        if (k.length < 4) Arrays.copyOf(k, 4);
        int n = v.length - 1,
            z = v[n],
            y = v[0],
            c = 0x86014019 | 0x183639A0,
            m,
            e,
            p,
            q = (int)Math.floor(6 + 52 / (n + 1)),
            d = 0;

        while (0 < q--) {
            d = d + c & (0x8CE0D9BF | 0x731F2640);
            e = d >>> 2 & 3;

            for (p = 0; p < n; p++) {
                y = v[p + 1];
                m = z >>> 5 ^ y << 2;
                m += y >>> 3 ^ z << 4 ^ (d ^ y);
                m += k[p & 3 ^ e] ^ z;
                z = v[p] = v[p] + m & (0xEFB8D130 | 0x10472ECF);
            }

            y = v[0];
            m = z >>> 5 ^ y << 2;
            m += y >>> 3 ^ z << 4 ^ (d ^ y);
            m += k[p & 3 ^ e] ^ z;
            z = v[n] = v[n] + m & (0xBB390742 | 0x44C6F8BD);
        }
        String[] v1 = new String[v.length];
        for(int i = 0 ;i<v.length;i++)
            v1[i] = Integer.toString(v[i]);

        return l(v1, false);
    }

    private static int cPointCheck(String a,int cPointIndex){
        if(cPointIndex<a.length())
            return a.codePointAt(cPointIndex);
        else
            return 0;
    }

    private static int[] s(String a, boolean b) {
        var c = a.length();
        var v = new int[c];

        for (var i = 0; i < c; i += 4) {
            v[i >> 2] = cPointCheck(a, i) | cPointCheck(a, i+1) << 8 | cPointCheck(a, i+2) << 16 | cPointCheck(a, i+3) << 24;
        }

        if (b) v[v.length-1] = c;
        return v;
    }

    private static String l(String[]a, boolean b) {
        var d = a.length;
        var c = d - 1 << 2;

        if (b) {
            var m = Integer.parseInt(a[d - 1]);
            if (m < c - 3 || m > c) return null;
            c = m;
        }

        for (var i = 0; i < d; i++) {
            a[i] = new String(new char[]{(char)(Integer.parseInt(a[i]) & (0xff)), (char)(Integer.parseInt(a[i]) >>> 8 & (0xff)), (char)(Integer.parseInt(a[i]) >>> 16 & (0xff)), (char)(Integer.parseInt(a[i]) >>> 24 & (0xff))});
        }

        return b ? String.join("",a).substring(0, c) : String.join("",a);
    }

   public static String getUserInfoEncoded(String info,String token){
        return "{SRBX1}" + encodeUserInfo(encode(info, token));
   }
//...

Page Break using Javascript Jquery in view and Print

I have this code which I want to use pagebreak when the data in the first page is overlap in must goes to the next page since the size of my container-body3 paper is A4 and I tried dynamically but it didn’t work until, can someone help me with this? Im out of option

enter image description here

function printForms() {
  window.print();
}
<style>     
        .container-wrapper {
          display: flex;
          flex-direction: column;
          align-items: center;
          justify-content: flex-start;
          height: auto;
          padding-bottom: 50px;
          background-color: #cccccc;
        }
          
        .container {
          display: flex;
          justify-content: space-between;
          align-items: center;
          width: 100%;
          height: 5%;
          background-color: #f0f0f0;
          border-radius: 8px;
          box-shadow: 0px 2px 4px rgba(0, 0, 0, 0.2);
          margin-bottom: 20px;
          padding: 0 10px;
        }
          
        .print-button {
          background-color: #b2c2ce;
          color: white;
          border: none;
          border-radius: 4px;
          padding: 8px 12px;
          cursor: pointer;
          margin-right: 500px;
        }

        .container-body3  {
          width: 210mm;
          height:297mm;
          background-color: #ffffff;
          box-shadow: 0px 0px 12px rgba(0, 0, 0, 0.5);
          display: flex;
          flex-direction: column;
          padding: 20px;
          position: relative;
          padding: 50px;
        }
        .appendix {
          position: absolute;
          top: 65px;
          right: 50px;
          font-size: 14px;
          font-style: italic;
        }
          
          table {
            border: 3px solid;
            border-collapse: collapse;
            width: 100%;
            margin-top: 40px;
          }
          
          th,
          td {
            border: 1px solid #000000;
            text-align: left;
            padding: 8px;
          }
          
          th {
            background-color: #f2f2f2;
          }
          
          .center-text {
            text-align: center;
            vertical-align: top;
          }
          .dvnumber {
            background-color:#c6e0b4;
            border:1.8px solid;
            font-size: 15px;
          }
        .coloredrow {
          background-color: rgb(158, 198, 255);
          -webkit-print-color-adjust: exact;
        }
        .align-u-left {
          text-align: left;
          vertical-align: top;
        }
        
        table.myClass * { /*new*/
          border: 0;
        }
         
        @media print {
          .container {
          display: none;
        }
        
        .container-body3 {
          page-break-inside: auto;
          margin: 0;
        }
        .page-break {
          page-break-before: always;
        }
        .header {
          margin-top: 0; /* Default margin for the header */
        }
        
        @page {
          margin: 10mm; /* Default margin for the whole page */
        }
        
        .header.large-margin {
          margin-top: 50mm; /* Adjust this value as needed */
        }
        
        .page-start-5 ~ .header {
          margin-top: 50mm; /* Larger margin to simulate a new header for pages starting after page 4 */
        }
        
        .container-body3{
          background-color: #f0f0f0;
          box-shadow: none;
          width: 210mm;
          height: 297mm;
          margin-top: -30px;
        }
        
          .container h3 {
            color: transparent;
          }
        
          .container-wrapper {
            align-items: flex-start;
          }
        
          table {
            margin-top: 15px;
            border: 3px solid;
          }
        
          .appendix {
            top: 45px;
          }
        
          /* Adjust font size for Disbursement Voucher in print */
          .center-text b {
            font-size: 14px;
          }
          .dvnumber {
            background-color: #c6e0b4 !important;
            -webkit-print-color-adjust: exact;
            color: black; /* Make sure text remains readable */
            border: 1.8px solid;
            font-size: 15px;
          }
        
        .container-body3{
          page-break-before: always;
        }
        .footer {
          margin-top: 95% !important;
        }}
        
        .innerTable{
          margin:0px;
          border-color:white;  
        }
        .lastRow{
          padding:0px;
        }
        
        .align-text-right{
        text-align: right;
        }
        .align-text-right{
        text-align: right;
        }
        .no-border{
        border: 0;
        }
        
        .footer {
        margin-top: 99%;
        }
        
        </style>
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.6.0/jquery.min.js"></script>
<script src="https://stackpath.bootstrapcdn.com/bootstrap/4.3.1/js/bootstrap.bundle.min.js"></script>

<html>
 
    <body>
        <div class="container-wrapper">
            <div class="container">
              <h3></h3>
    
              <button class="print-button" onclick="printForms()">Print</button>
    
            </div>
            <div class="container-body3">
                <br><br><br>
                <span style="font-family: Calibri, sans-serif;" ><center>TESTING HEADER HEADER HEADER HEADER<br> SUB HEADER / SUB HEADER / SUB<br> no# 24-03-767 <br> for January 29, 2024</center></span>
                <table style="font-family: Calibri, sans-serif;" >
                <thead></thead>
                <tbody>
                    <tr >
                    <td><b>No.</b></td>
                    <td><b>Account Number</b></td>
                    <td><b>ID NUMBER</b></td>
                    <td><b><center>NAME</center></b></td>
                    <td><b>AMOUNT</b></td>
                    <td><b>CHARGE</b></td>
                    <td><b><center>PURPOSE</center></b></td>
                    
                    </tr>              
                 
                    <tr>
                    <td class="align-text-right" style="padding: 2; width:6%">1</td>
                    <td class="align-text-right" style="padding: 4;">367167793</td>
                    <td class="align-text-left" style="padding: 4;">16-10653</td>
                    <td  class="align-text-left" style="padding: 4;">Santiago, Bruise N. </td>
                    <td style="padding: 4;" class="align-text-right">5,454,545.00</td>
                    <td class="align-text-left" style="padding: 4;">Charge test</td>
                    <td class="align-text-left" style="padding: 4;">TE for Mar 2024</td>
                    </tr>
                    <tr>
                      <td class="align-text-right" style="padding: 2; width:6%">1</td>
                      <td class="align-text-right" style="padding: 4;">367167793</td>
                      <td class="align-text-left" style="padding: 4;">16-10653</td>
                      <td  class="align-text-left" style="padding: 4;">Santiago, Bruise N. </td>
                      <td style="padding: 4;" class="align-text-right">5,454,545.00</td>
                      <td class="align-text-left" style="padding: 4;">Charge test</td>
                      <td class="align-text-left" style="padding: 4;">TE for Mar 2024</td>
                    </tr>
                    <tr>
                      <td class="align-text-right" style="padding: 2; width:6%">1</td>
                      <td class="align-text-right" style="padding: 4;">367167793</td>
                      <td class="align-text-left" style="padding: 4;">16-10653</td>
                      <td  class="align-text-left" style="padding: 4;">Santiago, Bruise N. </td>
                      <td style="padding: 4;" class="align-text-right">5,454,545.00</td>
                      <td class="align-text-left" style="padding: 4;">Charge test</td>
                      <td class="align-text-left" style="padding: 4;">TE for Mar 2024</td>
                    </tr>
                    <tr>
                      <td class="align-text-right" style="padding: 2; width:6%">1</td>
                      <td class="align-text-right" style="padding: 4;">367167793</td>
                      <td class="align-text-left" style="padding: 4;">16-10653</td>
                      <td  class="align-text-left" style="padding: 4;">Santiago, Bruise N. </td>
                      <td style="padding: 4;" class="align-text-right">5,454,545.00</td>
                      <td class="align-text-left" style="padding: 4;">Charge test</td>
                      <td class="align-text-left" style="padding: 4;">TE for Mar 2024</td>
                    </tr>
                    <tr>
                      <td class="align-text-right" style="padding: 2; width:6%">1</td>
                      <td class="align-text-right" style="padding: 4;">367167793</td>
                      <td class="align-text-left" style="padding: 4;">16-10653</td>
                      <td  class="align-text-left" style="padding: 4;">Santiago, Bruise N. </td>
                      <td style="padding: 4;" class="align-text-right">5,454,545.00</td>
                      <td class="align-text-left" style="padding: 4;">Charge test</td>
                      <td class="align-text-left" style="padding: 4;">TE for Mar 2024</td>
                    </tr>
                    <tr>
                      <td class="align-text-right" style="padding: 2; width:6%">1</td>
                      <td class="align-text-right" style="padding: 4;">367167793</td>
                      <td class="align-text-left" style="padding: 4;">16-10653</td>
                      <td  class="align-text-left" style="padding: 4;">Santiago, Bruise N. </td>
                      <td style="padding: 4;" class="align-text-right">5,454,545.00</td>
                      <td class="align-text-left" style="padding: 4;">Charge test</td>
                      <td class="align-text-left" style="padding: 4;">TE for Mar 2024</td>
                    </tr>
                    <tr>
                      <td class="align-text-right" style="padding: 2; width:6%">1</td>
                      <td class="align-text-right" style="padding: 4;">367167793</td>
                      <td class="ali  gn-text-left" style="padding: 4;">16-10653</td>
                      <td  class="align-text-left" style="padding: 4;">Santiago, Bruise N. </td>
                      <td style="padding: 4;" class="align-text-right">5,454,545.00</td>
                      <td class="align-text-left" style="padding: 4;">Charge test</td>
                      <td class="align-text-left" style="padding: 4;">TE for Mar 2024</td>
                    </tr>
                    <tr>
                      <td class="align-text-right" style="padding: 2; width:6%">1</td>
                      <td class="align-text-right" style="padding: 4;">367167793</td>
                      <td class="align-text-left" style="padding: 4;">16-10653</td>
                      <td  class="align-text-left" style="padding: 4;">Santiago, Bruise N. </td>
                      <td style="padding: 4;" class="align-text-right">5,454,545.00</td>
                      <td class="align-text-left" style="padding: 4;">Charge test</td>
                      <td class="align-text-left" style="padding: 4;">TE for Mar 2024</td>
                    </tr>

                    <tr>
                      <td class="align-text-right" style="padding: 2; width:6%">1</td>
                      <td class="align-text-right" style="padding: 4;">367167793</td>
                      <td class="align-text-left" style="padding: 4;">16-10653</td>
                      <td  class="align-text-left" style="padding: 4;">Santiago, Bruise N. </td>
                      <td style="padding: 4;" class="align-text-right">5,454,545.00</td>
                      <td class="align-text-left" style="padding: 4;">Charge test</td>
                      <td class="align-text-left" style="padding: 4;">TE for Mar 2024</td>
                    </tr>

                    <tr>
                      <td class="align-text-right" style="padding: 2; width:6%">1</td>
                      <td class="align-text-right" style="padding: 4;">367167793</td>
                      <td class="align-text-left" style="padding: 4;">16-10653</td>
                      <td  class="align-text-left" style="padding: 4;">Santiago, Bruise N. </td>
                      <td style="padding: 4;" class="align-text-right">5,454,545.00</td>
                      <td class="align-text-left" style="padding: 4;">Charge test</td>
                      <td class="align-text-left" style="padding: 4;">TE for Mar 2024</td>
                    </tr>

                    <tr>
                      <td class="align-text-right" style="padding: 2; width:6%">1</td>
                      <td class="align-text-right" style="padding: 4;">367167793</td>
                      <td class="align-text-left" style="padding: 4;">16-10653</td>
                      <td  class="align-text-left" style="padding: 4;">Santiago, Bruise N. </td>
                      <td style="padding: 4;" class="align-text-right">5,454,545.00</td>
                      <td class="align-text-left" style="padding: 4;">Charge test</td>
                      <td class="align-text-left" style="padding: 4;">TE for Mar 2024</td>
                    </tr>

                    <tr>
                      <td class="align-text-right" style="padding: 2; width:6%">1</td>
                      <td class="align-text-right" style="padding: 4;">367167793</td>
                      <td class="align-text-left" style="padding: 4;">16-10653</td>
                      <td  class="align-text-left" style="padding: 4;">Santiago, Bruise N. </td>
                      <td style="padding: 4;" class="align-text-right">5,454,545.00</td>
                      <td class="align-text-left" style="padding: 4;">Charge test</td>
                      <td class="align-text-left" style="padding: 4;">TE for Mar 2024</td>
                    </tr>

                    <tr>
                      <td class="align-text-right" style="padding: 2; width:6%">1</td>
                      <td class="align-text-right" style="padding: 4;">367167793</td>
                      <td class="align-text-left" style="padding: 4;">16-10653</td>
                      <td  class="align-text-left" style="padding: 4;">Santiago, Bruise N. </td>
                      <td style="padding: 4;" class="align-text-right">5,454,545.00</td>
                      <td class="align-text-left" style="padding: 4;">Charge test</td>
                      <td class="align-text-left" style="padding: 4;">TE for Mar 2024</td>
                    </tr>

                    <tr>
                      <td class="align-text-right" style="padding: 2; width:6%">1</td>
                      <td class="align-text-right" style="padding: 4;">367167793</td>
                      <td class="align-text-left" style="padding: 4;">16-10653</td>
                      <td  class="align-text-left" style="padding: 4;">Santiago, Bruise N. </td>
                      <td style="padding: 4;" class="align-text-right">5,454,545.00</td>
                      <td class="align-text-left" style="padding: 4;">Charge test</td>
                      <td class="align-text-left" style="padding: 4;">TE for Mar 2024</td>
                    </tr>
                    <tr>
                      <td class="align-text-right" style="padding: 2; width:6%">1</td>
                      <td class="align-text-right" style="padding: 4;">367167793</td>
                      <td class="align-text-left" style="padding: 4;">16-10653</td>
                      <td  class="align-text-left" style="padding: 4;">Santiago, Bruise N. </td>
                      <td style="padding: 4;" class="align-text-right">5,454,545.00</td>
                      <td class="align-text-left" style="padding: 4;">Charge test</td>
                      <td class="align-text-left" style="padding: 4;">TE for Mar 2024</td>
                    </tr>

                    <tr>
                      <td class="align-text-right" style="padding: 2; width:6%">1</td>
                      <td class="align-text-right" style="padding: 4;">367167793</td>
                      <td class="align-text-left" style="padding: 4;">16-10653</td>
                      <td  class="align-text-left" style="padding: 4;">Santiago, Bruise N. </td>
                      <td style="padding: 4;" class="align-text-right">5,454,545.00</td>
                      <td class="align-text-left" style="padding: 4;">Charge test</td>
                      <td class="align-text-left" style="padding: 4;">TE for Mar 2024</td>
                    </tr>

                    <tr>
                      <td class="align-text-right" style="padding: 2; width:6%">1</td>
                      <td class="align-text-right" style="padding: 4;">367167793</td>
                      <td class="align-text-left" style="padding: 4;">16-10653</td>
                      <td  class="align-text-left" style="padding: 4;">Santiago, Bruise N. </td>
                      <td style="padding: 4;" class="align-text-right">5,454,545.00</td>
                      <td class="align-text-left" style="padding: 4;">Charge test</td>
                      <td class="align-text-left" style="padding: 4;">TE for Mar 2024</td>
                    </tr>

                    <tr>
                      <td class="align-text-right" style="padding: 2; width:6%">1</td>
                      <td class="align-text-right" style="padding: 4;">367167793</td>
                      <td class="align-text-left" style="padding: 4;">16-10653</td>
                      <td  class="align-text-left" style="padding: 4;">Santiago, Bruise N. </td>
                      <td style="padding: 4;" class="align-text-right">5,454,545.00</td>
                      <td class="align-text-left" style="padding: 4;">Charge test</td>
                      <td class="align-text-left" style="padding: 4;">TE for Mar 2024</td>
                    </tr>

                    <tr>
                      <td class="align-text-right" style="padding: 2; width:6%">1</td>
                      <td class="align-text-right" style="padding: 4;">367167793</td>
                      <td class="align-text-left" style="padding: 4;">16-10653</td>
                      <td  class="align-text-left" style="padding: 4;">Santiago, Bruise N. </td>
                      <td style="padding: 4;" class="align-text-right">5,454,545.00</td>
                      <td class="align-text-left" style="padding: 4;">Charge test</td>
                      <td class="align-text-left" style="padding: 4;">TE for Mar 2024</td>
                    </tr>
                    <tr>
                      <td class="align-text-right" style="padding: 2; width:6%">1</td>
                      <td class="align-text-right" style="padding: 4;">367167793</td>
                      <td class="align-text-left" style="padding: 4;">16-10653</td>
                      <td  class="align-text-left" style="padding: 4;">Santiago, Bruise N. </td>
                      <td style="padding: 4;" class="align-text-right">5,454,545.00</td>
                      <td class="align-text-left" style="padding: 4;">Charge test</td>
                      <td class="align-text-left" style="padding: 4;">TE for Mar 2024</td>
                    </tr>
                    <tr>
                      <td class="align-text-right" style="padding: 2; width:6%">1</td>
                      <td class="align-text-right" style="padding: 4;">367167793</td>
                      <td class="align-text-left" style="padding: 4;">16-10653</td>
                      <td  class="align-text-left" style="padding: 4;">Santiago, Bruise N. </td>
                      <td style="padding: 4;" class="align-text-right">5,454,545.00</td>
                      <td class="align-text-left" style="padding: 4;">Charge test</td>
                      <td class="align-text-left" style="padding: 4;">TE for Mar 2024</td>
                    </tr>

                </tbody>
                </table>

                <table  style="border: 0; font-family: Calibri, sans-serif;" class="myClass" cellspacing="0" cellpadding="0" width="100%">
                <tbody>
                    <tr>
                    <td>
                        <table style="border: 0;">
                        <tbody>
                            <tr>
                            <td style="width: 0px;border:0;"></td>
                            <td style="width: 30px;border:0;"></td>
                            <td style="width: 100px;border:0;"></td>
                            </tr>
                            <tr>
                            <td style="font-size: 13px;padding: 0;" colspan="2" class="no-border">PREPARED BY:</td>
            
                            </tr>
                            <tr>
                            <td class="no-border"></td>
            
                            </tr>
                            <tr>
                            <td class="no-border"></td>
                            <td class="no-border" colspan="2" >
                                <!-- <center><b><u>Janice UUUUU</u></b></center> -->
                                <center><b><u><span contenteditable="true" id="editableName">Reymark Santiago</span></u></b></center>
                            </td>
                            </td>
                            </tr>
                            <tr>
                            <td class="no-border"></td>
                            <td class="no-border" colspan="2">
                                <center><span contenteditable="true" id="editablePosition">AAAA III</span></center>
                            </td>
                            </tr>
            
            
                        </tbody>
                        </table>
                    </td>
                    <td>
                        <table style="border: 0;">
                        <tbody>
                            <tr>
                            <td style="width: 140px;border:0;"></td>
                            <td style="width:80px;border:0;"></td>
                            <td style="width:72px;border:0;"></td>
                            <td style="border:0;"></td>
            
                            </tr>
                            <tr>
                            <td style="font-size: 15px;background-color:rgb(158, 198, 255); padding: 0;" class="no-border coloredrow"><b>CHARGE</b></td>
                            <td style="font-size: 15;background-color:rgb(158, 198, 255); padding: 0; text-align: right;" colspan="2" class="no-border coloredrow"><b>Sum of AMOUNT</b></td>
                            </tr>
            
                           
                            <tr>
                            <td style="padding: 0;" class="no-border"> charges</td>
                            <td style="padding: 0; text-align: right;" class="no-border" colspan="2">
                                5,482,119.00
                            </td>
                            </tr>
                            <tr>
                            <td style="padding: 0;;background-color:rgb(158, 198, 255);" class="no-border coloredrow"><b>GRAND Total</b></td>
                            <td style="padding: 0;background-color:rgb(158, 198, 255); text-align: right;"  class="no-border coloredrow" colspan="2"><b>5,482,119.00</b></td>
                            </tr>
                        </tbody>
                        </table>
                    </td>
                    </tr>
                </tbody>
                </table>
                
            </div>
        </div>
    </body>

</html>

Execute a function after popup window is closed

I have a popup window that I create as follows:

popupWindow = window.open("about:blank", "_blank", "popup=yes");

And I have a function afterFn() that I need to execute after the popupWindow is closed.

My current approach is as follows:

async function pollPopupWindow() {
  while (popupWindow) {
    await new Promise((r) => setTimeout(r, 1000));
    if (popupWindow.closed) {
      popupWindow = null;
      afterFn();
    }
  }
}
pollPopupWindow();

I was wondering if it’s possible to simply execute the afterFn() at the popup window closing time? I tried the following code but it did not work

popupWindow.addEventListener("beforeunload", () => {
  afterFn();
});

any ideas?

my Model.create() in sequelize and node.js does not save data on mysql database

I working on creating a detabase using mysql and node.js and sequelize . my model is saved on my database as i ordered but when i want send data it does not work
here is my codes
Database.js

const { Sequelize } = require("sequelize");
const sequelize = new Sequelize("node-compelet", "root", "zahra@1996", {
  dialect: "mysql",
  host: "localhost",
});
module.exports = sequelize;

and my Model called product.js

const sequelize = require("../util/database");
const { Sequelize, DataTypes } = require("sequelize");

const Product = sequelize.define("Product", {
  id: {
    type: DataTypes.INTEGER,
    autoIncrement: true,
    allowNull: false,
    primaryKey: true,
  },
  title: { type: DataTypes.STRING },
  price: { type: DataTypes.DOUBLE, allowNull: false },
  imgUrl: { type: DataTypes.STRING, allowNull: false },
  description: { type: DataTypes.STRING, allowNull: false },
});
module.exports = Product;

and my controller :

const Product = require("../models/product")
exports.postAddProduct = (req, res, next) => {
  const title = req.body.title;
  const imgUrl = req.body.imgUrl;
  const price = req.body.price;
  const description = req.body.description;
  console.log(req.body);
  Product.create({
    title: title,
    price: price,
    imgUrl: imgUrl,
    description: description,
  })
    .then((result) => {
      console.log("result");
      res.redirect("/");
    })
    .catch((err) => console.log(err));
};

and my app.js

const sequelize = require("./util/database");
const Product = require("../models/product")
sequelize
  .sync({ force: true })
  .then((result) => {
    app.listen(3000);
    console.log("synced secceed");
  })
  .catch((err) => {
    console.log(err);
    console.log("faild");
  });

every time I tried to send data from my form to database nothing happens and just my web page continue loading . also in my controller I tried to log received data but it didn’t worked . I got no error message . it seems that my model don’t work properly .
I checked router and my functions was added properly there .

Best way to remove gaps on candlestick chart using JS Observable Plot (d3)?

I have been working on a candlestick chart using Observable Plot, and I have come across a problem with gaps in the chart. In my dataset, there are of course gaps for weekends when no trading occurs, but I did not expect these gaps to appear in the final plot. This is my first time using Observable Plot.

const ticker = parseDates(tickerData);
const radioBtns = document.getElementsByName("chartType");
let chartType;

for(var i = 0; i < radioBtns.length; i++) {
  radioBtns[i].onclick = updateChart;
}

updateChart();

function updateChart() {
  // reset images
  candlestickLabel.childNodes[0].src = "assets/candlestick-unselected.png";
  lineLabel.childNodes[0].src = "assets/line-unselected.png";
  areaLabel.childNodes[0].src = "assets/area-unselected.png";

  for (let i = 0; i < radioBtns.length; i++) {
    // loop through radio buttons
    if (radioBtns[i].checked) {
      // set chartType to the value of the selected button
      chartType = radioBtns[i];
      
      // loop through labels and set the image to selected if checked
      const labels = document.getElementsByTagName("label");
      for (let j = 0; j < labels.length; j++) {
        if (labels[j].htmlFor == radioBtns[i].id) {
          labels[j].childNodes[0].src = "assets/" + chartType.value + "-selected.png";
        }
      }
    }
  }

  // set up chart based on selected type
  let plot = null;

  if (chartType.value == "candlestick") {plot = Plot.plot({
      inset: 20,
      width: 1000,
      height: 400,
      grid: true,
      x: {
        domain: [ticker[0].date, ticker[ticker.length - 1].date],
        reverse: true,
        tickFormat: d => Plot.formatIsoDate(d), // Format ticks as dates
        tickRotate: -15,
        tickPadding: 5,
      },
      y: {
        label: "↑ Stock price ($)"
      },
      color: {
        domain: [-1, 0, 1],
        range: ["#f23645", "currentColor", "#138808"]
      },
      marks: [
        Plot.ruleX(ticker.filter(d => d.low), {
          x: "date",
          y1: "low",
          y2: "high",
          stroke: d => Math.sign(d.close - d.open),
        }),
        Plot.ruleX(ticker, {
          x: "date",
          y1: "open",
          y2: "close",
          stroke: d => Math.sign(d.close - d.open),
          strokeWidth: 4,
          strokeLinecap: "butt"
        })
      ]
    });
  } else if (chartType.value == "line") {
    plot = Plot.plot({
      inset: 6,
      // width and height match that of container
      width: 1000,
      height: 400,
      grid: true,
      x: {
        // set the domain
        domain: [new Date(ticker[0].date), new Date(ticker[ticker.length - 1].date)],
        reverse: true
      },
      y: {
        label: "↑ Stock Price ($)"
      },
      marks: [
        Plot.lineY(ticker, {
          x: "date",
          y: "close",
          stroke: "#6495ed"
        })
      ]
    });
  } else {
    plot = Plot.plot({
      inset: 6,
      // width and height match that of container
      width: 1000,
      height: 400,
      grid: true,
      x: {
        // set the domain
        domain: [new Date(ticker[0].date), new Date(ticker[ticker.length - 1].date)],
        reverse: true
      },
      y: {
        label: "↑ Stock Price ($)"
      },
      marks: [
        Plot.lineY(ticker, {
          x: "date",
          y: "close",
          stroke: "#6495ed"
        }),
        Plot.areaY(ticker, {
          x: "date",
          y1: Math.min(...ticker.map((t) => t.close)) - 10,
          y2: "close",
          fill: "#6495ed",
          fillOpacity: 0.3
        })
      ]
    });
  }

  const div = chartDiv;
  div.innerHTML = "";
  div.append(plot);
}

// UTILITY FUNCTIONS

const weeks = (start, stop, stride) => d3.utcMonday.every(stride).range(start, +stop + 1);
const weekdays = (start, stop) => d3.utcDays(start, +stop + 1).filter(d => d.getUTCDay() !== 0 && d.getUTCDay() !== 6);

function parseDates(data) {
  return data.map(d => ({
    ...d,
    date: new Date(d.date)  // Ensure `date` is a Date object
  }));
}

Here is my dataset format:

const tickerData = [{
          date: "2024-09-10",
          open: 204.2000,
          high: 205.8300,
          low: 202.8700,
          close: 205.3200,
          volume: 3070644
        },{
          date: "2024-09-09",
          open: 201.9400,
          high: 205.0500,
          low: 201.4300,
          close: 203.5300,
          volume: 3705004
        },{
          date: "2024-09-06",
          open: 202.3800,
          high: 204.1000,
          low: 199.3350,
          close: 200.7400,
          volume: 3304491
        }
}]

I have tried several solutions, but to no avail. First I made sure that the dataset was parsed correctly and contained no weekend data. I have also tried several things using the tick, tickFormat, and domain options for the x-axis.

How to make Parse server login — case insensitive?

I have Parse server with MongoDB and KMP app where login method.

@POST("login")
@Headers(
    value = [
        "${ParseHeaders.CONTENT_TYPE}: application/json",
        "${ParseHeaders.APPLICATION_ID}: ${ParseConstants.APPLICATION_ID}",
        "${ParseHeaders.REST_API_KEY}: ${ParseConstants.REST_API_KEY}",
    ],
)
suspend fun logIn(@Body credentials: ParseLoginCredentials): ParseUserResponse

I need to make the username case-insensitive. Currently, usernames are stored in MongoDB in a disorganized way. We need to structure this on the server side, so the login username in the Parse server must be case-insensitive. I don’t see any login functions in the Parse backend code, yet the login works for some reason. Perhaps it’s handled internally by Parse. I’ve written an interceptor in the Parse server code, but it’s not working.

app.post('/login', function(req, res) {
  let fs = require('fs');
  let path = require('path');
  let bodyParser = require('body-parser');

  app.use(bodyParser.json());

  const { username, password } = req.body;

  if (!username || !password) {
    return res.status(400).send('Username and password are required');
  }

  const lowercasedUsername = username.toLowerCase();
  const loginRequest = new Parse.Query(Parse.User);
  loginRequest.equalTo("username", lowercasedUsername);

  loginRequest.first().then(function(user) {
    if (user) {
      const userStoredUsername = user.get("username").toLowerCase();

      if (userStoredUsername === lowercasedUsername) {
        user.authenticate(password).then(function(isAuthenticated) {
          if (isAuthenticated) {
            res.status(200).json({
              objectId: user.id,
              sessionToken: user.getSessionToken(),
            });
          } else {
            res.status(401).send('Invalid credentials');
          }
        }).catch(function(err) {
          res.status(500).send('Error authenticating user: ' + err.message);
        });
      } else {
        res.status(401).send('Invalid credentials');
      }
    } else {
      res.status(401).send('Invalid credentials');
    }
  }).catch(function(err) {
    res.status(500).send('Error finding user: ' + err.message);
  });
});

Is there any option to handle this on the MongoDB side? Or how can it be done with Parse Server? Do I need to write additional code, such as a case-insensitive login hook, or is there another solution?

I also tried modifying and hiding some indexes in the `_User` entity on MongoDB, but it had no effect.
enter image description here

Change select visible value while dropdown text remains unchanged

I have

    <?php
    $option_select=function($opt_val){
        if($opt_val==$_GET["order"]) {
            echo "selected";
        }
    };
    ?>

<form name="sort" id="sort" action="matches.php" method="get" style="float:right; margin:10px;">
    
    <select name="order" id="order" class="order_select" onchange="changeSort()">
        <option <?php $option_select("last_online"); ?> value="last_online">Last online</option>
        <option <?php $option_select("age_asc"); ?> value="age_asc">Age (Young to Old)</option>
        <option <?php $option_select("age_desc"); ?> value="age_desc">Age (Old to Young)</option>
        <option <?php $option_select("height_asc"); ?> value="height_asc">Height (Short to Tall)</option>
        <option <?php $option_select("height_desc"); ?> value="height_desc">Height (Tall to Short)</option>
        <option <?php $option_select("created_asc"); ?> value="created_asc">Date subscribed (New to Old)</option>
        <option <?php $option_select("created_desc"); ?> value="created_desc">Date subscribed (Old to New)</option>
    </select>
    <input type="submit" value=" Sort " class="btn btn-info" hidden/>
    </form>


<script>

var orderSelector = document.getElementById("order");
orderSelector.options[orderSelector.selectedIndex].text = "Sorted by: " + orderSelector.options[orderSelector.selectedIndex].text;

function changeSort() {
    var orderSelector = document.getElementById("order");
    orderSelector.options[orderSelector.selectedIndex].text = "Sorted by: " + orderSelector.options[orderSelector.selectedIndex].text;
    
    var orderForm = document.getElementById("sort");
    orderForm.submit();
}

</script>

I need the select field to show “Sort by: ” + selected value, however while keeping the value in the dropdown not changed.
I.e. dropdown displayed text says “Sort by: Age (Old to Young)”, while inside the dropdown it’s just “Age (Old to Young)” with the standard check on the left.
An example is ebay or amazon.com.