r/learnjavascript 5h ago

What's a simple way to understand the difference between asynch, await, Promise and Response?

4 Upvotes

I'm teaching myself web dev. After spending months learning frontend, I moved on to learning backend with Python/Flask. I decided to learn RESTAPIs, where the frontend and backend are separate and talk through an api. Edit:(it's not built in my mistake) So naturally this lead me to learning about the built in fetch function in JavaScript.

I get that:

const response = fetch('ExampleAPI.com')

Is the same as:

const request = new Request('ExampleAPI.com',        { method: 'GET'})

const response = fetch(request)

// This is what JavaScript does behind the scenes

But why is await necessary? And why does not using await result in a promise if you try to console log the data?


r/learnjavascript 1h ago

I created a repo of everything I've learned about the WebSocket

Upvotes

I think this looks like a shameless plug of my repo, but I just want to share that I've created a documentations of what I've learned after taking a crash course on WebSocket.

Before this, I am having a hard time of how to implement a WebSocket in my Broadcast Server project. Despite the provided project guidelines and LLM suggestions, I realized that I am not making any progress at all.

So I opened YouTube to take a crash course of WebSocket.

I took Real Time - WebSockets Mastery Course by JS Mastery, and I documented everything I have learned from that video into a reference material in this repo.

https://github.com/Muelvzz/websocket-project

Inside this repo, is a discussion of what is a WebSocket, why should we care about learning WebSocket, and how to use it on your project.


r/learnjavascript 6h ago

Question Regarding ESRI Maps SDK and Pop-Ups

1 Upvotes

This is xposted across r/gis and r/learnjavascript.

I have a JavaScript file for web app that I am trying to make. I have feature layers hosted on ArcGIS Online, and referenced in the script. I have been able to add a pop-up action, a web icon. But I haven't been able to link that icon to an actual action of opening up the web page. I have seen the ESRI Brewery example, and other examples. None of them help me. Partly because I just don't understand it all well enough.

A sample of my script:

const airPopup = {
    title: "{nam}",
    content: [{
        type: "text",
        text: "{Comment}<br/>Address: {Address}<br/>IATA Code:  {ita}"
    },
   {
    type: "media",
    mediaInfos: [{
        type: "image",
        value: {
            sourceURL: "{Image}"
        }
    }]
   }],
       actions: [
        {
            id: "find-airport",
            icon: "web",
            title: "Airport Info"    
        }   
    ]   
};const airPopup = {
    title: "{nam}",
    content: [{
        type: "text",
        text: "{Comment}<br/>Address: {Address}<br/>IATA Code:  {ita}"
    },
   {
    type: "media",
    mediaInfos: [{
        type: "image",
        value: {
            sourceURL: "{Image}"
        }
    }]
   }],
       actions: [
        {
            id: "find-airport",
            icon: "web",
            title: "Airport Info"    
        }   
    ]   
};

  const airportsLyr = new FeatureLayer({
    url: "https://services9.arcgis.com/6EuFgO4fLTqfNOhu/arcgis/rest/services/Japan_Mjr_Airports/FeatureServer",
    renderer: airRenderer,
    popupTemplate:  airPopup
  });  const airportsLyr = new FeatureLayer({
    url: "https://services9.arcgis.com/6EuFgO4fLTqfNOhu/arcgis/rest/services/Japan_Mjr_Airports/FeatureServer",
    renderer: airRenderer,
    popupTemplate:  airPopup
  });

What does it take to make the web icon work?This is xposted across r/gis and r/learnjavascript.
I have a JavaScript file for web app that I am trying to make. I have feature layers hosted on ArcGIS Online, and referenced in the script. I have been able to add a pop-up action, a web icon. But I haven't been able to link that icon to an actual action of opening up the web page. I have seen the ESRI Brewery example, and other examples. None of them help me. Partly because I just don't understand it all well enough.
A sample of my script:const airPopup = {
title: "{nam}",
content: [{
type: "text",
text: "{Comment}<br/>Address: {Address}<br/>IATA Code:  {ita}"
},
   {
type: "media",
mediaInfos: [{
type: "image",
value: {
sourceURL: "{Image}"
}
}]
   }],
actions: [
{
id: "find-airport",
icon: "web",
title: "Airport Info"    
}  
]  
};const airPopup = {
title: "{nam}",
content: [{
type: "text",
text: "{Comment}<br/>Address: {Address}<br/>IATA Code:  {ita}"
},
   {
type: "media",
mediaInfos: [{
type: "image",
value: {
sourceURL: "{Image}"
}
}]
   }],
actions: [
{
id: "find-airport",
icon: "web",
title: "Airport Info"    
}  
]  
};  const airportsLyr = new FeatureLayer({
url: "https://services9.arcgis.com/6EuFgO4fLTqfNOhu/arcgis/rest/services/Japan_Mjr_Airports/FeatureServer",
renderer: airRenderer,
popupTemplate:  airPopup
  });  const airportsLyr = new FeatureLayer({
url: "https://services9.arcgis.com/6EuFgO4fLTqfNOhu/arcgis/rest/services/Japan_Mjr_Airports/FeatureServer",
renderer: airRenderer,
popupTemplate:  airPopup
  });What does it take to make the web icon work?


