Skip to content
Aabha AI Academy
Skip to reading

JavaScript

Explain the reference one boundary at a time

Files you should read in order

Start with reference/index.html to identify controls and result containers. Read core.js next: it contains data rules without DOM calls. Read storage.js for the persistence boundary. Finally read app.js for the connections. events.json contains six synthetic records. empty, wrong-shape, malformed and unsafe-text fixtures exist only to practice edge cases. missing.json is deliberately absent.

Map the lessons to code

  • Lessons 02–04: seatLabel, comparisons, branches, parameters and returns
  • Lesson 05: filterEvents, toggleSaved, find, includes and array transformations
  • Lesson 06: makeCard, renderEvents, textContent and control listeners
  • Lesson 07: updateNameRule, form submit and reportValidity
  • Lesson 08: named imports and exports; pure rules separated from effects
  • Lesson 09: fetchEvents, load, try/catch/finally and fixture selection
  • Lesson 10: readSaved, writeSaved, clearSaved and the savedIds state

Why filterEvents has several inputs

It receives all the information needed for one decision: event records, query, category, saved-only flag and saved IDs. Each callback computes three booleans, then combines them. No DOM reads are hidden inside it. That makes tests simple: supply known inputs and compare output IDs. It returns existing records in a new result array, so treating records as read-only remains important.

Why toggleSaved makes a new array

If the ID is already present, filter removes it. Otherwise spread creates a new array containing previous IDs and the new ID. The input array is not changed. This is shallow copying, which is sufficient because IDs are strings. The caller must assign the return value to savedIds; merely calling the function does not update that variable.

The record validator is provided scaffolding

validateEvents enforces the fields the renderer uses. Array.isArray distinguishes the outer collection. The loop checks each record and records IDs seen so far. The small regular expressions check simple ID syntax and the shape YYYY-MM-DD; they do not alone prove a real calendar date. Date conversion plus an ISO round-trip rejects impossible dates such as February 30. This helper is more detailed than the core beginner syntax and may be supplied by an instructor. You should explain its purpose and test cases; writing date validation from memory is not a course outcome.

Why fetcher and getStorage can be supplied

The default fetcher is the browser's fetch. Tests may pass a small fake response function to exercise HTTP, parsing and network failures without depending on the internet. The default getStorage returns window.localStorage. Tests can pass a fake that throws, proving the fallback path. This technique is dependency injection: supply a collaborator rather than hard-code it. The name is optional knowledge; the practical idea is testing a boundary without a real failure on your machine.

The storage getter is called inside try. Accessing the localStorage property itself can fail, not just its methods. A default parameter that eagerly accessed storage before entering try would miss that failure. The arrow default postpones access until the protected block calls it.

Follow a save

makeCard creates one real button. Its callback computes a new savedIds array, attempts a write, reports persistence or a warning and updates the same button's pressed state. Its visible label stays “Save [title]” because it is a toggle. CSS gives pressed buttons a different visible style; status text confirms the outcome without relying only on color. In saved-only view, an unsaved card must disappear, so focus first moves to the saved-only checkbox.

A reload reads and deduplicates stored IDs once, before knowing which fixture will succeed. Only a successful normal events.json load removes unknown IDs. An empty or failure-test fixture is not a full catalog and must not erase an existing shortlist. Later fixture reloads keep the current in-memory shortlist. This avoids throwing away a choice when a previous write failed. Storage is scoped to the origin, not to the folder. The versioned app key reduces collisions with unrelated examples on the same local server.

Follow a load failure

load marks the app unready, disables dependent controls, clears stale results and displays loading. fetchEvents checks status, parses the body and validates records. A failure travels to catch, which clears event state and gives a retry message. finally makes the fixture picker and load button usable again. The form cannot report success with stale events because ready stays false. An empty valid array is a successful load with an explicit empty message.

Follow a practice submission

The listener cancels navigation before doing work. It clears the old result, checks that event data is ready, updates the custom name rule and requests constraint validation. It then resolves the selected event ID against current records and rejects missing/full events. Only afterward does it set a local practice success message. No field has a name attribute for the native fallback, and the JS handler makes no request. The message includes an event title through textContent, so markup-like text stays literal.

Deliberate limits

Search matches title substrings only. Dates are shown as date-only fixture text rather than converted to a local timezone. Local storage is best-effort and does not synchronize tabs. There is no real capacity reservation or organizer notification. These are explicit constraints, not features waiting behind an undocumented button. A production service would require a separate design and security review.

Download this source file