fideo-js docs

Start here

Initializing

Five entry points, two ways to configure them, and one set of precedence rules that decides who wins when you use both. Every player on this page is running the code shown beneath it.

Auto-init — no JavaScript at all

Loaded as a classic <script>, Fideo scans for [data-fideo] on DOMContentLoaded and mounts what it finds.

Mounted byauto-init on DOMContentLoaded
The whole integrationhtml
<script src="https://cdn.jsdelivr.net/gh/devjtv/fideo-js@v0.7.0/dist/fideo.global.js"></script>

<video
  data-fideo
  src="/media/clip.mp4"
  data-fideo-poster="/media/poster.jpg"
  data-fideo-muted
  data-fideo-loop
></video>
Optional — configure the auto passhtml
<!-- Must run before the library script -->
<script>
  window.__fideoAutoInit = {
    selector: '.hero-video',
    muted: true,
  };
</script>
Auto-init only fires for classic scripts. When Fideo is imported as a module it detects that (document.currentScript is null) and stays out of the way, so a bundled app never gets a surprise mount pass.

initFideo() — mount everything that matches

The same scan, run on demand. Returns the mounted players plus a destroy() that tears down the whole batch. Pass a selector to scope it; every other option becomes the default for each player it mounts.

One call mounted both
Scoped batch mountjs
const result = initFideo({
  selector: '[data-fideo-demo="batch"]',
  muted: true,
  loop: true,
  volume: 0.6,
});

result.players.length; // 2
result.destroy();      // unmounts both

// Same thing as a static method
Fideo.init({ selector: '[data-fideo-demo="batch"]' });

// Default selector when you pass nothing
initFideo(); // → [data-fideo]
Safe to call more than once. Mounted elements are tracked in a WeakMap, so a second pass skips them and returns the existing instances. Re-run it after injecting content and nothing is double-mounted. An element that cannot mount is warned about and skipped — it does not abort the batch.

new Fideo() — one player, by selector

The class form. Takes a CSS selector or an element and returns an instance carrying the full player API. The element does not need data-fideo — that attribute only matters to the selector-driven entry points.

Live state
No data attributes neededjs
const player = new Fideo('#player-new', {
  muted: true,
  loop: true,
  volume: 0.5,
  playbackRates: [0.5, 1, 1.5, 2],
});

await player.play();
await player.seek(8);
player.getState(); // { currentTime, duration, paused, … }

createFideo() — the same thing, without new

A factory wrapper around the class, for codebases that avoid new or where a function reads better. Identical arguments, identical instance. This one is handed a live element rather than a selector, which is what you usually have inside a framework ref.

Target passed asHTMLVideoElement
Element reference, not a selectorjs
const el = document.querySelector('#player-create');

const player = createFideo(el, {
  muted: true,
  loop: true,
  controlVisibility: { settings: false },
});

See Framework recipes for the React, Vue and SPA versions of this.

mountFideo() — element only, never duplicates

The primitive the other entry points are built on. It takes an element — never a selector — and is idempotent: call it twice on the same element and you get the same instance back rather than a second player stacked on the first.

Identity check
Idempotent by designjs
const el = document.querySelector('#player-mount');

const a = mountFideo(el, { muted: true });
const b = mountFideo(el, { muted: false });

a === b; // true — the second call's options are ignored
The second call's options are discarded. The existing instance comes back untouched. To change configuration, destroy() the player and mount it again.

Who wins when both are set

Anything you can set in JavaScript has a data-fideo-* equivalent, and the two mix freely on the same element. Most options let the data attribute override JavaScript, so a page author can adjust one player without touching the code that mounts it. Collection options merge instead, and there JavaScript wins per key.

Poster shown is the one JavaScript suppliedposters merged
Deliberately conflictingjs
mountFideo(el, {
  autoplay: true,   // attribute says "false" → attribute wins
  volume: 1,        // attribute says "0.25"  → attribute wins
  muted: true,      // no attribute           → JS applies
  posters: {         // merged map             → JS wins per key
    desktop: './media/poster-alt.jpg',
  },
});
Resolved options, read from the live instance above
OptionAttributeJavaScriptResolved
Reading instance…
The rules
OptionsWinner
Scalars — autoplay, muted, loop, controls, volume, lazy, preload, viewport, background, className, and every controlVisibility flag Data attribute
Maps — sources, posters, cssVarsJavaScript, per key
providerJavaScript
selector, icons, disabledProviders, injectStylesJavaScript only — no attribute exists
One override beats everything. background: true forces autoplay, muted, loop and playsInline on from either source, because a background video cannot work without them. See Background video.

Mount, destroy, mount again

destroy() unwraps the element, removes everything Fideo generated and releases the instance, leaving markup you can mount again with different options. That is the supported way to reconfigure a player, and what a single-page app should call when a route unmounts.

Status
Reconfiguring means remountingjs
let player = mountFideo(el, { muted: true });

// Options are locked in at mount, so swap the instance:
player.destroy();
player = mountFideo(el, {
  muted: true,
  cssVars: { '--fideo-accent': '#7ab8ff' },
});

// Or tear down a whole batch at once
const result = initFideo();
result.destroy();
Teardown is complete: listeners are dropped through AbortControllers, observers disconnect, the wrapper and generated nodes are removed, and the element returns to where it started.

Getting the library into your page

Browser globalhtml
<script src="/dist/fideo.global.js"></script>
<script>
  // window.Fideo, initFideo, createFideo, mountFideo
  Fideo.init();
</script>
ES module / bundlerjs
import { Fideo, initFideo, createFideo, mountFideo } from 'fideo-js';

initFideo(); // nothing auto-mounts for module imports
CommonJSjs
const { initFideo } = require('fideo-js');

Picking an entry point

CallTargetReturnsReach for it when
auto-initevery [data-fideo]nothingA static page or CMS, no build step
initFideo(options)a selector{ players, destroy() }Many players share one configuration
new Fideo(target, options)selector or elementplayer instanceOne player you hold a reference to
createFideo(target, options)selector or elementplayer instanceSame, without new
mountFideo(element, options)element onlyplayer instanceYou already have the node and want no duplicates