Div side-by-side alignment with YouTube video - html

While I understand that aligning two div's side by side is a common question, I am having a little bit of an issue getting the YouTube video and chat box to align next to each other. I should be using a span, since this would allow the chatbox in the same space as the youtube video correct? I'm still learning the ropes here in HTML. Here is what the page currently looks like:
Here is my current HTML code, the divs dealing with the youtube video is class name "youtube-video" and div dealing with the chat box is class "chat"
<!DOCTYPE html>
<html>
<head>
<title>Chat</title>
<link rel="stylesheet" href="main.css">
</head>
<body>
<div class="header-bar">
<div class="bar"></div>
<div class="dropshadow"></div>
</div>
<div class="DJ-text">Affinity FM DJ Room
<span class="Chat-text">Chat</span>
<div class="DJ-underline"></div>
<div class="Chat-underline"></div></div>
<div class="youtube-video" style="float: left;">
<iframe width="900px" height="500px" src="https://www.youtube.com/embed/2GvIq2SpVFM" frameborder="0" allowfullscreen></iframe>
</div>
<div class="chat" style="float: left; padding: 0px 0px 0px 12px;">
<input type="text" class="chat-name" placeholder="Chat">
<div class="info-rect">Info</div>
<div class="chat-messages"></div>
<textarea placeholder="Join the conversation..."></textarea>
<div class="chat-status">Status: <span>Idle</span></div>
</div>
<script src="http://127.0.0.1:8080/socket.io/socket.io.js"></script>
<script>
(function() {
var getNode = function(s) {
return document.querySelector(s);
},
// Get required nodes
status = getNode('.chat-status span'),
messages = getNode('.chat-messages'),
textarea = getNode('.chat textarea'),
chatName = getNode('.chat-name'),
statusDefault = status.textContent,
setStatus = function(s){
status.textContent = s;
if(s !== statusDefault){
var delay = setTimeout(function(){
setStatus(statusDefault);
clearInterval(delay);
}, 3000);
}
};
//try connection
try{
var socket = io.connect('http://127.0.0.1:8080');
} catch(e){
//Set status to warn user
}
if(socket !== undefined){
//Listen for output
socket.on('output', function(data){
if(data.length){
//Loop through results
for(var x = 0; x < data.length; x = x + 1){
var message = document.createElement('div');
message.setAttribute('class', 'chat-message');
message.textContent = ': ' + data[x].message;
var name=document.createElement('span');
name.setAttribute('class', 'userName');
name.textContent = data[x].name;
message.insertBefore(name, message.firstChild);
//Append
messages.appendChild(message);
messages.insertBefore(message, messages.firstChild);
}
}
});
//Listen for a status
socket.on('status', function(data){
setStatus((typeof data === 'object') ? data.message : data);
if(data.clear === true){
textarea.value = '';
}
});
//Listen for keydown
textarea.addEventListener('keydown', function(event){
var self = this,
name = chatName.value;
if(event.which === 13 && event.shiftKey === false){
socket.emit('input', {
name: name,
message: self.value
});
}
});
}
})();
</script>
</body>
</html>
Here is my CSS for youtube-video and chat:
body {
background-color: #0f0f17;
margin: 0px;
width: 100%;
}
body,
textarea,
input {
font: 13px "Raleway", sans-serif;
color: #ffffff;
}
.bar{
height: 115px;
width: 100%;
background-color: #15151d;
}
.DJ-text{
font-weight: 700;
position:relative;left:50px;
position:relative;top:80px;
text-transform: uppercase;
}
.Chat-text{
position:relative;left:900px;
}
.DJ-underline{
width: 900px;
height: 1px;
position:relative;top:20px;
background-color: #3f3f45;
}
.Chat-underline{
width: 400px;
position:relative;left:-140px;
float:right;
height: 1px;
position:relative;top:20px;
background-color: #3f3f45;
}
/*.youtube-video{
position: relative; left: 50px;
position: relative; top: 130px;
}
.chat {
max-width: 400px;
background-color: #0f0f17;
position:relative;left:1093px;
position:relative;top:150px;
}*/
.chat-messages,
.chat-textarea,
.chat-name {
border: 1px solid #1a1a23;
background-color: #1a1a23;
}
.userName{
font-weight: 700;
color: #079ce0;
}
.chat-messages {
width:100%;
height:400px;
overflow-y:scroll;
padding:10px;
}
.chat-message {
margin-bottom:10px;
}
.info-rect{
height: 40px;
width: 180px;
padding:10px;
max-width: 100%;
margin:0;
border:0;
display: flex;
align-items: center;
justify-content: center;
font-weight: 700;
text-transform: uppercase;
}
.chat-name{
height: 40px;
max-width: 100%;
width: 180px;
padding:10px;
border:0;
margin:0;
font-weight: 700;
text-transform: uppercase;
float:left;
text-align: center;
}
.chat textarea {
width:100%;
padding:10px;
margin:0;
border-top:0;
max-width:100%;
border-top: 1px solid #0f0f17;
border-bottom: 1px solid #1a1a23;
border-right: 1px solid #1a1a23;
border-left: 1px solid #1a1a23;
background-color: #1a1a23;
}
.chat-status {
color: #bbb;
background-color: #0f0f17;
}
.info-rect,
.chat textarea,
.chat-name {
max-width: 100%;
}
Using the code above supplied by #georges_user2251342, this is what the page looks like:
Here is the reference PSD: http://imgur.com/4XU62C9

It is true what they say! If I understand correctly, by centering, you mean to put 2 things side by side, next to each other so to speak.
In your case, the "youtube-video" element and the "chat" element need to be put side by side with percentages, yes. However, I would use 66% with 33% for percentages instead of 80% with 20%. Because your "chat" element doesn't look good with just 20%. It looks crunched up.
Look at these :
(66%-33%) http://lespointscom.com/a/misc/demo/2016_06_18/main_4.html
(80%-20%) http://lespointscom.com/a/misc/demo/2016_06_18/main_5.html
AGAIN THE NEW HTML :
<!DOCTYPE html>
<html>
<head>
<title>Chat</title>
<link rel="stylesheet" href="main6.css">
</head>
<body>
<div class="header-bar">
<div class="bar"></div>
<div class="dropshadow"></div>
</div>
<div class="container">
<div class="youtube-video">
<div class="DJ-text">Affinity FM DJ Room</div>
<div class="DJ-underline"></div>
<iframe class="iframe" src="https://www.youtube.com/embed/2GvIq2SpVFM" frameborder="0" allowfullscreen></iframe>
</div>
<div class="chat">
<div class="Chat-text">Chat</div>
<div class="Chat-underline"></div>
<input type="text" class="chat-name" placeholder="Chat">
<div class="info-rect">Info</div>
<div class="chat-messages"></div>
<textarea placeholder="Join the conversation..."></textarea>
<div class="chat-status">Status: <span>Idle</span></div>
</div>
</div>
<script src="http://127.0.0.1:8080/socket.io/socket.io.js"></script>
<script>
(function() {
var getNode = function(s) {
return document.querySelector(s);
},
// Get required nodes
status = getNode('.chat-status span'),
messages = getNode('.chat-messages'),
textarea = getNode('.chat textarea'),
chatName = getNode('.chat-name'),
statusDefault = status.textContent,
setStatus = function(s){
status.textContent = s;
if(s !== statusDefault){
var delay = setTimeout(function(){
setStatus(statusDefault);
clearInterval(delay);
}, 3000);
}
};
//try connection
try{
var socket = io.connect('http://127.0.0.1:8080');
} catch(e){
//Set status to warn user
}
if(socket !== undefined){
//Listen for output
socket.on('output', function(data){
if(data.length){
//Loop through results
for(var x = 0; x < data.length; x = x + 1){
var message = document.createElement('div');
message.setAttribute('class', 'chat-message');
message.textContent = ': ' + data[x].message;
var name=document.createElement('span');
name.setAttribute('class', 'userName');
name.textContent = data[x].name;
message.insertBefore(name, message.firstChild);
//Append
messages.appendChild(message);
messages.insertBefore(message, messages.firstChild);
}
}
});
//Listen for a status
socket.on('status', function(data){
setStatus((typeof data === 'object') ? data.message : data);
if(data.clear === true){
textarea.value = '';
}
});
//Listen for keydown
textarea.addEventListener('keydown', function(event){
var self = this,
name = chatName.value;
if(event.which === 13 && event.shiftKey === false){
socket.emit('input', {
name: name,
message: self.value
});
}
});
}
})();
</script>
</body>
</html>
AGAIN THE NEW CSS :
.youtube-video{
float: left;
width:66%;
}
.chat {
float: left;
width:33%;
}
.iframe {
width:98%;
min-height:500px;
}
.container {
width:98%;
}
body {
background-color: #0f0f17;
margin: 0px;
width: 100%;
}
body,
textarea,
input {
font: 13px "Raleway", sans-serif;
color: #ffffff;
}
.bar{
height: 115px;
width: 100%;
background-color: #15151d;
}
.DJ-text{
font-weight: 700;
/*position:relative;
left:50px;
top:80px;*/
text-transform: uppercase;
}
.Chat-text{
font-weight: 700;
/*position:relative;left:900px;*/
text-transform: uppercase;
}
.DJ-underline{
width: 98%;
height: 1px;
position:relative;top:20px;
background-color: #3f3f45;
margin: 0px 0px 50px;
}
.Chat-underline{
width: 100%;
position:relative;
/*left:-140px;*/
float:right;
height: 1px;
position:relative;top:20px;
background-color: #3f3f45;
margin: 0px 0px 50px;
}
.chat-messages,
.chat-textarea,
.chat-name {
border: 1px solid #1a1a23;
background-color: #1a1a23;
}
.userName{
font-weight: 700;
color: #079ce0;
}
.chat-messages {
width:95%;
height:400px;
overflow-y:scroll;
padding:10px;
}
.chat-message {
margin-bottom:10px;
}
.info-rect{
height: 40px;
width: 180px;
padding:10px;
max-width: 100%;
margin:0;
border:0;
display: flex;
align-items: center;
justify-content: center;
font-weight: 700;
text-transform: uppercase;
}
.chat-name{
height: 40px;
max-width: 100%;
width: 180px;
padding:10px;
border:0;
margin:0;
font-weight: 700;
text-transform: uppercase;
float:left;
text-align: center;
}
.chat textarea {
width:95%;
padding:10px;
margin:0;
border-top:0;
max-width:100%;
border-top: 1px solid #0f0f17;
border-bottom: 1px solid #1a1a23;
border-right: 1px solid #1a1a23;
border-left: 1px solid #1a1a23;
background-color: #1a1a23;
}
.chat-status {
color: #bbb;
background-color: #0f0f17;
}
.info-rect,
.chat textarea,
.chat-name {
max-width: 100%;
}
#media only screen and (max-width: 772px) and (min-width: 0px)
{
.youtube-video{
width:100%;
}
.chat{
width:100%;
}
}
#media only screen and (max-width: 1254px) and (min-width: 0px)
{
.info-rect{
width:30%;
}
}
#media only screen and (max-width: 1054px) and (min-width: 0px)
{
.info-rect{
width:10%;
}
}

