What a simple table that pulls information from YAML looks like:
```dataviewjs
const container = this.container;
const allPages = dv.pages('"2. Areas/Сериалы и фильмы/7. Сериалы"')
.where(p => p.Жанр && p.Рейтинг)
.sort(p => -Number(p.Рейтинг));
// --- UI block: Filter + Search ---
const controls = document.createElement("div");
controls.style.display = "flex";
controls.style.gap = "1rem";
controls.style.marginBottom = "1rem";
// Filter by genres
const genres = [...new Set(allPages.flatMap(p => Array.isArray(p.Жанр) ? p.Жанр : [p.Жанр]))];
const genreSelect = document.createElement("select");
const allOption = document.createElement("option");
allOption.value = "all";
allOption.textContent = "All genres";
genreSelect.appendChild(allOption);
for (let genre of genres.sort()) {
const option = document.createElement("option");
option.value = genre;
option.textContent = genre;
genreSelect.appendChild(option);
}
controls.appendChild(genreSelect);
// Search field
const searchInput = document.createElement("input");
searchInput.type = "text";
searchInput.placeholder = "🔍 Search by title...";
searchInput.style.flex = "1";
controls.appendChild(searchInput);
container.appendChild(controls);
// --- Table ---
const table = document.createElement("table");
table.className = "dataview table-view-table";
const header = table.insertRow();
["🎬 Cover", "🎞 Title", "🎭 Genre", "⭐ Rating", "🧠 Insight"].forEach(text => {
const th = document.createElement("th");
th.textContent = text;
header.appendChild(th);
});
function renderTable(filterGenre = "all", searchTerm = "") {
table.querySelectorAll("tr:not(:first-child)").forEach(row => row.remove());
const filteredPages = allPages.filter(p => {
const genreMatch = filterGenre === "all" || (Array.isArray(p.Жанр) ? p.Жанр.includes(filterGenre) : p.Жанр === filterGenre);
const searchMatch = !searchTerm || p.file.name.toLowerCase().includes(searchTerm.toLowerCase());
return genreMatch && searchMatch;
});
for (let p of filteredPages) {
const row = table.insertRow();
const cellCover = row.insertCell();
cellCover.innerHTML = p.Постер
? `<img src="${p.Постер}" width="100" style="border-radius: 8px;">`
: "—";
const cellTitle = row.insertCell();
const link = document.createElement("a");
link.href = p.file.path;
link.textContent = p.file.name;
link.className = "internal-link";
cellTitle.appendChild(link);
const cellGenre = row.insertCell();
cellGenre.textContent = Array.isArray(p.Жанр) ? p.Жанр.join(", ") : p.Жанр;
const cellRating = row.insertCell();
cellRating.textContent = p.Рейтинг + "/10";
const cellInsight = row.insertCell();
cellInsight.textContent = p.Инсайт || "–";
}
}
// --- Listeners ---
genreSelect.onchange = () => renderTable(genreSelect.value, searchInput.value);
searchInput.oninput = () => renderTable(genreSelect.value, searchInput.value);
// First render
renderTable();
container.appendChild(table);```
→ const allPages = dv.pages(‘“2. Areas/Сериалы и фильмы/7. Сериалы”’) — replace with your own path where your notes with YAML are stored → Move the last three apostrophe characters to a new line
🧠 An explanation for those who want to understand this code more deeply:
📁 1. Loading the notes from the right folder
const allPages = dv.pages('"2. Areas/Сериалы и фильмы/7. Сериалы"')
.where(p => p.Жанр && p.Рейтинг)
.sort(p => -Number(p.Рейтинг));-
Here all the notes from the “Shows” folder are loaded.
-
Only those that have
Жанр(Genre) andРейтинг(Rating) are selected. -
Sorted by descending rating — the top ones are at the top.
📌 Replace the path with your own folder if your structure is different.
🎛️ 2. The interface: filter by genre + search
const genres = [...new Set(allPages.flatMap(...))];-
All the unique genres are gathered (e.g.: Drama, Comedy, Anime).
-
A dropdown list is created — you can filter only “Sci-Fi” or only “Anime”.
searchInput.placeholder = "🔍 Search by title...";-
The search field filters by the note name (usually that’s the show’s title).
-
It works in real time — convenient!
📋 3. The table: what each row looks like
["🎬 Cover", "🎞 Title", "🎭 Genre", "⭐ Rating", "🧠 Insight"]Each row is one show, where the following is displayed:
| Column | What it shows |
|---|---|
| 🎬 Cover | The image from the Постер (Poster) field (if any) |
| 🎞 Title | The show’s title, as a link to the note |
| 🎭 Genre | One or several genres |
| ⭐ Rating | A score on a 10-point scale (Рейтинг) |
| 🧠 Insight | Your thought, takeaway or quote from the show |
🧠 4. Filtering and rendering
function renderTable(filterGenre = "all", searchTerm = "") { ... }-
Removes the old table rows and redraws only those that match the selected genre or the entered text.
-
This makes the table live: it reacts to the user’s actions.
🔁 5. Event listeners
genreSelect.onchange = () => renderTable(...)
searchInput.oninput = () => renderTable(...)-
When you change the genre or type into the search — the table updates.
-
It all happens live, without a reload.
✅ What you need in YAML
For this code to work, make sure these fields are specified in your show notes:
Постер: https://link-to-image.jpg
Жанр: [Sci-Fi, Drama]
Рейтинг: 8.7
Инсайт: An inspiring look at the technology of the future.🔥 The result
You get a cool catalogue:
-
everything is nicely styled;
-
you can filter by mood (genre);
-
you can quickly find and rewatch;
-
you can share it with friends or subscribers.
