how to collapse rows multiple times in html css js

TO ACHIVE: freeze header, freeze first column and collapse row multiple times.

ALREADY ACHIVED: freeze header, freeze first column and collapse only one time.

MY CODE SO FAR:

</head>
<body>
<div class="table-container">
<table>
<thead class="freeze-header">
<tr>
<th class="freeze-col">Header 1</th>
<th>Header 2</th>
</tr>
</thead>
<tbody>
<tr class="parent-row">
<td class="freeze-col"><i class="fas fa-caret-right collapse-icon"></i> Row 1, Column 1</td>
<td>Row 1, Column 2</td>
</tr>
<tr class="collapse">
<td colspan="3">
<table>
<tbody>
<tr class="parent-row">
<td class="freeze-col"><i class="fas fa-caret-right collapse-icon"></i> Row 1.1, Column 1</td>
<td>Row 1.1, Column 2</td>
</tr>
<tr class="collapse">
<td colspan="3">
<table><tbody><tr>
<td>Row 1.1.1, Column 1</td>
<td>Row 1.1.1, Column 2</td>
</tr></tbody></table></td></tr></tbody></table></td></tr>
<tr class="parent-row">
<td class="freeze-col"><i class="fas fa-caret-right collapse-icon"></i> Row 2, Column 1</td>
<td>Row 2, Column 2</td>
<td>Row 2, Column 3</td>
</tr>
</tbody></table></div>

<script>
    // JavaScript to handle collapse functionality
    document.querySelectorAll('.parent-row').forEach(function(row) {
        row.addEventListener('click', function() {
            var nextRow = row.nextElementSibling;
            if (nextRow && nextRow.classList.contains('collapse')) {
                nextRow.classList.toggle('show');
                row.querySelector('.collapse-icon').classList.toggle('fa-caret-right');
                row.querySelector('.collapse-icon').classList.toggle('fa-caret-down');
            }
        });
    });
</script>

How to achieve same as below image? thank you.
Layout to achieve

Como aprender a programar desde 0 hasta un pro [closed]

Soy nuevo en el mundo de la programación y estoy interesado en desarrollar una sólida base lógica para programar. Mi objetivo es comenzar desde cero y progresar hasta llegar a un nivel competente. Me gustaría solicitar su orientación en las siguientes áreas:

¿Cuál sería la mejor plataforma o programa para un principiante en programación?
¿Qué conceptos fundamentales debería entender antes de empezar a programar?

Quiero tener una buena lógica de programación

Unable to upload PDF to S3 bucket via presigned URL created from my Node backend

Scenario:

  1. Client (Nextjs client component) queries backend (NextJS rest endpoint) for pre-signed URL
  2. Backend gets presigned URL for S3 via getSignedUrl
import { S3Client, PutObjectCommand } from "@aws-sdk/client-s3";
import { getSignedUrl } from "@aws-sdk/s3-request-presigner";
import { env } from "@/env";

const AWS_REGION = "ap-southeast-2";

const s3Client = new S3Client({
  region: AWS_REGION,
  credentials: {
    accessKeyId: env.AWS_S3_ACCESS_ID,
    secretAccessKey: env.AWS_S3_ACCESS_KEY,
  },
});

const command = new PutObjectCommand({
     Bucket: s3Object.bucket,
     Key: s3Object.key,
     // I also tried passing the contenttype here to see if it changed anything. But no it didn't.
     // ContentType: s3Object.contentType,
     // Might need more fields here to refine...
});

// Calculate dynamic expiration time based on file size, user's internet connection speed, etc.
const expiresIn = calculateExpirationTime(s3Object);

const presignedUrl = await getSignedUrl(s3Client, command, { expiresIn });

return presignedUrl;
  1. Client receives presigned URL from backend
  2. Client sends file chunk to presigned URL