You can bring the chat box to the right by using position property.
Add this css for youtube-video
width:80%;
height:100%;
position:absolute;
left:0;
top:0;
Add this css for chat
width:20%;
height:100%;
position:absolute;
right:0;
top:0;
So, by doing this, you can bring the chat box to right.
Here is the Plnkr
Hope it works for you :)

Just put a float: left; to both divs :
<!DOCTYPE html>
<html>
<head>
<title>Chat</title>
<link rel="stylesheet" href="main.css">
</head>
<body>
<div class="header-bar">
<div class="bar"></div>
<div class="dropshadow"></div>
</div>
<div class="DJ-text">Affinity FM DJ Room
<span class="Chat-text">Chat</span>
<div class="DJ-underline"></div>
<div class="Chat-underline"></div></div>
<div class="youtube-video" style="float: left;">
<iframe width="900px" height="500px" src="https://www.youtube.com/embed/2GvIq2SpVFM" frameborder="0" allowfullscreen></iframe>
</div>
<div class="chat" style="float: left; padding: 0px 0px 0px 12px;">
<input type="text" class="chat-name" placeholder="Chat">
<div class="info-rect">Info</div>
<div class="chat-messages"></div>
<textarea placeholder="Join the conversation..."></textarea>
<div class="chat-status">Status: <span>Idle</span></div>
</div>
<script src="http://127.0.0.1:8080/socket.io/socket.io.js"></script>
<script>
(function() {
var getNode = function(s) {
return document.querySelector(s);
},
// Get required nodes
status = getNode('.chat-status span'),
messages = getNode('.chat-messages'),
textarea = getNode('.chat textarea'),
chatName = getNode('.chat-name'),
statusDefault = status.textContent,
setStatus = function(s){
status.textContent = s;
if(s !== statusDefault){
var delay = setTimeout(function(){
setStatus(statusDefault);
clearInterval(delay);
}, 3000);
}
};
//try connection
try{
var socket = io.connect('http://127.0.0.1:8080');
} catch(e){
//Set status to warn user
}
if(socket !== undefined){
//Listen for output
socket.on('output', function(data){
if(data.length){
//Loop through results
for(var x = 0; x < data.length; x = x + 1){
var message = document.createElement('div');
message.setAttribute('class', 'chat-message');
message.textContent = ': ' + data[x].message;
var name=document.createElement('span');
name.setAttribute('class', 'userName');
name.textContent = data[x].name;
message.insertBefore(name, message.firstChild);
//Append
messages.appendChild(message);
messages.insertBefore(message, messages.firstChild);
}
}
});
//Listen for a status
socket.on('status', function(data){
setStatus((typeof data === 'object') ? data.message : data);
if(data.clear === true){
textarea.value = '';
}
});
//Listen for keydown
textarea.addEventListener('keydown', function(event){
var self = this,
name = chatName.value;
if(event.which === 13 && event.shiftKey === false){
socket.emit('input', {
name: name,
message: self.value
});
}
});
}
})();
</script>
</body>
</html>
and for a better look, add padding: 0px 0px 0px 12px; or a similar small padding to seperate both divs.

Add this css for youtube-video
width:80%;
float:left;
Add this css for chat
width:20%;
float:left;

Related

Different text + QR every refresh with JS

How can i shuffle random (given) strings every refresh?
Every refresh, i want to show a different "author" you can ignore the 'quote' or 'order1' if you want
This is what i have:
(sorry i started learning the JS basics, this is the result of a page of what i want to accomplish)
Im a beginner so please explain the solution and go easy on me
Please fix according to
jsfiddle or create a similar one
const quotes = [
{
quote: 'QRimg1.jpg', //or https://chart.googleapis.com/chart?chs=200x200&cht=qr&chl=text1
author: 'text1',
order1: 'Order ID: #1'
},
{
quote: 'QRimg2.jpg', //or https://chart.googleapis.com/chart?chs=200x200&cht=qr&chl=text2
author: 'text2',
order1: 'Order ID: #2'
},
]
const quoteBtn = document.getElementById('quote-btn');
const quote = document.querySelector('.quote');
const author = document.querySelector('.author');
const order1 = document.querySelector('.order1');
function qrCode() {
let random = Math.floor(Math.random() * quotes.length);
quote.getElementsByTagName("IMG")[0].src = quotes[random].quote;
author.innerHTML = quotes[random].author;
order1.innerHTML = quotes[random].order1;
}
#box1{
margin-top:70px;
margin-left:35px;
width:430px;
}
.tablink {
background-color: #555;
color: black;
font-weight: 500;
float: left;
border: solid 1px black;
margin-top:0px;
outline: none;
cursor: pointer;
padding: 8px 8px;
font-size: 15px;
width:100%;
}
/* Style the tab content */
.tabcontent {
border:solid black 2px;
color: black;
display: none;
padding:100px;
text-align: center;
height:380px;
}
.container_box{
margin: 20px;
margin-top:50px;
width:455px;
height:400px;
}
.quote img{
width: 160px;
height: 160px;
margin-top:-85px;
display: block;
margin-left: 13px;
margin-right: auto;
margin-bottom:10px;
z-index:100;
}
.order1{
font-size:18px;
color:black;
font-weight:800;
left:50px;
position:absolute;
margin-top:-35px;
z-index:50;
}
*{
box-sizing:border-box;
}
.container{
width:50%;
}
.author{
font-size:15px;
color:black;
font-weight:400;
border:1px solid black;
border-radius:3px;
background-color: #f0f0f0;
width: 352px;
height:22px;
padding-top:2px;
}
.author{
position:absolute;
left:72px;
top:320px;
}
<!DOCTYPE html>
<html>
<head>
<meta name="viewport" content="width=device-width, initial-scale=1.0">
</head>
<body>
<div id= "box1">
<div class="tablink" onclick="someFunction('orange', this, '#FF9900')" id="defaultOpen">Some text</div>
<div class="order1">ID: #0</div>
<div id="orange" class="tabcontent">
<div class="container_box">
<span class="quote"><img src="https://chart.googleapis.com/chart?chs=200x200&cht=qr&chl=text0"></span>
</div>
<div class="author">text0</div>
</div>
</div>
<script>
//colorchange for topbar
function someFunction(otherName,elmnt,color) {
var i, tabcontent, tablinks;
tabcontent = document.getElementsByClassName("tabcontent");
for (i = 0; i < tabcontent.length; i++) {
tabcontent[i].style.display = "none";
}
tablinks = document.getElementsByClassName("tablink");
for (i = 0; i < tablinks.length; i++) {
tablinks[i].style.backgroundColor = "";
}
document.getElementById(otherName).style.display = "block";
elmnt.style.backgroundColor = color;
}
// Get the element with id="defaultOpen" and click on it
document.getElementById("defaultOpen").click();
</script>
<script type="text/javascript">
window.onload = qrCode;
</script>
</body>
</html>
p.s sorry for not putting 'javascript' tag, it shows an error for some reason,
Please instead of closing my question, you can edit/add tag if you wish
it's a wrong call of qrCode function,
const quotes = [
{
quote: 'https://chart.googleapis.com/chart?chs=200x200&cht=qr&chl=text1', //or
author: 'text1',
order1: 'Order ID: #1'
},
{
quote: 'https://chart.googleapis.com/chart?chs=200x200&cht=qr&chl=text2', //or
author: 'text2',
order1: 'Order ID: #2'
},
]
const quoteBtn = document.getElementById('quote-btn');
const quote = document.querySelector('.quote');
const author = document.querySelector('.author');
const order1 = document.querySelector('.order1');
function qrCode() {
let random = Math.floor(Math.random() * quotes.length);
quote.getElementsByTagName("IMG")[0].src = quotes[random].quote;
author.innerHTML = quotes[random].author;
order1.innerHTML = quotes[random].order1;
}
qrCode();
#box1{
margin-top:70px;
margin-left:35px;
width:430px;
}
.tablink {
background-color: #555;
color: black;
font-weight: 500;
float: left;
border: solid 1px black;
margin-top:0px;
outline: none;
cursor: pointer;
padding: 8px 8px;
font-size: 15px;
width:100%;
}
/* Style the tab content */
.tabcontent {
border:solid black 2px;
color: black;
display: none;
padding:100px;
text-align: center;
height:380px;
}
.container_box{
margin: 20px;
margin-top:50px;
width:455px;
height:400px;
}
.quote img{
width: 160px;
height: 160px;
margin-top:-85px;
display: block;
margin-left: 13px;
margin-right: auto;
margin-bottom:10px;
z-index:100;
}
.order1{
font-size:18px;
color:black;
font-weight:800;
left:50px;
position:absolute;
margin-top:-35px;
z-index:50;
}
*{
box-sizing:border-box;
}
.container{
width:50%;
}
.author{
font-size:15px;
color:black;
font-weight:400;
border:1px solid black;
border-radius:3px;
background-color: #f0f0f0;
width: 352px;
height:22px;
padding-top:2px;
}
.author{
position:absolute;
left:72px;
top:320px;
}
<!DOCTYPE html>
<html>
<head>
<meta name="viewport" content="width=device-width, initial-scale=1.0">
</head>
<body>
<div id= "box1">
<div class="tablink" onclick="someFunction('orange', this, '#FF9900')" id="defaultOpen">Some text</div>
<div class="order1">ID: #0</div>
<div id="orange" class="tabcontent">
<div class="container_box">
<span class="quote"><img src="https://chart.googleapis.com/chart?chs=200x200&cht=qr&chl=text0"></span>
</div>
<div class="author">text0</div>
</div>
</div>
<script type="text/javascript">
//colorchange for topbar
function someFunction(otherName,elmnt,color) {
var i, tabcontent, tablinks;
tabcontent = document.getElementsByClassName("tabcontent");
for (i = 0; i < tabcontent.length; i++) {
tabcontent[i].style.display = "none";
}
tablinks = document.getElementsByClassName("tablink");
for (i = 0; i < tablinks.length; i++) {
tablinks[i].style.backgroundColor = "";
}
document.getElementById(otherName).style.display = "block";
elmnt.style.backgroundColor = color;
}
// Get the element with id="defaultOpen" and click on it
document.getElementById("defaultOpen").click();
</script>
</body>
</html>

