TheDocumentation 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.
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
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.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.Duration in milliseconds for the fade-in animation on the very first channel load. Subsequent channel changes use
warmupTime / 10 for a snappier transition.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.| Property | Type | Description |
|---|---|---|
this.maxWidth | number | Resolved max width (from constructor argument). |
this.maxHeight | number | Resolved max height (from constructor argument). |
this.warmupTime | number | Resolved warmup duration in milliseconds. |
this.firstStart | boolean | Whether the next channel load should use the full warmup animation. Set to false after the first showChannel call. |
this.channel | Channel | The currently active Channel instance. undefined until showChannel is called for the first time. |
this.muted | boolean | Current mute state. Updated by toggleMute() and reflected in the #tvm-bottom-left overlay. |
this.classes | object | A 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()
$(document).ready() callback. Performs the following steps in order:
- If not a mobile device (
Helpers.isMobile().any()is falsy), registers aresizeevent handler on$(window)and adds the.scanlinesCSS class to.screen. - Calls
handleResize()immediately to set the initial scale. - Wires up the
#about-buttonclick handler to toggle.about. - Wires up the
#tv-muteclick handler to calltoggleMute(). - Listens for the custom
youtubeReadyDOM event (dispatched byonYouTubeIframeAPIReady), then fetchesdata/guide.xmlvia$.ajax. On success, parses the XML intowindow.guideDataand callsshowChannelwith the number of the firstchannel[watchable][default]element. - Calls
YouTubeApi.loadYouTubeAPI()to inject the YouTube IFrame API script, which eventually firesyoutubeReady.
showChannel(number)
- If
this.channelexists, callsthis.channel.teardown()to clean up the previous channel. - Fades out
#tvm-top-rightand.current-channel, then sets the container’sidtoch-{number}. - Loads
channels/{padded-number}/layout.htmlvia jQuery.load(). - Inside the load callback, instantiates
new this.classes['Channel' + number](...), calls.show(), and animates opacity back to 1. The animation duration usesthis.warmupTimewhenfirstStartistrue, otherwisethis.warmupTime / 10. - After animation completes, calls
this.channel.ready(). - Sets
#tvm-top-rightto the zero-padded channel number for 4 seconds, then clears it. - Sets
this.firstStart = false.
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()
YouTubeApi.toggleMuteVideo(this.channel.player) and stores the returned boolean in this.muted. Calls afterMute() to update the on-screen indicator.
mute()
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()
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()
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()
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.maxHeight — this.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.