export default class YouTube {
states = Object.freeze({
INIT: 'INIT',
PLAY: 'PLAY',
PAUSE: 'PAUSE',
});
constructor({container, videoId}) {
this.container = container;
this.videoId = videoId;
this.isPlayerReady = false;
this.initState = this.states.INIT;
this.resizeTimeout = null;
this.resizeTimeoutDelay = 500;
YouTube.addScript();
YouTube.onYouTubeIframeAPIReady(() => {
this.player = this.getPlayer();
});
$(window).on('resize', () => {
clearTimeout(this.resizeTimeout);
this.resizeTimeout = setTimeout(() => {
this.setDimensions();
}, this.resizeTimeoutDelay);
});
}
setDimensions() {
$.getJSON(`https://www.youtube.com/oembed?url=https://www.youtube.com/watch?v=${this.videoId}&format=json`,
({width, height}) => {
const elm = $(this.player.getIframe());
const elmWidth = elm.width();
const elmHeight = height * elmWidth / width;
elm.height(Math.floor(elmHeight));
});
}
isPauseState() {
return this.states.PAUSE === this.initState;
}
isPlayState() {
return this.states.PLAY === this.initState;
}
onPlayerReady() {
this.isPlayerReady = true;
if (this.isPauseState())
this.pause();
else if (this.isPlayState())
this.play();
this.setDimensions();
}
play() {
if (this.isPlayerReady)
this.player.playVideo();
this.initState = this.states.PLAY;
};
pause() {
if (this.isPlayerReady)
this.player.pauseVideo();
this.initState = this.states.PAUSE;
};
getPlayer() {
return new YT.Player(this.container, {
videoId: this.videoId,
width: 945,
events: {
'onReady': this.onPlayerReady.bind(this),
}
});
}
static onYouTubeIframeAPIReady(fn) {
if (!window.hasOwnProperty('onYouTubeIframeAPIReadyEvents') && !Array.isArray(window.onYouTubeIframeAPIReadyEvents))
window.onYouTubeIframeAPIReadyEvents = [];
if (!window.hasOwnProperty('onYouTubeIframeAPIReady') || !window.onYouTubeIframeAPIReady) {
window.onYouTubeIframeAPIReady = function () {
for (let i = 0; i < window.onYouTubeIframeAPIReadyEvents.length; i++)
window.onYouTubeIframeAPIReadyEvents[i]();
};
}
window.onYouTubeIframeAPIReadyEvents.push(fn);
}
static addScript() {
if (!YouTube.isScriptAdded()) {
const tag = document.createElement('script');
tag.src = 'https://www.youtube.com/iframe_api';
const firstScriptTag = document.getElementsByTagName('script')[0];
firstScriptTag.parentNode.insertBefore(tag, firstScriptTag);
window.youTubeScriptAdded = true;
}
}
static isScriptAdded() {
return window.hasOwnProperty('youTubeScriptAdded') && window.youTubeScriptAdded;
}
}
import YouTube from '../../../utils/YouTube';
$(window).on('load', () => {
const video = $('.video-js');
const playButton = $('.video_button-js');
const youTube = new YouTube({
container: video.get(0),
videoId: 'ТУТ ВИДЕО ID', // обычно get параметр в ссылке на видео "v=ВИДЕО_ID'"
});
playButton .on('click', () => {
youTube.play();
// youTube.pause();
});
});
<div class="video-js"></div>
<div class="video_button-js">Play</div>
1 - уведомить пользователя user1 о том что данные были изменены и попросить дождаться синхронизации данных, после этого по-новому подтянуть актуальные данные и повторить потом операцию редактирования.
.block_container{
display: flex;
flex-flow: row wrap;
}
/*
[][]
[ ]
[][]
[ ]
*/
.block-1, .block-2{ order: 1}
.banner-1{ order: 2}
.block-3, .block-4{ order: 3}
.banner-2{ order: 4}
/*...*/
/*
[][][]
[ ]
[][][]
[ ]
*/
@media (min-width: 768px){
.block-1, .block-2, .block-3{ order: 1}
.banner-1{ order: 2}
.block-4, .block-5, .block-6{ order: 3}
.banner-2{ order: 4}
/*...*/
}
/*...*/
Как в onclick передать родителя?
Есть ли какой-нибудь более элегантный способ, чем мой?
class FormSubmitHandler{
constructor(form){
this.form = form;
this.isSending = false;
this.form.addEventListener('submit', this.onSubmit.bind(this));
}
onSubmit(e){
e.preventDefault();
// не отправляем форму пока ответ не пришел
if(this.isSending)
return;
const data = new FormData(this.form);
if(!this.validate(data))
return;
this.isSending = true;
this.send(this.form.getAttribute("php"), data);
}
send(url, data){
fetch(url, {
method: "POST",
body: data,
})
.then(response => response.json())
.then(this.onCommit.bind(this))
.catch(this.onBadRequest.bind(this));
}
onCommit(responseData){
console.log(responseData, this.form);
this.isSending = false;
}
onBadRequest(error){
console.log(error, this.form);
this.isSending = false;
}
validate(data){
console.log(data.getAll(), this.form);
// проверка полей формы
}
}
///////////////////////////////////////////////
document.querySelectorAll('form').forEach((formElm) => {
new FormSubmitHandler(formElm);
});
//...
// клик на кнопку следующего месяца, если текущее представление дни месяца:
datepicker.next();
// клик на кнопку следующего года, если текущее представление дни месяца:
datepicker.view = 'months';
datepicker.next();
datepicker.view = 'days';
//...
.bottom-menu-mobile{
position: fixed;
top: auto;
bottom: 0;
left: 0;
right: 0;
}
/**
* @param string $role
*
* @return array
*/
public function findWithoutRole($role)
{
$qb = $this->_em->createQueryBuilder();
$qb->select('u')
->from($this->_entityName, 'u')
->where('u.roles NOT LIKE :roles')
->setParameter('roles', '%"' . $role . '"%');
return $qb->getQuery()->getResult();
}
<?
require __DIR__ . '/vendor/autoload.php';
use Ahc\Jwt\JWT;
use ElephantIO\Client;
use ElephantIO\Engine\SocketIO\Version2X;
$secret = 'shecret';
$host = 'http://localhost';
$port = 3000;
$maxAge = 600;
$payload = [
'data' => '123',
];
$jwt = new JWT($secret, 'HS256', $maxAge);
$token = $jwt->encode($payload);
$client = new Client(new Version2X($host .':'. $port));
$client->initialize();
$client->emit('authenticate', ['token' => $token]);
$isAuthenticated = formatResponse($client->read());
if('authenticated' !== $isAuthenticated['event']){
$client->close();
}
$data = [
'data' => 'from client'
];
$token = $jwt->encode($data);
$client->emit('action', ['token' => $token]);
$response = formatResponse($client->read());
if($response['data']){
$response = ($jwt->decode($response['data']->token))['data'];
}
$client->close();
echo '<pre>';
print_r($response);
echo '</pre>';
function formatResponse($response){
$response = json_decode(preg_replace('/^\d*/i', '', $response));
return $response ? [
'event' => $response[0],
'data' => $response[1],
] : false;
}
require("@babel/register");
const
socketIO = require('socket.io'),
jwt = require('jsonwebtoken'),
socketioJwt = require('socketio-jwt'),
port = 3000,
server = socketIO.listen(port),
secret = 'shecret',
maxAge = 600;
server
.on(
'connection',
socketioJwt.authorize({
secret: secret,
timeout: 10000,
callback: false
}
))
.on('connection', socket => {
console.log('on connection to server (server)');
})
.on('authenticated', socket => {
console.log('on authenticated to server (server), socket.decoded_token', socket.decoded_token);
socket.on('action', data => {
console.log('on action (server)', data);
if(data && 'token' in data){
let decoded = null;
try {
decoded = jwt.verify(data.token, secret);
} catch (err) {
console.log(err);
}
if(decoded){
console.log(decoded);
const token = jwt.sign(
{
exp: Math.floor(Date.now() / 1000) + maxAge,
data: 'from server'
},
secret);
socket.emit('action', {token: token});
} else {
socket.disconnect(true);
}
}
})
})
;
// composer.json
"adhocore/jwt": "^0.1.0",
"wisembly/elephant.io": "^3.3"
// package.json
"jsonwebtoken": "^8.5.1",
"socket.io": "^2.3.0",
"socketio-jwt": "^4.5.0"
Can't find file /home/userone/.vnc/example123.com:1.pid