How do I make the array print out in the console log (recursion)

I am doing recursion for the first time in javascript. I made an array and want it to print out every element however it only printso ut the first element (1)

function loop4(){
    arr = [1,2,3,4,5,6,7,8,9,10]
    i=0
    console.log(arr[i])
    i++
    if(i<arr.length){
        loop4(i)
    }
    else{
        return

    }
    
}

loop4()

This is the code for the program

I have looked at it logically and can see where my mistake was. When the loop starts again “i” is set as 0 therefore infintanly printing out “1” How can I upadte the code in order for it to print out an array with recursion ?

I expect the code to print out the array however i am incapible of doing that so any help would be appreciated

How to Keep Edit Icon Always Visible at the Bottom of Notes?

<!DOCTYPE html>
<html lang="en">
<head>
  <meta charset="UTF-8">
  <meta name="viewport" content="width=device-width, initial-scale=1.0">
  <title>Document</title>
  <link rel="stylesheet" href="style.css">
  <link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/font-awesome/6.5.1/css/all.min.css">
  <script defer src="script.js"></script>
</head>
<body>
  <div class="container">
    <div class="add">
      <i class="fa-duotone fa-plus"></i>
    </div>
    <div class="new-note">
      <h1>New Note</h1>
      <textarea name="" id="" placeholder="Enter your note..."></textarea>
      <button class = 'create-note'>Create Note</button>
      <button class=  'close-btn'>Close</button>
    </div>
  </div>
</body>
</html>
* {
  box-sizing: border-box;
}