Checkbox need two clicks to uncheck?

My checkboxes need 2 clicks to be unchecked.
I have the issue in all 7 checkboxes.
To check the boxes, one click is enough.
I have no onchange() function or something in TS.
.............................................................................................................................................................
import { Component, OnInit, Inject } from '#angular/core';
import { PHPAPIService } from '../../php-api.service';
import * as socketIO from 'socket.io-client';
import {MatTableModule} from '#angular/material/table';
import * as $ from 'jquery';
import { ToastrService } from 'ngx-toastr';
import {MatDialog, MatDialogRef, MAT_DIALOG_DATA} from '#angular/material';
export interface DialogData {
name: string;
}
#Component({
selector: 'app-module',
templateUrl: './module.component.html',
styleUrls: ['./module.component.css'],
providers: [PHPAPIService]
})
export class ModuleComponent implements OnInit {
toastChanges = 0;
xForToastMSG = 1;
moduleTimer = [];
fileToUpload: File = null;
moduleExpandState = [];
constructor(public PHPAPIService:PHPAPIService, private toastrService: ToastrService, public dialog: MatDialog) {
}
ngOnInit() {
for(var i=0;i<1000;i++)
this.moduleExpandState[i] = false;
this.PHPAPIService.get("tprofile").subscribe(
(data) => this.PHPAPIService.profiles = data
);
this.PHPAPIService.get("ttimer").subscribe(
(data) => this.PHPAPIService.timers = data
);
this.PHPAPIService.get("tmodule").subscribe(
(data) => this.PHPAPIService.modules = data
);
const socket = socketIO(this.PHPAPIService.apiUrl);
socket.on('tmodule', (snapshot) => this.PHPAPIService.modules = snapshot);
socket.on('timeUpdate', (snapshot) => this.PHPAPIService.date = snapshot);
setTimeout(()=>{
for(var i=0; i< this.PHPAPIService.modules.length ;i++){
/*Konvertiert die einelenen Daten HH und MM in ein String HH:MM*/
this.moduleTimer[i] = this.PHPAPIService.modules[i].time_h + ":" + this.PHPAPIService.modules[i].time_m;
//console.log(this.localTimerVar[i].on);
}
},1200);
//socket.on('tmodule', () => this.showSuccess());
}
/* showSuccess(text) {
/* if(this.xForToastMSG == 1){
this.xForToastMSG = 0;*/
// this.toastrService.success(text,'',{
// positionClass: 'toast-bottom-right'
// });
/* this.toastChanges = 1;*/
// }
/* setTimeout(()=>{
this.toastChanges = 0;
this.xForToastMSG = 1;
},500);*/
//}*/
showWarning(text) {
this.toastrService.warning(text,'',{
positionClass: 'toast-bottom-right'
});
}
/* showDownload() {
this.toastrService.success('Datensicherung wird erstellt','',{
positionClass: 'toast-bottom-right'
});
}*/
/*NUR FÜR MEHERERE FILES*/
/*handleFileInput(files: FileList) {
// console.log("TEST");
this.fileToUpload = files.item(0);
this.uploadFileToActivity();
}
*/
uploadFileToActivity(files: FileList) {
this.fileToUpload = files.item(0);
console.log(files.item(0));
if(files.item(0).name.substring(0,6) === 'module'){
this.PHPAPIService.uploadBackupModule(files.item(0)).subscribe(data => {
// do something, if upload success
this.showSuccess('Import erfolgreich!');
console.log(data);
}, error => {
console.log(error);
});
}else{
this.showWarning('fehlerhafte Datei');
}
}
backupModule(m_id, m_name){
this.showSuccess('Datensicherung wird erstellt');
this.PHPAPIService.backupModule(m_id, m_name).subscribe(response => this.downLoadFile(response.text(), "application/plain", m_name));
}
downLoadFile(data: any, type: string, name) {
var blob = new Blob([data], { type: type});
var url = window.URL.createObjectURL(blob);
// var pwa = window.open(url);
var anchor = document.createElement("a");
anchor.setAttribute("type", "hidden"); // make it hidden if needed
anchor.download = "module_"+name+".sql";
anchor.href = url;
document.body.appendChild(anchor);
anchor.click();
anchor.remove();
/*if (!pwa || pwa.closed || typeof pwa.closed == 'undefined') {
alert( 'Please disable your Pop-up blocker and try again.');
}*/
}
showSuccessNoChanges() {
this.toastrService.warning('keine Änderungen','',{
positionClass: 'toast-bottom-right'
});
}
showSuccess(x){
console.log(this.PHPAPIService.modules[x].time_h);
if(this.PHPAPIService.modules[x].time_h != '' && this.PHPAPIService.modules[x].time_m != ''){
this.toastrService.success('Änderung gespeichert','',{
positionClass: 'toast-bottom-right'
});
}else{
this.toastrService.error('Bitte Zeit eintragen','',{
positionClass: 'toast-bottom-right'
});
}
if(x == "zeit verfügbar"){
this.toastrService.error('Zeit bereits verfügbar','Die eingetragene Zeit ist bereits in einem andern Modul verfügbar, bitte eine andere Uhrzeit eintragen.',{
positionClass: 'toast-bottom-right'
});
}
}
togglePanel(x){
this.moduleExpandState[x] = !this.moduleExpandState[x];
$('#nameInput-'+x+' ').toggleClass('inputEdit');
}
saveModule(mID, x){
if(this.PHPAPIService.modules[x]['0'] == false) this.PHPAPIService.modules[x]['0'] = "";
if(this.PHPAPIService.modules[x]['1'] == false) this.PHPAPIService.modules[x]['1'] = "";
if(this.PHPAPIService.modules[x]['2'] == false) this.PHPAPIService.modules[x]['2'] = "";
if(this.PHPAPIService.modules[x]['3'] == false) this.PHPAPIService.modules[x]['3'] = "";
if(this.PHPAPIService.modules[x]['4'] == false) this.PHPAPIService.modules[x]['4'] = "";
if(this.PHPAPIService.modules[x]['5'] == false) this.PHPAPIService.modules[x]['5'] = "";
if(this.PHPAPIService.modules[x]['6'] == false) this.PHPAPIService.modules[x]['6'] = "";
if(this.PHPAPIService.modules[x]['0'] == true) this.PHPAPIService.modules[x]['0'] = "checked";
if(this.PHPAPIService.modules[x]['1'] == true) this.PHPAPIService.modules[x]['1'] = "checked";
if(this.PHPAPIService.modules[x]['2'] == true) this.PHPAPIService.modules[x]['2'] = "checked";
if(this.PHPAPIService.modules[x]['3'] == true) this.PHPAPIService.modules[x]['3'] = "checked";
if(this.PHPAPIService.modules[x]['4'] == true) this.PHPAPIService.modules[x]['4'] = "checked";
if(this.PHPAPIService.modules[x]['5'] == true) this.PHPAPIService.modules[x]['5'] = "checked";
if(this.PHPAPIService.modules[x]['6'] == true) this.PHPAPIService.modules[x]['6'] = "checked";
/*checke ob gleiche Uhrzeiten verfügbar sind*/
/*for(var i = 0; i < this.PHPAPIService.modules.length+1; i++){
console.log(this.moduleTimer[x]);
console.log(this.PHPAPIService.modules[x].time_h+":"+this.PHPAPIService.modules[x].time_m);
if(this.PHPAPIService.modules[i].time_h+":"+this.PHPAPIService.modules[i].time_m == this.moduleTimer[x]){
this.showSuccess("zeit verfügbar");
return null;
}
}*/
/*Konvertiert den 19:45 String in 19 und 45*/
//console.log(this.PHPAPIService.modules[x]);
if(this.PHPAPIService.modules[x].m_active == false){
this.PHPAPIService.modules[x].m_active = "";
}
if(this.PHPAPIService.modules[x].m_active == true){
this.PHPAPIService.modules[x].m_active = "checked";
// this.PHPAPIService.saveModule(mID, this.PHPAPIService.modules[x]).subscribe();
}
if(this.moduleTimer[x] != ''){
this.PHPAPIService.modules[x].time_h = this.moduleTimer[x].split(":")[0];
this.PHPAPIService.modules[x].time_m = this.moduleTimer[x].split(":")[1];
}
if(this.PHPAPIService.modules[x].time_h != '' && this.PHPAPIService.modules[x].time_m != ''){
this.PHPAPIService.saveModule(mID, this.PHPAPIService.modules[x]).subscribe();
}
setTimeout(()=>{
// if(this.toastChanges != 1){
this.showSuccess(x);
// };
},200);
}
deleteModule(mID, x){
const dialogRef = this.dialog.open(DialogOverviewModule, {
width: '250px',
data: {name: this.PHPAPIService.modules[x].m_name}
});
dialogRef.afterClosed().subscribe(result => {
console.log(result);
if(result == true){
this.PHPAPIService.deleteModule(mID).subscribe();
}
});
//this.PHPAPIService.deleteModule(mID).subscribe();
// this.PHPAPIService.profiles[x] = null;
}
addModule(){
this.PHPAPIService.addModule().subscribe();
for(var i=0;i<1000;i++)
this.moduleExpandState[i] = false;
// this.PHPAPIService.profiles[x] = null;
}
}
#Component({
selector: 'dialog-overview-example-dialog',
templateUrl: 'dialog-overview-example-dialog.html',
})
export class DialogOverviewModule {
constructor(
public dialogRef: MatDialogRef<DialogOverviewModule>,
#Inject(MAT_DIALOG_DATA) public data: DialogData) {}
save = true;
onNoClick(): void {
this.dialogRef.close();
}
}
h1{
display: block;
margin: 0;
padding: 20px;
padding-left: 220px;
}
h4{
margin: auto 0px;
padding: 0;
font-weight: 200;
padding-right: 50px;
}
h2{
margin: 10px;
font-weight: 100;
}
header{
display: flex;
flex-direction: row;
justify-content: space-between;
margin: 0;
margin-left:200px;
padding-left: 20px;
padding-right: 20px;
background-color: #323741;
color: #D7E2F7;
}
input[type="file"] + label {
margin: 0;
padding: 0;
}
/*input[type="file"]:focus + label,
input[type="file"] + label:hover {
background-color: red;
}*/
input[type="file"]{
float: right;
margin: 20px;
width: 0.1px;
height: 0.1px;
opacity: 0;
overflow: hidden;
position: absolute;
z-index: -1;
}
.modSelect, .modSelect option{
font-size: 1.2em;
width: 250px !important;
}
input{
height: 30px;
outline: none;
border: none;
background: transparent;
font-size: 1.2em;
}
input:focus{
background: white;
outline: none;
border: solid 1px black;
}
input[type="checkbox"]{
margin: auto 0px;
margin-left: 10px;
width: 18px;
}
/deep/ .mat-expansion-panel-header{
padding-top: 10px !important;
padding-bottom: 10px !important;
margin-left:200px;
}
.row_expansion_column{
display: flex;
flex-wrap: nowrap;
flex-direction: row;
justify-content: center;
align-items: center;
flex-grow: 0;
text-align: center;
margin-left:200px;
}
.row_expansion_column select{
margin: 10px;
width: 100px;
}
.delBtn{
background-color: #ed1212;
border: 1px solid #ed1212;
font-size: 1.2em;
color: white;
}
.saveBtn{
background-color: green;
border: 1px solid green;
font-size: 1.2em;
color: white;
}
.exportBtn{
background-color: #707070FF;
border: 1px solid #707070FF;
font-size: 1.2em;
color: white;
}
.addBtn{
background-color: #707070FF;
border: 1px solid #707070FF;
float: right;
margin: 20px;
padding: 0 10px;
font-size: 1.2em;
color : white;
}
.importBtn{
background-color: #707070FF;
border: 1px solid #707070FF;
float: right;
margin: 20px;
padding: 0;
font-size: 1.2em;
color : white;
}
.fileBtn{
background-color: #707070FF;
border: 1px solid #707070FF;
float: right;
padding: 0px 20px;
font-size: 1em;
color : white;
line-height: 34px;
cursor: pointer;
}
.editBtn{
margin: 0 0 0 auto;
//background-color: #DADADAFF;
border: 1px solid #707070FF;
color : #707070FF;
padding: 2px 10px 2px 10px;
font-size: 1.2em;
}
input[type="text"]{
outline: none;
border: none;
background: transparent;
height: 30px;
font-size: 1.2em;
pointer-events: none;
}
input[type="text"]:hover{
cursor: default;
pointer-events: none;
}
input[type="text"].inputEdit:hover{
pointer-events: auto;
outline: none;
cursor: text;
border: 1px solid #707070FF;
}
input[type="text"].inputEdit{
background: white;
pointer-events: auto;
outline: none;
cursor: text;
border: 1px solid #707070FF;
}
img{
width: 120px;
position: absolute;
right: 20px;
bottom: 20px;
}
/deep/ .mat-slide-toggle.mat-warn.mat-checked:not(.mat-disabled) .mat-slide-toggle-thumb {
background-color: blue;
float: right;
}
/deep/ .mat-slide-toggle.mat-warn.mat-checked:not(.mat-disabled) .mat-slide-toggle-bar {
background-color: rgba(124, 172, 249,.5);
float: right;
}
/deep/ .mat-slide-toggle{
position: relative;
top: 15px;
padding-right: 10px;
margin-left: 20px;
}
/deep/ .mat-slide-toggle-bar {
height: 15px !important;
width: 40px !important;
}
/deep/ .mat-slide-toggle-thumb {
height: 25px !important;
width: 25px !important;
background-color: #ececec;
margin-left: -2px;
margin-top: -2px;
}
/deep/ .mat-slide-toggle.mat-checked .mat-slide-toggle-thumb-container {
transform: translate3d(23px,0,0) !important;
}
.seperateContainer{
padding-left: 20px;
display: inherit;
background-color: #f5f5f5;
}
#modAct{
margin-left: 20px;
}
#media only screen and (max-width: 600px) {
header h2{
padding-left: 20px;
}
.row_expansion_column{
margin-left:0px;
}
/deep/ .mat-expansion-panel-header{
margin-left:0px;
}
header{
margin-left:0px;
}
}
<header>
<h2>Module</h2>
<h4 [(ngModel)]="PHPAPIService.date" ngDefaultControl>
{{PHPAPIService.date | date:'HH:mm:ss dd.MM.yyyy'}}
</h4>
</header>
<mat-expansion-panel *ngFor="let module of PHPAPIService.modules; let x = index" [expanded]="moduleExpandState[module.m_id]"
[disabled]="true">
<mat-expansion-panel-header>
<input type="text" name="" id="{{ 'nameInput-' + module.m_id }}" placeholder="Bezeichnung"
required [(ngModel)]="module.m_name" [value]="module.m_name"/>
<button mat-button class="editBtn" (click)="togglePanel(module.m_id)">Bearbeiten</button>
</mat-expansion-panel-header>
<div class="row_expansion">
<div class=row_expansion_column>
<h3>Profil</h3>
<select class="modSelect" required [(ngModel)]="module.m_profile">
<option [value]="profile.profileID" *ngFor="let profile of PHPAPIService.profiles">{{profile.Name}}</option>
</select>
<h3>schaltetzeit</h3>
<input type="time" name="" required [(ngModel)]="moduleTimer[x]" value="{{module.time_h}}:{{module.time_m}}"/>
<div class="seperateContainer">
<div class="dayCheckBox"><h3>MO</h3>
<input type="checkbox" required [(ngModel)]="module['1']" checked="{{module['1']}}"/> <!-- timer.1 funktiniert nicht, DB hat leider 0 - 7 als spalten -->
</div>
<div class="dayCheckBox"><h3>DI</h3>
<input type="checkbox" required [(ngModel)]="module['2']" checked="{{module['2']}}"/></div>
<div class="dayCheckBox"><h3>MI</h3>
<input type="checkbox" required [(ngModel)]="module['3']" checked="{{module['3']}}"/></div>
<div class="dayCheckBox"><h3>DO</h3>
<input type="checkbox" required [(ngModel)]="module['4']" checked="{{module['4']}}"/></div>
<div class="dayCheckBox"><h3>FR</h3>
<input type="checkbox" required [(ngModel)]="module['5']" checked="{{module['5']}}"/></div>
<div class="dayCheckBox"><h3>SA</h3>
<input type="checkbox" required [(ngModel)]="module['6']" checked="{{module['6']}}"/></div>
<div class="dayCheckBox"><h3>SO</h3>
<input type="checkbox" required [(ngModel)]="module['0']" checked="{{module['0']}}"/></div>
</div>
<h3 id="modAct">Active</h3>
<mat-slide-toggle [(ngModel)]="module.m_active" color="warn"
[checked]="module.m_active"></mat-slide-toggle>
</div>
</div>
<mat-action-row>
<button mat-button class="exportBtn" (click)="backupModule(module.m_id, module.m_name)">Export</button>
<button mat-button class="delBtn" (click)="deleteModule(module.m_id, x)">Löschen</button>
<button mat-button class="saveBtn" (click)="saveModule(module.m_id, x)">Speichern</button>
</mat-action-row>
</mat-expansion-panel>
<button mat-button class="addBtn" (click)="addModule()">neues Modul erstellen</button>
<!-- <div class="form-group"> -->
<!-- <button mat-button class="fileBtn"> <label for="file">Datei auswählen</label></button> -->
<input type="file"
class="inputfile"
enctype="multipart/form-data"
id="file"
name="filetoupload"
(change)="uploadFileToActivity($event.target.files)" >
<button mat-button class="importBtn" ><label for="file"class="fileBtn">Import</label></button>
<!-- <label for="file"class="fileBtn">Import</label> -->
<!-- </div> -->
You don't need checked="{{module['1']}}", data binding is handling that. So please remove below code from your check boxes and it would work.
checked="{{module['1']}}" //Remove this
Let me know if you need full code, I can share.
Check running code at below repository.
https://stackblitz.com/github/nitin1982/StackOverFlowProblems/tree/master/CheckBoxIssue?file=src%2Fapp%2Fapp.component.html

