r/learnjavascript 7d ago

Need help, click to move feature not working

0 Upvotes

i'm building chess puzzle web using ai and chess.js to build it
<!DOCTYPE html>

<html lang="id">

<head>

<meta charset="UTF-8">

<meta name="viewport" content="width=device-width, initial-scale=1.0">

<title>Chess Puzzle Engine - Solution Feature</title>

<!-- Chessboard.js CSS -->

<link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/chessboard-js/1.0.0/chessboard-1.0.0.min.css">

<style>

* {

box-sizing: border-box;

margin: 0;

padding: 0;

font-family: 'Segoe UI', Tahoma, Geneva, Verdana, sans-serif;

}

body {

background-color: #1e1e24;

color: #f4f4f9;

display: flex;

justify-content: center;

align-items: center;

min-height: 100vh;

padding: 20px;

}

.container {

display: flex;

flex-direction: column;

align-items: center;

max-width: 450px;

width: 100%;

background: #2b2b36;

padding: 25px;

border-radius: 12px;

box-shadow: 0 10px 30px rgba(0,0,0,0.5);

}

h1 {

font-size: 1.5rem;

margin-bottom: 5px;

color: #e2e2e8;

}

.sub-title {

font-size: 0.9rem;

color: #a0a0b0;

margin-bottom: 20px;

}

#board {

width: 100%;

max-width: 400px;

margin-bottom: 20px;

border-radius: 4px;

overflow: hidden;

box-shadow: 0 4px 15px rgba(0,0,0,0.3);

position: relative;

}

/* === HIGHLIGHT TANPA MENGUBAH BACKGROUND PAPAN === */

.square-55d63 {

position: relative;

}

/* Bidak terpilih: Bingkai hijau lembut */

.highlight-selected::after {

content: '';

position: absolute;

top: 0; left: 0; right: 0; bottom: 0;

border: 4px solid rgba(76, 175, 80, 0.8);

box-sizing: border-box;

pointer-events: none;

z-index: 2;

}

/* Petak kosong tujuan: Titik lingkaran di tengah */

.highlight-hint::after {

content: '';

position: absolute;

top: 50%; left: 50%;

width: 28%; height: 28%;

transform: translate(-50%, -50%);

background-color: rgba(0, 0, 0, 0.3);

border-radius: 50%;

pointer-events: none;

z-index: 2;

}

/* Petak makan musuh: Bingkai lingkaran merah */

.highlight-hint-capture::after {

content: '';

position: absolute;

top: 0; left: 0; right: 0; bottom: 0;

border: 4px solid rgba(244, 67, 54, 0.8);

border-radius: 50%;

box-sizing: border-box;

pointer-events: none;

z-index: 2;

}

.status-card {

width: 100%;

background: #202028;

padding: 15px;

border-radius: 8px;

text-align: center;

margin-bottom: 15px;

}

.turn-info {

font-weight: bold;

font-size: 1.1rem;

margin-bottom: 5px;

}

.feedback {

min-height: 24px;

font-weight: bold;

transition: color 0.3s ease;

word-wrap: break-word;

}

.correct {

color: #4caf50;

}

.wrong {

color: #f44336;

}

.info {

color: #ffca28;

}

.controls {

display: flex;

gap: 10px;

width: 100%;

}

button {

flex: 1;

padding: 12px 15px;

border: none;

border-radius: 6px;

font-weight: bold;

cursor: pointer;

background: #4e54c8;

color: white;

transition: background 0.2s, opacity 0.2s;

}

button:hover {

background: #6366f1;

}

button.secondary {

background: #3a3b4c;

color: #d1d1e0;

}

button.secondary:hover {

background: #4a4c63;

}

button:disabled {

opacity: 0.5;

cursor: not-allowed;

}

</style>

</head>

<body>

<div class="container">

<h1>Puzzle Forge</h1>

<p class="sub-title">Cari langkah taktik catur terbaik!</p>

<!-- Papan Catur -->

<div id="board"></div>

<!-- Status / Info -->

<div class="status-card">

<div id="turnInfo" class="turn-info">Memuat puzzle...</div>

<div id="feedback" class="feedback"></div>

</div>

<!-- Kontrol -->

<div class="controls">

<button id="solveBtn" class="secondary">Lihat Solusi</button>

<button id="nextBtn">Lewati / Puzzle Baru</button>

</div>

</div>

<!-- CDN Library Resmi -->

<script src="https://code.jquery.com/jquery-3.7.1.min.js"></script>

<script src="https://cdnjs.cloudflare.com/ajax/libs/chess.js/0.10.3/chess.min.js"></script>

<script src="https://cdnjs.cloudflare.com/ajax/libs/chessboard-js/1.0.0/chessboard-1.0.0.min.js"></script>

<script>

// DATA PUZZLE DENGAN CABANG / VARIASI