body {
  background-image: linear-gradient(to right,#8c53ff,#725f97);
  display: flex;
  height: 96vh;
  justify-content: center;
  align-items: center;
}
.container {
  width: 853px;
  height: 600px;
  border: 1px solid white;
  background-color: white;  
  border-radius: 8px;
  overflow-y: scroll;
  display: flex;
  flex-wrap: wrap;
}

.add {
  width: 237px;
  height: 241px;
  border: 1px solid #ddd;
  border-radius: 6px;
  background-color: #f9f9f9;
  margin-left: 6%;
  margin-top: 2%;
  display: flex;
  align-items: center;
  justify-content: center;
}
.add:hover {
  background-color: rgb(239, 238, 238);
}
.fa-duotone {
  font-size: 85px;
  font-weight: 800;
  color: gainsboro;
  font-family: "Font Awesome 6 Free";
  font-style: normal;
}

.new-note {
  width: 441px;
  height: 341px;
  border: 1px solid white;
  box-shadow: 0 0 10px rgba(0, 0, 0, 0.1);
  position: absolute;
  top: 20%;
  left: 36%;
  border-radius: 10px;
  background-color: white;
  display: none;
  z-index: 1;
}

.new-note h1 {
  margin-left: 36%;
}

textarea {
  width: 300px;
  height: 144px;
  border: 2px solid #8c53ff;
  padding: 12px;
  margin-left: 18%;
  border-radius: 10px;
}

.create-note {
  background-color: #8c53ff;
  color: white;
  border: none;
  margin-left: 120px;
  margin-top: 16px;
}
.close-btn {
  height: 36.8px;
  width: 100px;
  background-color: gainsboro;
  border: none;
  color: white;
  margin-left: 8px;
}

.create-note,.close-btn {
  font-size: 14px;
  width: 100px;
  height: 36.8px;
  border-radius: 5px;
}

.blank-div1,.blank-div2 {
  height: 240px;
  width: 240px;
  background-color: gainsboro;
}


.notes {
  height: 240px;
  width: 240px;
  background-color: #fff385;
  border-radius: 10px;
  box-shadow: 9px 9px 18px #b3b3b3;
  overflow-y: auto;
  padding: 18px;
  margin-left: 4%;
  margin-top: 2%;
  position: relative;
}

.fa-solid {
  position: absolute;
}

@media only screen and (max-width: 600px) {
  body {
    height: 84vh;
  }
  .container {
    width: 408px;
    height: 440px;
  }
  .add {
    width: 186px;
    height: 182px;
    top: 21%;
    left: 8%;
    border-radius: 15px;
  }
  .new-note {
    left: 1%;
    width: 424px;
  }
}
let add = document.querySelector('.add');
let newDiv = document.querySelector('.new-note');
let close_btn = document.querySelector('.close-btn');
let create_btn = document.querySelector('.create-note');
let text_area = document.querySelector('textarea');
let text = '';
let edit = document.createElement('i');
edit.className = 'fa-solid';
let container = document.querySelector('.container');

add.addEventListener('click', () => {
    newDiv.style.display = 'block';
});

close_btn.addEventListener('click', () => {
    newDiv.style.display = 'none';
});

create_btn.addEventListener('click', () => {
    newDiv.style.display = 'none';
    let newNote = document.createElement('div');
    newNote.textContent = text_area.value;
    newNote.className = 'notes';
    newNote.appendChild(edit);
    container.appendChild(newNote);
});

I’m working on a simple notes app where users can create notes, and each note has an edit and delete button. The edit button is supposed to always be visible inside each note, but for some reason, it is not displaying as expected. I have to scroll to the bottom of each note to make the edit icon appear.

What I’ve Tried:
Adding the edit button inside the note div – I used appendChild() to add the edit button () to the newly created note div, but it is not consistently visible.
Using CSS to position it – I tried setting position: absolute inside the note div to place the edit button, but it still disappears when the content grows.
Adding a separate span for text – I wrapped the note content inside a and attempted to set its height smaller than the note div, hoping to leave space for the edit button, but it had no effect.
Using flexbox/grid – I attempted to use display: flex and justify-content properties, but the button still moves unexpectedly.
How can I ensure that the edit button remains visible at all times inside each note, regardless of the content size?

How to combine lots of static JavaScript files into one big one using Rails and Propshaft?

I just created a brand new Ruby on Rails 8.0.1 app with Propshaft included. I got the SCSS part working but I can’t seem to get the JavaScript part working.

Unlike with most other apps, I have only a bunch of static JS files that I want to combine into one big file, e.g. application.js. I don’t need modules nor do I need Importmaps.

When using Sprockets in my previous app, I could simple put this into my application.js file:

//= require_tree .

And it would combine all my 50 JS files into one big file.

How can something similar be achieved with Propshaft?

Visualforce table with add new row with input file

My company needs a simple table with add and delete row for external site based on visualforce. This table must contain 3 fields: Full Name, Date of birth, File (passport scan). User must add new row and then fill all fields (also attach the file), then user press new row and do the same. The problem is in rerender table and view state. I’ve solved rerender issue, but stuck with view state. View state is too large, because all attachment data saved in controller variables, because I need to save them after form save.

My question is how to solve that problem and implement this type of table. Thinking about using js for table construction, and after save pull all data from js object to controller, but I think it also cause view state error.

My page code is next:

<apex:page controller="TestPageController" html-autocomplete="off" standardStylesheets="false" showHeader="false" applyBodyTag="false" applyHtmlTag="false" docType="html-5.0" title="GBM" cache="false" id="page" language="en">
<script>
var attachmentList;
    var maxStringSize = 6000000;
    var j;

    function uploadFiles(index){
        var fileId = 'passportFile' + index;
        input = document.getElementById(fileId);;
        attachmentList = input.files;

        if (j == undefined)
            j = 0;
        var file;

        file = attachmentList[0];
        var name = file.name;
        var reader = new FileReader();
        reader.onload = function (e) {
            var attachmentbodybase64 = reader.result.replace(/^data:.+;base64,/, ''); //console log will print : ZGF0YTppbWFnZS9wbmc7YmFzZTY0LGlWQk9SdzB.....
            console.log(attachmentbodybase64.length);
            if (attachmentbodybase64.length > maxStringSize)
                alert("File size is too large to handle");
            else {
                j++;
                let path = 'page:form:repeat:';
                let rowI = index-1;
                $("[id$='"+path+rowI+":fileBody']").val(attachmentbodybase64).trigger('change');
                $("[id$='"+path+rowI+":fileName']").val(name).trigger('change');

                $("[id$='passportFile"+index+"label']").text(name);

            }
        }
        reader.readAsDataURL(file);
    }
</script>
<apex:form id="form" styleClass="form">
    <apex:outputPanel id="Form">
        <ul class="pagination justify-content-center">
            <div class="form-group required tbl">
                <br/>
                <div style="font-size:30px;" class="text-center">
                    Directors
                </div>
                <apex:actionregion>
                    <apex:outputPanel id="directorsPanel">
                        <apex:variable value="{!0}" var="index"/>
                        <table class="table table-bordered" id="dTable">
                            <thead>
                                <tr>
                                    <th scope="col">Full Name</th>
                                    <th scope="col">Date of Birth</th>
                                    <th scope="col" style="width:25%">Copy of passport</th>
                                </tr>
                            </thead>
                            <tbody class="table-group-divider">
                                <apex:repeat value="{!selectDirectorsList}" var="i" id="repeat" >
                                    <tr id="trow">
                                        <td>
                                            <apex:input id="table_fullName" styleclass="form-control {!IF(i.fullName == '','is-invalid','is-valid')}" onchange="validate(this);" value="{!i.fullName}"/>
                                        </td>
                                        <td>
                                            <apex:input id="table_birthday" styleClass="form-control {!IF(i.birthday == '','is-invalid','is-valid')} date" onchange="validate(this);" value="{!i.birthday}"/>
                                        </td>
                                        <td style="vertical-align: middle;">
                                            <apex:variable value="{!index+1}" var="index" />
                                            <label id="passportFile{!index}label" for="passportFile{!index}" class="form-control {!IF(i.fileBody == '','is-invalid','is-valid')}" style="margin-bottom: 0%;">{!IF(i.fileName == '','Select file',i.fileName)}</label>
                                            
                                            <input type="file" 
                                            class="form-control custom-file-input {!IF(i.fileBody == '','is-invalid','is-valid')}" 
                                            multiple="false" 
                                            name="{!i.fileName}"
                                            value="{!i.fileBody}"
                                            id="passportFile{!index}" 
                                            onchange="uploadFiles('{!index}');validateFile(this,{!index});" style="display:none;"/>
                                            <apex:inputTextArea value="{!i.fileBody}"  Id="fileBody" style="display:none;"/>
                                            <apex:inputText value="{!i.fileName}" Id="fileName" style="display:none;"/>
                                        </td>
                                    </tr>
                                </apex:repeat>
                            </tbody>
                        </table>
                    </apex:outputPanel>
                    <ul class="pagination justify-content-end">
                        <div class="btn-group me-2" role="group">
                            <apex:commandButton oncomplete="activateDatePicker();" image="{!URLFOR($Resource.PersonDash)}" action="{!deleteDirector}" id="delRow" value="Del row" styleclass="btn btn-default" reRender="directorsPanel" immediate="false" style="background-color:#fb3b3b;width: 55px;height: 40px;color: white;"/>
                        </div>
                        <div class="btn-group me-2" role="group">
                            <apex:commandButton oncomplete="activateDatePicker();" image="{!URLFOR($Resource.PersonAdd)}" action="{!addDirector}" id="newRow" value="Add row" styleclass="btn btn-default" reRender="directorsPanel" immediate="false" style="background-color:#19d708;width: 55px;height: 40px;color: white;"/>
                        </div>
                    </ul>
                </apex:actionregion>
            </div>
        </ul>
    </apex:outputPanel>
</apex:form>
</apex:page>

And my Page controller is:

    global without sharing class TestPageController {
    public List<DirectorsWrapper> selectDirectorsList {get; set;}
    public Integer rowIndex                { get; set; }

    public TestAssessmentController() {
        rowIndex = 0;
        selectDirectorsList = new list<DirectorsWrapper>();
        selectDirectorsList.add(new DirectorsWrapper(rowIndex,'','','','',null));
    }

    public void addDirector() {
        rowIndex += 1;
        selectDirectorsList.add(new DirectorsWrapper(rowIndex,'','','','',null));
    }

    public void deleteDirector() { 
        if(rowIndex != 0){      
            selectDirectorsList.remove(rowIndex);
            rowIndex -= 1;
        }
    }

    public void save(){}

    public class DirectorsWrapper{
        public Integer row                  { get; set; }
        public String fullName              { get; set; }
        public String birthday              { get; set; }
        public Attachment passportAttach    { get {if (passportAttach == null){ passportAttach = new Attachment(); } return passportAttach; } set; }
        public String fileName              { get; set; }
        public transient blob fileBody      { get; set; }

        public DirectorsWrapper(Integer rowW,String fullNameW, String birthdayW, Attachment passportAttachW, String fileNameW, Blob fileBodyW){
            this.row = rowW;
            this.fullName = fullNameW;
            this.birthday = birthdayW;
            this.passportAttach = passportAttachW;
            this.fileName = fileNameW;
            this.fileBody = fileBodyW;
        }
    }
}

Unexpected 2-4px Height Increase in SVG After Extracting to Angular Component

After extracting it to a separate Angular component, I’m encountering an issue where an SVG’s height increases by several pixels. The SVG displays correctly when inline, but the height grows unexpectedly in the component.
pause.component.html

<svg xmlns="http://www.w3.org/2000/svg" [attr.width]='width' [attr.height]="height" viewBox="0 0 100 100"
  xml:space="preserve">
  <path
    d="M34.124 33.604a23.1 23.1 0 0 1 16.396-6.791 23.12 23.12 0 0 1 16.396 6.791 23.1 23.1 0 0 1 6.791 16.392 23.12 23.12 0 0 1-6.791 16.4c-9.055 9.055-23.737 9.055-32.792 0s-9.055-23.737 0-32.792M45.747 40v20m9.547-20v20"
    fill="none" [attr.stroke]="strokeColor" [attr.stroke-width]="strokeWidth" stroke-linecap="round"
    stroke-linejoin="round" stroke-miterlimit="10" />
</svg>

pause.component.ts

import { Component, Input } from '@angular/core';

@Component({
  selector: 'pause-icon',
  imports: [],
  templateUrl: './pause.component.html',
})
export default class PauseIcon {
  @Input() width?: number = 800;
  @Input() height?: number = 800;
  @Input() strokeColor?: string = '#fff';
  @Input() strokeWidth?: number = 4;
}

Inside other component:

<button type='button' class='play-pause'>
  <pause-icon [width]="24" [height]="24" />
</button>

Below I attached two pictures: the first is an SVG size, and the second is a pause component size.
SVG size
pause component size

javascript fetch automatically retries file streaming requests

I am running into a strange issue and i dont quite understand if this is expected or if this is a bug caused by me and if so how to fix it.

The problem:

When using the fetch function in javascript to upload a file to my server, if the server rejects the request and returns with 4xx or 5xx status codes, the fetch function or something deeper in javascript seems to make the request again instantly multiple times.

I have tracing enabled on my server and am able to see the request is retryed almost instantly after it is rejected:

2025-02-25T13:41:15.276671Z DEBUG request{method=POST uri=/upload_file version=HTTP/1.1}: tower_http::trace::on_request: started processing request
2025-02-25T13:41:15.276853Z ERROR request{method=POST uri=/upload_file version=HTTP/1.1}: web_servicer_library::axum_server::web_api_request_processor: error_message="Request failed validation: filename size exceeds 50"
2025-02-25T13:41:15.276996Z DEBUG request{method=POST uri=/upload_file version=HTTP/1.1}: tower_http::trace::on_response: finished processing request latency=0 ms status=400
2025-02-25T13:41:15.277970Z DEBUG request{method=POST uri=/upload_file version=HTTP/1.1}: tower_http::trace::on_request: started processing request
2025-02-25T13:41:15.278064Z ERROR request{method=POST uri=/upload_file version=HTTP/1.1}: web_servicer_library::axum_server::web_api_request_processor: error_message="Request failed validation: filename size exceeds 50"
2025-02-25T13:41:15.278171Z DEBUG request{method=POST uri=/upload_file version=HTTP/1.1}: tower_http::trace::on_response: finished processing request latency=0 ms status=400
2025-02-25T13:41:15.279220Z DEBUG request{method=POST uri=/upload_file version=HTTP/1.1}: tower_http::trace::on_request: started processing request
2025-02-25T13:41:15.279310Z ERROR request{method=POST uri=/upload_file version=HTTP/1.1}: web_servicer_library::axum_server::web_api_request_processor: error_message="Request failed validation: filename size exceeds 50"
2025-02-25T13:41:15.279411Z DEBUG request{method=POST uri=/upload_file version=HTTP/1.1}: tower_http::trace::on_response: finished processing request latency=0 ms status=400
2025-02-25T13:41:15.280077Z DEBUG request{method=POST uri=/upload_file version=HTTP/1.1}: tower_http::trace::on_request: started processing request
2025-02-25T13:41:15.280153Z ERROR request{method=POST uri=/upload_file version=HTTP/1.1}: web_servicer_library::axum_server::web_api_request_processor: error_message="Request failed validation: filename size exceeds 50"
2025-02-25T13:41:15.280237Z DEBUG request{method=POST uri=/upload_file version=HTTP/1.1}: tower_http::trace::on_response: finished processing request latency=0 ms status=400
2025-02-25T13:41:15.282600Z DEBUG request{method=POST uri=/upload_file version=HTTP/1.1}: tower_http::trace::on_request: started processing request
2025-02-25T13:41:15.282678Z ERROR request{method=POST uri=/upload_file version=HTTP/1.1}: web_servicer_library::axum_server::web_api_request_processor: error_message="Request failed validation: filename size exceeds 50"
2025-02-25T13:41:15.282767Z DEBUG request{method=POST uri=/upload_file version=HTTP/1.1}: tower_http::trace::on_response: finished processing request latency=0 ms status=400
2025-02-25T13:41:23.860972Z DEBUG request{method=POST uri=/upload_file version=HTTP/1.1}: tower_http::trace::on_request: started processing request
2025-02-25T13:41:23.877111Z DEBUG request{method=GET uri=/_app/immutable/assets/ProximaNova-Semibold.BI3UiExG.otf version=HTTP/1.1}: tower_http::trace::on_request: started processing request
2025-02-25T13:41:23.878281Z DEBUG request{method=GET uri=/_app/immutable/assets/ProximaNova-Semibold.BI3UiExG.otf version=HTTP/1.1}: tower_http::trace::on_response: finished processing request latency=1 ms status=200
2025-02-25T13:41:24.525978Z DEBUG request{method=POST uri=/upload_file version=HTTP/1.1}: tower_http::trace::on_response: finished processing request latency=665 ms status=200

This seems to happen an arbitrary number of times. Sometimes it happens only once. This behaviour does not happen for other API requests nor does it seems to ever happen when the response is a success leading me to speculate that its related to the file streaming request.

Maybe because my server does not start reading the request and rejects it instead, javascript under the hood tries to make the request again? This happens on other browsers too btw, not just Chrome. Does anyone have any idea why this would be happening?

Background and setup:

Backend:

  • Is made with Rust using the Axum libraries.
  • Has tracing enabled meaning that each request beginning and end is logged so i have an overview of the activity.
  • Has an API to stream(upload) a file to a location on the server.
  • This API does some validation, for example it only expects a file of a certain type. It also has a size check and rejects files that are too large.
  • The response from the server to the client contains a custom structure json in the body indicating if anything went wrong.

The main function of the server is basically something like this (minus all the setup of axum, server routing and rust trait implementations):

pub async fn upload_file(
    headers: HeaderMap,
    req: Request<axum::body::Body>,
) -> impl IntoResponse {
    // Code to check headers and reject if invalid.
    
    // Code to create directory and file and return if error
    
    // If a size of the body is provided, check early.
    let mut body: axum::body::Body = req.into_body();
    if body
        .size_hint()
        .upper()
        .is_some_and(|size| size > FILE_UPLOAD_FILE_MAX_SIZE_IN_BYTES.try_into().unwrap())
    {
        // return error.
    }
    
    while let Some(chunk) = body.frame().await {
        match chunk {
            Ok(frame) => {
                if let Some(data) = frame.data_ref() {
                    file_size_in_bytes_tally += data.len();

                    // File size check.
                    if file_size_in_bytes_tally > FILE_UPLOAD_FILE_MAX_SIZE_IN_BYTES {
                        // return error.
                    }
                        
                    // Write and check its result.
                    if let Err(e) = file.write_all(data).await {
                        // return error.
                    }       
                }
            }
            Err(e) => {
                // return error.
            }
        }
    }
    
    // return success
}

Frontend:

  • Is made with svelte and typescript.
  • has a file picker component that will then stream the file using fetch
  • Parses the response from the server and evaluates what happened.
    The code:
/**
 * Helper function to make a request to the server with a file as the body.
 * @param urlAndMethod The URL and HTTP method to call for this request
 * @param file The file to stream over to the server
 * @returns A response from the server
 */
export async function MakeServerRequestWithFileBody(
    urlAndMethod: UrlAndMethodPair,
    file: File
): Promise<Response> {
    const headers = new Headers();
    headers.append(FILE_UPLOAD_NAME_HTTP_HEADER_KEY, file.name);

    let request: RequestInit = {
        method: urlAndMethod.method,
        headers: headers,
        body: file,
    };

    const response = await fetch(urlAndMethod.url, request);

    if (response.ok == false) {
        console.error(
            "Server could not handle " +
                urlAndMethod.url +
                " request, result code: " +
                response.status +
                " with accompanying text: " +
                response.statusText,
            request,
            response
        );
    } else {
        console.log(
            "Made successful request with to " + urlAndMethod.url,
            request,
            response
        );
    }

    return response;
}
  • UrlAndMethodPair is a custom type simply containing the url and http method type.
  • Response is returned and processed by the calling function.

Hi im trying the cut these spheres into the other direction to keep the “bitten part” of the spheres

Title: How to properly quarter-cut spheres in Three.js with clipping planes?

Body:

I’m working on a Three.js project where I’m trying to create a visual of layered spheres, and I want to cut each sphere in a “quarter-cut” style — keeping three quarters of the sphere while removing one quarter, like in these typical cross-section graphics of the Earth’s layers.

So far, I’ve been trying to use clipping planes, but I can’t seem to get the right part of the sphere to remain — it either cuts too much or leaves the wrong section. I tried flipping the planes and moving them on different axes, but it didn’t help.

Here’s the current code:

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>Orbital</title>
    <style>
        #slider, #rotationSlider {
            position: absolute;
            top: 10px;
            left: 50%;
            transform: translateX(-50%);
        }
        #rotationSlider {
            top: 40px;
        }
    </style>