Aligning + and - for shopping basket incrementer

I want to have my code like in this image
It is a simple shopping basket incrementer. I put the border around for 1 but i'm not sure how to align + and - and put the border around. I searched for many incrementers but I couldn't find one like in the image.
Someone please give me a help.
$(function() {
$(".numbers-row").append('<div class="inc button">+</div><div class="dec button">-</div>');
$(".button").on("click", function() {
var $button = $(this);
var oldValue = $button.parent().find("input").val();
if ($button.text() == "+") {
var newVal = parseFloat(oldValue) + 1;
} else {
// Don't allow decrementing below zero
if (oldValue > 0) {
var newVal = parseFloat(oldValue) - 1;
} else {
newVal = 0;
}
}
$button.parent().find("input").val(newVal);
});
});
input[type=text] {
float: left;
width: 40px;
font: bold 20px Helvetica, sans-serif;
padding: 3px 0 0 0;
text-align: center;
}
<!DOCTYPE html>
<html>
<head>
<title></title>
<script src="https://ajax.googleapis.com/ajax/libs/jquery/1.12.4/jquery.min.js"></script>
</head>
<body>
<form method="post" action="#">
<div class="numbers-row">
<input type="text" id="incrementer" value="1">
</div>
</form>
</body>
</html>
Forget JavaScript. Just use a number input in the first place.
input[type=number] {
float: left;
width: 40px;
font: bold 20px Helvetica, sans-serif;
padding: 3px 0 0 0;
text-align: center;
}
<form method="post" action="#">
<div class="numbers-row">
<input type="number" id="incrementer" min="0" value="1">
</div>
</form>
You have to just add some icons in place of + and minus sign and there you go.
$(function() {
$(".numbers-row").append('<div class="inc button">+</div><div class="dec button">-</div>');
$(".button").on("click", function() {
var $button = $(this);
var oldValue = $button.parent().find("input").val();
if ($button.text() == "+") {
var newVal = parseFloat(oldValue) + 1;
} else {
// Don't allow decrementing below zero
if (oldValue > 0) {
var newVal = parseFloat(oldValue) - 1;
} else {
newVal = 0;
}
}
$button.parent().find("input").val(newVal);
});
});
input[type=text] {
float: left;
width: 40px;
font: bold 20px Helvetica, sans-serif;
padding: 3px 0 0 0;
text-align: center;
position: absolute;
border-bottom-left-radius: 3px;
border-top-left-radius: 3px;
border: 1px solid #C9C6C6;
}
.inc.button {
display: inline-block;
position: relative;
border: 1px solid #C9C6C6;
left: 41px;
height: 13px;
top: 2px;
border-top-right-radius: 3px;
}
.dec.button {
display: inline-block;
position: relative;
border: 1px solid #C9C6C6;
left: 30px;
height: 7px;
top: 16px;
width: 9px;
border-bottom-right-radius: 3px;
padding: 0px 0px 5px 0px;
}
<!DOCTYPE html>
<html>
<head>
<title></title>
<script src="https://ajax.googleapis.com/ajax/libs/jquery/1.12.4/jquery.min.js"></script>
</head>
<body>
<form method="post" action="#">
<div class="numbers-row">
<input type="text" id="incrementer" value="1">
</div>
</form>
</body>
</html>
try below code:
$(function() {
$(".numbers-row").append('<div class="inc button">+</div><div class="dec button">-</div>');
$(".button").on("click", function() {
var $button = $(this);
var oldValue = $button.parent().find("input").val();
if ($button.text() == "+") {
var newVal = parseFloat(oldValue) + 1;
} else {
// Don't allow decrementing below zero
if (oldValue > 0) {
var newVal = parseFloat(oldValue) - 1;
} else {
newVal = 0;
}
}
$button.parent().find("input").val(newVal);
});
});
input[type="text"] {
float: left;
font: bold 20px Helvetica,sans-serif;
padding: 5px 11px;
text-align: left;
width: 50px;
}
.inc.button {
border-bottom: 1px solid #ccc;
border-left: 1px solid #ccc;
left: 57px;
padding: 0 6px 0 8px;
position: absolute;
}
.dec.button {
border-left: 1px solid #ccc;
left: 57px;
padding: 0 10px;
position: absolute;
top: 25px;
}
<!DOCTYPE html>
<html>
<head>
<title></title>
<script src="https://ajax.googleapis.com/ajax/libs/jquery/1.12.4/jquery.min.js"></script>
</head>
<body>
<form method="post" action="#">
<div class="numbers-row">
<input type="text" id="incrementer" value="1">
</div>
</form>
</body>
</html>