// Uploads a chunk to the presigned URL
const uploadPart = (opts: {
  url: string;
  chunk: Blob;
  contentType: string;
  chunkSize: number;
  fileName: string;
  maxRetries: number;
}) =>
  fetch(opts.url, {
    method: "PUT",
    body: opts.chunk,
    //headers: {
    //  "Content-Type": opts.contentType,
    //},
  })
  1. Frontend throws a CORs error:
Access to fetch at 'https://mybucket.s3.ap-southeast-2.amazonaws.com/mydoc.pdf?X-Amz-Algorithm=AWS4-HMAC-SHA256&X-Amz-Content-Sha256=UNSIGNED-PAYLOAD&X-Amz-Credential=AMZ_VALUE%2Fap-southeast-2%2Fs3%2Faws4_request&X-Amz-Date=20240516T010037Z&X-Amz-Expires=14400&X-Amz-Signature=SIGNATURE&X-Amz-SignedHeaders=host&x-id=PutObject' from origin 'http://localhost:3000' has been blocked by CORS policy: Response to preflight request doesn't pass access control check: No 'Access-Control-Allow-Origin' header is present on the requested resource. If an opaque response serves your needs, set the request's mode to 'no-cors' to fetch the resource with CORS disabled.

OPTIONS request is sent and comes back as 403 Forbidden

Request Method:
OPTIONS
Status Code:
403 Forbidden
Remote Address:
<IP>:443
Referrer Policy:
strict-origin-when-cross-origin

RESPONSE HEADERS:

Content-Type:
application/xml
Date:
Thu, 16 May 2024 01:03:33 GMT
Server:
AmazonS3
Transfer-Encoding:
chunked
X-Amz-Id-2:
<ID>
X-Amz-Request-Id:
<ID>

REQUEST HEADERS:

Accept:
*/*
Accept-Encoding:
gzip, deflate, br, zstd
Accept-Language:
en-US,en;q=0.9
Access-Control-Request-Method:
PUT
Cache-Control:
no-cache
Connection:
keep-alive
Host:
mybucket.s3.ap-southeast-2.amazonaws.com
Origin:
http://localhost:3000
Pragma:
no-cache
Referer:
http://localhost:3000/
Sec-Fetch-Dest:
empty
Sec-Fetch-Mode:
cors
Sec-Fetch-Site:
cross-site
User-Agent:
<AGENT>

S3 Bucket Permissions

I have configured this correctly. I have tried many different variations including explicitly defining localhost:3000 in the AllowedOrigins.

CORS settings:

[
    {
        "AllowedHeaders": [
            "*"
        ],
        "AllowedMethods": [
            "GET",
            "PUT",
            "POST",
            "DELETE",
            "HEAD"
        ],
        "AllowedOrigins": [
            "*"
        ]
    }
]

Policy attached to the user

The user who is generating the presigned URL has the following policy attached:

  {
    "Version": "2012-10-17",
    "Statement": [
      {
        "Action": [
          "s3:GetObject",
          "s3:GetObjectVersion",
          "s3:PutObject"
        ],
        "Resource": [
          "arn:aws:s3:::mybucket",
          "arn:aws:s3:::bmybucket/*"
        ],
        "Effect": "Allow"
      }
    ]
  }

I have been struggling with this one for quite some time and tried so many of the suggestions from around SO and Google. None have worked. I have a feeling I have missed some small detail and it’s causing me all this grief.

Firebase pipeline problem: I’m trying to deploy changes to my website but I keep getting an error. build is passing but deploy is failing

the error I keep getting is “Error: Assertion failed: resolving hosting target of a site with no site name or target name. This should have caused an error earlier”. I checked with my boss and he says the firebasesrc is the right id and we have been making changes to the firebase.json but have not been able to get a passing pipeline.

as i mentioned above we changed the firebase.json file a few times. (tried adding needs, dependencies, and cache) We also tried to re-initialize hosting. We are currently trying to deploy locally.

this is what the firebase.json looks like currently:

{
  "hosting": {
    "public": "public",
    "ignore": [
      "firebase.json",
      "**/.*",
      "**/node_modules/**"
    ],
    "rewrites": [
      {
        "source": "**",
        "destination": "/index.html"
      }
    ]
  },
  "storage": {
    "rules": "storage.rules"
  }
}