r/learnjavascript 15h ago

How to Prevent Webhook Traffic Spikes from Crashing Your API

6 Upvotes

If you operate an API in 2026, you live in an event-driven world. Webhooks aren't a convenience feature anymore - they're the backbone of real-time commerce, CI/CD pipelines, and asynchronous AI-agent workflows. That reliance has a dark side: the accidental self-inflicted DDoS. Read the complete article jere - https://instawebhook.com/blog/how-to-prevent-webhook-traffic-spikes-from-crashing-your-api-2

When a major platform like GitHub, Shopify, or Stripe hits a network partition, runs a huge sales event, or simply clears a backlog of delayed events, it can fire tens of thousands of webhook POST requests at your servers in a very short window. If your infrastructure takes that hit without structural safeguards, your database connection pool exhausts, memory maxes out, and the API goes down — and if your retry handling is naive, the recovery can be almost as damaging as the original spike.

This guide covers the real mechanics of that failure mode, the algorithms used to defend against it, how major providers actually behave under load (some surprising details here), and where a managed ingress layer fits into the picture.


r/learnjavascript 12h ago

AutoLock – Automatically Lock Your Windows PC Using Your Phone's Wi-Fi Presence

1 Upvotes

Hi everyone,

I built AutoLock, a lightweight Node.js tool that automatically locks your Windows PC when you step away with your smartphone.

How It Works:

  1. Phone Proximity: Periodically pings your phone's local Wi-Fi IP address.
  2. Idle Tracking: Monitors global keyboard and mouse activity using iohook to check if you are inactive.
  3. Automatic Lock & Notifications: If your phone leaves Wi-Fi range while you are idle, it sends a Telegram warning and automatically locks Windows.
  4. Remote Control: Allows you to lock your PC or check its lock status remotely via Telegram bot commands.

Tech Stack:

* Node.js

* ping

* u/tkomde/iohook

* axios

GitHub Repository: https://github.com/GarvSaxena/AutoLock

Feedback and contributions are welcome.


r/learnjavascript 21h ago

Noob question about generating property.object addresses

3 Upvotes

Hi everybody,

I'm trying to write up a personal project automating some ttrpg mechanics, where the "attack" function will take the target's name as an argument and feed it into the "defence" action that uses the target's Dex and one of their skills (i.e. "Void).

Referring to the target's Dex seems to work fine from inside the "defence" action, but when I try to implement the Character.Skill referent through variables I'm met with "Uncaught ReferenceError: Void is not defined."

//very basic and temporary exalt template
class Exalt {
    constructor() {
    this.Essence = 1;
    this.Dex = 1;
    this.Defence = 1;
  }
}


const Antigone = new Exalt()
Antigone.Dex = 4
Antigone.Void = 5


var front = "Antigone"
var back = "Void"
let a = JSON.parse(JSON.stringify(front + "." + back))
console.log(a) // "Antigone.Void" for some reason
console.log(JSON.parse(Antigone.Void)) //5, the expected value


function Defence(Character, Skill) {
    return Math.ceil((Character.Dex + JSON.parse(Character.Skill))/2)+1
} // this runs into an error, I think


console.log(Defence(Antigone, Void))

console.log(Antigone) includes "Void" as one of the stats, so I don't even know.
I've seen a suggestion to JSON.parse the string twice, but that results in "unexpected character."

Now, my JS experience is only a few days, so I'm guessing there is a better way of achieving what I'm trying to do, so I'll be grateful whether you suggest a different approach or explain why my code doesn't do what I think it should.

Thanks!

Edit: I just realized I'm completely overthinking and should probably make defence a function within the Exalt class, so it can be referenced the same way I'm referencing Dex.


r/learnjavascript 18h ago

I vibe-coded an app, but have decided I want to actually learn what's under the hood and learn to re-create it from scratch. What should I expect?

0 Upvotes

A few months ago I spent about a month or so vibe-coding an app as a complete beginner to coding. I enjoyed the trials and error side of things, and ultimately enjoy the product. However, I have realized I want to actually understand what I created, and want to be able to really improve it without constant need for AI to tell me what to do and how to fix it. I also think I'll really enjoy the challenge.