Extract YouTube Thumbnails From Videos Within A Playlist & Display On Webpage

My webpage plays a YouTube playlist and displays the track name at the bottom (spent most of the day on that), I figured it would be great to have a thumbnail of the specific video playing from the playlist displayed at the bottom next to the track title. I understand how to do this for a specific video, but how would I implement this for a playlist of videos? It is important that the image is refreshed for each new song that is played.
Here is a jsfiddle with my current work: https://jsfiddle.net/ruumL5s7/
ALSO, I am having issues with vertically aligning the video and chat divs between the top and bottom bar. I'm also running into issues with the bottom bar not staying a 'full' bar when the screen is resized (the different divs all break apart), I've tried a couple ideas to prevent that, with no avail. So any assistance is greatly appreciated!
Thank you!
HTML:
<!DOCTYPE html>
<html>
<head>
<title>Chat</title>
<link rel="stylesheet" href="main.css">
</head>
<div class="all-content">
<body>
<div class="header-bar">
<div class="bar">
<img src="C:\Users\jlewa\Desktop\assets\affinity_fm_only_letters.png" class="top-logo" style="float: left;">
<ul class="standard-nav" style="float: left;">
<li>Home</li>
<li>Lyrics Hub</li>
<li>Affinity LIVE</li>
<li>Merchandise</li>
</ul>
</div>
<div class="dropshadow"></div>
</div>
<div class="container-middle-third">
<div class="youtube-video" style="float: left;">
<div class="DJ-text">Affinity FM DJ Room</div>
<div class="DJ-underline"></div>
<div id="player" style="width: 1280px; height: 720px;"></div></div>
</div>
<div class="chat" style="float: left;">
<div class="Chat-text">Chat</div>
<div class="Chat-underline"></div>
<input type="text" class="chat-name" placeholder="Chat">
<div class="info-rect">Info</div>
<div class="chat-messages"></div>
<textarea placeholder="Join the conversation..."></textarea>
<div class="chat-status">Status: <span>Idle</span></div>
</div>
<div class="bottom-bar">
<div class="thumbnail" id="thumbnail" style="float: left"></div>
<div class="title-bar" style="float: left;">
<div class="title" id="title"></div>
<div class="dj-playing">Affinity FM is playing</div>
<div class="progress-background">
<div id="progress-bar" class="progress-bar"></div>
</div>
</div>
<div class="subscribe" style="float: left;">
<div class="g-ytsubscribe" data-channel="SAMusicPlaylist" data-layout="full" data-theme="dark" data-count="default"></div>
</div>
</div>
<script src="http://127.0.0.1:8080/socket.io/socket.io.js"></script>
<script src="https://apis.google.com/js/platform.js"></script>
<script>
(function() {
var getNode = function(s) {
return document.querySelector(s);
},
// Get required nodes
status = getNode('.chat-status span'),
messages = getNode('.chat-messages'),
textarea = getNode('.chat textarea'),
chatName = getNode('.chat-name'),
statusDefault = status.textContent,
setStatus = function(s){
status.textContent = s;
if(s !== statusDefault){
var delay = setTimeout(function(){
setStatus(statusDefault);
clearInterval(delay);
}, 3000);
}
};
//try connection
try{
var socket = io.connect('http://127.0.0.1:8080');
} catch(e){
//Set status to warn user
}
if(socket !== undefined){
//Listen for output
socket.on('output', function(data){
if(data.length){
//Loop through results
for(var x = 0; x < data.length; x = x + 1){
var message = document.createElement('div');
message.setAttribute('class', 'chat-message');
message.textContent = ': ' + data[x].message;
var name=document.createElement('span');
name.setAttribute('class', 'userName');
name.textContent = data[x].name;
message.insertBefore(name, message.firstChild);
//Append
messages.appendChild(message);
messages.insertBefore(message, messages.firstChild);
}
}
});
//Listen for a status
socket.on('status', function(data){
setStatus((typeof data === 'object') ? data.message : data);
if(data.clear === true){
textarea.value = '';
}
});
//Listen for keydown
textarea.addEventListener('keydown', function(event){
var self = this,
name = chatName.value;
if(event.which === 13 && event.shiftKey === false){
socket.emit('input', {
name: name,
message: self.value
});
}
});
}
})();
</script>
<script>
var time_total;
var timeout_setter;
var player;
var tag = document.createElement("script");//This code loads the IFrame Player API code asynchronously
tag.src = "https://www.youtube.com/iframe_api";
var firstScriptTag = document.getElementsByTagName("script")[0];
firstScriptTag.parentNode.insertBefore(tag, firstScriptTag);
//This function creates an <iframe> (and YouTube player) OR uses the iframe if it exists at the "player" element after the API code downloads
function onYouTubeIframeAPIReady()
{
player = new YT.Player("player",
{
height: "853",
width: "480",
/* videoId: "GGmxVDXM5X2UxaP9PvWQ4Z171DXyGcq", */
playerVars: {
listType:'playlist',
list: 'PL_GGmxVDXM5X2UxaP9PvWQ4Z171DXyGcq',
controls: '0',
html5: '1',
cc_load_policy: '0',
disablekb: '1',
iv_load_policy: '3',
modestbranding: '1',
showinfo: '0',
rel: '0',
},
events:
{
"onReady": onPlayerReady,
"onStateChange": onPlayerStateChange
}
});
}
var num = (1 + Math.floor(Math.random() * 10));
//The API will call this function when the video player is ready
function onPlayerReady(event)
{
event.target.playVideo();
time_total = convert_to_mins_and_secs(player.getDuration(), 1);
loopy();
player.addEventListener('onStateChange', 'onPlayerStateChange');
player.setShuffle( {
'shufflePlaylist': 1
} );
}
function loopy()
{
var current_time = convert_to_mins_and_secs(player.getCurrentTime(), 0);
document.getElementById("progress-bar").style.width = (player.getCurrentTime()/player.getDuration())*100+"%";
console.log( current_time + " / " + time_total);
timeout_setter = setTimeout(loopy, 300);
}
function convert_to_mins_and_secs(seconds, minus1)
{
var mins = (seconds>=60) ?Math.round(seconds/60):0;
var secs = (seconds%60!=0) ?Math.round(seconds%60):0;
var secs = (minus1==true) ?(secs-1):secs; //Youtube always displays 1 sec less than its duration time!!! Then we have to set minus1 flag to true for converting player.getDuration()
var time = mins + ":" + ((secs<10)?"0"+secs:secs);
return time;
}
// 5. The API calls this function when the player's state changes
function onPlayerStateChange(event)
{
if (event.data == YT.PlayerState.ENDED)
{
console.log("END!");
clearTimeout(timeout_setter);
document.getElementById("progress-bar").style.cssText = "transition: none;";
}
else if (event.data == YT.PlayerState.PLAYING)
{
console.log("PLAYING");
loopy();
document.getElementById("progress-bar").style.cssText = "transition: all 300ms linear 0s;";
console.log(player.getPlayerState());
if (player.getPlayerState() == 1) {
document.getElementById( "title" ).innerText = player.getVideoData().title;
}
}
else if (event.data == YT.PlayerState.PAUSED)
{
event.target.playVideo();
console.log("PLAUSED");
}
else
{
console.log(event.data);
}
}
</script>
</body>
</div>
</html>
CSS:
body {
background-color: #0f0f17;
margin: 0px;
width: 100%;
}
.container-middle-third{
margin-top: 20px;
margin-left: 70px;
}
body,
textarea,
input {
font: 13px "Raleway", sans-serif;
color: #ffffff;
}
.all-content{
width: 1920px;
display: block;
margin-left: auto;
margin-right: auto;
}
.bar{
height: 90px;
width: 1920px;
background-color: #15151d;
}
.top-logo{
max-height: 100%;
max-width: 100%;
margin-left: 4%
}
/*li{
display: inline;
padding-right: 20px;
}
.standard-nav {
list-style: none;
padding: 0;
text-transform: uppercase;
line-height: 13px;
font-weight: 700;
margin-left: 63%;
max-height: 100%;
} */
.DJ-text{
font-weight: 700;
/*position:relative;*/
text-transform: uppercase;
}
.Chat-text{
font-weight: 700;
text-transform: uppercase;
}
.DJ-underline{
width: 1280px;
height: 1px;
position:relative;top:10px;
background-color: #3f3f45;
margin: 0px 0px 40px;
}
.Chat-underline{
width: 100%;
position:relative;
/*left:-140px;*/
float:right;
height: 1px;
position:relative;top:10px;
background-color: #3f3f45;
margin: 0px 0px 40px;
}
.youtube-video{
position: relative;
}
.transparent-layer{
width: 850px;
height: 477px;
pointer-events: none;
background-color: #ffffff;
}
.ad{
width: 728px;
height: 90px;
border: 1px solid #000000;
margin-left: 11px;
margin-top: 20px;
}
.chat {
position: relative;
min-width: 400px;
margin: 0px 0px 0px 112px;
}
.chat-messages,
.chat-textarea,
.chat-name {
border: 1px solid #1a1a23;
background-color: #1a1a23;
}
.userName{
font-weight: 700;
color: #079ce0;
}
.chat-messages {
width:380px;
height:586px;
overflow-y:scroll;
padding:10px;
}
.chat-message {
margin-bottom:10px;
}
.info-rect{
height: 40px;
width: 180px;
padding:10px;
max-width: 100%;
margin:0;
border:0;
display: flex;
align-items: center;
justify-content: center;
font-weight: 700;
text-transform: uppercase;
background-color: #15151d
}
.chat-name{
height: 40px;
max-width: 100%;
width: 180px;
padding:10px;
border:0;
margin:0;
font-weight: 700;
text-transform: uppercase;
float:left;
text-align: center;
}
.chat textarea {
width:380px;
padding:10px;
margin:0;
border-top:0;
max-width:100%;
border-top: 1px solid #0f0f17;
border-bottom: 1px solid #1a1a23;
border-right: 1px solid #1a1a23;
border-left: 1px solid #1a1a23;
background-color: #1a1a23;
}
.chat-status {
color: #bbb;
opacity: 0;
background-color: #0f0f17;
}
.info-rect,
.chat textarea,
.chat-name {
max-width: 100%;
}
.bottom-bar{
position: absolute;
bottom: 0;
display:table;
}
.thumbnail{
width: 90px;
height: 80px;
opacity: 0.2;
background-color: #ffffff;
}
.title-bar{
width:1372px;
height: 80px;
background-color: #1a1a23;
}
.title{
font-weight: 700;
text-transform: uppercase;
margin-left: 30px;
margin-top: 25px;
}
.dj-playing{
margin-left: 30px;
}
.progress-background{
width: 1372px;
height: 3px;
background-color: #313139;
position: fixed;
bottom: 0;
}
.progress-bar{
height: 3px;
width: 0px;
transition: all 300ms linear;
background-color: #fa1d57;
bottom: 0;
}
.subscribe{
width: 458px;
height: 80px;
background-color: #15151d;
display:table-cell;
}
.g-ytsubscribe{
width: 450px;
display: block;
margin-left: auto;
margin-right: auto;
}
This time you have to use a key with the Youtube API 3.
You can do that with either js or Php.
Php
<?
$api_key = "AIzaSyDRfgPj9a2vnckVkSGoKktNfrozbMvjkdw";
$play_list_id = "PLcV3JzAz3r32-on4upkyAv0VtvYXAl-Nz";
$url = "https://www.googleapis.com/youtube/v3/playlists?part=snippet&id=" . $play_list_id;
$ch = curl_init();
curl_setopt($ch, CURLOPT_URL, $url);
curl_setopt($ch, CURLOPT_TIMEOUT, 30);
curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1);
curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, 0);
$response_raw = curl_exec($ch);
$response = json_decode($response_raw);
echo "default image :" . $response->items[0]->snippet->thumbnails->default->url;
echo "<br />\n<br />\n";
echo "medium image :" . $response->items[0]->snippet->thumbnails->medium->url;
echo "<br />\n<br />\n";
echo "maxres image :" . $response->items[0]->snippet->thumbnails->maxres->url;
echo "<br />\n<br />\n";
echo print_r($response, 1);
?>
The most important thing in the script is the url with the query parameters. Just remember to replace the $api_key, and the $play_list_id with your own.
Now with javascript, it's almost the same thing.
JS
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.2.0/jquery.min.js"></script>
<script>
function make_request()
{
var response = "";
var response1 = "";
var api_key = "AIzaSyBaS4_vwohJW7Ndb9EkjSqsoD75O4f4jXI";
var play_list_id = "PLcV3JzAz3r32-on4upkyAv0VtvYXAl-Nz";
var url = "https://www.googleapis.com/youtube/v3/playlists?part=snippet&id=" + play_list_id + "&key=" + api_key;
$.ajax
({
url: url,
dataType: "json",
type: "get",
async: false,
success: function(data)
{
response = JSON.stringify(data);
response1 = data;
}
});
alert(response1.items[0].snippet.thumbnails.default.url);
console.log(response1.items[0].snippet.thumbnails.default.url);
console.log(response);
}
function init()
{
gapi.client.setApiKey("AIzaSyBaS4_vwohJW7Ndb9EkjSqsoD75O4f4jXI");
gapi.client.load('youtube', 'v3').then(make_request);
}
</script>
<script src="https://apis.google.com/js/client.js?onload=init"></script>
Take a look at those in action :
http://lespointscom.com/a/misc/demo/2016_06_21/curl_any.php
http://lespointscom.com/a/misc/demo/2016_06_21/curl_any.zip
http://lespointscom.com/a/misc/demo/2016_06_21/gapi_1.html
But remember: when you do it with Php, you have to create a Google server key. When you do it with js, guess what? You do it with a browser key. But most important, remember to enable Youtube data api 3 in developers console!
Reference to get a KEY :
https://developers.google.com/api-client-library/javascript/start/start-js#choose-google-services