Inverse Kinematics issues in three.js

I am trying to use inverse kinematics on a hand model.
I have downloaded a pre-rigged model from github.
I modify the model in Blender, adding target-bones and inverse kinematics constraints, and everything works perfectly from the Blender side.
However, when I export as glb and try to apply the IK using the CCDIKSolver in three.js, everything breaks, with the bones starting to jitter randomly.

Do you know what the issue might be?
Can anyone demonstrate an example for this case?

I have tried applying IK contstraints in Blender, different parenting trees removing all other bones just to test one chain etc. but nothing seems to help.

how to use free text in reactjs + material ui + react hook form

I have an autocomplete React Material component that fetches data from the server. However, in some scenarios, I want to convert the autocomplete to a text field if a user enters a slash (‘/’).

here it was suggested to use freesolo property
how to show textfield or 2 different component in react js?

https://mui.com/material-ui/react-autocomplete/#free-solo

I tried to using this but not able to apply .. I also want to fetch the entered value..

here is my code

https://stackblitz.com/edit/vitejs-vite-sctdxd?file=src%2FApp.tsx,src%2Findex.css,src%2Fmain.tsx,package.json&terminal=dev

export default function App() {
  const [options, setOptions] = React.useState<typeof top100Films>([]);
  const [open, setOpen] = React.useState(false);

  const loading = open && options.length === 0;

  const defaultValues = {
    movie: null,
  };

  React.useEffect(() => {
    let active = true;

    if (!loading) {
      return undefined;
    }

    (async () => {
      if (active) {
        setOptions([...top100Films]);
      }
    })();

    return () => {
      active = false;
    };
  }, [loading]);

  React.useEffect(() => {
    if (!open) {
      setOptions([]);
    }
  }, [open]);

  const { registerState, handleSubmit, getValues } = useHookForm({
    defaultValues,
  });

  const onSubmit = (_data: typeof defaultValues) => {
    console.log(_data);
  };
  return (
    <div className="App">
      {JSON.stringify(getValues(), 2, null)}
      <form onSubmit={handleSubmit(onSubmit)}>
        <h2>Asynchronous `Request` state can be optained</h2>
        <Grid container spacing={3} sx={{ minHeight: 120 }}>
          <HookAutoComplete
            {...registerState('movie')}
            autocompleteProps={{
              options,
              autoHighlight: true,
              isOptionEqualToValue: ({ label }, value) => label === value.label,
              loading,
              open,
              onOpen: () => {
                setOpen(true);
              },
              onClose: () => {
                setOpen(false);
              },
            }}
            textFieldProps={{
              label: 'Movie',
              placeholder: 'The...',
              InputProps: {
                endAdornment: (
                  <>
                    {loading ? (
                      <CircularProgress color="inherit" size={20} />
                    ) : null}
                  </>
                ),
              },
              onChange: (event) => {
                console.log('event', event.target.value);
              },
            }}
            gridProps={{
              xs: 12,
            }}
            rules={{
              required: {
                message: 'Required',
                value: true,
              },
            }}
          />
        </Grid>

        <Grid>
          <Button type="submit" variant="contained">
            Submit
          </Button>
        </Grid>
      </form>
    </div>
  );
}

Main issue : how to fetch user enter value ? Currently it is showing NULL if user enter “the/as”
why ?

Why Isn’t My HTML Form Working with JavaScript?

when i press enter on the search bar its going all blank or saying file doesn’t exist. how do i fix it. it is also Khan Academy.

HTML

