function _bsdnUnwrapBitMask(number) {
return number.toString(2).split("").reverse().map(x => x === "1");
}
function _bsdnToHumanTime(time) {
time = Math.ceil(time);
let mins = Math.floor(time / 60);
let secs = (time - (mins * 60));
if(secs < 10)
secs = "0" + secs;
if(mins < 10)
mins = "0" + mins;
return mins + ":" + secs;
}
function _bsdnTpl(name, author) {
name = escapeHtml(name);
author = escapeHtml(author);
return `
`;
}
function _bsdnTerebilkaEventFactory(el, terebilka, callback, otherListeners) {
let terebilkaSize = () => el.querySelector(terebilka).getBoundingClientRect().width; // чтобы просралось
let listeners = {
mousemove: [
e => {
let buttonsPresseed = _bsdnUnwrapBitMask(e.buttons);
if(!buttonsPresseed[0])
return; // user doesn't click so nothing should be done
let offset = e.offsetX;
let percents = Math.max(0, Math.min(100, offset / (terebilkaSize() / 100)));
return callback(percents);
}
],
mousedown: [
e => {
let offset = e.offsetX;
let percents = Math.max(0, Math.min(100, offset / (terebilkaSize() / 100)));
return callback(percents);
}
]
};
for(eventName in (otherListeners || {})) {
if(listeners.hasOwnProperty(eventName))
listeners[eventName] = otherListeners[eventName].concat(listeners[eventName]);
else
listeners[eventName] = otherListeners[eventName];
}
return listeners;
}
function _bsdnEventListenerFactory(el, v) {
return {
".bsdn-player": {
click: [
e => {
if(el.querySelector(".bsdn_controls").contains(e.target) || el.querySelector(".bsdn_teaser").contains(e.target) || el.querySelector(".bsdn_contextMenu").contains(e.target))
return;
if(el.querySelector(".bsdn_contextMenu").style.display !== "none") {
el.querySelector(".bsdn_contextMenu").style.display = "none";
return;
}
if(v.paused)
v.play();
else
v.pause();
}
],
contextmenu: [
e => {
e.preventDefault();
if(el.querySelector(".bsdn_controls").contains(e.target) || el.querySelector(".bsdn_contextMenu").contains(e.target))
return;
let rect = el.querySelector(".bsdn-player").getBoundingClientRect();
let h = rect.height, w = rect.width;
let x, y;
if(document.fullscreen) {
x = e.screenX;
y = e.screenY;
} else {
let rx = rect.x + window.scrollX, ry = rect.y + window.scrollY;
x = e.pageX - rx;
y = e.pageY - ry;
}
if(h - y < 169)
y = Math.max(0, y - 169);
if(w - x < 238)
x = Math.max(0, x - 238);
let menu = el.querySelector(".bsdn_contextMenu");
menu.style.top = y + "px";
menu.style.left = x + "px";
menu.style.display = "unset";
}
]
},
".bsdn_contextMenuElement": {
click: [ () => el.querySelector(".bsdn_contextMenu").style.display = "none" ]
},
".bsdn_copyVideoUrl": {
click: [
async () => {
let videoUrl = el.querySelector(".bsdn_video > video").src;
let fallback = () => {
prompt("URL:", videoUrl);
};
if(typeof navigator.clipboard == "undefined") {
fallback();
} else {
try {
await navigator.clipboard.writeText(videoUrl);
confirm("👍🏼");
} catch(e) {
fallback();
}
}
}
]
},
".bsdn_video > video": {
play: [
() => {
if(!el.querySelector(".bsdn-player").classList.contains("bsdn-dirty"))
el.querySelector(".bsdn-player").classList.add("bsdn-dirty")
el.querySelector(".bsdn_playButton").innerHTML = "";
el.querySelector(".bsdn-player").classList.add("_bsdn_playing");
el.querySelector(".bsdn_teaserWrap").style.display = "none";
}
],
pause: [
() => {
el.querySelector(".bsdn_playButton").innerHTML = "";
el.querySelector(".bsdn-player").classList.remove("_bsdn_playing");
el.querySelector(".bsdn_teaserWrap").style.display = "flex";
}
],
timeupdate: [
() => {
el.querySelector(".bsdn_timeReal").innerHTML = _bsdnToHumanTime(v.currentTime);
let terebilkaSize = el.querySelector(".bsdn_terebilkaLowerWrap").getBoundingClientRect().width;
let brickSize = 15;
let percents = Math.ceil(v.currentTime / (v.duration / 100));
let offset = ((terebilkaSize - brickSize) / 100) * percents;
el.querySelector(".bsdn_terebilkaBrick").style.left = `min(calc(100% - 15px), ${offset}px`; // смешной мясной костыль ибо мне лень делать onresize
}
],
volumechange: [
() => {
if(v.volume === 0)
el.querySelector(".bsdn_soundIcon").src = "/assets/packages/static/openvk/img/bsdn/speaker_muted.gif";
else
el.querySelector(".bsdn_soundIcon").src = "/assets/packages/static/openvk/img/bsdn/speaker.gif";
let scSize = el.querySelector(".bsdn_soundControlSubWrap").getBoundingClientRect().width;
let brickSize = 10;
let offset = (scSize - brickSize) * v.volume;
el.querySelector(".bsdn_soundControlBrick").style.left = offset + "px";
}
],
loadedmetadata: [
() => {
el.querySelector(".bsdn_timeFull").innerHTML = _bsdnToHumanTime(v.duration);
}
]
},
".bsdn_repeatButton": {
click: [
() => {
if(!v.loop) {
v.loop = true
el.querySelector(".bsdn_repeatButton").classList.add("pressed")
if(v.currentTime == v.duration) {
v.currentTime = 0
v.play()
}
} else {
v.loop = false
el.querySelector(".bsdn_repeatButton").classList.remove("pressed")
}
}
]
},
".bsdn_fullScreenButton": {
click: [
() => {
if(document.fullscreen) {
document.exitFullscreen();
} else {
el.querySelector(".bsdn-player").requestFullscreen();
}
}
]
},
".bsdn_teaserButton|.bsdn_playButton": {
click: [
() => {
if(v.paused)
v.play();
else
v.pause();
}
]
},
".bsdn_terebilkaLowerWrap": _bsdnTerebilkaEventFactory(el, ".bsdn_terebilkaLowerWrap", function(p) {
let time = (v.duration / 100) * p;
setTimeout(() => {
v.currentTime = time;
if(v.currentTime === 0) {
console.warn("[!] Хромог момент");
console.warn("Теребилка не работает в хроме если сервер не реализует HTTP полностью.");
console.warn("Встроенный сервер РНР не возвращает заголовки Accept-Range из-за чего хром отказывается seek'ать. Google как всегда.");
console.warn("Установите Firefox для лучшей безопасности в сети: https://www.mozilla.org/ru/firefox/enterprise/#download");
}
}, 0);
}, {
mousedown: [
e => v.pause()
],
mouseup: [
e => v.play()
]
}),
".bsdn_soundControlSubWrap": _bsdnTerebilkaEventFactory(el, ".bsdn_soundControlSubWrap", function(p) {
let volume = p / 100;
v.volume = volume;
}),
".bsdn_soundIcon": {
click: [
e => v.volume = v.volume === 0 ? 0.75 : 0
]
}
}
}
function _bsdnApplyBindings(el, v) {
let listeners = _bsdnEventListenerFactory(el, v);
for(key in listeners) {
let selectors = key.split("|");
selectors.forEach(sel => {
for(eventName in listeners[key]) {
listeners[key][eventName].forEach(listener => {
el.querySelectorAll(sel).forEach(target => {
target.addEventListener(eventName, listener, {
passive: (["contextmenu"]).indexOf(eventName) === -1
});
});
});
}
});
}
}
function bsdnInitElement(el) {
if(el.querySelector(".bdsn-hydrated") != null) {
console.debug(el, " is already hydrated.");
return;
}
let video = el.querySelector("video");
if(!video) {
console.warning(el, " does not contain any