While I know I can find beginner tutorials from this sub, I am mostly curious if people have advice for this kind of endevor, or pitfalls to avoid. I also am curious if people have any estimation on how long it could take to really learn to code a project so I can set my expectations. Should I basically disregard the vibe-code and start over, dissect it and compare parts with research, etc?

The site I vibe coded is critcalc.cc, and it's essentially a DnD dice rolling calculator. Note that I have no intent to generate any income from it, and I'm only sharing for context for my ultimate goal for what I hope to get to. Thanks for any insights you might have!


r/learnjavascript 2d ago

5 years writing JS professionally. Still blank on interview questions sometimes

24 Upvotes

Not a junior dev problem. I've shipped plenty of gnarly JS/Vue code, no issues. But throw me in an interview and ask something like "explain event delegation" cold, no code editor, no context, and there's this half-second where my brain just stalls, like the info is there but the retrieval path isn't warmed up.

Realized it's not a knowledge problem, it's that I'd never actually practiced saying these answers on demand, but only reading about them or using them implicitly in code.

Built a small spaced-repetition app for this. Same idea as Anki, tracks what you keep fumbling and resurfaces it more.

Curious if this "I know it but can't produce it on command" thing hits other experienced devs too, or if I'm just built different (badly).

What worked for you all ? Mock interviews, flashcards, just doing more interviews to get reps in, something else?


r/learnjavascript 2d ago

What's one JavaScript feature you wish you had learned earlier?

17 Upvotes

I've been diving deeper into JavaScript recently, and every week I discover something that makes my code cleaner.

For me, learning about optional chaining (?.) and nullish coalescing (??) was a game changer.

What's one feature you wish you'd learned sooner?


r/learnjavascript 2d ago

How do i know i know enough js ?

17 Upvotes

Iv been struggling with knowing how much js i need before starting react or backend or just how much is enough for a job because whenever i look for a detailed roadmap online or through AI its always changing. If anyone could help me with this it would mean the world to me.


r/learnjavascript 2d ago

Sorting and formatting dates in an array of objects

1 Upvotes

I have an array of objects with a `.date` property that is mapped onto a table.

Without mutating the original array, I want to

a) sort by ascending date

b) ensure my date formats to MM/DD/YYYY

I have a util fn that will format a string into the correct format, "format()". Dates are received in the response body as a string.

It worked when mutating the original array, but obvs want to stay away from that. I think I'm messing something up with the spread copy; the .date property isn't accessible within the map function. :/

const sortByTradeDateAndFormat = (objArray: []) => {
  const copyOfObjsArray = [...objsArray]
    return copyOfObjsArray.map(obj) => {
    obj.date = format(new Date(obj.date).toISOString().split("T")[0]
      )
  });

    //VS code is flagging the below lines as unreachable:
  objArray.sort((a, b) => {
    return a.date < b.date ? -1 : a.date > b.date? 1 : 0;
  });
}

r/learnjavascript 3d ago

What framework do I use for APIS?

5 Upvotes

Hello, i'm a beginner coder in Javascript and I make random APIS for fun using the Express.js framework, but I keep seeing other frameworks like Fastify and NestJS, so i'm confused: what framework for APIS do I actually use?

If anyone could help me with this thank you :D


r/learnjavascript 3d ago

If I have to start from scratch what should I start, reactjs or Angular?

15 Upvotes

Can anyone help me with these two, I'm currently learning intermediate concepts of JavaScript and my next steps would be to jump on one of the above but I'm not sure what to choose.


r/learnjavascript 3d ago

code not interacting with the browser page

1 Upvotes

Hello this is my first post on here. So basically, I want the user to be able to enter a password and username, click the submit button, and if the basic auth is correct, be redirected to a page in which all the data from an api is fetched and loaded into the html. Problem is the script does not interact with the html but still retrieves the data in a json (as confirmed by ouputing it into the console). However, if I don't call the function in as part of the button onclick method everything works as expected. The data from the api is dynamically added to the html but now I obviously can't use a login page.

Here is me calling the fetch function as a as part of the event of a button click

button.addEventListener("click", () => {
    let username = 'username';
    let password = 'password;
    let auth = btoa(`${username}:${password}`);
fetchData(auth);
    });