<form id="Search" onsubmit="Search()">
      <input type="text" id="Search-bar" placeholder="Search or type a URL"
      onclick="this.select();"
      onfocus="this.placeholder = ''"onblur="this.placeholder = 'Search or type a URL'">
      <input type="submit" id="Search-Button" >
      </form>
<div id="Website1">
        <h1>asasgdajs</h1>
    </div>

JavaScript


var input = document.getElementById("Search-bar");
input.addEventListener("keypress", function(event) {
  if (event.key === "Enter") {
    event.preventDefault();
    document.getElementById("Search-Button").click();
  }
});

     function Search() {
  var x = document.getElementById('Search-bar').value;
  if (x == "" || x == null) {
    return false;
  }
  else if (x=== "website.com")document.getElementById('Website1').style.display = "block";
  else {return true;}
  
}

CSS

#Search-bar {
      position: absolute;
      top: 38px;
      width: 90%;
      height: 12px;
      border:none;
        background-color:rgb(236, 239, 247);  
      border-radius: 25px;
      padding: 6px;
      font-size: 14px;
      margin-bottom: 10px;
      
      transition: background-color 0.3s ease-out;
      
    }
    #Search-bar:hover {
     background-color:rgb(220, 223, 232);         
    }
    #Search-bar:focus {
     background-color:rgb(255, 255, 255);
    outline: none !important;
    border:1.5px solid blue;
    position:absolute;
          top: 37px;
          left:7px;
    
    }
#Website1{display:none;}
#Search-Button{display:none;}

If you want the rest of the code:
https://www.khanacademy.org/computer-programming/browser-v01/5205239442096128?width=786&height=650

Flexbox layout without item re-rendering to new parent

This is the layout i’m trying to make:

I have a difficult flexbox layout that I’m trying to achieve, and I have a difficult restriction that one of the items is a Webgl player and cannot be conditionally rendered because that would restart the WebGl player. All of the items should be able to occupy item 1 position when clicked on. How would you code this flex layout knowing that item 2 can only change its order, not its parent.

I’ve tried making item 2 absolutely positioned though that is less than ideal.

¿Ag-Grid, How to update the agSelectCellEditor correctly?

I am using Ag-Grid with JS.

I have a column to list airports, the list is saved in the airport variable, if I dynamically select an airport I see it visually, but if I click on the cell it, adds the first value of the airport list. What is this due to?

I dynamically added the airport from the change event:

rowData.origin = { airport_id: 1, name: 'Cancun' };
gridApi.applyTransaction({ update: [rowData] });

and if it matches the data, but clicking the cell again adds the first value in the list.

Chrome extension: injected value disappears after content script runs

I am writing a chrome extension (Manifest V3) where I am trying to let the content script know what the tab ID is by setting a window property (because I use it a few times later). I am doing this using executeScript() in the following manner in my background.js:

function setTabIDInContent(id) { 
  window.tabId = id; }

chrome.tabs.onUpdated.addListener(async (tabId, changeInfo, tab) => {
    if (tab.url?.startsWith("chrome://")) return undefined;

    chrome.scripting.executeScript({
      target: { tabId: tabId },
      args: [tabId],
      world: "MAIN",
      func: setTabIDInContent
    });
    
});

In my content script, I have a listener defined in the following manner:

chrome.runtime.onMessage.addListener((request, sender, sendResponse) => {  
        sendResponse({tabId: window.tabId, 
          info: 'other stuff'});
        
});

I am observing this peculiar behavior:

  • Right after a page loads, typing window.tabId in the console window prints the correct value.
  • However, after the content script runs – specifically, after I send a message to it from the background script, and it invokes the listener, window.tabId becomes undefined. Putting a breakpoint in the content script’s listener method, I verified that window.tabId is indeed undefined during execution. After the listener finishes execution, when I go back to the console window and type out window.tabId, I see it has become undefined there was well.

Why would this happen and what might I do to persist this value?

Trouble in Insert MySql Workbench

