Added search function using YT data API. Fixed slider and scrollbar on web kit. Minor changes
All checks were successful
Gitea/YTDJ/pipeline/head This commit looks good
All checks were successful
Gitea/YTDJ/pipeline/head This commit looks good
This commit is contained in:
@@ -6,12 +6,15 @@ It's a simple way to play music from Youtube and smoothly fade between tracks th
|
|||||||
|
|
||||||
## What's next?
|
## What's next?
|
||||||
### Maybe one day
|
### Maybe one day
|
||||||
- Search videos straight from the app (needs API key and calls)
|
- ~~Search videos straight from the app (needs API key and calls)~~
|
||||||
- Compatibility with Bandcamp music (not sure if it can be done without too much hacks)
|
- Compatibility with Bandcamp music (not sure if it can be done without too much hacks)
|
||||||
|
- A playlist of to-be-played tracks that can be added manually ("add url") or through the search
|
||||||
|
- A history of played tracks?
|
||||||
### Should be done quickly
|
### Should be done quickly
|
||||||
- Clean code (especially old P5JS)
|
- Clean code (especially old P5JS)
|
||||||
- Sanitize it (naming, organization, comments...)
|
- Sanitize it (naming, organization, comments...)
|
||||||
- Add current tracks/playlists as hashes in the URL so we can share track combinations
|
- Add current tracks/playlists as hashes in the URL so we can share track combinations
|
||||||
|
- Better indication of the video current status (playing or paused),maybe using `outline` on the iframe, or changing the `box-shadow color`?
|
||||||
|
|
||||||
## External resources and inspiration
|
## External resources and inspiration
|
||||||
### Inspiration
|
### Inspiration
|
||||||
|
186
css/main.css
186
css/main.css
@@ -1,5 +1,5 @@
|
|||||||
:root {
|
:root {
|
||||||
--bg-color: #223;
|
--bg-color: 34, 34, 51; /* #223 */
|
||||||
--text-color: #eee;
|
--text-color: #eee;
|
||||||
--text-color-light: #bbb;
|
--text-color-light: #bbb;
|
||||||
--accent-color-1: #ff91d8;
|
--accent-color-1: #ff91d8;
|
||||||
@@ -9,7 +9,6 @@
|
|||||||
--crossfader-thumb-width: 30px;
|
--crossfader-thumb-width: 30px;
|
||||||
--crossfader-thumb-height: 60px;
|
--crossfader-thumb-height: 60px;
|
||||||
--crossfader-thumb-radius: 15px;
|
--crossfader-thumb-radius: 15px;
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@font-face {
|
@font-face {
|
||||||
@@ -79,6 +78,11 @@ textarea {
|
|||||||
resize: vertical;
|
resize: vertical;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
a, a:visited {
|
||||||
|
color: inherit;
|
||||||
|
text-decoration: none;
|
||||||
|
}
|
||||||
|
|
||||||
#bg {
|
#bg {
|
||||||
z-index: -2;
|
z-index: -2;
|
||||||
overflow: hidden;
|
overflow: hidden;
|
||||||
@@ -105,8 +109,7 @@ textarea {
|
|||||||
#players, #search-area {
|
#players, #search-area {
|
||||||
display: flex;
|
display: flex;
|
||||||
justify-content: center;
|
justify-content: center;
|
||||||
padding-bottom: 2em;
|
/* gap: 15px; */
|
||||||
gap: 15px;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
.hidden {
|
.hidden {
|
||||||
@@ -142,15 +145,20 @@ iframe {
|
|||||||
/* right: 0; */
|
/* right: 0; */
|
||||||
}
|
}
|
||||||
|
|
||||||
|
input[type=button], button {
|
||||||
|
cursor: pointer;
|
||||||
|
border: none;
|
||||||
|
background-color: var(--accent-color-2);
|
||||||
|
color: rgb(var(--bg-color));
|
||||||
|
border-radius: 5px;
|
||||||
|
font-weight: 900;
|
||||||
|
transition: transform 0.2s ease;
|
||||||
|
}
|
||||||
|
|
||||||
|
input[type=button]:hover, button:hover {
|
||||||
|
transform: scale(1.1);
|
||||||
|
}
|
||||||
.load-button {
|
.load-button {
|
||||||
/* flex-grow: 2; */
|
|
||||||
cursor: pointer;
|
|
||||||
border: none;
|
|
||||||
background-color: var(--accent-color-2);
|
|
||||||
color: var(--bg-color);
|
|
||||||
font-weight: 900;
|
|
||||||
border-radius: 5px;
|
|
||||||
/* padding: 2em; */
|
|
||||||
width: 50%;
|
width: 50%;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -244,6 +252,8 @@ input[type=range]:focus {
|
|||||||
input[type=range]::-webkit-slider-runnable-track {
|
input[type=range]::-webkit-slider-runnable-track {
|
||||||
background: var(--accent-color-1);
|
background: var(--accent-color-1);
|
||||||
border-radius: 25px;
|
border-radius: 25px;
|
||||||
|
margin-bottom: 0.5em;
|
||||||
|
height: 4px;
|
||||||
width: 100%;
|
width: 100%;
|
||||||
cursor: pointer;
|
cursor: pointer;
|
||||||
}
|
}
|
||||||
@@ -251,12 +261,13 @@ input[type=range]::-webkit-slider-thumb {
|
|||||||
background: var(--accent-color-2);
|
background: var(--accent-color-2);
|
||||||
border: solid var(--accent-color-1-light);
|
border: solid var(--accent-color-1-light);
|
||||||
border-width: 0px;
|
border-width: 0px;
|
||||||
|
margin-top: -0.4em;
|
||||||
|
width: 1em;
|
||||||
|
height: 1em;
|
||||||
|
border-radius: 1em;
|
||||||
cursor: pointer;
|
cursor: pointer;
|
||||||
-webkit-appearance: none;
|
-webkit-appearance: none;
|
||||||
}
|
}
|
||||||
input[type=range]:focus::-webkit-slider-runnable-track {
|
|
||||||
background: var(--accent-color-1-light);
|
|
||||||
}
|
|
||||||
input[type=range]::-moz-range-track {
|
input[type=range]::-moz-range-track {
|
||||||
background: var(--accent-color-1);
|
background: var(--accent-color-1);
|
||||||
width: 100%;
|
width: 100%;
|
||||||
@@ -265,39 +276,10 @@ input[type=range]::-moz-range-track {
|
|||||||
}
|
}
|
||||||
input[type=range]::-moz-range-thumb {
|
input[type=range]::-moz-range-thumb {
|
||||||
background: var(--accent-color-2);
|
background: var(--accent-color-2);
|
||||||
/* border: solid var(--accent-color-1-light); */
|
|
||||||
cursor: pointer;
|
cursor: pointer;
|
||||||
border-width: 0px;
|
border-width: 0px;
|
||||||
border-radius: var(--crossfader-thumb-radius);
|
border-radius: var(--crossfader-thumb-radius);
|
||||||
}
|
}
|
||||||
input[type=range]::-ms-track {
|
|
||||||
background: transparent;
|
|
||||||
border-color: transparent;
|
|
||||||
color: transparent;
|
|
||||||
width: 100%;
|
|
||||||
cursor: pointer;
|
|
||||||
}
|
|
||||||
input[type=range]::-ms-fill-lower {
|
|
||||||
background: var(--accent-color-1);
|
|
||||||
border-radius: 25px;
|
|
||||||
}
|
|
||||||
input[type=range]::-ms-fill-upper {
|
|
||||||
background: var(--accent-color-1);
|
|
||||||
border-radius: 25px;
|
|
||||||
}
|
|
||||||
input[type=range]::-ms-thumb {
|
|
||||||
background: var(--accent-color-2);
|
|
||||||
/* border: solid var(--accent-color-1-light); */
|
|
||||||
cursor: pointer;
|
|
||||||
margin-top: 0px;
|
|
||||||
/*Needed to keep the Edge thumb centred*/
|
|
||||||
}
|
|
||||||
input[type=range]:focus::-ms-fill-lower {
|
|
||||||
background: var(--accent-color-1);
|
|
||||||
}
|
|
||||||
input[type=range]:focus::-ms-fill-upper {
|
|
||||||
background: var(--accent-color-1-light);
|
|
||||||
}
|
|
||||||
|
|
||||||
/*------------------------*/
|
/*------------------------*/
|
||||||
input[type=range]#crossfader::-webkit-slider-runnable-track {
|
input[type=range]#crossfader::-webkit-slider-runnable-track {
|
||||||
@@ -307,12 +289,11 @@ input[type=range]#crossfader::-webkit-slider-thumb {
|
|||||||
margin-top: -20.65px;
|
margin-top: -20.65px;
|
||||||
width: var(--crossfader-thumb-width);
|
width: var(--crossfader-thumb-width);
|
||||||
height: var(--crossfader-thumb-height);
|
height: var(--crossfader-thumb-height);
|
||||||
/* border-width: 5px;
|
border-radius: var(--crossfader-thumb-radius);
|
||||||
border-radius: 12px; */
|
|
||||||
}
|
}
|
||||||
|
|
||||||
input[type=range]#crossfader::-moz-range-track {
|
input[type=range]#crossfader::-moz-range-track {
|
||||||
/* border-radius: 25px; */
|
border-radius: var(--crossfader-thumb-radius);
|
||||||
width: 100%;
|
width: 100%;
|
||||||
height: 13.3px;
|
height: 13.3px;
|
||||||
cursor: pointer;
|
cursor: pointer;
|
||||||
@@ -320,39 +301,100 @@ input[type=range]#crossfader::-moz-range-track {
|
|||||||
input[type=range]#crossfader::-moz-range-thumb {
|
input[type=range]#crossfader::-moz-range-thumb {
|
||||||
width: var(--crossfader-thumb-width);
|
width: var(--crossfader-thumb-width);
|
||||||
height: var(--crossfader-thumb-height);
|
height: var(--crossfader-thumb-height);
|
||||||
/* border-width: 5px; */
|
border-radius: var(--crossfader-thumb-radius);
|
||||||
/* border-radius: 12px; */
|
|
||||||
cursor: pointer;
|
cursor: pointer;
|
||||||
}
|
}
|
||||||
input[type=range]#crossfader::-ms-track {
|
|
||||||
/* border-width: 18.75px 0; */
|
.search-wrapper {
|
||||||
height: 13.3px;
|
/* margin-bottom: 2em; */
|
||||||
}
|
}
|
||||||
input[type=range]#crossfader::-ms-fill-lower {
|
.search-bar-wrapper {
|
||||||
/* border-width: 2.3px;
|
display: flex;
|
||||||
border-radius: 50px; */
|
justify-content: center;
|
||||||
}
|
align-items: center;
|
||||||
input[type=range]#crossfader::-ms-fill-upper {
|
height: 2em;
|
||||||
/* border-radius: 50px; */
|
margin-bottom: 1em;
|
||||||
}
|
|
||||||
input[type=range]#crossfader::-ms-thumb {
|
|
||||||
width: var(--crossfader-thumb-width);
|
|
||||||
height: var(--crossfader-thumb-height);
|
|
||||||
/* border-width: 5px;
|
|
||||||
border-radius: 12px; */
|
|
||||||
cursor: pointer;
|
|
||||||
margin-top: 0px;
|
|
||||||
/*Needed to keep the Edge thumb centred*/
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#search-bar {
|
||||||
|
display: flex;
|
||||||
|
column-gap: 1em;
|
||||||
|
}
|
||||||
|
#search-bar input, #search-bar button {
|
||||||
|
height: 2em;;
|
||||||
|
}
|
||||||
|
|
||||||
|
#search-button {
|
||||||
|
padding: 0.2em 1em;
|
||||||
|
}
|
||||||
|
|
||||||
|
#search-results {
|
||||||
|
display: flex;
|
||||||
|
overflow: auto;
|
||||||
|
width: 95vw;
|
||||||
|
/* flex-direction: column; */
|
||||||
|
column-gap: 1em;
|
||||||
|
/* padding-bottom: 1em; */
|
||||||
|
|
||||||
|
scrollbar-width: thin;
|
||||||
|
scrollbar-color: rgba(255,255,255,0.8) rgba(0,0,0,0);
|
||||||
|
border-radius: 6px;
|
||||||
|
}
|
||||||
|
|
||||||
|
#search-results::-webkit-scrollbar {
|
||||||
|
height: 9px;
|
||||||
|
}
|
||||||
|
#search-results::-webkit-scrollbar-track {
|
||||||
|
background: rgba(0,0,0,0);
|
||||||
|
}
|
||||||
|
#search-results::-webkit-scrollbar-thumb {
|
||||||
|
background-color: rgba(255,255,255,0.8);
|
||||||
|
width: 9px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.search-item {
|
||||||
|
display: flex;
|
||||||
|
justify-content: space-between;
|
||||||
|
align-items: center;
|
||||||
|
flex-direction: column;
|
||||||
|
position: relative;
|
||||||
|
}
|
||||||
|
|
||||||
|
.search-item-info {
|
||||||
|
position: relative;
|
||||||
|
}
|
||||||
|
|
||||||
|
.search-item-title {
|
||||||
|
position: absolute;
|
||||||
|
top: 0;
|
||||||
|
margin: 0.5em;
|
||||||
|
}
|
||||||
|
|
||||||
|
.search-item-thumbnail img {
|
||||||
|
/* width: 80%; */
|
||||||
|
}
|
||||||
|
.search-item-title span {
|
||||||
|
display: inline;
|
||||||
|
background-color: rgba(var(--bg-color), 0.8);
|
||||||
|
padding: 0.3em 0;
|
||||||
|
line-height: 1.8em;
|
||||||
|
}
|
||||||
|
|
||||||
|
.search-item-controls {
|
||||||
|
display: flex;
|
||||||
|
/* justify-content: center; */
|
||||||
|
column-gap: 1em;
|
||||||
|
margin: 0.5em;
|
||||||
|
position: absolute;
|
||||||
|
bottom: 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
.load-to-A, .load-to-B {
|
||||||
|
padding: 0.5em;
|
||||||
|
}
|
||||||
.footer {
|
.footer {
|
||||||
font-weight: 100;
|
font-weight: 100;
|
||||||
padding-top: 2em;
|
/* padding-top: 2em; */
|
||||||
}
|
|
||||||
.footer a, .footer a:visited {
|
|
||||||
color: var(--text-color);
|
|
||||||
text-decoration: none;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
.footer span {
|
.footer span {
|
||||||
|
33
index.html
33
index.html
@@ -84,24 +84,53 @@
|
|||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
|
<div class="search-wrapper">
|
||||||
|
<div class="search-bar-wrapper">
|
||||||
|
<form id="search-bar">
|
||||||
|
<input id='search-query' type="search" minlength="4" maxlength="512" placeholder="Search for Youtube videos">
|
||||||
|
<button id='search-button' type="submit">Search</button>
|
||||||
|
</form>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div id="search-results">
|
||||||
|
|
||||||
|
<div class="search-item" data-id="">
|
||||||
|
<div class="search-item-info">
|
||||||
|
<div class="search-item-thumbnail">
|
||||||
|
<img src="" alt="">
|
||||||
|
</div>
|
||||||
|
<div class="search-item-title">
|
||||||
|
<a href="#" rel="noreferrer" target="_blank"><span>Titre vidéo</span></a>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div class="search-item-controls">
|
||||||
|
<input type="button" class="load-to-A" value="Load to desk A">
|
||||||
|
<input type="button" class="load-to-B" value="Load to desk B">
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
<h1>🔊 Mix like a pro youtube DJ! 🎧</h1>
|
<h1>🔊 Mix like a pro youtube DJ! 🎧</h1>
|
||||||
|
|
||||||
<div class="footer">
|
<div class="footer">
|
||||||
<p><span id='shooting-stars-enable'></span> <span class="spacer"></span>
|
<p><span id='shooting-stars-enable'></span> <span class="spacer"></span>
|
||||||
<a href="https://tflcl.xyz" target="_blank" >💜 Made by tflcl.xyz 💜</a>
|
<a href="https://tflcl.xyz" target="_blank" >💜 Made by tflcl.xyz 💜</a>
|
||||||
<span class="spacer"></span>
|
<span class="spacer"></span>
|
||||||
<a href="#" id="contact-me">💌 Contact me 💌</a>
|
<a href="#" id="contact-me">💌 Contact me 💌</a>
|
||||||
<span class="spacer"></span>
|
<span class="spacer"></span>
|
||||||
<a href="https://git.tflcl.xyz/tfl/YTDJ">🧩 Source code 🧩</a>
|
<a href="https://git.tflcl.xyz/tfl/YTDJ">🧩 More info / Source code 🧩</a>
|
||||||
</p>
|
</p>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<!-- REMOVE THIS LINE (Some light analytics to know how people use this website) -->
|
|
||||||
<script async defer data-website-id="c073e27d-91e4-47fa-bd38-578b7fe727eb" src="https://stats.tflcl.xyz/sucre.js"></script>
|
<script async defer data-website-id="c073e27d-91e4-47fa-bd38-578b7fe727eb" src="https://stats.tflcl.xyz/sucre.js"></script>
|
||||||
<!-- Background was first made using P5JS -->
|
<!-- Background was first made using P5JS -->
|
||||||
<!-- <script src="/js/vendor/p5.js"></script>
|
<!-- <script src="/js/vendor/p5.js"></script>
|
||||||
<script src="/js/vendor/p5.svg.js"></script>
|
<script src="/js/vendor/p5.svg.js"></script>
|
||||||
<script src="/js/sketch.js"></script> -->
|
<script src="/js/sketch.js"></script> -->
|
||||||
|
<script src="https://apis.google.com/js/api.js"></script>
|
||||||
<script src="/js/main.js"></script>
|
<script src="/js/main.js"></script>
|
||||||
|
|
||||||
|
|
||||||
|
107
js/main.js
107
js/main.js
@@ -116,6 +116,10 @@ class player {
|
|||||||
this.player.loadVideoById(trackID);
|
this.player.loadVideoById(trackID);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
cue(trackID) {
|
||||||
|
this.player.cueVideoById(trackID);
|
||||||
|
}
|
||||||
|
|
||||||
loadPlaylist(playlistID) {
|
loadPlaylist(playlistID) {
|
||||||
//First element should be the playlist ID, second element the index of the video to play
|
//First element should be the playlist ID, second element the index of the video to play
|
||||||
let list = playlistID[0];
|
let list = playlistID[0];
|
||||||
@@ -201,9 +205,9 @@ function get_playlist_id(url) {
|
|||||||
let regPlaylist = /[?&]list=([^#\&\?]+)/;
|
let regPlaylist = /[?&]list=([^#\&\?]+)/;
|
||||||
let regIndex = /[?&]index=([^#]+)/;
|
let regIndex = /[?&]index=([^#]+)/;
|
||||||
let match = url.match(regPlaylist);
|
let match = url.match(regPlaylist);
|
||||||
console.log('match ' + match);
|
// console.log('match ' + match);
|
||||||
let matchIndex = url.match(regIndex);
|
let matchIndex = url.match(regIndex);
|
||||||
console.log('matchindex ' + matchIndex);
|
// console.log('matchindex ' + matchIndex);
|
||||||
// console.log('regexp ' + match.match(/=LL([^#\&\?]*)/));
|
// console.log('regexp ' + match.match(/=LL([^#\&\?]*)/));
|
||||||
let index = 0;
|
let index = 0;
|
||||||
if (matchIndex != null) {
|
if (matchIndex != null) {
|
||||||
@@ -313,8 +317,6 @@ function newShootingStar() {
|
|||||||
document.documentElement.style.setProperty('--shooting-star-angle', angle + "deg");
|
document.documentElement.style.setProperty('--shooting-star-angle', angle + "deg");
|
||||||
document.documentElement.style.setProperty('--shooting-star-direction', direction);
|
document.documentElement.style.setProperty('--shooting-star-direction', direction);
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
shootingStarWrapper.appendChild(shootingStar);
|
shootingStarWrapper.appendChild(shootingStar);
|
||||||
shootingStar.classList.add('shooting-star');
|
shootingStar.classList.add('shooting-star');
|
||||||
|
|
||||||
@@ -346,8 +348,6 @@ document.getElementById('shooting-stars-enable').addEventListener('click', () =>
|
|||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
// Enable/disable shooting stars (with P5JS background)
|
// Enable/disable shooting stars (with P5JS background)
|
||||||
// if (typeof processingSketch !== 'undefined') {
|
// if (typeof processingSketch !== 'undefined') {
|
||||||
// let separatorSpan = document.createElement('span');
|
// let separatorSpan = document.createElement('span');
|
||||||
@@ -371,7 +371,6 @@ document.getElementById('shooting-stars-enable').addEventListener('click', () =>
|
|||||||
- EMAIL OBFUSCATION - found here http://www.grall.name/posts/1/antiSpam-emailAddressObfuscation.html
|
- EMAIL OBFUSCATION - found here http://www.grall.name/posts/1/antiSpam-emailAddressObfuscation.html
|
||||||
-------------------------------------------------------*/
|
-------------------------------------------------------*/
|
||||||
document.getElementById('contact-me').addEventListener('click', (e) => {
|
document.getElementById('contact-me').addEventListener('click', (e) => {
|
||||||
console.log('okay');
|
|
||||||
var y = decode("pbagnpg@gsypy.klm"); //https://rot13.com/
|
var y = decode("pbagnpg@gsypy.klm"); //https://rot13.com/
|
||||||
e.target.setAttribute("href", "mailto:" + y);
|
e.target.setAttribute("href", "mailto:" + y);
|
||||||
})
|
})
|
||||||
@@ -383,3 +382,97 @@ function decode(a) {
|
|||||||
return String.fromCharCode((c <= "Z" ? 90 : 122) >= (c = c.charCodeAt(0) + 13) ? c : c - 26);
|
return String.fromCharCode((c <= "Z" ? 90 : 122) >= (c = c.charCodeAt(0) + 13) ? c : c - 26);
|
||||||
})
|
})
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
SEARCH WITH YOUTUBE API
|
||||||
|
*/
|
||||||
|
let lastSearchQuery;
|
||||||
|
let results;
|
||||||
|
|
||||||
|
gapi.load("client", loadClient);
|
||||||
|
|
||||||
|
// https://developers.google.com/youtube/v3/docs/search/list
|
||||||
|
function loadClient() {
|
||||||
|
gapi.client.setApiKey("AIzaSyCuz5tGc9oDxw6RZnpibakYFHzMvsd8bUs");
|
||||||
|
return gapi.client.load("https://www.googleapis.com/discovery/v1/apis/youtube/v3/rest")
|
||||||
|
.then(function() { console.log("GAPI client loaded for API"); },
|
||||||
|
function(err) { console.error("Error loading GAPI client for API", err); });
|
||||||
|
}
|
||||||
|
|
||||||
|
function execute(query) {
|
||||||
|
// Make sure the client is loaded before calling this method.
|
||||||
|
return gapi.client.youtube.search.list({
|
||||||
|
"part": [
|
||||||
|
"snippet"
|
||||||
|
],
|
||||||
|
"maxResults": 15,
|
||||||
|
"q": query,
|
||||||
|
"type": [
|
||||||
|
"video"
|
||||||
|
],
|
||||||
|
"fields": "items(id/videoId,snippet(title,thumbnails/medium))"
|
||||||
|
})
|
||||||
|
.then(function(response) {
|
||||||
|
if (response.status == 200) {
|
||||||
|
results = response.result;
|
||||||
|
localStorage.setItem('sres', JSON.stringify(results));
|
||||||
|
displaySearchResults(results);
|
||||||
|
}
|
||||||
|
// Handle the results here (response.result has the parsed body).
|
||||||
|
console.log("Response", response);
|
||||||
|
|
||||||
|
},
|
||||||
|
function(err) {
|
||||||
|
console.error("Execute error", err);
|
||||||
|
alert("Whoops, something went wrong. \n Maybe all of my daily Youtube Data API requests have been used. Try again later! \n Maybe it's something else. Try again later?");
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
const searchForm = document.getElementById('search-bar');
|
||||||
|
const searchQueryObj = document.getElementById('search-query');
|
||||||
|
const searchButtonObj = document.getElementById('search-button');
|
||||||
|
const searchResultsObj = document.getElementById('search-results');
|
||||||
|
//When the page has loaded, store the hidden search-item class div as a template for future searchs
|
||||||
|
const searchResultItemObj = searchResultsObj.querySelector('.search-item').cloneNode(true);
|
||||||
|
searchResultsObj.querySelector('.search-item').remove();
|
||||||
|
|
||||||
|
|
||||||
|
searchForm.addEventListener('submit', (e) => {
|
||||||
|
e.preventDefault(); // We handle the form submit by ourselve
|
||||||
|
if (searchQueryObj.value != lastSearchQuery) { // prevent useless requests
|
||||||
|
console.log('Search for: ' + searchQueryObj.value);
|
||||||
|
execute(searchQueryObj.value);
|
||||||
|
lastSearchQuery = searchQueryObj.value;
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
});
|
||||||
|
|
||||||
|
|
||||||
|
function displaySearchResults(res) {
|
||||||
|
// First we clean previous search results
|
||||||
|
while (searchResultsObj.firstChild) {
|
||||||
|
searchResultsObj.removeChild(searchResultsObj.firstChild);
|
||||||
|
}
|
||||||
|
|
||||||
|
res.items.forEach((item) => {
|
||||||
|
let itemElmt = searchResultItemObj.cloneNode(true);
|
||||||
|
itemElmt.querySelector('.search-item-info img').setAttribute('src', item.snippet.thumbnails.medium.url);
|
||||||
|
itemElmt.querySelector('.search-item-info span').innerHTML = item.snippet.title;
|
||||||
|
itemElmt.querySelector('.search-item-info a').setAttribute('href', 'https://www.youtube.com/watch?v=' + item.id.videoId)
|
||||||
|
itemElmt.dataset.id = item.id.videoId;
|
||||||
|
itemElmt.querySelector('.load-to-A').addEventListener('click', () => {
|
||||||
|
playerA.cue(item.id.videoId);
|
||||||
|
});
|
||||||
|
itemElmt.querySelector('.load-to-B').addEventListener('click', () => {
|
||||||
|
playerB.cue(item.id.videoId);
|
||||||
|
});
|
||||||
|
console.log(itemElmt);
|
||||||
|
searchResultsObj.appendChild(itemElmt);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
// For testing purpose
|
||||||
|
results = JSON.parse(localStorage.getItem('sres'));
|
||||||
|
displaySearchResults(results);
|
||||||
|
Reference in New Issue
Block a user