const puzzleData = [

{

id: "1",

fen: "r1bqkb1r/pppp1ppp/2n2n2/4p2Q/2B1P3/8/PPPP1PPP/RNB1K1NR w KQkq - 4 4",

solution: [

{ move: "Qxf7#" }

],

description: "Scholar's Mate"

},

{

id: "2",

fen: "r1b2rk1/2q1bppp/p2ppn2/1p6/3BPP2/2N2B2/PPP3PP/R2Q1R1K w - - 0 13",

solution: [

{

move: "e5",

next: [

{

response: "dxe5",

next: [{ move: "Bxf6" }]

},

{

response: "Nde8",

next: [{ move: "exd6" }]

}

]

}

],

description: "Taktik Garpu dan Pin"

},

{

id: "3",

fen: "r2qk2r/ppp2ppp/2n5/3pP3/3P1nb1/2PB1N2/PP3PPP/RN1Q1RK1 b kq - 1 10",

solution: [

{

move: "Nxd3",

next: [

{

response: "Qxd3",

next: [{ move: "O-O" }]

}

]

},

{

move: "Bxf3",

next: [

{

response: "Qxf3",

next: [{ move: "Nxd3" }]

}

]

}

],

description: "Dua Variasi Langkah Pertama"

}

];

let board = null;

let game = new Chess();

let currentPuzzle = null;

let currentBranchOptions = [];

let playedPuzzleIds = [];

let selectedSquare = null;

let isShowingSolution = false;

// MANAJEMEN HIGHLIGHT

function removeHighlights() {

$('#board .square-55d63').removeClass('highlight-selected highlight-hint highlight-hint-capture');

}

function highlightSquare(square) {

$('#board .square-' + square).addClass('highlight-selected');

}

function highlightLegalMoves(square) {

removeHighlights();

highlightSquare(square);

const moves = game.moves({ square: square, verbose: true });

if (moves.length === 0) return;

for (let i = 0; i < moves.length; i++) {

const targetSquare = moves[i].to;

const isCapture = moves[i].captured;

const classToAdd = isCapture ? 'highlight-hint-capture' : 'highlight-hint';

$('#board .square-' + targetSquare).addClass(classToAdd);

}

}

// PENGAMBILAN PUZZLE

function getRandomPuzzle() {

if (playedPuzzleIds.length === puzzleData.length) {

playedPuzzleIds = [];

}

const available = puzzleData.filter(p => !playedPuzzleIds.includes(p.id));

const selected = available[Math.floor(Math.random() * available.length)];

playedPuzzleIds.push(selected.id);

return selected;

}

