Skip to main content

Documentation Index

Fetch the complete documentation index at: https://mintlify.com/zshall/program-guide/llms.txt

Use this file to discover all available pages before exploring further.

The TV class is the top-level controller for Television Simulator ‘99. Defined in js/core/tv.js, it owns the application lifecycle: it bootstraps the YouTube IFrame API, fetches data/guide.xml, manages channel transitions, handles viewport scaling, and exposes mute controls. Every page load creates exactly one TV instance and calls startUp() on it.

Constructor

new TV(maxWidth?, maxHeight?, warmupTime?, firstStart?)
Creates a new TV instance. All parameters are optional and fall back to sensible defaults matching the simulator’s original 1200×1000 design canvas.
maxWidth
number
default:"1200"
Maximum display width in pixels. When the viewport is at least this wide, no CSS transform: scale() is applied to the .tv element. Scaling kicks in below this threshold.
maxHeight
number
default:"1000"
Maximum display height in pixels. Works in tandem with maxWidth; the scale factor is the smaller of the two ratios so the TV always fits the viewport.
warmupTime
number
default:"3000"
Duration in milliseconds for the fade-in animation on the very first channel load. Subsequent channel changes use warmupTime / 10 for a snappier transition.
firstStart
boolean
default:"true"
Controls which fade duration is used when animating .current-channel and #tvm-top-right into view. true means the full warmupTime is applied; false means warmupTime / 10. This flag is set to false automatically after the first showChannel call.

Properties

The following instance properties are set during construction and updated at runtime.
PropertyTypeDescription
this.maxWidthnumberResolved max width (from constructor argument).
this.maxHeightnumberResolved max height (from constructor argument).
this.warmupTimenumberResolved warmup duration in milliseconds.
this.firstStartbooleanWhether the next channel load should use the full warmup animation. Set to false after the first showChannel call.
this.channelChannelThe currently active Channel instance. undefined until showChannel is called for the first time.
this.mutedbooleanCurrent mute state. Updated by toggleMute() and reflected in the #tvm-bottom-left overlay.
this.classesobjectA map of channel class names to their constructors, populated at construction time. The default map contains { Channel12 }. Add entries here when registering new channel classes.

Methods

startUp()

tv.startUp(): void
Bootstraps the entire application inside a $(document).ready() callback. Performs the following steps in order:
  1. If not a mobile device (Helpers.isMobile().any() is falsy), registers a resize event handler on $(window) and adds the .scanlines CSS class to .screen.
  2. Calls handleResize() immediately to set the initial scale.
  3. Wires up the #about-button click handler to toggle .about.
  4. Wires up the #tv-mute click handler to call toggleMute().
  5. Listens for the custom youtubeReady DOM event (dispatched by onYouTubeIframeAPIReady), then fetches data/guide.xml via $.ajax. On success, parses the XML into window.guideData and calls showChannel with the number of the first channel[watchable][default] element.
  6. Calls YouTubeApi.loadYouTubeAPI() to inject the YouTube IFrame API script, which eventually fires youtubeReady.

showChannel(number)

tv.showChannel(number: string | number): void
Performs a full channel transition:
  1. If this.channel exists, calls this.channel.teardown() to clean up the previous channel.
  2. Fades out #tvm-top-right and .current-channel, then sets the container’s id to ch-{number}.
  3. Loads channels/{padded-number}/layout.html via jQuery .load().
  4. Inside the load callback, instantiates new this.classes['Channel' + number](...), calls .show(), and animates opacity back to 1. The animation duration uses this.warmupTime when firstStart is true, otherwise this.warmupTime / 10.
  5. After animation completes, calls this.channel.ready().
  6. Sets #tvm-top-right to the zero-padded channel number for 4 seconds, then clears it.
  7. Sets this.firstStart = false.
number
string | number
required
The channel number to load. Must correspond to both a folder under channels/ (zero-padded to three digits) and a key in this.classes (e.g., passing 12 looks up this.classes['Channel12']).

toggleMute()

tv.toggleMute(): void
Delegates to YouTubeApi.toggleMuteVideo(this.channel.player) and stores the returned boolean in this.muted. Calls afterMute() to update the on-screen indicator.

mute()

tv.mute(): void
Calls this.toggleMute(true) then this.afterMute().
toggleMute() does not accept or use a boolean argument — it always delegates to YouTubeApi.toggleMuteVideo, which simply toggles the current state. As a result, mute() and unmute() both behave identically to calling toggleMute() directly. Neither method guarantees a specific final mute state; they simply flip whatever the current state is and call afterMute() a second time.

unmute()

tv.unmute(): void
Calls this.toggleMute(false) then this.afterMute(). See the note on mute() — the boolean argument is ignored by toggleMute(), so this behaves identically to mute().

afterMute()

tv.afterMute(): void
Internal helper called by toggleMute(), mute(), and unmute(). Updates the #tvm-bottom-left overlay element: sets its text to 'MUTING' when this.muted is true, or clears it when false.

handleResize()

tv.handleResize(): void
Recalculates the CSS transform: scale() value applied to .tv so the simulator fits the current viewport. Called on construction via startUp() and on every window.resize event (desktop only). The scale factor is Math.min(width / this.maxWidth, height / this.maxHeight). If both viewport dimensions are at or above the maximums, the transform is cleared entirely so the TV renders at its native size.
The early-exit condition in the source reads this.height >= this.maxHeightthis.height is never defined on the instance, so the check always fails, meaning the transform is never cleared when the viewport is large enough. This is a known bug in the source. The scale calculation itself (height variable from $window.height()) is unaffected.
On mobile devices, startUp() skips registering the resize listener and adding scanlines, so handleResize is called once at startup but never again. This is intentional — the scanline overlay and continuous resize calculations are expensive on mobile hardware.

Usage Examples

Default initialization

The standard way to start the simulator. The TV constructor uses its defaults (1200×1000 canvas, 3-second warmup):
var tv = new TV();
tv.startUp();

Custom canvas size and warmup

Override the defaults when embedding the simulator in a non-standard container or when a shorter warmup animation is desired:
var tv = new TV(1600, 1200, 2000);
tv.startUp();
This sets the design canvas to 1600×1200 pixels and reduces the first-load fade-in to 2 seconds.

Build docs developers (and LLMs) love