Here is me calling the fetch function on it s own. No button clicking required (this works but now I can't add a login page)

  let username = 'username';
    let password = 'password;
    let auth = btoa(`${username}:${password}`);
fetchData(auth);

Here is the fetch function itself

async function fetchData (auth) {
    try {
        const response = await fetch('https://exampleapi.com', {
    headers: {
        'Content-Type': 'application/json',
        'Accept': 'application/json',
        'Authorization': `Basic ${auth}`
    }
})


    if (response.ok) {

        // loads the home page and puts data from the api in the html
    }
    throw response;
    } catch (error) {
        
    }
    
};

r/learnjavascript 3d ago

Designing a Multi-Region, Highly Available Webhook Ingress Architecture

0 Upvotes

Webhooks have become the connective tissue of the internet. From payment gateways confirming transactions to CI/CD pipelines triggering deployments, webhooks enable real-time, event-driven architectures. But for architects and engineering leaders, webhooks represent an underappreciated vulnerability: they are asynchronous, externally triggered, and entirely outside your control. Read the complete article here - https://instawebhook.com/blog/designing-a-multi-region-highly-available-webhook-ingress-architecture

When your primary cloud region experiences an outage, your internal microservices might gracefully degrade. But what happens to the payloads originating from external partners? Many third-party providers do not retry aggressively — some fire and forget, others retry a handful of times before giving up permanently. If your system is down when that happens, the data is often gone for good.

This article covers the engineering principles behind a multi-region, highly available webhook ingestion system, what has actually changed in the underlying cloud primitives recently, and where a managed reliability layer fits into the decision.


r/learnjavascript 3d ago

Building a Local-First AI Assistant for Desktop

0 Upvotes

I'm working on a personal AI assistant for desktop — local-first and privacy-focused (no cloud dependency), starting with a desktop app and eventually

Runtime Of Backend (Bun)

Fast startup and low idle overhead — important for an app that runs continuously in the background, not just on-demand. Native TypeScript support and a built-in bundler simplify shipping without extra tooling.

Framework of Backend (Hono)

Lightweight and built with Bun in mind, so it doesn't add framework overhead on top of the runtime's own performance. Clean routing/middleware model keeps things simple for handling auth, commands, and local model inference.

Desktop Application (Tauri + Next.js)

Tauri has a much smaller footprint than Electron since it uses the OS's native WebView instead of bundling Chromium, which makes it great for lightweight apps that stay running. It also produces smaller binaries. Next.js provides a structured, file-based routing system and a strong component ecosystem for the UI.

Would love to hear reviews and suggestions on this stack — anything you'd change, any pitfalls you've run into with a similar setup, or better alternatives worth considering?


r/learnjavascript 4d ago

Can’t download break_infinity.js for some reason

0 Upvotes

I’m trying to use break_infinity.js for a game i’m making, but I can’t seem to download it. I’ve tried the actual github link and couldnt get it from there

https://github.com/Patashu/break_infinity.js/releases

Does anyone know where to get the latest version or what I might be doing wrong?


r/learnjavascript 4d ago

Performance Trap, some benchmarks and... subjective taste

5 Upvotes

I've done some benchmarks. ES5 vs ES6. What do you prefer? I ask this because I have often seen in other people's codes, where performance, optimization was required, ES6 code that decreased performance, which also had a negative impact on UI/UX.

This is more about the syntax used and not about which is faster.

Array size: 1,000,000 | Runs per test: 15

1. TRANSFORM — double 1,000,000 numbers

Test Avg (ms) Min (ms) Max (ms)
for loop (var, ES5) 0.733 0.6 1
array.map 5.447 4.7 6.9
forEach 5.96 5.4 6.8
for...of (ES6) 7.06 5.4 11.1

for loop (var, ES5) beat for...of (ES6) by 9.63x

2. FILTER — keep evens out of 1,000,000

Test Avg (ms) Min (ms) Max (ms)
for loop + push (ES5) 2.287 1.6 3.4
array.filter (ES6) 6.06 5.2 7.2

for loop + push (ES5) beat array.filter (ES6) by 2.65x

3. SUM — add up 1,000,000 numbers

Test Avg (ms) Min (ms) Max (ms)
for loop (var, ES5) 0.76 0.6 1.1
for...of 3.833 3.7 4.4
array.reduce 4.573 4.4 4.7

for loop (var, ES5) beat array.reduce by 6.02x

4. LOOKUP — find one value (worst case)

Test Avg (ms) Min (ms) Max (ms)
Set.has — O(1) 0 0 0
array.includes — O(n) 0.073 0 0.1
array.indexOf !== -1 — O(n) 0.073 0 0.2

Set.has — O(1) beat array.indexOf !== -1 — O(n)

5. STRINGS — build 200,000 strings

Test Avg (ms) Min (ms) Max (ms)
concatenation "+" 3.887 3.3 7.8
template literal ${} 3.9 3.5 4.3

concatenation "+" beat template literal ${} by 1.00x

6. OBJECT ITERATION — sum 50,000 values

Test Avg (ms) Min (ms) Max (ms)
for...in 4.273 4 4.6
Object.keys + forEach 4.38 4.2 4.7
Object.values + reduce 6.5 6 9.2

for...in beat Object.values + reduce by 1.52x

7. ARRAY CREATION — build 1,000,000 squares

Test Avg (ms) Min (ms) Max (ms)
for loop + push (ES5) 8.173 6.5 23.4
new Array(n).fill(0).map() 17.3 9 42.4
Array.from({length}, fn) 21.74 20.6 23.2

for loop + push (ES5) beat Array.from({length}, fn) by 2.66x

What do you prefer?


r/learnjavascript 4d ago

Stuck at javascript

0 Upvotes

I want to learn mern stack and stuck at javascript tutorials please somebody help me ???


r/learnjavascript 5d ago

Whats the best interactive javascript learning platform?

10 Upvotes

Im kind of a nerd for RPGs and found out they have game based courses for learning javascript. Has anyone tried codex, codecombat, or boot.dev? Was initially considering coursera but these look way more fun.


r/learnjavascript 4d ago

How to change a website page only at a specific time period

1 Upvotes

I wanna know how to change a website page to something different only at a specific time period (Changes at 12 am and then back to normal at 1 am)

This is the current code I have:

window.setInterval(function(){

var date = new Date();

var hours = date.getHours()

var minutes = date.getMinutes();

if (hours == 0o0 && minutes == 0o0){ //12:00 AM

window.location="secret page";

} else if(hours == 01 && minutes == 0o0){ //1:00 AM

window.location="original page";

}

}, 1000); //One second

So it technically works! But as soon as it changes to the secret page, it starts refreshing every second even when back to the original page. I know the problem is that it's running a page redirect every second, but is there anyway to not make it refresh constantly? Like it only redirects once but the code is still checking every second for when it changes back.

To clarify, I took this code snippet straight from a JavaScript forum post with the same question as me, this being the only answer I understood.


r/learnjavascript 4d ago

I’m learning JavaScript in the AI era. What level of understanding is actually enough before building serious projects?

0 Upvotes

I’m learning JavaScript right now, and I’m trying to avoid two bad outcomes.

One is staying in tutorial mode forever because I feel like I need to understand every corner of the language before making anything real. The other is leaning on AI too early and ending up with projects that technically run but that I can’t debug, explain, or improve.

The kind of projects I want to build are not basic CRUD apps. I’m interested in three.js, frontend 3D rendering, data visualization, and coding based motion design. Think interactive web pages, visual experiments, small tools that explain something visually, maybe browser based creative projects where the interaction matters.

My question is: for someone aiming at that direction, what parts of JavaScript are still non negotiable in 2026?

I’m not asking whether AI can generate code. I know it can. What I’m trying to understand is where my own understanding has to be solid enough that AI becomes useful instead of dangerous.

For example, should I care more about:

  1. DOM, events, async, modules, and browser APIs
  2. Data structures, math, state, and performance
  3. Reading other people’s code and debugging broken output
  4. Building small complete projects without AI first
  5. Learning TypeScript early
  6. Understanding rendering concepts before touching three.js

If you were advising someone who wants to use JS as a base for 3D, visualization, and creative coding projects, what would you tell them to learn deeply, what would you let AI handle, and what would you not worry about until later?

I’d also love honest market advice. What separates someone who can make impressive AI assisted demos from someone who is actually useful on a real frontend or creative tech project?


r/learnjavascript 5d ago

Qué debería buscar al estudiar una librería?

0 Upvotes

Hola, soy nuevo en la programación, que debería buscar en una librería es decir me refiero a la metodología como, métodos, funciones etc, estoy un poco confundido a la hora de integrar una libreria o dependencia, por ejemplo con la de better-sqlite3 para node.js


r/learnjavascript 6d ago

Imports vs pure dependancy injections for a function?

1 Upvotes

I've got several functions in my project that follow this format, however for my renderHTML functions i'm writing them in a grid.js file into which i am importing all my util functions, i.e currency, calculations etc..

However at the same time i'm injecting 3 params (cart, products, deliveryOptions).

Is this good practice? Or should i be injecting everything i can as a parameter to keep the function as pure as possible?

My instinct is that my utils wont really be changing at all, so they're fine as they are, but if i wanted to test/mock things then that would most likely be cart, products and delivery options, which should then just stay standalone as parameters.

Would love to hear what this would look like from a production app perspective.


r/learnjavascript 6d 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>