const TestClass = (function() {
class TestClass {
constructor() {
this.calls = '';
}
toString() {
return this.calls;
}
}
Object.setPrototypeOf(TestClass.prototype, Function.prototype);
function callTestClassInstance(el) {
this.calls += String(el);
}
return new Proxy(TestClass, {
construct(TestClass, args) {
const instance = new TestClass(...args);
const target = args => callTestClassInstance.apply(instance, args);
Object.setPrototypeOf(target, TestClass.prototype);
return new Proxy(target, {
apply(target, _, args) {
return target(args);
},
get(_, name) {
return instance[name];
},
set(_, name, value) {
instance[name] = value;
return true;
},
has(_, name) {
return name in instance;
},
deleteProperty(_, name) {
return delete instance[name];
},
defineProperty(_, name, descriptor) {
return Object.defineProperty(instance, name, descriptor);
},
getOwnPropertyDescriptor(_, name) {
return Object.getOwnPropertyDescriptor(instance, name);
},
ownKeys() {
return Object.getOwnPropertyNames(instance).concat(Object.getOwnPropertySymbols(instance));
}
});
}
});
})();
const appleDevice = /iP(hone|od|ad)/;
const applePhone = /iPhone/i;
const appleIPod = /iPod/i;
const appleTablet = /iPad/i;
const androidPhone = /(?=.*\bAndroid\b)(?=.*\bMobile\b)/i;
const androidTablet = /Android/i;
const windowsPhone = /Windows Phone/i;
const windowsTablet = /(?=.*\bWindows\b)(?=.*\bARM\b)/i;
const otherBlackberry = /BlackBerry/i;
const otherOpera = /Opera Mini/i;
const otherFirefox = /(?=.*\bFirefox\b)(?=.*\bMobile\b)/i;
const sevenInch = /(?:Nexus 7|BNTV250|Kindle Fire|Silk|GT-P1000)/i;
function match(regex, target = navigator.userAgent) {
return regex.test(target);
}
export const isAppleDevice = match(applePhone) || match(appleIPod) || match(appleTablet) || match(appleDevice, navigator.platform);
export const isAndroidDevice = match(androidPhone) || match(androidTablet);
export const isWindowsDevice = match(windowsPhone) || match(windowsTablet);
export const isOtherDevice = match(otherBlackberry) || match(otherOpera) || match(otherFirefox);
export const isSevenInch = match(sevenInch);
export const isMobileDevice = isAppleDevice || isAndroidDevice || isWindowsDevice || isOtherDevice || isSevenInch;
export const isEmulator = isMobileDevice && !isWindowsDevice && (match(/Mac/, navigator.platform) || match(/Win32/, navigator.platform));
// мне кажется, что ждать полной загрузки страницы тут незачем
document.addEventListener('DOMContentLoaded', () => {
new Slider({
images: ".slider__galary img",
btnPrev: ".btnPrev",
btnNext: ".btnNext",
rate: false
});
});
// хелпер для прослушивания событий
class EventListener {
constructor(ctx, handlers, target) {
this.ctx = ctx;
this.handlers = handlers;
Object.keys(handlers).forEach(event => target.addEventListener(event, this));
}
handleEvent(event) {
const {handlers, ctx} = this;
const {type} = event;
if(typeof handlers[type] !== 'function') return;
handlers[type].call(ctx, event);
}
}
class Slider {
construnctor({images, btnPrev, btnNext, rate, time = 1000}) {
this.images = document.querySelectorAll(images);
this.i = 0;
new EventListener(this, {
click: this.prev
}, document.querySelector(btnPrev));
new EventListener(this, {
click: this.next
}, document.querySelector(btnNext));
if(rate) {
setInterval(() => this.next(), time);
}
}
prev() {
this.images[i].classList.remove("showed");
this.i--;
if(this.i < 0){
this.i = this.images.length - 1;
}
this.images[i].classList.add("showed");
}
next() {
this.images[i].classList.remove("showed");
this.i++;
if(this.i >= this.images.length){
this.i = 0;
}
this.images[i].classList.add("showed");
}
}
const {PassThrough} = require('stream');
const youtubeStream = new PassThrough();
youtubeApi.downloadVideo(
'v=4P1-JwZF0Vo&t=4519s',
chunk => youtubeStream.write(chunk),
() => youtubeStream.end()
);
youtubeStream.pipe(res); // где res - выходной поток к клиенту
// для начала я вынесу массив с разрешениями из функции, чтоб не создавать его для каждого вызова:
var resolutions = ['maxresdefault', 'hqdefault', 'mqdefault'];
function fetch_highest_res(videoid) {
// сама функция будет возвращать промис, полученный сверткой массива resolutions
return resolutions.reduce(
function(promise, resolution) {
// перехватываем только ошибку загрузки, если была успешная загрузка - просто отдаем ее дальше
return promise.catch(function() {
return new Promise(function(resolve, reject) {
var img = new Image();
// повесим таймаут в 3 секунды (если надо, поставьте больше), генерирующий ошибку
setTimeout(reject, 3000);
// отследим ошибку загрузки
img.onerror = reject;
// а в случае успешной загрузки отдадим результат
img.onload = function() {
resolve(resolution);
};
// и только когда навесили обработчики начинаем загрузку
img.src = 'https://i.ytimg.com/vi/' + videoid + '/' + resolution + '.jpg';
});
});
},
// в качестве инициализирующего значения отдаем отклоненный промис
// так как следующая картинка должна пробоваться только если не получилось загрузить предыдущую
// а отслеживать мы это будем по ошибке загрузки
Promise.reject()
// ну и перехватим случай, если ничего не удалось загрузить
).catch(function() { return null; });
}
// ну и функция теперь у нас возвращает асинхронный результат в виде промиса
// поэтому и получать его надо соответствующе
fetch_highest_res('eei-soH5Gx8').then(function(resolution) {
console.log(resolution); // hqdefault
});
function handleClick() {
$('.photo').removeClass('active-element');
$(this).addClass('active-element');
$('.point li').removeClass('active-point').
filter((index, item) => $(this).data('id') == $(item).data('id')).addClass('active-point');
$('.about-text p').text($(this).data('text'));
$('.about-site p').text($(this).data('info'));
$('.about-site a').text($(this).data('website')).attr("href", "#");
}
$('.photo').click(handleClick);
$('.point li').click(function() {
$('.point li').removeClass('active-point');
$(this).addClass('active-point');
handleClick.call(this)
});