Sync Embedded YouTube Video Time Stamp to Custom Progress Bar

I am stuck on a portion of a project I have been working on today. The task is to sync the timestamp information from the embedded youtube video and display a custom progress bar matching the length of the song at the bottom of the page. Here is the layout so far:
So basically, how do I pull constant timestamps to update the progress and how do I animate the bar to complete 100% matching the end of the video.
I have already disabled the user's ability to scrobble the embedded youtube video. NOTE: the user should not be able to change the time of the youtube video using the custom progress bar either (it is just there for visual queue)!
Please let me know if you need more clarification. HTML and CSS are below. Thank you!! :)
HTML >>>
<!DOCTYPE html>
<html>
<head>
<title>Chat</title>
<link rel="stylesheet" href="main.css">
</head>
<body>
<div class="header-bar">
<div class="bar"></div>
<div class="dropshadow"></div>
</div>
<div class="container-middle-third">
<div class="youtube-video" style="float: left;">
<div class="DJ-text">Affinity FM DJ Room</div>
<div class="DJ-underline"></div>
<div class="transparent-layer"> <iframe width="850px" height="477px" src="https://www.youtube.com/embed/2GvIq2SpVFM?autoplay=0&showinfo=0&controls=0" frameborder="0" allowfullscreen></iframe></div>
</div>
<div class="chat" style="float: left;">
<div class="Chat-text">Chat</div>
<div class="Chat-underline"></div>
<input type="text" class="chat-name" placeholder="Chat">
<div class="info-rect">Info</div>
<div class="chat-messages"></div>
<textarea placeholder="Join the conversation..."></textarea>
<div class="chat-status">Status: <span>Idle</span></div>
</div>
</div>
<div class="bottom-bar">
<div class="thumbnail" style="float: left"></div>
<div class="title-bar" style="float: left;">
<div class="song-name">Finding Hope - Let Go (feat. Deverano)</div>
<div class="dj-playing">Affinity FM is playing</div>
<div class="progress-background"></div>
<div class="progress-bar"></div>
</div>
<div class="subscribe" style="float: left;"></div>
</div>
<script src="http://127.0.0.1:8080/socket.io/socket.io.js"></script>
<script>
(function() {
var getNode = function(s) {
return document.querySelector(s);
},
// Get required nodes
status = getNode('.chat-status span'),
messages = getNode('.chat-messages'),
textarea = getNode('.chat textarea'),
chatName = getNode('.chat-name'),
statusDefault = status.textContent,
setStatus = function(s){
status.textContent = s;
if(s !== statusDefault){
var delay = setTimeout(function(){
setStatus(statusDefault);
clearInterval(delay);
}, 3000);
}
};
//try connection
try{
var socket = io.connect('http://127.0.0.1:8080');
} catch(e){
//Set status to warn user
}
if(socket !== undefined){
//Listen for output
socket.on('output', function(data){
if(data.length){
//Loop through results
for(var x = 0; x < data.length; x = x + 1){
var message = document.createElement('div');
message.setAttribute('class', 'chat-message');
message.textContent = ': ' + data[x].message;
var name=document.createElement('span');
name.setAttribute('class', 'userName');
name.textContent = data[x].name;
message.insertBefore(name, message.firstChild);
//Append
messages.appendChild(message);
messages.insertBefore(message, messages.firstChild);
}
}
});
//Listen for a status
socket.on('status', function(data){
setStatus((typeof data === 'object') ? data.message : data);
if(data.clear === true){
textarea.value = '';
}
});
//Listen for keydown
textarea.addEventListener('keydown', function(event){
var self = this,
name = chatName.value;
if(event.which === 13 && event.shiftKey === false){
socket.emit('input', {
name: name,
message: self.value
});
}
});
}
})();
</script>
</body>
</html>
and CSS >>>
body {
background-color: #0f0f17;
margin: 0px;
width: 100%;
}
.container-middle-third{
margin-top: 20px;
margin-left: 155px;
}
body,
textarea,
input {
font: 13px "Raleway", sans-serif;
color: #ffffff;
}
.bar{
height: 80px;
width: 100%;
background-color: #15151d;
}
.DJ-text{
font-weight: 700;
/*position:relative;*/
text-transform: uppercase;
}
.Chat-text{
font-weight: 700;
text-transform: uppercase;
}
.DJ-underline{
width: 850px;
height: 1px;
position:relative;top:10px;
background-color: #3f3f45;
margin: 0px 0px 40px;
}
.Chat-underline{
width: 100%;
position:relative;
/*left:-140px;*/
float:right;
height: 1px;
position:relative;top:10px;
background-color: #3f3f45;
margin: 0px 0px 40px;
}
.transparent-layer{
width: 850px;
height: 477px;
pointer-events: none;
background-color: #ffffff;
}
.ad{
width: 728px;
height: 90px;
border: 1px solid #000000;
margin-left: 11px;
margin-top: 20px;
}
.chat {
min-width: 400px;
margin: 0px 0px 0px 135px;
}
.chat-messages,
.chat-textarea,
.chat-name {
border: 1px solid #1a1a23;
background-color: #1a1a23;
}
.userName{
font-weight: 700;
color: #079ce0;
}
.chat-messages {
width:380px;
height:400px;
overflow-y:scroll;
padding:10px;
}
.chat-message {
margin-bottom:10px;
}
.info-rect{
height: 40px;
width: 180px;
padding:10px;
max-width: 100%;
margin:0;
border:0;
display: flex;
align-items: center;
justify-content: center;
font-weight: 700;
text-transform: uppercase;
background-color: #15151d
}
.chat-name{
height: 40px;
max-width: 100%;
width: 180px;
padding:10px;
border:0;
margin:0;
font-weight: 700;
text-transform: uppercase;
float:left;
text-align: center;
}
.chat textarea {
width:380px;
padding:10px;
margin:0;
border-top:0;
max-width:100%;
border-top: 1px solid #0f0f17;
border-bottom: 1px solid #1a1a23;
border-right: 1px solid #1a1a23;
border-left: 1px solid #1a1a23;
background-color: #1a1a23;
}
.chat-status {
color: #bbb;
opacity: 0;
background-color: #0f0f17;
}
.info-rect,
.chat textarea,
.chat-name {
max-width: 100%;
}
.bottom-bar{
position: fixed;
bottom: 0;
width: 100%;
}
.thumbnail{
width: 80px;
height: 80px;
background-color: #ffffff
}
.title-bar{
width:1000px;
height: 80px;
background-color: #1a1a23;
}
.song-name{
font-weight: 700;
text-transform: uppercase;
margin-left: 30px;
margin-top: 25px;
}
.dj-playing{
margin-left: 30px;
}
.progress-background{
width: 1000px;
height: 4px;
background-color: #313139;
position: fixed;
bottom: 0;
}
.progress-bar{
width: 400px;
height: 4px;
background-color: #fa1d57;
position: fixed;
bottom: 0;
}
.subscribe{
width: 520px;
height: 80px;
background-color: #15151d;
}
Love your questions!
switch the iframe with a div with id="player" (any name you want, it could be "my_own_player" or "XYZ_player"...)
Then now you're all set to convert your iframe player into a Youtube player object so that you can accomplish what you desire, using the "IFrame player API".
Make sure you style your div the same way you wanted your iframe.
Just add the following script :
//This function creates an <iframe> (and YouTube player)
function onYouTubeIframeAPIReady()
{
player = new YT.Player("player",
{
height: "850",
width: "477",
videoId: "2GvIq2SpVFM",
events:
{
"onReady": onPlayerReady,
"onStateChange": onPlayerStateChange
}
});
}
Replace videoId with your video's ID.
Replace height with your video's height.
Replace width with your video's width.
NOW, to get the "Video Time Stamps" like you say, in order to make the progress bar is easy. The player object has two methods that will do that:
getCurrentTime()
getDuration()
getDuration is the total time of the video in seconds. While getCurrentTime is the time where the video has played up to. Divide
getCurrentTime by getDuration and you'll get a ratio for the progress bar. Multiply it by 100 and you get the percentage you're looking for:
(player.getCurrentTime()/player.getDuration())*100;
That's it! Once you got a percentage that represents getCurrentTime / getDuration, you don't need anything else for an html progress bar. Just style that html bar element's width to that percentage. Just make sure that red "bar" has a background (another div) that's easily recognized as the outward limit for the progress bar. Or just put it inside another div that's visible on the page like so :
<div id="progress" style="width: 800px; height: 10px; border: 1px solid #fff;">
<div id="bar" style="width: 1px; height: 10px; background: #f00;"></div>
</div>
Please, just try out your modified HTML:
<!DOCTYPE html>
<html>
<head>
<title>Chat</title>
<link rel="stylesheet" href="main.css">
</head>
<body>
<div class="header-bar">
<div class="bar"></div>
<div class="dropshadow"></div>
</div>
<div class="container-middle-third">
<div class="youtube-video" style="float: left;">
<div class="DJ-text">Affinity FM DJ Room</div>
<div class="DJ-underline"></div>
<div class="transparent-layer"> <div id="player" style="width: 850px; height: 477px;"></div></div>
</div>
<div class="chat" style="float: left;">
<div class="Chat-text">Chat</div>
<div class="Chat-underline"></div>
<input type="text" class="chat-name" placeholder="Chat">
<div class="info-rect">Info</div>
<div class="chat-messages"></div>
<textarea placeholder="Join the conversation..."></textarea>
<div class="chat-status">Status: <span>Idle</span></div>
</div>
</div>
<div class="bottom-bar">
<div class="thumbnail" style="float: left"></div>
<div class="title-bar" style="float: left;">
<div class="song-name">Finding Hope - Let Go (feat. Deverano)</div>
<div class="dj-playing">Affinity FM is playing</div>
<div class="progress-background">
<div id="progress-bar" class="progress-bar"></div>
</div>
</div>
<div class="subscribe" style="float: left;"></div>
</div>
<script src="http://127.0.0.1:8080/socket.io/socket.io.js"></script>
<script>
(function() {
var getNode = function(s) {
return document.querySelector(s);
},
// Get required nodes
status = getNode('.chat-status span'),
messages = getNode('.chat-messages'),
textarea = getNode('.chat textarea'),
chatName = getNode('.chat-name'),
statusDefault = status.textContent,
setStatus = function(s){
status.textContent = s;
if(s !== statusDefault){
var delay = setTimeout(function(){
setStatus(statusDefault);
clearInterval(delay);
}, 3000);
}
};
//try connection
try{
var socket = io.connect('http://127.0.0.1:8080');
} catch(e){
//Set status to warn user
}
if(socket !== undefined){
//Listen for output
socket.on('output', function(data){
if(data.length){
//Loop through results
for(var x = 0; x < data.length; x = x + 1){
var message = document.createElement('div');
message.setAttribute('class', 'chat-message');
message.textContent = ': ' + data[x].message;
var name=document.createElement('span');
name.setAttribute('class', 'userName');
name.textContent = data[x].name;
message.insertBefore(name, message.firstChild);
//Append
messages.appendChild(message);
messages.insertBefore(message, messages.firstChild);
}
}
});
//Listen for a status
socket.on('status', function(data){
setStatus((typeof data === 'object') ? data.message : data);
if(data.clear === true){
textarea.value = '';
}
});
//Listen for keydown
textarea.addEventListener('keydown', function(event){
var self = this,
name = chatName.value;
if(event.which === 13 && event.shiftKey === false){
socket.emit('input', {
name: name,
message: self.value
});
}
});
}
})();
</script>
<script>
var time_total;
var timeout_setter;
var player;
var tag = document.createElement("script");//This code loads the IFrame Player API code asynchronously
tag.src = "https://www.youtube.com/iframe_api";
var firstScriptTag = document.getElementsByTagName("script")[0];
firstScriptTag.parentNode.insertBefore(tag, firstScriptTag);
//This function creates an <iframe> (and YouTube player) OR uses the iframe if it exists at the "player" element after the API code downloads
function onYouTubeIframeAPIReady()
{
player = new YT.Player("player",
{
height: "850",
width: "477",
videoId: "2GvIq2SpVFM",
events:
{
"onReady": onPlayerReady,
"onStateChange": onPlayerStateChange
}
});
}
//The API will call this function when the video player is ready
function onPlayerReady(event)
{
event.target.playVideo();
time_total = convert_to_mins_and_secs(player.getDuration(), 1);
loopy();
}
function loopy()
{
var current_time = convert_to_mins_and_secs(player.getCurrentTime(), 0);
document.getElementById("progress-bar").style.width = (player.getCurrentTime()/player.getDuration())*100+"%";
console.log( current_time + " / " + time_total);
timeout_setter = setTimeout(loopy, 1000);
}
function convert_to_mins_and_secs(seconds, minus1)
{
var mins = (seconds>=60) ?Math.round(seconds/60):0;
var secs = (seconds%60!=0) ?Math.round(seconds%60):0;
var secs = (minus1==true) ?(secs-1):secs; //Youtube always displays 1 sec less than its duration time!!! Then we have to set minus1 flag to true for converting player.getDuration()
var time = mins + ":" + ((secs<10)?"0"+secs:secs);
return time;
}
// 5. The API calls this function when the player's state changes
function onPlayerStateChange(event)
{
if (event.data == YT.PlayerState.ENDED)
{
console.log("END!");
clearTimeout(timeout_setter);
}
else
{
console.log(event.data);
}
}
</script>
</body>
</html>
With your CSS:
body {
background-color: #0f0f17;
margin: 0px;
width: 100%;
}
.container-middle-third{
margin-top: 20px;
margin-left: 155px;
}
body,
textarea,
input {
font: 13px "Raleway", sans-serif;
color: #ffffff;
}
.bar{
height: 80px;
width: 100%;
background-color: #15151d;
}
.DJ-text{
font-weight: 700;
/*position:relative;*/
text-transform: uppercase;
}
.Chat-text{
font-weight: 700;
text-transform: uppercase;
}
.DJ-underline{
width: 850px;
height: 1px;
position:relative;top:10px;
background-color: #3f3f45;
margin: 0px 0px 40px;
}
.Chat-underline{
width: 100%;
position:relative;
/*left:-140px;*/
float:right;
height: 1px;
position:relative;top:10px;
background-color: #3f3f45;
margin: 0px 0px 40px;
}
.transparent-layer{
width: 850px;
height: 477px;
pointer-events: none;
background-color: #ffffff;
}
.ad{
width: 728px;
height: 90px;
border: 1px solid #000000;
margin-left: 11px;
margin-top: 20px;
}
.chat {
min-width: 400px;
margin: 0px 0px 0px 135px;
}
.chat-messages,
.chat-textarea,
.chat-name {
border: 1px solid #1a1a23;
background-color: #1a1a23;
}
.userName{
font-weight: 700;
color: #079ce0;
}
.chat-messages {
width:380px;
height:400px;
overflow-y:scroll;
padding:10px;
}
.chat-message {
margin-bottom:10px;
}
.info-rect{
height: 40px;
width: 180px;
padding:10px;
max-width: 100%;
margin:0;
border:0;
display: flex;
align-items: center;
justify-content: center;
font-weight: 700;
text-transform: uppercase;
background-color: #15151d
}
.chat-name{
height: 40px;
max-width: 100%;
width: 180px;
padding:10px;
border:0;
margin:0;
font-weight: 700;
text-transform: uppercase;
float:left;
text-align: center;
}
.chat textarea {
width:380px;
padding:10px;
margin:0;
border-top:0;
max-width:100%;
border-top: 1px solid #0f0f17;
border-bottom: 1px solid #1a1a23;
border-right: 1px solid #1a1a23;
border-left: 1px solid #1a1a23;
background-color: #1a1a23;
}
.chat-status {
color: #bbb;
opacity: 0;
background-color: #0f0f17;
}
.info-rect,
.chat textarea,
.chat-name {
max-width: 100%;
}
.bottom-bar{
position: fixed;
bottom: 0;
width: 100%;
}
.thumbnail{
width: 80px;
height: 80px;
background-color: #ffffff
}
.title-bar{
width:1000px;
height: 80px;
background-color: #1a1a23;
}
.song-name{
font-weight: 700;
text-transform: uppercase;
margin-left: 30px;
margin-top: 25px;
}
.dj-playing{
margin-left: 30px;
}
.progress-background{
width: 1000px;
height: 4px;
background-color: #313139;
position: fixed;
bottom: 0;
}
.progress-bar{
width: 400px;
height: 4px;
background-color: #fa1d57;
position: fixed;
bottom: 0;
}
.subscribe{
width: 520px;
height: 80px;
background-color: #15151d;
}
Or just look at the result there :
http://lespointscom.com/a/misc/demo/2016_06_19/main.html
IFrame player API reference:
https://developers.google.com/youtube/iframe_api_reference#Loading_a_Video_Player