</head>
<body>
    <input type="range" id="slider" min="-10" max="10" value="0" step="0.1">
    <input type="range" id="rotationSlider" min="0" max="0.1" value="0.01" step="0.001">
    <script type="module">
        import * as THREE from "https://esm.sh/[email protected]";
        import { OrbitControls } from "https://esm.sh/[email protected]/examples/jsm/controls/OrbitControls.js";

        const scene = new THREE.Scene();
        const camera = new THREE.PerspectiveCamera(75, window.innerWidth / window.innerHeight, 0.1, 1000);
        camera.position.z = 30;

        const renderer = new THREE.WebGLRenderer();
        renderer.localClippingEnabled = true;
        renderer.setSize(window.innerWidth, window.innerHeight);
        document.body.appendChild(renderer.domElement);

        const controls = new OrbitControls(camera, renderer.domElement);
        controls.enableDamping = true; // Enable damping (inertia)
        controls.dampingFactor = 0.25; // Damping factor
        controls.enableZoom = true; // Enable zooming

        const ambientLight = new THREE.AmbientLight(0xffffff, 0.5); // Soft white light
        scene.add(ambientLight);

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

        // Create a clipping plane
        // Angled planes meeting at the "bite" point
        const cut = 3;
        const planeX = new THREE.Plane(new THREE.Vector3(-1, 0, 0), -cut);
        const planeY = new THREE.Plane(new THREE.Vector3(0, -1, 0), -cut);
        const planeHelperX = new THREE.PlaneHelper(planeX, 20, 0xffffff);
        const planeHelperY = new THREE.PlaneHelper(planeY, 20, 0xffffff);
        scene.add(planeHelperX);
        scene.add(planeHelperY);
        
        // Add additional spheres
        const numSpheres = 6;
        const radius = 3;
        const spheres = [];
        for (let i = 0; i < numSpheres; i++) {
            const colors = [0xff0000, 0xff3b3b, 0xff6b6b, 0xff9292, 0xffbdbd, 0xfffafa];
            const angle = (i / numSpheres) * Math.PI * 2;

            const material = new THREE.MeshPhongMaterial({
                color: colors[i],
                side: THREE.DoubleSide,
                wireframe: false,
                transparent: false,
                opacity: 1-(i/numSpheres),
                clippingPlanes: [ planeX, planeY ],
                clipShadows: true
            });
            const geometry = new THREE.SphereGeometry(radius + i, 64, 64);
            const sphere = new THREE.Mesh(geometry, material);
            sphere.position.set(0, 0, 0);
            spheres.push(sphere);
            scene.add(sphere);
        }

        // Create particles as small spheres
        const particleCountX = 150;
        const particleCountY = 150;
        const particleGeometry = new THREE.SphereGeometry(0.05, 8, 8);
        const particleMaterial = new THREE.MeshPhongMaterial({ color: 0xffffff, transparent:true, opacity:0.2 });
        const particlesMatrix = [];
        const particleAngles = [];
        for (let j = 0; j < particleCountX; j++) {
            particlesMatrix[j] = [];
            for (let k = 0; k < particleCountY; k++) {
                const particle = new THREE.Mesh(particleGeometry, particleMaterial);
                particlesMatrix[j][k] = particle;
                particleAngles.push({ angleX: (j / particleCountX) * Math.PI * 2, angleY: (k / particleCountY) * Math.PI * 2 });
                scene.add(particle);
            }
        }

        // Handle slider input
        slider.addEventListener('input', function() {
            const depth = parseFloat(this.value);
            planeX.constant = depth;
            planeY.constant = depth;
        });

        const rotationSlider = document.getElementById('rotationSlider');
        let rotationSpeed = parseFloat(rotationSlider.value);
        rotationSlider.addEventListener('input', function() {
            rotationSpeed = parseFloat(this.value);
        });

        let clock = new THREE.Clock();
        let timeScale = 10; // Adjust this value to slow down or speed up the particle movement

        // Animation loop
        function animate() {
            requestAnimationFrame(animate);

            let deltaTime = clock.getDelta() * timeScale;

            // Update particles to follow spheres
            for (let j = 0; j < particleCountX; j++) {
                for (let k = 0; k < particleCountY; k++) {
                    const particle = particlesMatrix[j][k];
                    const sphere = spheres[(j + k) % spheres.length];
                    const angles = particleAngles[j * particleCountY + k];
                    angles.angleX += rotationSpeed * deltaTime;
                    angles.angleY += rotationSpeed * deltaTime;
                    const x = sphere.position.x + (radius + (j + k) % numSpheres) * Math.cos(angles.angleX) * Math.sin(angles.angleY);
                    const y = sphere.position.y + (radius + (j + k) % numSpheres) * Math.sin(angles.angleX) * Math.sin(angles.angleY);
                    const z = sphere.position.z + (radius + (j + k) % numSpheres) * Math.cos(angles.angleY);
                    particle.position.set(x, y, z);
                }
            }

            // Rotate spheres
            spheres.forEach(sphere => {
                sphere.rotation.y += rotationSpeed * deltaTime;
            });

            controls.update();
            renderer.render(scene, camera);
        }
        animate();
    </script>