I am creating a login system using js, express and sequelize to connect the Database (MySql Workebench), but when I complete the registration, only createAt, updateAt and the registration Id are inserted, the ’email’ and ‘password’ fields are empty , giving insert in the other fields and not in the two, and in the log it appears:

Executing (default): INSERT INTO 'Usuarios_teste' ('id', 'createdAt', 'updatedAt') VALUES (DEFAULT,?,?);

My LoginModel.js:

`const { Model, DataTypes} = require('sequelize');
const validator = require('validator');
const bcryptjs = require('bcryptjs');
const sequelize = require('../config/database');


class Login extends Model {
    constructor(body) {
    super();
    this.body = body;
    this.errors = [];
    this.user = null;
  }

  async login() {
    this.valida();
    if(this.errors.length > 0) return;
    this.user = await Login.findOne({ where: { email: this.body.email } });



    if(!this.user) {
      this.errors.push('Usuário não existe.');
      return;
     }

    if(!bcryptjs.compareSync(this.body.password, this.user.password)) {
      this.error.push('Senha inválida');
      this.user = null;
      return;
    }
  }

  async register() {
    this.valida();
    if(this.errors.length > 0) return;

    await this.userExists();

    if(this.errors.length > 0) return;

    if(this.user) return;

    const salt = bcryptjs.genSaltSync();
    this.body.password = bcryptjs.hashSync(this.body.password, salt);


  try {
      this.user = await Login.create({
      email: this.body.email,
      password: this.body.password
    });
  } catch (e) {
    console.error("Erro ao criar novo usuário: ", error);
    this.errors.push("Erro ao criar novo usuário.")
  }
  }
    //Valição pra conferir se o usuário já existe
   async userExists() {
    this.user = await Login.findOne({ where: { email: this.body.email } });
    if (this.user) this.errors.push('Usuário já existe.')

  }

  valida() {
    this.cleanUp();

    // **Validação de campos**
    // O email precisa ser válido
    if(!validator.isEmail(this.body.email)) this.errors.push('E-mail Inválido');
    // A senha precisa ter entre 5 a 15 caracteres
    if(this.body.password.length < 5 || this.body.password.length > 15) {
      this.errors.push('A senha precisa ter entre 5 e 15 caracteres.')
    }
  }

  cleanUp() {
    for(const key in this.body) {
      if (typeof this.body[key] !== 'string') {
      this.body[key] = '';
      }
    }

    this.body = {
      email: this.body.email,
      password: this.body.password
    };
  }
}

Login.init({
  id: {
   type: DataTypes.INTEGER,
   primaryKey: true,
   autoIncrement: true
  },
  email: { type: DataTypes.STRING, allowNull: true},
  password: { type: DataTypes.STRING, allowNull: true}
 }, {
  sequelize,
  modelName: 'Login',
  tableName: 'Usuarios_teste'
 });

//Cria o novo usuário apenas se ele não existir.
(async () => {
  try {
     await sequelize.sync();
     console.log("Modelo sincronizado com o banco de dados.");
 } catch (e) {
   console.error("Erro ao sincronizar o modelo com o banco de dados: ", e);
  }

   })();

   module.exports = Login;`