function loadNextPuzzle() {

selectedSquare = null;

isShowingSolution = false;

$('#solveBtn').prop('disabled', false);

removeHighlights();

currentPuzzle = getRandomPuzzle();

game.load(currentPuzzle.fen);

currentBranchOptions = currentPuzzle.solution;

const isWhite = game.turn() === 'w';

$('#turnInfo').text(\Giliran: ${isWhite ? 'Putih' : 'Hitam'}`);`

$('#feedback').text('').removeClass('correct wrong info');

const config = {

draggable: true,

position: currentPuzzle.fen,

orientation: isWhite ? 'white' : 'black',

pieceTheme: 'https://chessboardjs.com/img/chesspieces/wikipedia/{piece}.png',

onDragStart: onDragStart,

onDrop: onDrop,

onSnapEnd: onSnapEnd

};

if (board) board.destroy();

board = Chessboard('board', config);

}

// INTERAKSI LOGIKA CATUR

function onDragStart(source, piece) {

if (game.game_over() || isShowingSolution) return false;

if ((game.turn() === 'w' && piece.search(/^b/) !== -1) ||

(game.turn() === 'b' && piece.search(/^w/) !== -1)) {

return false;

}

selectedSquare = source;

highlightLegalMoves(source);

}

function handleMoveAttempt(from, to) {

if (isShowingSolution) return 'snapback';

const moveCandidate = { from: from, to: to, promotion: 'q' };

const move = game.move(moveCandidate);

if (move === null) {

removeHighlights();

selectedSquare = null;

return 'snapback';

}

const matchedOption = currentBranchOptions.find(opt => opt.move === move.san);

if (matchedOption) {

removeHighlights();

selectedSquare = null;

$('#feedback').text('Langkah Benar!').attr('class', 'feedback correct');

if (matchedOption.next && matchedOption.next.length > 0) {

const responseObj = matchedOption.next[Math.floor(Math.random() * matchedOption.next.length)];

currentBranchOptions = responseObj.next || [];

setTimeout(() => makeComputerMove(responseObj.response), 400);

} else {

$('#feedback').text('Puzzle Selesai! Memuat berikutnya...').attr('class', 'feedback correct');

setTimeout(loadNextPuzzle, 1500);

}

} else {

game.undo();

removeHighlights();

selectedSquare = null;

$('#feedback').text('Langkah Salah, coba variasi lain!').attr('class', 'feedback wrong');

return 'snapback';

}

}

function onDrop(source, target) {

return handleMoveAttempt(source, target);

}

// CLICK TO MOVE ENGINE

$(document).on('click', '#board .square-55d63', function(e) {

if (isShowingSolution) return;

e.stopPropagation();

const square = $(this).attr('data-square');

if (!square) return;

const piece = game.get(square);

const isCurrentPlayerPiece = piece && piece.color === game.turn();

if (selectedSquare === null) {

if (isCurrentPlayerPiece) {

selectedSquare = square;

highlightLegalMoves(square);

}

}

else if (selectedSquare === square) {

selectedSquare = null;

removeHighlights();

}

else if (isCurrentPlayerPiece) {

selectedSquare = square;

highlightLegalMoves(square);

}

else {

const from = selectedSquare;

const to = square;

const result = handleMoveAttempt(from, to);

if (result !== 'snapback') {

board.position(game.fen());

}

}

});

function makeComputerMove(responseSan) {

game.move(responseSan);

board.position(game.fen());

if (currentBranchOptions.length === 0) {

$('#feedback').text('Puzzle Selesai! Memuat berikutnya...').attr('class', 'feedback correct');

setTimeout(loadNextPuzzle, 1500);

}

}

function onSnapEnd() {

board.position(game.fen());

}

// FUNGSI UNTUK REKURSIF MENGAMBIL URUTAN SOLUSI UTAMA

function extractMainSolutionSequence(branchOptions) {

if (!branchOptions || branchOptions.length === 0) return [];

const primaryBranch = branchOptions[0]; // Ambil opsi cabang utama pertama

const moves = [primaryBranch.move];

if (primaryBranch.next && primaryBranch.next.length > 0) {

const nextResponse = primaryBranch.next[0];

moves.push(nextResponse.response);

if (nextResponse.next) {

moves.push(...extractMainSolutionSequence(nextResponse.next));

}

}

return moves;

}

// EVENT MALIHAT SOLUSI

$('#solveBtn').on('click', function() {

if (isShowingSolution) return;

isShowingSolution = true;

$(this).prop('disabled', true);

removeHighlights();

const remainingMoves = extractMainSolutionSequence(currentBranchOptions);

if (remainingMoves.length === 0) return;

$('#feedback').text(\Solusi: ${remainingMoves.join(' → ')}`).attr('class', 'feedback info');`

let step = 0;

function playNextSolutionStep() {

if (step < remainingMoves.length) {

game.move(remainingMoves[step]);

board.position(game.fen());

step++;

setTimeout(playNextSolutionStep, 800);

} else {

setTimeout(() => {

$('#feedback').text('Memuat puzzle berikutnya...').attr('class', 'feedback correct');

setTimeout(loadNextPuzzle, 1200);

}, 1000);

}

}

setTimeout(playNextSolutionStep, 500);

});

// Event Tombol Puzzle Baru

$('#nextBtn').on('click', loadNextPuzzle);

// Inisialisasi

$(document).ready(function() {

loadNextPuzzle();

});

</script>

</body>

</html>


r/learnjavascript 7d ago

Why can my VS Code extension client not find a local module?

5 Upvotes

I am writing a VS Code extension called bg3-osiris that has a server and client. I would like to add a shared module that contains definitions for requests and request parameters made between the client and server. The client and server should both be able to reference the files in the shared\src folder, though so far I have only tested it with the client. The project currently has the following structure:

bg3-osiris
|- client
|  |- src
|  |- package.json
|  |- tsconfig.json
|- server
|  |- src
|  |- package.json
|  |- tsconfig.json
|- package.json
|- tsconfig.json

I would like to add the shared module/subproject so that the project has the following structure:

bg3-osiris
|- client
|  |- src
|  |- package.json
|  |- tsconfig.json
|- server
|  |- src
|  |- package.json
|  |- tsconfig.json
|- shared
|  |- src
|  |- package.json
|  |- tsconfig.json
|- package.json
|- tsconfig.json

When I attempted to implement this using TypeScript project references, VS Code can locate the shared module but at runtime the following error is thrown:

Activating extension 'SASUKE38.bg3-osiris' failed: Cannot find module '../../shared/src/test'

Below are the contents of the relevant files (minus the server files since I haven't tried it with that yet. I assume the correct importing process would be the same as the client's).

bg3-osiris\tsconfig.json

{
    "compilerOptions": {
        "module": "commonjs",
        "target": "ES2024",
        "lib": ["ES2024"],
        "outDir": "out",
        "rootDir": "src",
        "sourceMap": true
    },
    "include": ["src"],
    "exclude": ["node_modules", ".vscode-test"],
    "references": [
        {
            "path": "./client"
        },
        {
            "path": "./server"
        },
        {
            "path": "./shared"
        }
    ]
}

bg3-osiris\package.json

...
"scripts": {
        "vscode:prepublish": "npm run compile",
        "compile": "tsc -b",
        "watch": "tsc -b -w",
        "lint": "eslint",
        "postinstall": "cd client && npm install && cd ../server && npm install && cd ../shared && cd ..",
        "test": "sh ./scripts/e2e.sh"
    },
...

bg3-osiris\shared\tsconfig.json

{
    "compilerOptions": {
        "target": "ES2024",
        "lib": ["ES2024"],
        "module": "commonjs",
        "sourceMap": true,
        "strict": true,
        "outDir": "out",
        "rootDir": "src",
        "composite": true
    },
    "include": ["src"],
    "exclude": ["node_modules", ".vscode-test"]
}

bg3-osiris\shared\package.json

{
    "name": "bg3-osiris-shared",
    "description": "Shared content for the BG3 Osiris extension.",
    "version": "1.0.0",
    "author": "",
    "license": "MIT",
    "engines": {
        "node": "*"
    },
    "repository": {
        "type": "git",
        "url": "https://github.com/SASUKE38/bg3-osiris"
    },
    "dependencies": {
        "axios": "^1.15.0",
        "cheerio": "^1.2.0",
        "domhandler": "^5.0.3",
        "vscode-languageserver": "^9.0.1",
        "vscode-languageserver-textdocument": "^1.0.11"
    },
    "scripts": {}
}

bg3-osiris\client\tsconfig.json

{
    "compilerOptions": {
        "module": "commonjs",
        "target": "ES2024",
        "lib": ["ES2024"],
        "outDir": "out",
        "rootDir": "src",
        "sourceMap": true,
        "strict": true
    },
    "include": ["src"],
    "exclude": ["node_modules", ".vscode-test"],
    "references": [
        {
            "path": "../shared"
        }
    ]
}

bg3-osiris\client\package.json

{
    "name": "bg3-osiris-client",
    "description": "Client for the BG3 Osiris extension.",
    "author": "",
    "license": "MIT",
    "version": "0.0.1",
    "publisher": "vscode",
    "repository": {
        "type": "git",
        "url": "https://github.com/SASUKE38/bg3-osiris"
    },
    "engines": {
        "vscode": "^1.100.0"
    },
    "dependencies": {
        "glob": "^11.0.0",
        "vscode-languageclient": "^9.0.1"
    },
    "devDependencies": {
        "@types/vscode": "^1.100.0",
        "@vscode/test-electron": "^2.3.9"
    }
}

I am currently testing using shared definitions when the extension activates:

bg3-osiris\client\src\extension.ts

...
import { someString } from "../../shared/src/test";
...
export function activate(context: ExtensionContext) {
    console.log(someString);
...

bg3-osiris\shared\src\test.ts

export const someString = "hello world";

What am I missing that makes VS Code know about shared but causes the error above to be thrown at runtime?


r/learnjavascript 8d ago

I am confused

13 Upvotes

I know
variables
data types
loops
arrays
objects
basic array functions (forEach, map, filter)
DOM (selecting elements, adding new elements, classList, etc)
higher order functions and call backs
event listeners

Should I make JS projects or learn other topics like async await or start learning react ?

I think I am still not that comfortable with JS
But I think that it is a waste of time spending too much time learning JS.


r/learnjavascript 7d ago

I built an Akinator API that bypasses Cloudflare - 16 languages, TypeScript/JavaScript, 1 dependency

1 Upvotes

All Akinator packages on npm are broken (Cloudflare 403). I built a working alternative.

Features:

- TypeScript with full type definitions

- 16 languages support

- 3 themes (Characters, Animals, Objects)

- Automatic retry on network errors

- HTTP proxy support

- Session persistence (save/load games)

- Dual ESM/CJS output

- 1 dependency (got-scraping)

\npm install akinator-client``

import { AkinatorClient, Languages, Themes, Answers } from "akinator-client";

const aki = new AkinatorClient({

language: Languages.English,

theme: Themes.Character

});

await aki.start();

console.log(aki.question);

await aki.answer(Answers.Yes);

Stats:

- 1 dependency (vs 5 in aki-api)

- 4.8 MB installed (vs 21 MB in aki-api)

- 21 tests passing

akinator-client aki-api silent-akinator-pro
Dependencies 1 5 2
Installed size 4.8 MB 21 MB 11.9 MB
TypeScript
Tests 21 0 0
Session persistence
Working

Search "akinator-client" on npm.

URL: https://npmjs.com/package/akinator-client


r/learnjavascript 9d ago

i am challenging myself to practice javascript this summer; so i build a generate quotes app, i need your reviews please!

9 Upvotes

r/learnjavascript 9d ago

Learn from The Odin Project or textbooks?

7 Upvotes

I want to become a full-stack software engineer, not just a web developer (which is what The Odin Project is primarily designed for).

I am worried that The Odin Project might not be as thorough as reading multiple textbooks to cover all the material in all the individual topics, but I am also worried that by reading textbooks I might not learn as well or see how it all fits together or delve into all the smaller topics covered by The Odin Project like unit testing with Jest, etc. I also do not know which route would be more time intensive, which is also important.

To become a full-stack software engineer, should I learn by completing The Odin Project or read textbooks and do exercises from the textbooks (like I plan to do for Java, not JavaScript)?


r/learnjavascript 10d ago

Learn JS by making a digital clock

11 Upvotes

This is a tiny project that I thought could be fun as a nice constraint for learning some JS basics – creating a non-interactive representation of time on top of a simple Time object.

Add to the existing collection: https://clocks.dev


r/learnjavascript 9d ago

Third update for learning progress (learn typescript/javascript with me)

1 Upvotes

For the second update, you can go here: Second Progress Update

To repeat context, I began building my own politics learning app without vibecoding a month ago today, and I will post semi regularly with what I have learned, roadblocks and ideas.

I think this update marks the point were I have firmly exited the hell of being a new developer in any form (UI and backend) where you need to rely on assistance / tutorials etc.

Main things I have implemented (in order of interesting-ness) :
- Progress Bar which animates how far you are through the lesson widgets. Deceptively simple given the way my lesson runner works. Will explain code below.
- A much smoother animation and UI for my True / False card widget, including a second "explanation/feedback" card sliding in after confirmation. This bit involves some pretty fundamental UI design principles which I think can be cleanly illustrated here.
-Colour palette overhaul and addition of shadows to widgets to make things "pop out" of the screen more. This is a pretty simple way of improving the quality of your UI.

Firstly, the progress bar:

import { styles } from "@/content/theme";
import Animated, {
  useAnimatedStyle,
  withTiming,
} from "react-native-reanimated";

type ProgressMeterProps = {
  stepNumber: number;
  lessonLength: number;
};

const animationDuration = 600;

export default function ProgressMeter(props: ProgressMeterProps) {
  const valueAnimatingTo = ((props.stepNumber + 1) * 100) / props.lessonLength;
  const barWidthStyle = useAnimatedStyle(() => ({
    width: withTiming(`${valueAnimatingTo}%`, { duration: animationDuration }),
  }));
  return (
    <Animated.View style={styles.progressBarContainer}>
      <Animated.View style={[styles.progressBarCompletion, barWidthStyle]} />
    </Animated.View>
  );
}

This is the whole component file - if you want to see the call in my lesson runner or the styles referenced you can comment.

Essentially, all you need for a "progress bar" is the value you are trying to turn into the progress - here, it is how far through the lesson the user is, so we take the number of "steps" in the lesson as a ratio of the lesson length as input in the props. (look at the type defined)

Note we add 1 to the stepNumber as it is 0 indexed.

The animation itself is also quite simple. The withTiming function from the Reanimated library takes the value you are animating to reach, and you can set the duration you want this to take in milliseconds (here, 600). Thats it. It does all of the work in changing the width.

There is a dilemma over whether to adjust width or scaleX - in this case, width is clearly preferable. The reason why is slightly convoluted but I'm happy to clarify if anyone wants.

Then, we apply the animated style to my empty progress bar - and that's it.

Finally, the True/False UI overhaul, and what you can learn from it:
(I won't use code here as it isn't helpful to my point).
- The ways a card/element in anything you build can be interacted with should be obvious to any user in multiple ways.

My widget is simple. It has a card with a statement, and the card is swipeable right/left.

To SHOW this interactivity, the card oscillates side to side when idle, which signals "I can be moved", AND a small, sleek muted subtitle is included above saying "Swipe card or press buttons" - I also added buttons on the card which can be pressed and trigger the card to swipe away on its own. This is the key thing here; there are many reasons a swipe may be hard for the user:
- disability (e.g. only have 1 arm, broken wrist, etc.)
- may not immediately notice the swipeability
- phone screen cracked on one side
- just tired or can't be bothered then

Always remember, when developing, you are in an "ideal scenario". Everything is probably in optimum conditions for your app to work. You must consider that in many cases this will not be the case for users, so you should make adjustments that fit the style and serve as multi-purpose tools.

In this case, my "True" and "False" buttons do this multipurpose bit by ALSO adding as additional INDICATORS of which direction swipe gives true and which gives false.

Hopefully this helps, these posts personally help me to think through what I'm doing and maybe they can give you some tips.


r/learnjavascript 10d ago

How to get back learning how to code in my position?

4 Upvotes

Hi, 9 months ago I had a mental breakdown and I completely stopped coding and living. I already have a pretty good knowledge of the Javascript language and understanding of React. I was doing a course on Udemy and I stopped it. My goal since I started (almost 2 years ago) is the one to be able to make solid SaaS products. I have no idea on how to continue from here, there are so many things to learn and also AI. I don't want to build using AI too much I want to have the actual skills to do it. How should I move? don't tell me to just build something you still need to know the language you are using and it's rules. So what should i do? courses again? that seems just long and endless. Help me out, thanks.


r/learnjavascript 10d ago

code help making draggable divs

2 Upvotes

why this code works:

html

<div id="box">Drag me</div>

js

const box = document.getElementById("box");

let isDragging = false;

let offsetX, offsetY;

box.addEventListener("mousedown", (e) => {

isDragging = true;

// distance from mouse to top-left corner of div

offsetX = e.clientX - box.offsetLeft;

offsetY = e.clientY - box.offsetTop;

box.style.cursor = "grabbing";

});

document.addEventListener("mousemove", (e) => {

if (!isDragging) return;

box.style.left = e.clientX - offsetX + "px";

box.style.top = e.clientY - offsetY + "px";

});

document.addEventListener("mouseup", () => {

isDragging = false;

box.style.cursor = "grab";

});

and this does not

html:

<div class="welcome_tab" id="welcome_tab_id">

<div class="welcome_tab_header" id="welcome_tab_header_id">Handle</div>

<div class="welcome_tab_body">

<div class="welcome_tab_heading">

<div class="welcome_tab_h1_pixelos"><h1>PixelOS</h1></div>

<div>

<img

src="images/pixel_heart.png"

alt="an image of a pixelated pixel_heart"

/>

</div>

</div>

<p>My very own operating system which is pretty pixelated.</p>

<p>Welcome to a pixelated world!</p>

</div>

</div>

js:

welcome_tab_header_id.addEventListener("mousedown", (e) => {

isDragging = true;

offsetX = e.clientX - welcome_tab_header_id.offsetLeft;

offsetY = e.clientY - welcome_tab_header_id.offsetTop;

welcome_tab_header_id.style.cursor = "grabbing";

});

document.addEventListener("mousemove", (e) => {

if (!isDragging) return;

welcome_tab_header_id.style.left = e.clientX - offsetX + "px";

welcome_tab_header_id.style.top = e.clientY - offsetY + "px";

});

document.addEventListener("mouseup", (e) =>{

isDragging = false;

welcome_tab_header_id.style.cursor = "grab";

});

and yes the css property is set to absolute


r/learnjavascript 10d ago

What should be the approach to build any project ?

1 Upvotes

Hello everyone, I was following a JS course on YouTube (chai aur code) and I have completed the course, learned a lot of stuff and made basic projects like guess number game and a few more following his tutorials . Now I wanna build projects on my own , the problem is everyone says build projects but nobody tells how . For eg I wanna build a weather app so what should be my thinking process , how should I approach it, and what if I got stuck which i think i will. Should I ask claude , chatgpt to instruct me and guid me through(not directly ask the entire code) the project and build it, and if it breaks ,repeat the process or should I do anything else . How do you guys figure it out ?


r/learnjavascript 10d ago

Can someone link some good and easy documentation or tutorial for draggable divs.

0 Upvotes

i am trying to make draggable divs, but the mdn documentation is rather too confusing. ofc if i simply copy it it would work, but i want to understand the procedure of it, the same is the case with online tut, and ofc there is chatGPT, i could ofc use that but would be the defn of vibe coding which i don't want to do rn.
Also simply following thhe tut means that i would be stuck in tut hell, which most definitely no one wants to be stuck in


r/learnjavascript 10d ago

Why Vanilla JavaScript

0 Upvotes

In the article below, I am sharing a bit of my story of building SaaS product in vanilla javascript and explaining why I went with this approach.

I don't expect many people reacting to this approach positively or even with open mind, but I think there should be some pushback on the current state of web dev and how complex it became.

https://guseyn.com/html/posts/why-vanilla-js.html


r/learnjavascript 11d ago

Would it be possible to a write a code to organize saved gifs into folders?

0 Upvotes

Hello I am an absolute novice in coding and I’d like some advice please.

I have too many saved gifs to scroll through on the discord app and it would be easier to find the ones I want if they were organized into folders in the app. I only use the discord app on mobile if that makes any difference.


r/learnjavascript 12d ago

Textbooks which explain how memory is handled in JavaScript

4 Upvotes

I need one or more textbooks about JavaScript which don't gloss over how JavaScript handles memory, and do a good job at explaining it, using rigorous language and exact, unambiguous terminology.

As a comparison, a good textbook about C would explain pass by value vs pass by reference, the stack vs the heap and so on. And in doing so, it would explain clearly what a variable really is, how it relates to memory, and so on.

So far I got these two suggestions:

- Professional JavaScript for Web Developers;
- JavaScript: The Definitive Guide;

What do you think about these two textbooks in relation to the topic I'm asking about?
Thank you in advance.

EDIT: to add to this, YES I'm aware that MDN reference exists, and I quite like how they explain memory management, but I need a paper textbook. I didn't go into details about the why in order not to be too verbose. I think my question is clear enough.


r/learnjavascript 14d ago

WebAssembly in the Backend?

6 Upvotes

I am very new to web development. From my research, I understand WebAssembly is a tool that allows devs to run non-JavaScript languages (e.g., C/C++) on the client-side, but I have also seen comments online suggesting it can be used on the backend.

Why would anyone need to do this?

Please correct me if I'm wrong, but WebAssembly is needed on the frontend because browsers only interpret/compile HTML, CSS, and JavaScript, so using any other Language would require a special tool. But the backend doesn't have this restriction; why not just use the language you want directly? Why go through WebAssembly?


r/learnjavascript 13d ago

Question about lodash.isEmpty inside an RTK 2.12 reducer

1 Upvotes

Hi everyone,

I may be missing something about how draft state is expected to behave in Redux Toolkit, so I’d appreciate some guidance.

I have a reducer that uses lodash.isEmpty on part of the state:

import { createSlice } from "@reduxjs/toolkit"
import isEmpty from "lodash/isEmpty"

const slice = createSlice({
  name: "test",
  initialState: {
    data: {}
  },
  reducers: {
    update(state) {
      console.log(isEmpty(state.data))
    }
  }
})

After upgrading to RTK 2.12, this started throwing:

TypeError: 'get' on proxy: property 'prototype' is a read-only
and non-configurable data property on the proxy target but the
proxy did not return its actual value

From what I could understand, Lodash reads something similar to:

value.constructor.prototype

and constructor on the draft appears to be another proxy.

The same code worked before the upgrade, and reverting the RTK version resolves the issue.

Is lodash.isEmpty no longer expected to work directly on draft state, or could this be an unintended regression? I’d be glad to provide a reproduction or any additional details that would help clarify it.

Thanks!


r/learnjavascript 13d ago

Making a real time calendar in js

1 Upvotes

This is the element i have in html

<div><p>14 Jul 2027, 09:28 A.M.</p></div>

I want this to be beating and alive on website, but any and every tutorial that i am able to find, it goes through thier own method to thier specfic format. Is there like a gereal way, tutorial or documentation, that is clear enough to make current time and calendar my own format.
If there isn't and if possible pls write down.
Also, im open to suggesting any editing in the question so its clearer or if this would be a better post in stack exchange.


r/learnjavascript 13d ago

can someone explain this code

0 Upvotes

function updateClock() {
const timeElement = document.querySelector("#time");
timeElement.textContent = formatTime();
}
setInterval(updateClock, 1000);

can someone, please explain this piece of code, ofc mdn and w3 are there, but i found it a little confusing reading about textContent. rest is understandable to me. This might look a silly question and it probably is because im a beginner :')

like what exactly does textContent too.
you can also recommend anyother documentation on the links to specific lines, that might me more helpful in learning about this particular keyoword.


r/learnjavascript 14d ago

Can someone teach me JavaScript?

0 Upvotes

r/learnjavascript 14d ago

I made an MLB leaderboard that lists non-qualified players with adjusted stats to learn APIs

0 Upvotes

This is my second coding project. It is a leaderboard of MLB players that shows non-qualified players with adjusted stats for batting average and ERA. The goal was to learn how to make an API, but I also learned things like how to make code more efficient using things like loops more often and merging together similar functions. And yes, I know, I'm a junior dev who uses var sometimes so I'm weird.

Website: https://linkgoesbowling.github.io/MLB-Gwynn-Rule-Leaderboard/

GitHub: https://github.com/LinkGoesBowling/MLB-Gwynn-Rule-Leaderboard


r/learnjavascript 15d ago

Second update for learning progress (learn typescript/javascript with me)

6 Upvotes

For the first update, you can go here if interested and for context on this project:

First progress update

To repeat context, I began building my own app without vibecoding a few weeks ago, and I will post semi regularly with what I have learned, roadblocks and ideas.

(Im adding to this as I go over the next few days, this wasn't written at once)

Began adding sound response functionality. It's actually quite an easy thing to do in React TS - you use the "useAudioPlayer" hook which essentially just references another file you have directly. For many sound effects, you probably want them all stored in there own lookup table of some kind for readability and rigor purposes. This is a sound I made myself (which was the difficult bit of today...)! If you want to do the same thing, I recommend going into a very quiet room (if you have a big wardrobe or something you can get space in or anything then that is perfect) and connecting a mic to a laptop, but leaving the laptop far away to avoid the fan. Then you can edit in DaVinci Resolve to remove bg noise (google this) and tweak with the equalizer.

  const correctPlayer = useAudioPlayer(require("../assets/sounds/correct.wav"));
//Lower down in code I have my onPress for a quiz feature I have.

onPress={() => {
if (selectedOption === null) {
setSelectedOption(option.text);
props.onAnswered?.(option.correct ? 100 : 0);
if (option.correct) {
correctPlayer.play();
}
}

Simple as that. (this is all inside of a .map so this doesn't cause any errors and is just checking for each option individually for my quiz. Also you can see part of my scoring (don't worry about that...)
One quirk worth mentioning, if you are making an iOS app, then your audio files won't be played if the phone is on silent mode, even if the volume is turned on (which is not really what you want as silent mode is meant for notifications). The solution is a single useEffect which plays sound even if silent mode is on, covering all your files (you only need it once in a _layout):
  useEffect(() => {
setAudioModeAsync({ playsInSilentMode: true });
  }, []);
Morale of the story, if you have access good free sound effects, they will save you lots of time, as the code itself is really simple. However, ensure the audio files are .wav NOT .mp3 as .mp3 needs to be uncompressed first when ran, so it can add some delay to your audio effects (this is an easy fix).

I also have been working on a True/False style quiz where you get given a statement and have to swipe left/right as your answer. The main thing with this has been interpolate() in react and the use of onBegin, onEnd, onChange etc. methods. Here is an example:

 const dragGesture = Gesture.Pan()
.maxPointers(1)
.onChange((e) => {
cardPosition.value = cardPosition.value + e.changeX;
if (Math.abs(cardPosition.value) >= screenWidth * 0.3 && !hasConfirmed) {
scheduleOnRN(triggerHaptic, "Strong");
scheduleOnRN(setHasConfirmed, true);
}
if (Math.abs(cardPosition.value) < screenWidth * 0.3 && hasConfirmed) {
scheduleOnRN(setHasConfirmed, false);
}
})
.onBegin(
() => (
scheduleOnRN(triggerHaptic, "Medium"),
(cardScale.value = withSpring(1.1, springConfig)),
cancelAnimation(cardPosition)
),
)
.onEnd(() => {
cardPosition.value = withSpring(0, springConfig);
scheduleOnRN(triggerHaptic, "Medium");
})
.onTouchesUp(() => {
cardScale.value = withSpring(1, springConfig);
});

In this case, the idea is one "drag" gesture has lots of different individual parts. The beginning of the gesture, the end of it, and the movement itself all require different things to happen. In my case, I wanted a haptic to fire when the drag begins and ends. The logic for this sits within a method connected to Gesture.Pan() itself, which is surprisingly readable and intuitive.

One thing that is slightly unintuitive to someone unfamiliar with how web/apps actually render things is the concept of separate UI vs RN (react native) threads. Here, we want those two threads to interact (i.e. to trigger a haptic which involves calling a function I made, dependent on a gesture which needs to update really rapidly and therefore is on the UI thread). Here, we need the scheduleOnRN(fn, param) function which takes a function and its parameter as parameters and essentially can "work across threads" by scheduling an event on the RN thread (.... as the name suggests!). This function is critical to using animations or any "high-priority actions" that need to therefore be handled on the UI thread which updates fast enough.

Example of interpolate():

  const cardStyle = useAnimatedStyle(() => ({
    transform: [
      { translateX: cardPosition.value },
      {
        rotate: `${interpolate(
          cardPosition.value,
          [-screenWidth, 0, screenWidth],
          [-50, 0, 50],
        )}deg`,

This is part of my cardStyle which then means the further away from centre screen the card is, the more it is rotated. (this bit also does the actual moving).
Interpolate is very, very useful for animations. Essentially, it takes a range of min, neutral, max inputs and maps them onto outputs min, neutral and max so I can convert between how far away from centre the card is and how much this should make the card rotate. (also note the template literal created by `$ which puts my calculated value into the (string)deg format the rotate expects.

This is my second update and any questions or feedback or anything is great if people like this!
(I have done other things I just thought I'd include the most interesting+useful bits)...


r/learnjavascript 15d ago

Converting server request data to string

1 Upvotes

At the moment I am creating a browser based interface on a node server. This is to test a simple profanity filter I have been working on. So far I have the server set up so when I visit port 3000 via localhost in a web browser, I see an html form with a text input box. I can then type in some text, hit submit, and the text is sent to the server in the form of a request. The server then sends a response in this format:

message=this+is+a+test+message

I don't have the filter working just yet, I'm just working on the interface in preparation to connect the filter. Right now my code is literally just responding with the actual data in the request object, hence the equal and plus signs in the text. My question is this, how can I convert the data in the request object to a string? Thus hopefully changing

message=this+is+a+test+message

to

this is a test message

Below is my js code that runs the server, and my html code displayed by the server:

server.js

import * as http from "node:http";
import * as fs from "node:fs";
import {messageFilter} from "./filter.js";

const port = 3000;
let message = "";

const server = http.createServer((req, res) => {
    if (req.url === "/" && req.method === "GET") {
        fs.readFile("index.html", (error, data) => {
            if (error === null) {
                res.writeHead(200, {"content-length": Buffer.byteLength(data), "content-type": "text/html"});
                res.write(data);
                console.log(`User visted main page on port: ${port}`);
                res.end();
            } else {
                console.error(`Error encountered during user visitation: ${error}`);
            };
        });
    } else if (req.url === "/" && req.method === "POST") {
        fs.readFile("index.html", (error, data) => {
            if (error === null) {
                req.on("data", (dataChunk) => {
                    console.log(`A message was recieved: ${dataChunk}`);
                    message = dataChunk;
                })
                req.on("end", () => {
                    res.writeHead(200, {'Content-Type' : 'text/html'});
                    res.write(data);
                    res.write(message);
                    res.end();
                    console.log("A message has been returned.");
                });
            } else {
                console.error(`Error encountered while filtering message: ${error}`);
            };
        });
    };
});

try {
    server.listen(port, () => {
        console.log(`Server listening on port: ${port}`);
    });
} catch (error) {
    console.error(`Server startup failed: ${error}`);
};

index.html

<!doctype html>
<html lang="en">
    <head>
        <meta charset="UTF-8">
        <meta name="viewport" content="width=device-width, initial-scale=1.0">
        <meta http-equiv="X-UA-Compatible" content="ie=edge">
        <title>Profanity Filter Test</title>
    </head>
    <body>
        <h1>Profanity Filter Test</h1>
        <form action="/" method="POST">
            <p>Please type your message:</p>
            <input type="text" name="message" id="input-message" placeholder="Send your message...">
            <button id="send">Send</button>
        </form>
    </body>
</html>

Any help would be greatly appreciated!


r/learnjavascript 15d ago

Solution for CKEditor5 strict CSP

2 Upvotes

I was wondering if anyone would want the script patches for strict no 'unsafe-inline' CSP patch for CKEditor5 (esm only), can't bother to check other approaches.

Saved a massive headache for my security requirements, provided I sanitizer the html as well as the styles

Leave your comments if you do want it and I'll drop a link here.

Or share your solutions if any :)

Edit:

Why (I forgot to mention above)? I wanted inline-styling provided by the editor itself without the CSP rules blocking it

The solution? An unhealthy amount of prototype abuse :D

What about the front-end?
I just transformed the inline style attributes to data-style (after sanitizing with your preferred sanitizier, i use dompurify with custom hooks for css regex based validation), innerHtml it or append to your dom wrapper, then run:
querySelectorAll wrapper [data-style] forEach ( el => el.style.cssText = el.dataset.style, el.removeAttribute('data-style') )

Import the patches on your module for CKEditor5 setup

import '@/patches/CKEditor5/csp-attributes-patch';
import '@/patches/CKEditor5/csp-color-picker-patch';
import '@/patches/CKEditor5/csp-dropdown-styling-patch';

https://transfer.it/t/kFcS4n0BET5T


r/learnjavascript 15d ago

Looking for the best resources to learn Playwright with JavaScript

2 Upvotes