Skip to content

Commit

Permalink
Timelens optimizations to reduce requests
Browse files Browse the repository at this point in the history
  • Loading branch information
QbDesu committed Dec 31, 2024
1 parent 4e7b02f commit 57a3c1e
Show file tree
Hide file tree
Showing 3 changed files with 67 additions and 50 deletions.
9 changes: 5 additions & 4 deletions app/assets/javascripts/activate-timelens.js
Original file line number Diff line number Diff line change
@@ -1,13 +1,14 @@
$(document).on("turbolinks:load", function() {
$(".timelens:empty").each(function() {
$(document).on("turbolinks:load", function () {
$(".timelens:empty").each(function () {
const t = this;
timelens(this, {
timeline: this.dataset.timeline,
thumbnails: this.dataset.thumbnails,
seek: function(position) {
seek: function (position) {
location.href =
"/v/" + t.dataset.slug + "#t=" + Math.round(position);
}
},
lazyThumbnails: this.dataset.lazy
});
});
});
2 changes: 1 addition & 1 deletion app/views/frontend/shared/_event_metadata.haml
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@
= truncate(event.subtitle, length: 60, separator: ' ', omission: '…')

- if event.timelens_present?
%div.timelens{data: {timeline: event.timeline_url, thumbnails: event.thumbnails_url, slug: event.slug, duration: event.duration}}
%div.timelens{data: {timeline: event.timeline_url, thumbnails: event.thumbnails_url, slug: event.slug, duration: event.duration, lazy: "yes"}}

%ul.metadata
- if !event.tags.nil? && event.tags.length > 3
Expand Down
106 changes: 61 additions & 45 deletions vendor/assets/javascripts/timelens.js
Original file line number Diff line number Diff line change
@@ -1,6 +1,45 @@
/* Common functionality */

function timelens(container, options) {
// Use querySelector if a selector string is specified.
if (typeof container == "string")
container = document.querySelector(container);
container.className += " timelens";

// Create .timeline img, which displays the visual timeline.
const timeline = document.createElement("img");
timeline.className = "timelens-timeline";
timeline.setAttribute("loading", "lazy");
timeline.src = options.timeline;
// Prevent the timeline image to be dragged
timeline.setAttribute("draggable", "false");

// Create .marker div, which is used to display the current position.
if (options.position) {
const marker = document.createElement("div");
marker.className = "timelens-marker-border";
container.appendChild(marker);

const markerInner = document.createElement("div");
markerInner.className = "timelens-marker";
marker.appendChild(markerInner);
container.appendChild(marker);
}

container.appendChild(timeline);

if (!options.lazyThumbnails) {
loadThumbnails(container, options);
} else {
const once = function (event) {
loadThumbnails(container, options, { offsetX: event.offsetX, pageX: event.pageX });
timeline.removeEventListener("mousemove", once);
}
timeline.addEventListener("mousemove", once);
}
}

function loadThumbnails(container, options, event) {
// Load VTT file asynchronously, then continue with the initialization.
let vtt_url;
if (options.thumbnails) {
Expand All @@ -10,71 +49,51 @@ function timelens(container, options) {
const request = new XMLHttpRequest();
request.open("GET", vtt_url, true);
request.send(null);
request.onreadystatechange = function() {
request.onreadystatechange = function () {
if (request.readyState === 4 && request.status === 200) {
const type = request.getResponseHeader("Content-Type");
if (type.indexOf("text") !== 1) {
timelens2(container, request.responseText, options);
initThumbnails(container, request.responseText, options, event);
}
}
};
}

// Actually initialize Timelens.
function timelens2(container, vtt, options) {
function initThumbnails(container, vtt, options, event) {
const thumbnails = parseVTT(vtt);
const duration = thumbnails[thumbnails.length - 1].to;

// Use querySelector if a selector string is specified.
if (typeof container == "string")
container = document.querySelector(container);

// This will be our main .timelens div, which will contain all new elements.
if (container.className != "") {
container.className += " ";
}
container.className += "timelens";
// Create div which contains the thumbnail time.
const time = document.createElement("div");
time.className = "timelens-time";

// Create div which contains the preview thumbnails.
const thumbnail = document.createElement("div");
thumbnail.className = "timelens-thumbnail";

// Create div which contains the thumbnail time.
const time = document.createElement("div");
time.className = "timelens-time";
thumbnail.appendChild(time);
container.appendChild(thumbnail);

// Create .timeline img, which displays the visual timeline.
const timeline = document.createElement("img");
timeline.setAttribute("loading", "lazy");
timeline.src = options.timeline;
// Prevent the timeline image to be dragged
timeline.setAttribute("draggable", "false");
const timeline = container.querySelector(".timelens-timeline");
const marker = container.querySelector(".timelens-marker-border");

// Create .marker div, which is used to display the current position.
if (options.position) {
var marker = document.createElement("div");
marker.className = "timelens-marker-border";
container.appendChild(marker);

var markerInner = document.createElement("div");
markerInner.className = "timelens-marker";
marker.appendChild(markerInner);
setInterval(function () {
marker.style.marginLeft =
(options.position() / duration) * timeline.offsetWidth + "px";
}, 1);
}

// Assemble everything together.
container.appendChild(timeline);
container.appendChild(thumbnail);
thumbnail.appendChild(time);

// When clicking the timeline, seek to the respective position.
if (options.seek) {
timeline.onclick = function(event) {
timeline.onclick = function (event) {
const progress = progressAtMouse(event, timeline);
options.seek(progress * duration);
};
}

timeline.onmousemove = function(event) {
const mouseMove = function (event) {
// Calculate click position in seconds.
const progress = progressAtMouse(event, timeline);
const seconds = progress * duration;
Expand Down Expand Up @@ -114,12 +133,9 @@ function timelens2(container, vtt, options) {

time.innerHTML = to_timestamp(seconds);
};

if (options.position) {
setInterval(function() {
marker.style.marginLeft =
(options.position() / duration) * timeline.offsetWidth + "px";
}, 1);
timeline.onmousemove = mouseMove;
if (event) {
mouseMove(event);
}
}

Expand Down Expand Up @@ -163,7 +179,7 @@ function to_timestamp(seconds_total) {

// How far is the mouse into the timeline, in a range from 0 to 1?
function progressAtMouse(event, timeline) {
const x = event.offsetX ? event.offsetX : event.pageX - timeline.offsetLeft;
const x = typeof event.offsetX === "number" ? event.offsetX : event.pageX - timeline.offsetLeft;
return x / timeline.offsetWidth;
}

Expand Down Expand Up @@ -235,7 +251,7 @@ if (typeof MediaElementPlayer !== "undefined") {
timelens(slider, {
timeline: timeline,
thumbnails: thumbnails,
position: function() {
position: function () {
return player.currentTime;
}
});
Expand Down Expand Up @@ -274,7 +290,7 @@ if (typeof Clappr !== "undefined") {
timelens(bar, {
timeline: this.core.options.timelens.timeline,
thumbnails: this.core.options.timelens.thumbnails,
position: function() {
position: function () {
return t.core.containers[0].getCurrentTime();
}
});
Expand Down

0 comments on commit 57a3c1e

Please sign in to comment.