`

Can I get all hyperlinks that contain “@” then open them in new tabs?

I’m trying to open all hyperlinks on a page with link text that includes the “@” symbol.

Here’s an example below

[[email protected]](https://stackoverflow.com/2342342352) 
[[email protected]](https://stackoverflow.com/2342525233423)
[[email protected]](https://stackoverflow.com/23943234)

So far, I can collect each of the lines that include an @ symbol with this jQuery selector:

$("a:contains('@')")

This gives me a list of every anchor tag that has @ in the link text, it looks like this:

jQuery.fn.init {0: a, 1:a, 2:a,}

For a cleaner array, I used

$("a:contains('@')").get

Which returns

(3) [a, a, a]

I tried using this for loop to click every a tag in the array but as soon as I click the first one, it stops.

var mapps = $("a:contains('@')").get()

for (var i = 0, len = mapps.length; i < len; i++) {
  mapps[i].click();
}

So to open multiple links in new tabs, I’m going to try using window.open() which I believe requires the URL.

I can extract the URL in the first anchor tag by using this code:

$("a:contains('@')").prop('href');

However, .prop only returns the first URL.

Is there a way for me to return all URLs then feed them into a for loop and open them in new tabs?

I’m trying to figure this out with .each() but it’s been very difficult for me. Please let me know if you need more context and forgive my lack of experience.

How to round the edges of a whole section/div

I have an image like this
(https://i.sstatic.net/oz4mb8A4.png)
and it zooms in when you hover.

However I am trying to round the edges of the image and the overlay that covers the image when I hover. How do I do this?

This is my code in html

<section class="effects">
<div class="container">

   <div class="image-01-outer">

    <div class="image-01">
      <img src="PHILIPPA'S NEW VIDEO.png" alt="">

          <div class="overlay1">
              <div class="text-content">
                  <h3 class="h3-img"> Header</h3>
                  <p>Body of text. Body.</p>
              </div>
          </div>
  </div>

   </div>

</div>

</section>

and in css I have this

.effects .image-01 
{
border: 1px solid blue;  
border-radius: 4rem;  
position: relative; 
}

.effects .image-01 img
{
    max-width: 120rem;
}

.effects .image-01 .overlay1
{
    width: 100%;
    height: 100%;
    position: absolute;
    bottom: 0;
    left: 0;
    opacity: 0;
    transition: 0.5s ease;
    background-color: rgba(228, 20, 255, 0.327);
}

.effects .image-01:hover .overlay1
{
    opacity: 1;
}

.effects .image-01:hover 
{
    transition: transform .4s;
    transform: scale(1.1);
    transform-origin: 100% 50%;
}

Tween.js – Trying to play SVG animation forwards on mouse-over and backwards on mouse-out

In my current code, the animation plays forwards and backwards on mouse-over. Is there a way to make it play forwards on mouse-over and backwards on mouse-out? Thanks.

// write a simple tween object
var tween = KUTE.fromTo('#rectangle',  // target shape
   { path: '#rectangle' }, // from shape
   { path: '#star' }, // to shape
   { // options
      easing: 'easingCubicInOut', 
      yoyo: true, repeat: 1, duration: 2000}
 ).start();

// trigger it whenever you want
document.getElementById('wrapper').onmouseover = function() {
  !tween.playing && tween.start();
}
svg {
overflow: visible;
}

body {
background: #333;
color: #ccc;
overflow: hidden;
}

#wrapper {
width: 200px;
float: left;
margin: 0 20px 0 10px;
}
<script src="https://cdn.jsdelivr.net/npm/[email protected]/dist/kute.min.js"></script>
<div id="wrapper">
  <svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 600 600" >
    <path id="rectangle" fill="lime" d="M38.01,5.653h526.531c17.905,0,32.422,14.516,32.422,32.422v526.531 c0,17.905-14.517,32.422-32.422,32.422H38.01c-17.906,0-32.422-14.517-32.422-32.422V38.075C5.588,20.169,20.104,5.653,38.01,5.653z" />
    <path id="star" style="visibility:hidden" d="M301.113,12.011l99.25,179.996l201.864,38.778L461.706,380.808
    l25.508,203.958l-186.101-87.287L115.01,584.766l25.507-203.958L0,230.785l201.86-38.778L301.113,12.011"/>
  </svg>
</div>

event.preventDefault doesnt work when i use formData with constructor

event.preventDefault() doesnt work when i use formData with constructor , but when i used $("#obatForm").serialize(), it works. but its impossible to use serialize because the form im using are from jquery html like this

$(document).ready(function () {
  $("#addNav").click(function (event) {
    event.preventDefault();

    const dataList = $("#results");
    const formAdd = $(` 
    <div class="container-input bg-FAFAFA">
    <!--input-->
  
    <form
      enctype="multipart/form-data"
      id="obatForm"
      class="m-8 p-9 grid grid-cols-2 bg-FAFAFA rounded-lg"
    >
      <label for="nama">Nama : </label>
      <input
        type="text"
        name="nama"
        id="nama"
        class="m-2 border border-solid text-teal-950"
      />
      <label for="kode">Kode : </label>
      <input
        type="text"
        name="kode"
        id="kode"
        class="m-2 border border-solid text-teal-950"
      />
      <label for="fisik">Fisik : </label>
      <select name="fisik" id="fisik" class="border m-2">
        <option>Kapsul</option>
        <option>Tablet</option>
        <option>Inject</option>
        <option>Sirup</option>
        <option>Pil</option>
        <option>Inhale</option>
        <option>Infus</option>
        <option>Tetes</option>
        <option>Larutan</option>
        <option>Salep</option>
        <option>Kaplet</option>
        <option>Cairan</option>
        <option>Tempel</option>
      </select>
      <label for="harga">Harga : </label>
      <input
        type="text"
        name="harga"
        id="harga"
        class="m-2 border border-solid text-teal-950"
      />
      <label for="stok">Stok : </label>
      <input
        type="text"
        name="stok"
        id="stok"
        class="m-2 border border-solid text-teal-950"
      />
      <label for="gambar">Gambar:</label>
      <input
        type="file"
        name="gambar"
        id="gambar"
        class="m-2 border border-solid text-teal-950"
      />
  
      <div class="w-full">
        <button
          id="submitButton"
          type="cutton"
          class="border border-teal-200 px-2 hover:bg-emerald-400 rounded-md bg-green-200"
        >
          Tambah
        </button>
      </div>
    </form>
  </div>
  
  <div id="dataObat"></div>
  `);
    dataList.html("");
    dataList.append(formAdd);
  });
});

this is the send code to node js within data and image and the issue is the preventdefault will not work because of the constructor or not using serialize

$(document).on("submit", "#obatForm", function (event) {
  event.preventDefault();

  const formData = new FormData(this); // Ctambah new form data biar enctype included

  $.ajax({
    url: "http://localhost:3000/submit",
    method: "POST",
    data: formData,
    processData: false, // Prevent jQuery from processing the data
    contentType: false, // Prevent jQuery from setting contentType
    dataType: "json",
    beforeSend: function () {
      $("#message").html("").fadeIn();
      var loading = $("<img>")
        .attr("src", "../images/spin.gif")

        .addClass("w-5 mx-2 filter invert");
      $("#submitButton").html("").prop("disabled", true).prepend(loading);
    },
    success: function (data) {
      $("#submitButton").prop("disabled", false);
      if (data.message) {
        // Assuming you have a button with the id "myButton"

        var img = $("<img>")
          .attr("src", "../images/bell.png")

          .addClass("w-5 mx-2 filter invert");

        $("#message")
          .html("Berhasil !")
          .fadeIn(2000)
          .prepend(img)
          .fadeOut(4000)
          .css("background-color", "green");

        $("#submitButton").html("Tambah");
        $("#obatForm")[0].reset();
        $("#addNav").trigger("click");
      } else {
        $("#message").html("Data gagal ditambahkan").fadeOut(3000);
      }
    },
    error: function (xhr, status, error) {
      var img = $("<img>")
        .attr("src", "./images/bell.png")
        .addClass("w-3 mx-2 filter invert");

      $("#message").html("").fadeIn();
      console.error("AJAX error:", error);
      $("#submitButton").html("Tambah").prop("disabled", false);
      $("#message")
        .html("Gagal Ditambahkan")
        .prepend(img)
        .css("background-color", "red")
        .fadeOut(4000);
    },
  });
});

im trying to change the form with normal form with serialize, it makes the preventdefault work again but it makes the data undefined because i have images to upload to multer node js.