</body>
</html>

What I’d like to achieve:

Keep three quarters of the spheres (like a visible cross-section) while cutting along two perpendicular planes.

Adjust the cut depth with a slider.

What’s happening now:

The planes cut the spheres, but I often see the wrong part of the shape remaining.

What am I missing? Is there a better approach to achieve this type of clipping in Three.js? Any guidance would be appreciated!

Assign js var as php variable array key [duplicate]

I have a form with an input number field. When the field value is incremented, a table row with a few inputs is added and vice-versa.

The code (the important to the question part) is:

$(document).ready(function () {
    var i = 1
    $('#packCount').change(function () {
        var total = $(this).val()

        while (i <= total) {
            $('#packsTable').append('<tr>' + '<td>' + i + '</td>' + '<td><input type="text" name="weight[]" value="<?= $weight ?>" class="minwidth100 maxwidth100"/></td>'</tr>');
            i = i + 1;
        }
    })
});

What I want is to be able to set the field value from the post data i.e. For the first row, I want to have $weight[0], for the second $weight[1] etc.

My question is, how to have the i value as an array key?

Put ellipsis in the middle of input field

How can I put ellipsis in the middle of texts and have the results like this

sdghkjsd ... ndfgjknk

I want to truncate words on mobile and tablet view only supported on all browsers

and I want to be able to enter new values in input and make submit without the changes getting truncate (like I found sdghkjsd ... ndfgjknk and enter sdghkjsdghhjdfgjhdjghjdfhghjhgkdfgjnfkdgnjkndfgjknk and submit it without being truncated (submit the original, longer value)

// making the input editable
$(".long-value-input").on("click", function() {
  $(this).prop("readonly", "");
  $(this).focus();
});
/* For smart phones */
@media screen and (max-width: 600px) {
  .field {
    text-overflow: ellipsis;
    white-space: nowrap;
    overflow: hidden;
  }
}

/* For tablets */
@media screen and (min-width: 600px) and (max-width: 900px) {
  .field {
    text-overflow: ellipsis;
    white-space: nowrap;
    overflow: hidden;
  }
}
<input type="text" class="field" value="sdghkjsdghhjdfgjhdjghjdfhghjhgkdfgjnfkdgnjkndfgjknk" />
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>

Calling javascript event in Angular after DOM is fully loaded – async pipe

I’m new to Angular and trying to execute custom JS event (NavigationContentLoaded) when all categories are fetched from service and displayed but I’m unable to find correct event for that.
Here is my component:

ngOnInit() {
  this.categories$ = this.shoppingFacade.navigationCategories$();
  this.deviceType$ = this.appFacade.deviceType$;
}

And here is html:

<ng-container *ngFor="let category of categories$ | async">
<li *ngIf="!category.isRoot" [ngClass]="hasChildren(category) ? 'has-submenu' : ''">
  <a
    [routerLink]="hasChildren(category) && (deviceType$ | async) === 'mobile' ? undefined : category.url"
    class="main-navigation__link"
    [attr.data-testing-id]="category.uniqueId + '-link'"
  >
    {{ category.name }}
  </a>
  <ish-sub-category-navigation
    [categoryUniqueId]="category.uniqueId"
    [subCategoriesDepth]="1"
    [view]="view"
    [parentCategoryName]="category.name"
    [parentCategoryUrl]="category.url"
    *ngIf="hasChildren(category)"
  />
</li>
</ng-container>

Problem is that all ‘li’ elements must be fully loaded and displayed before I can trigger “NavigationContentLoaded” event which expects fully loaded navigation (it queries HTML nodes).
I tried all Angular events (AfterViewInit, AfterViewChecked, AfterContent…, afterNextRender) but they do not work as they are triggered before observable and async pipe is finished rendering. Only solution which I found until now is to wait until whole Angular application is stable, but that takes too much time as whole page needs to be fully loaded and I just need that my navigation component is finished rendering.
Does anyone knows if this is possible?
It is Angular 16.

Thank you for your help!

react-codemirror: Cannot get the same CSS color style as shown on https://uiwjs.github.io/react-codemirror/

I want to get the same color CSS styling as shown on https://uiwjs.github.io/react-codemirror/ for theme: dark and language: JSON

Image

But when I tried it with react-codemirror ("@uiw/react-codemirror": "^4.23.8"):

                        <CodeMirror
                            value={{ JSON .... }}
                            minHeight={"120px"}
                            theme={basicDark}
                            extensions={[
                                basicDark,
                                javascript({ jsx: true }),
                                // EditorView.lineWrapping
                            ]}
                            onChange={onChange}
                        />

it looks like this instead:

Image

On the online example the HTML for the JSON "message": "Network Error" have seperate CSS classes for the JSON key and value:

Image

Image

But the one on my localhost both JSON key and value have the same class:

Image

Image

It seems my localhost react-codemirror is missing alot of classes and styling, why is that?

Does anyone know why this is happening?

Why is it that the outcome is different from the example shown on https://uiwjs.github.io/react-codemirror/?

How to trigger a native HTML validation error for URLs in input or textarea fields instead of a custom one?

I’m working on a form using Formik in React, and I need to prevent users from entering URLs in a textarea or input field.

Currently, I’m using setCustomValidity to show an error when a URL is detected:

<Formik
  enableReinitialize={enableReinitialize}
  initialValues={initialValues}
  onSubmit={(values, { setSubmitting, setStatus, resetForm }) => {
    const urlRegex = /(https?://|www.)[^s/$.?#].[^s]*/gi;
    const descriptionInput = document.querySelector(
      'textarea[name="description"], input[name="description"]'
    );

    if (descriptionInput && urlRegex.test(values.description)) {
      descriptionInput.setCustomValidity(
        'URLs are not allowed. Please enter text without links.'
      );
      descriptionInput.reportValidity();
      setSubmitting(false);
      return;
    }

    this.handleSubmit(values, setSubmitting, setStatus, resetForm);
  }}
>

The problem:

Since setCustomValidity requires me to manually translate the error message for multiple languages, I would prefer to trigger a native HTML validation error instead, which automatically displays in the user’s browser language.

What I tried:

  • Using the pattern attribute:
    <textarea name="description" pattern="^(?!.*(https?://|www.)).*$"></textarea>
    

    This prevents form submission but doesn’t show the error when the user types a URL.

  • Setting type="url" isn’t an option because I want to disallow URLs, not validate them.

Question:

Is there a way to leverage native HTML validation to prevent users from entering URLs and display the built-in error message instead of using setCustomValidity?

Any suggestions or alternative approaches would be appreciated!

cannot remove click listener from div [duplicate]

I want to remove a clicklistener from a div with classname .w-grid-list

firefox inspect element shows event

I tried with javascript:

const gridLists = document.querySelectorAll('.w-grid-list');
gridLists.forEach(gridList => {
  const clonedGridList = gridList.cloneNode(true);
  gridList.replaceWith(clonedGridList);
});

I do not know the functionname

Raycasting skew on large FOV angles

I wrote a raycaster in Javascript following Lodev’s tutorials. (https://lodev.org/cgtutor/raycasting.html)

I think I understand the math and everything, and the raycaster works pretty great on normal/narrow FOV angles, but on large FOV angles the object go on a sort of elliptical path around the raycaster origin instead of rotating in a circle when rotating left/right. Now I’m pretty sure this is not expected and it looks whacky. See video (excuse the whacky colors I had to get it down to an appropriate size for stackoverflow):

enter image description here

You can clearly see that the wall goes in an elliptical curve around the player. On the image, I’m using direction vector length 1 and plane vector length 2.2 (Giving us a large FOV)

I cannot find any faults in the algorithm and the math used should most likely not produce this sort of result. For each ray, we should be going the right direction by adding the direction and plane vectors scaled by the X coordinate of the camera. Then taking the perpendicular distances to the camera plane.

Any ideas?

Here’s the code, I’ve really made only amendments for Javascript and haven’t modified the algorithm from the original tutorial.

let ZBuffer: { [key: number]: number } = {};
let width = Math.ceil(this.spacing);

this.ctx.save();
for (let column = 0; column < this.resolution; column++) {
  // x-coordinate in camera space scaled from -1 to 1
  let cameraX = (2 * column) / this.resolution - 1;

  // get the ray direction vector
  let rayDirX = player.position.dirX + player.position.planeX * cameraX;
  let rayDirY = player.position.dirY + player.position.planeY * cameraX;

  // which box of the map we're in
  let mapX = Math.floor(player.position.x);
  let mapY = Math.floor(player.position.y);

  // length of ray from current position to next x or y-side
  let sideDistX: number;
  let sideDistY: number;

  //length of ray from one x or y-side to next x or y-side
  //these are derived as:
  //deltaDistX = sqrt(1 + (rayDirY * rayDirY) / (rayDirX * rayDirX))
  //deltaDistY = sqrt(1 + (rayDirX * rayDirX) / (rayDirY * rayDirY))
  //which can be simplified to abs(|rayDir| / rayDirX) and abs(|rayDir| / rayDirY)
  //where |rayDir| is the length of the vector (rayDirX, rayDirY). Its length,
  //unlike (dirX, dirY) is not 1, however this does not matter, only the
  //ratio between deltaDistX and deltaDistY matters, due to the way the DDA
  //stepping further below works. So the values can be computed as below.
  // Division through zero is prevented
  let deltaDistX = Math.abs(1 / rayDirX);
  let deltaDistY = Math.abs(1 / rayDirY);

  // perpendicular wall distance
  let perpWallDist: number;

  // what direction to step in x or y-direction (either +1 or -1)
  let stepX: number;
  let stepY: number;

  let hit: number = 0; // was there a wall hit?
  let side: number; // was a NS or a EW wall hit? if x then side = 0, if y then side = 1

  // calculate step and initial sideDist
  if (rayDirX < 0) {
    stepX = -1;
    sideDistX = (player.position.x - mapX) * deltaDistX;
  } else {
    stepX = 1;
    sideDistX = (mapX + 1.0 - player.position.x) * deltaDistX;
  }

  if (rayDirY < 0) {
    stepY = -1;
    sideDistY = (player.position.y - mapY) * deltaDistY;
  } else {
    stepY = 1;
    sideDistY = (mapY + 1.0 - player.position.y) * deltaDistY;
  }

  // perform DDA
  let range = this.range;
  while (hit == 0 && range >= 0) {
    // jump to next map square, either in x-direction, or in y-direction
    if (sideDistX < sideDistY) {
      sideDistX += deltaDistX;
      mapX += stepX;
      side = 0;
    } else {
      sideDistY += deltaDistY;
      mapY += stepY;
      side = 1;
    }
    // Check if ray has hit a wall
    if (map.get(mapX, mapY) == 1) hit = 1;
    range -= 1;
  }
  // Calculate distance projected on camera direction. This is the shortest distance from the point where the wall is
  // hit to the camera plane. Euclidean to center camera plane would give fisheye effect!
  // This can be computed as (mapX - posX + (1 - stepX) / 2) / rayDirX for side == 0, or same formula with Y
  // for size == 1, but can be simplified to the code below thanks to how sideDist and deltaDist are computed:
  // because they were left scaled to |rayDir|. sideDist is the entire length of the ray above after the multiple
  // steps, but we subtract deltaDist once because one step more into the wall was taken above.
  if (side == 0) perpWallDist = sideDistX - deltaDistX;
  else perpWallDist = sideDistY - deltaDistY;

  // SET THE ZBUFFER FOR THE SPRITE CASTING
  ZBuffer[column] = perpWallDist; //perpendicular distance is used

  // Calculate height of line to draw on screen
  let lineHeight: number = this.height / perpWallDist;

  // calculate lowest and highest pixel to fill in current stripe
  let drawStartY = -lineHeight / 2 + this.height / 2;
  let drawEndY = lineHeight / 2 + this.height / 2;

  let texture = map.wallTexture;

  // calculate value of wallX
  let wallX: number; // where exactly the wall was hit
  if (side == 0) wallX = player.position.y + perpWallDist * rayDirY;
  else wallX = player.position.x + perpWallDist * rayDirX;
  wallX -= Math.floor(wallX);

  // x coordinate on the texture
  let texX = Math.floor(wallX * texture.width);
  if (side == 0 && rayDirX > 0) texX = texture.width - texX - 1;
  if (side == 1 && rayDirY < 0) texX = texture.width - texX - 1;

  this.ctx.globalAlpha = 1;
  if (hit) {
    let left = Math.floor(column * this.spacing);
    let wallHeight = drawEndY - drawStartY;

    this.ctx.drawImage(
      texture.image,
      texX, // sx
      0, // sy
      1, // sw
      texture.height, // sh
      left, // dx
      drawStartY, // dy - yes we go into minus here, it'll be ignored anyway
      width, // dw
      wallHeight // dh
    );

    // this is the shading of the texture - a sort of black overlay
    this.ctx.fillStyle = `#000000`;
    let alpha =
      (perpWallDist +
        // step.shading
        0) /
        this.lightRange -
      map.light;
    alpha = Math.min(alpha, 0.8);
    if (side == 1) {
      // give x and y sides different brightness
      alpha = alpha * 2;
    }
    alpha = Math.min(alpha, 0.85);
    // ensure walls are always at least a little bit visible - alpha 1 is all black
    this.ctx.globalAlpha = alpha;
    this.ctx.fillRect(left, drawStartY, width, wallHeight);
    this.ctx.globalAlpha = 1;
  }
}

If anyone wants to play with the full version it’s at https://github.com/xtrinch/raycaster/tree/rewrite, can modify the length of the plane vector in function findSpawnPoint