re-organized js files, first attempt of adding Vue SFC

This commit is contained in:
Roberto Tonino 2020-04-16 19:57:34 +02:00
parent 7824aef125
commit dfc30468cf
16 changed files with 875 additions and 322 deletions

View File

@ -1,14 +1,19 @@
{ {
"css": { "css": {
"allowed_file_extensions": ["css", "scss", "sass", "less"], "allowed_file_extensions": [
"end_with_newline": true, "css",
"indent_char": " ", "scss",
"indent_size": 2, "sass",
"indent_with_tabs": true, "less"
"newline_between_rules": true, ],
"selector_separator": " ", "end_with_newline": true,
"selector_separator_newline": true, "indent_char": " ",
"preserve_newlines": true, "indent_size": 2,
"max_preserve_newlines": 10 "indent_with_tabs": true,
"newline_between_rules": true,
"selector_separator": " ",
"selector_separator_newline": true,
"preserve_newlines": true,
"max_preserve_newlines": 10
} }
} }

View File

@ -1,9 +1,11 @@
{ {
"tabWidth": 2,
"useTabs": true, "useTabs": true,
"tabWidth": 2,
"semi": false, "semi": false,
"singleQuote": true, "singleQuote": true,
"bracketSpacing": true, "bracketSpacing": true,
"trailingComma": "none",
"printWidth": 120,
"arrowParens": "avoid", "arrowParens": "avoid",
"vueIndentScriptAndStyle": false "vueIndentScriptAndStyle": false
} }

View File

@ -42,6 +42,9 @@
<button class="search_tablinks" id="search_artist_tab" onclick="changeTab(event, 'search', 'artist_search')">Artist</button> <button class="search_tablinks" id="search_artist_tab" onclick="changeTab(event, 'search', 'artist_search')">Artist</button>
<button class="search_tablinks" id="search_playlist_tab" onclick="changeTab(event, 'search', 'playlist_search')">Playlist</button> <button class="search_tablinks" id="search_playlist_tab" onclick="changeTab(event, 'search', 'playlist_search')">Playlist</button>
</div> </div>
<div id="v-app">
<app></app>
</div>
<div id="search_tab_content"> <div id="search_tab_content">
<!-- ### Main Search Tab ### --> <!-- ### Main Search Tab ### -->
<div id="main_search" class="search_tabcontent"> <div id="main_search" class="search_tabcontent">
@ -53,7 +56,7 @@ <h1 v-on:click="changeSearchTab(section)">{{ names[section] }}</h1>
<div class="cover_container"> <div class="cover_container">
<img v-bind:src="(results.TOP_RESULT[0].__TYPE__ == 'artist' ? 'https://e-cdns-images.dzcdn.net/images/artist/' + results.TOP_RESULT[0].ART_PICTURE : results.TOP_RESULT[0].__TYPE__ == 'album' ? 'https://e-cdns-images.dzcdn.net/images/cover/' + results.TOP_RESULT[0].ALB_PICTURE : results.TOP_RESULT[0].__TYPE__ == 'playlist' ? 'https://e-cdns-images.dzcdn.net/images/'+ results.TOP_RESULT[0].PICTURE_TYPE +'/' + results.TOP_RESULT[0].PLAYLIST_PICTURE :'https://e-cdns-images.dzcdn.net/images/cover/') + '/156x156-000000-80-0-0.jpg'" <img v-bind:src="(results.TOP_RESULT[0].__TYPE__ == 'artist' ? 'https://e-cdns-images.dzcdn.net/images/artist/' + results.TOP_RESULT[0].ART_PICTURE : results.TOP_RESULT[0].__TYPE__ == 'album' ? 'https://e-cdns-images.dzcdn.net/images/cover/' + results.TOP_RESULT[0].ALB_PICTURE : results.TOP_RESULT[0].__TYPE__ == 'playlist' ? 'https://e-cdns-images.dzcdn.net/images/'+ results.TOP_RESULT[0].PICTURE_TYPE +'/' + results.TOP_RESULT[0].PLAYLIST_PICTURE :'https://e-cdns-images.dzcdn.net/images/cover/') + '/156x156-000000-80-0-0.jpg'"
v-bind:class="(results.TOP_RESULT[0].__TYPE__ == 'artist' ? 'circle' : 'rounded') + ' coverart'"></img> v-bind:class="(results.TOP_RESULT[0].__TYPE__ == 'artist' ? 'circle' : 'rounded') + ' coverart'"></img>
<div v-on:click="addToQueue('https://deezer.com/'+results.TOP_RESULT[0].__TYPE__+'/'+(results.TOP_RESULT[0].__TYPE__ == 'artist' ? results.TOP_RESULT[0].ART_ID : results.TOP_RESULT[0].__TYPE__ == 'album' ? results.TOP_RESULT[0].ALB_ID : results.TOP_RESULT[0].__TYPE__ == 'playlist' ? results.TOP_RESULT[0].PLAYLIST_ID : ''))" class="download_overlay"><i class="material-icons">get_app</i></div> <div role="button" aria-label="download" v-on:contextmenu="openQualityModal(event)" v-on:click="addToQueue(event)" v-bind:data-link="'https://deezer.com/'+results.TOP_RESULT[0].__TYPE__+'/'+(results.TOP_RESULT[0].__TYPE__ == 'artist' ? results.TOP_RESULT[0].ART_ID : results.TOP_RESULT[0].__TYPE__ == 'album' ? results.TOP_RESULT[0].ALB_ID : results.TOP_RESULT[0].__TYPE__ == 'playlist' ? results.TOP_RESULT[0].PLAYLIST_ID : '')" class="download_overlay"><i class="material-icons">get_app</i></div>
</div> </div>
<div class="info_box"> <div class="info_box">
<p class="primary-text">{{ results.TOP_RESULT[0].__TYPE__ == 'artist' ? results.TOP_RESULT[0].ART_NAME : results.TOP_RESULT[0].__TYPE__ == 'album' ? results.TOP_RESULT[0].ALB_TITLE : results.TOP_RESULT[0].__TYPE__ == 'playlist' ? results.TOP_RESULT[0].TITLE : '' }}</p> <p class="primary-text">{{ results.TOP_RESULT[0].__TYPE__ == 'artist' ? results.TOP_RESULT[0].ART_NAME : results.TOP_RESULT[0].__TYPE__ == 'album' ? results.TOP_RESULT[0].ALB_TITLE : results.TOP_RESULT[0].__TYPE__ == 'playlist' ? results.TOP_RESULT[0].TITLE : '' }}</p>
@ -69,7 +72,7 @@ <h1 v-on:click="changeSearchTab(section)">{{ names[section] }}</h1>
<td class="breakline"><span v-for="artist in track.ARTISTS">{{artist.ART_NAME}} </span></td> <td class="breakline"><span v-for="artist in track.ARTISTS">{{artist.ART_NAME}} </span></td>
<td class="breakline">{{track.ALB_TITLE}}</td> <td class="breakline">{{track.ALB_TITLE}}</td>
<td>{{convertDuration(track.DURATION)}}</td> <td>{{convertDuration(track.DURATION)}}</td>
<td v-on:click="addToQueue('https://www.deezer.com/track/'+track.SNG_ID)" style="width: 56px; text-align: center;" class="clickable"><i class="material-icons">get_app</i></td> <td role="button" aria-label="download" v-on:contextmenu="openQualityModal(event)" v-on:click="addToQueue(event)" v-bind:data-link="'https://www.deezer.com/track/'+track.SNG_ID" style="width: 56px; text-align: center;" class="clickable"><i class="material-icons">get_app</i></td>
</tr> </tr>
</table> </table>
</div> </div>
@ -77,7 +80,7 @@ <h1 v-on:click="changeSearchTab(section)">{{ names[section] }}</h1>
<div v-for="release in results[section].data.slice(0, 10)" class="release"> <div v-for="release in results[section].data.slice(0, 10)" class="release">
<div class="cover_container"> <div class="cover_container">
<img v-bind:class="(section == 'ARTIST' ? 'circle' : 'rounded') + ' coverart'" v-bind:src="(section == 'ARTIST' ? 'https://e-cdns-images.dzcdn.net/images/artist/' + release.ART_PICTURE : section == 'ALBUM' ? 'https://e-cdns-images.dzcdn.net/images/cover/' + release.ALB_PICTURE : section == 'PLAYLIST' ? 'https://e-cdns-images.dzcdn.net/images/'+ release.PICTURE_TYPE +'/' + release.PLAYLIST_PICTURE : 'https://e-cdns-images.dzcdn.net/images/cover/' ) + '/156x156-000000-80-0-0.jpg'"> <img v-bind:class="(section == 'ARTIST' ? 'circle' : 'rounded') + ' coverart'" v-bind:src="(section == 'ARTIST' ? 'https://e-cdns-images.dzcdn.net/images/artist/' + release.ART_PICTURE : section == 'ALBUM' ? 'https://e-cdns-images.dzcdn.net/images/cover/' + release.ALB_PICTURE : section == 'PLAYLIST' ? 'https://e-cdns-images.dzcdn.net/images/'+ release.PICTURE_TYPE +'/' + release.PLAYLIST_PICTURE : 'https://e-cdns-images.dzcdn.net/images/cover/' ) + '/156x156-000000-80-0-0.jpg'">
<div v-on:click="addToQueue('https://deezer.com/'+(section == 'ARTIST' ? 'artist/'+release.ART_ID : section == 'ALBUM' ? 'album/'+release.ALB_ID : section == 'PLAYLIST' ? 'playlist/'+release.PLAYLIST_ID : ''))" class="download_overlay"><i class="material-icons">get_app</i></div> <div role="button" aria-label="download" v-on:contextmenu="openQualityModal(event)" v-on:click="addToQueue(event)" v-bind:data-link="'https://deezer.com/'+(section == 'ARTIST' ? 'artist/'+release.ART_ID : section == 'ALBUM' ? 'album/'+release.ALB_ID : section == 'PLAYLIST' ? 'playlist/'+release.PLAYLIST_ID : '')" class="download_overlay"><i class="material-icons">get_app</i></div>
</div> </div>
<p class="primary-text">{{ section == 'ARTIST' ? release.ART_NAME : section == 'ALBUM' ? release.ALB_TITLE : section == 'PLAYLIST' ? release.TITLE : '' }}</p> <p class="primary-text">{{ section == 'ARTIST' ? release.ART_NAME : section == 'ALBUM' ? release.ALB_TITLE : section == 'PLAYLIST' ? release.TITLE : '' }}</p>
<p class="secondary-text">{{ section == 'ARTIST' ? numberWithDots(release.NB_FAN) + ' fans' : section == 'ALBUM' ? release.ART_NAME+' - '+release.NUMBER_TRACK+' tracks' : section == 'PLAYLIST' ? release.NB_SONG+' tracks' : '' }}</p> <p class="secondary-text">{{ section == 'ARTIST' ? numberWithDots(release.NB_FAN) + ' fans' : section == 'ALBUM' ? release.ART_NAME+' - '+release.NUMBER_TRACK+' tracks' : section == 'PLAYLIST' ? release.NB_SONG+' tracks' : '' }}</p>
@ -109,7 +112,7 @@ <h1>No Tracks found</h1>
<td class="breakline"><span v-for="artist in track.ARTISTS">{{artist.ART_NAME}} </span></td> <td class="breakline"><span v-for="artist in track.ARTISTS">{{artist.ART_NAME}} </span></td>
<td class="breakline">{{track.ALB_TITLE}}</td> <td class="breakline">{{track.ALB_TITLE}}</td>
<td>{{convertDuration(track.DURATION)}}</td> <td>{{convertDuration(track.DURATION)}}</td>
<td v-on:click="addToQueue('https://www.deezer.com/track/'+track.SNG_ID)" style="width: 56px; text-align: center;" class="clickable"><i class="material-icons">get_app</i></td> <td role="button" aria-label="download" v-on:contextmenu="openQualityModal(event)" v-on:click="addToQueue(event)" v-bind:data-link="'https://www.deezer.com/track/'+track.SNG_ID" style="width: 56px; text-align: center;" class="clickable"><i class="material-icons">get_app</i></td>
</tr> </tr>
</table> </table>
</div> </div>
@ -122,7 +125,7 @@ <h1>No Albums found</h1>
<div v-for="release in results.data" class="release"> <div v-for="release in results.data" class="release">
<div class="cover_container"> <div class="cover_container">
<img class="rounded coverart" v-bind:src="'https://e-cdns-images.dzcdn.net/images/cover/' + release.ALB_PICTURE + '/156x156-000000-80-0-0.jpg'"> <img class="rounded coverart" v-bind:src="'https://e-cdns-images.dzcdn.net/images/cover/' + release.ALB_PICTURE + '/156x156-000000-80-0-0.jpg'">
<div v-on:click="addToQueue('https://www.deezer.com/album/'+release.ALB_ID)" class="download_overlay"><i class="material-icons">get_app</i></div> <div role="button" aria-label="download" v-on:contextmenu="openQualityModal(event)" v-on:click="addToQueue(event)" v-bind:data-link="'https://www.deezer.com/album/'+release.ALB_ID" class="download_overlay"><i class="material-icons">get_app</i></div>
</div> </div>
<p class="primary-text">{{ release.ALB_TITLE }}</p> <p class="primary-text">{{ release.ALB_TITLE }}</p>
<p class="secondary-text">{{ 'by '+release.ART_NAME }}</p> <p class="secondary-text">{{ 'by '+release.ART_NAME }}</p>
@ -138,7 +141,7 @@ <h1>No Artists found</h1>
<div v-for="release in results.data" class="release"> <div v-for="release in results.data" class="release">
<div class="cover_container"> <div class="cover_container">
<img class="circle coverart" v-bind:src="'https://e-cdns-images.dzcdn.net/images/artist/' + release.ART_PICTURE + '/156x156-000000-80-0-0.jpg'"> <img class="circle coverart" v-bind:src="'https://e-cdns-images.dzcdn.net/images/artist/' + release.ART_PICTURE + '/156x156-000000-80-0-0.jpg'">
<div v-on:click="addToQueue('https://www.deezer.com/artist/'+release.ART_ID)" class="download_overlay"><i class="material-icons">get_app</i></div> <div role="button" aria-label="download" v-on:contextmenu="openQualityModal(event)" v-on:click="addToQueue(event)" v-bind:data-link="'https://www.deezer.com/artist/'+release.ART_ID" class="download_overlay"><i class="material-icons">get_app</i></div>
</div> </div>
<p class="primary-text">{{ release.ART_NAME }}</p> <p class="primary-text">{{ release.ART_NAME }}</p>
<p class="secondary-text">{{ numberWithDots(release.NB_FAN) + ' fans' }}</p> <p class="secondary-text">{{ numberWithDots(release.NB_FAN) + ' fans' }}</p>
@ -154,7 +157,7 @@ <h1>No Playlists found</h1>
<div v-for="release in results.data" class="release"> <div v-for="release in results.data" class="release">
<div class="cover_container"> <div class="cover_container">
<img class="rounded coverart" v-bind:src="'https://e-cdns-images.dzcdn.net/images/'+ release.PICTURE_TYPE +'/' + release.PLAYLIST_PICTURE + '/156x156-000000-80-0-0.jpg'"> <img class="rounded coverart" v-bind:src="'https://e-cdns-images.dzcdn.net/images/'+ release.PICTURE_TYPE +'/' + release.PLAYLIST_PICTURE + '/156x156-000000-80-0-0.jpg'">
<div v-on:click="addToQueue('https://www.deezer.com/playlist/'+release.PLAYLIST_ID)" class="download_overlay"><i class="material-icons">get_app</i></div> <div role="button" aria-label="download" v-on:contextmenu="openQualityModal(event)" v-on:click="addToQueue(event)" v-bind:data-link="'https://www.deezer.com/playlist/'+release.PLAYLIST_ID" class="download_overlay"><i class="material-icons">get_app</i></div>
</div> </div>
<p class="primary-text">{{ release.TITLE }}</p> <p class="primary-text">{{ release.TITLE }}</p>
<p class="secondary-text">{{ release.NB_SONG+' tracks' }}</p> <p class="secondary-text">{{ release.NB_SONG+' tracks' }}</p>
@ -377,13 +380,14 @@ <h1>Settings</h1>
<div id="download_list" class=""></div> <div id="download_list" class=""></div>
</div> </div>
</div> </div>
</main> </main>
</body> </body>
<script type="text/javascript" src="/public/js/socket.io.js"></script> <script type="text/javascript" src="/public/js/vendor/httpVueLoader.js"></script>
<script type="text/javascript" src="/public/js/jquery-3.3.1.min.js"></script> <script type="text/javascript" src="/public/js/vendor/socket.io.js"></script>
<script type="text/javascript" src="/public/js/vue.min.js"></script> <script type="text/javascript" src="/public/js/vendor/jquery-3.3.1.min.js"></script>
<script type="text/javascript" src="/public/js/toastify.js"></script> <script type="text/javascript" src="/public/js/vendor/vue.min.js"></script>
<script type="text/javascript" src="/public/js/vendor/toastify.js"></script>
<script type="text/javascript" src="/public/js/app/v-app.js"></script>
<script type="text/javascript" src="/public/js/app/app.js"></script> <script type="text/javascript" src="/public/js/app/app.js"></script>
<script type="text/javascript" src="/public/js/app/utils.js"></script> <script type="text/javascript" src="/public/js/app/utils.js"></script>
<script type="text/javascript" src="/public/js/app/search.js"></script> <script type="text/javascript" src="/public/js/app/search.js"></script>

View File

@ -1,214 +1,219 @@
// Initialization // Initialization
const socket = io.connect(window.location.href) const socket = io.connect(window.location.href)
localStorage = window.localStorage; localStorage = window.localStorage
// tabs stuff // tabs stuff
search_selected = "" let search_selected = ''
main_selected="" let main_selected = ''
// toasts stuff // toasts stuff
toastsWithId = {} let toastsWithId = {}
// settings // settings
lastSettings = {} let lastSettings = {}
function toast(msg, icon=null, dismiss=true, id=null){ function toast(msg, icon = null, dismiss = true, id = null) {
if (toastsWithId[id]){ if (toastsWithId[id]) {
let toastObj = toastsWithId[id] let toastObj = toastsWithId[id]
let toastDOM = $(`div.toastify[toast_id=${id}]`) let toastDOM = $(`div.toastify[toast_id=${id}]`)
if (msg){ if (msg) {
toastDOM.find(".toast-message").html(msg) toastDOM.find('.toast-message').html(msg)
} }
if (icon){ if (icon) {
if (icon=='loading') if (icon == 'loading') icon = `<div class="circle-loader"></div>`
icon = `<div class="circle-loader"></div>` else icon = `<i class="material-icons">${icon}</i>`
else toastDOM.find('.toast-icon').html(icon)
icon = `<i class="material-icons">${icon}</i>`
toastDOM.find(".toast-icon").html(icon)
} }
console.log(dismiss) console.log({ dismiss })
if (dismiss !== null && dismiss){ if (dismiss !== null && dismiss) {
setTimeout(function(){ setTimeout(function () {
toastObj.hideToast() toastObj.hideToast()
delete toastsWithId[id] delete toastsWithId[id]
}, 3000); }, 3000)
} }
}else{ } else {
if (icon == null) if (icon == null) icon = ''
icon = "" else if (icon == 'loading') icon = `<div class="circle-loader"></div>`
else if (icon=='loading') else icon = `<i class="material-icons">${icon}</i>`
icon = `<div class="circle-loader"></div>`
else
icon = `<i class="material-icons">${icon}</i>`
let toastObj = Toastify({ let toastObj = Toastify({
text: `<span class="toast-icon">${icon}</span><span class="toast-message">${msg}</toast>`, text: `<span class="toast-icon">${icon}</span><span class="toast-message">${msg}</toast>`,
duration: dismiss ? 3000 : 0, duration: dismiss ? 3000 : 0,
gravity: 'bottom', gravity: 'bottom',
position: 'left' position: 'left'
}).showToast() }).showToast()
if (id){ if (id) {
toastsWithId[id] = toastObj toastsWithId[id] = toastObj
$(toastObj.toastElement).attr('toast_id', id) $(toastObj.toastElement).attr('toast_id', id)
} }
} }
} }
socket.on("toast", (data)=>{ socket.on('toast', data => {
toast(data.msg, data.icon || null, data.dismiss !== undefined ? data.dismiss : true, data.id || null) toast(data.msg, data.icon || null, data.dismiss !== undefined ? data.dismiss : true, data.id || null)
}) })
// Debug messages for socketio // Debug messages for socketio
socket.on("message", function(msg){ socket.on('message', function (msg) {
console.log(msg) console.log(msg)
}) })
$(function(){ $(function () {
if (localStorage.getItem("arl")){ if (localStorage.getItem('arl')) {
socket.emit("login", localStorage.getItem("arl")); socket.emit('login', localStorage.getItem('arl'))
$("#login_input_arl").val(localStorage.getItem("arl")) $('#login_input_arl').val(localStorage.getItem('arl'))
} }
// Check if download tab should be open // Check if download tab should be open
if (eval(localStorage.getItem("downloadTabOpen"))) if (eval(localStorage.getItem('downloadTabOpen'))) $('#show_download_tab').click()
$("#show_download_tab").click() else $('#hide_download_tab').click()
else
$("#hide_download_tab").click()
// Open default tab // Open default tab
document.getElementById("main_home_tablink").click(); document.getElementById('main_home_tablink').click()
}) })
// Show/Hide Download Tab // Show/Hide Download Tab
document.querySelector("#show_download_tab").onclick = (ev)=>{ document.querySelector('#show_download_tab').onclick = ev => {
ev.preventDefault(); ev.preventDefault()
document.querySelector("#download_tab_bar").style.display = "none"; document.querySelector('#download_tab_bar').style.display = 'none'
document.querySelector("#download_tab").style.display = "block"; document.querySelector('#download_tab').style.display = 'block'
localStorage.setItem("downloadTabOpen", true) localStorage.setItem('downloadTabOpen', true)
} }
document.querySelector("#hide_download_tab").onclick = (ev)=>{ document.querySelector('#hide_download_tab').onclick = ev => {
ev.preventDefault(); ev.preventDefault()
document.querySelector("#download_tab_bar").style.display = "block"; document.querySelector('#download_tab_bar').style.display = 'block'
document.querySelector("#download_tab").style.display = "none"; document.querySelector('#download_tab').style.display = 'none'
localStorage.setItem("downloadTabOpen", false) localStorage.setItem('downloadTabOpen', false)
} }
// Login stuff // Login stuff
function loginButton(){ function loginButton() {
let arl = document.querySelector("#login_input_arl").value let arl = document.querySelector('#login_input_arl').value
if (arl != "" && arl != localStorage.getItem("arl")){ if (arl != '' && arl != localStorage.getItem('arl')) {
socket.emit("login", arl, true) socket.emit('login', arl, true)
} }
} }
function copyARLtoClipboard(){ function copyARLtoClipboard() {
$("#login_input_arl").attr("type", "text"); $('#login_input_arl').attr('type', 'text')
let copyText = document.querySelector("#login_input_arl") let copyText = document.querySelector('#login_input_arl')
copyText.select(); copyText.select()
copyText.setSelectionRange(0, 99999); copyText.setSelectionRange(0, 99999)
document.execCommand("copy"); document.execCommand('copy')
$("#login_input_arl").attr("type", "password"); $('#login_input_arl').attr('type', 'password')
toast("ARL copied to clipboard", 'assignment') toast('ARL copied to clipboard', 'assignment')
} }
function logout(){ function logout() {
socket.emit("logout"); socket.emit('logout')
} }
socket.on("logging_in", function(){ socket.on('logging_in', function () {
toast("Logging in", "loading", false, "login-toast") toast('Logging in', 'loading', false, 'login-toast')
}) })
socket.on("logged_in", function(data){ socket.on('logged_in', function (data) {
console.log(data) console.log(data)
switch (data.status) { switch (data.status) {
case 1: case 1:
case 3: case 3:
toast("Logged in", "done", true, "login-toast") toast('Logged in', 'done', true, 'login-toast')
if (data.arl){ if (data.arl) {
localStorage.setItem("arl", data.arl) localStorage.setItem('arl', data.arl)
$("#login_input_arl").val(data.arl) $('#login_input_arl').val(data.arl)
} }
$('#open_login_prompt').hide() $('#open_login_prompt').hide()
if (data.user){ if (data.user) {
$("#settings_username").text(data.user.name) $('#settings_username').text(data.user.name)
$("#settings_picture").attr("src",`https://e-cdns-images.dzcdn.net/images/user/${data.user.picture}/125x125-000000-80-0-0.jpg`) $('#settings_picture').attr(
$("#logged_in_info").show() 'src',
`https://e-cdns-images.dzcdn.net/images/user/${data.user.picture}/125x125-000000-80-0-0.jpg`
)
$('#logged_in_info').show()
} }
break; break
case 2: case 2:
toast("Already logged in", "done", true, "login-toast") toast('Already logged in', 'done', true, 'login-toast')
if (data.user){ if (data.user) {
$("#settings_username").text(data.user.name) $('#settings_username').text(data.user.name)
$("#settings_picture").attr("src",`https://e-cdns-images.dzcdn.net/images/user/${data.user.picture}/125x125-000000-80-0-0.jpg`) $('#settings_picture').attr(
$("#logged_in_info").show() 'src',
`https://e-cdns-images.dzcdn.net/images/user/${data.user.picture}/125x125-000000-80-0-0.jpg`
)
$('#logged_in_info').show()
} }
break; break
case 0: case 0:
toast("Couldn't log in", "close", true, "login-toast") toast("Couldn't log in", 'close', true, 'login-toast')
localStorage.removeItem("arl") localStorage.removeItem('arl')
$("#login_input_arl").val("") $('#login_input_arl').val('')
$('#open_login_prompt').show() $('#open_login_prompt').show()
$("#logged_in_info").hide() $('#logged_in_info').hide()
$("#settings_username").text("Not Logged") $('#settings_username').text('Not Logged')
$("#settings_picture").attr("src",`https://e-cdns-images.dzcdn.net/images/user/125x125-000000-80-0-0.jpg`) $('#settings_picture').attr('src', `https://e-cdns-images.dzcdn.net/images/user/125x125-000000-80-0-0.jpg`)
break; break
} }
}) })
socket.on("logged_out", function(){ socket.on('logged_out', function () {
toast("Logged out", "done", true, "login-toast") toast('Logged out', 'done', true, 'login-toast')
localStorage.removeItem("arl") localStorage.removeItem('arl')
$("#login_input_arl").val("") $('#login_input_arl').val('')
$('#open_login_prompt').show() $('#open_login_prompt').show()
$("#logged_in_info").hide() $('#logged_in_info').hide()
$("#settings_username").text("Not Logged") $('#settings_username').text('Not Logged')
$("#settings_picture").attr("src",`https://e-cdns-images.dzcdn.net/images/user/125x125-000000-80-0-0.jpg`) $('#settings_picture').attr('src', `https://e-cdns-images.dzcdn.net/images/user/125x125-000000-80-0-0.jpg`)
}) })
// settings stuff // settings stuff
var settingsTab = new Vue({ var settingsTab = new Vue({
el: '#settings_tab', el: '#settings_tab',
data: { data: {
settings: {} settings: {}
} }
}) })
socket.on("init_settings", function(settings){ socket.on('init_settings', function (settings) {
loadSettings(settings) loadSettings(settings)
toast("Settings loaded!", 'settings') toast('Settings loaded!', 'settings')
}) })
socket.on("updateSettings", function(settings){ socket.on('updateSettings', function (settings) {
loadSettings(settings) loadSettings(settings)
toast("Settings updated!", 'settings') toast('Settings updated!', 'settings')
}) })
function loadSettings(settings){ function loadSettings(settings) {
lastSettings = {...settings} lastSettings = { ...settings }
settingsTab.settings = settings settingsTab.settings = settings
} }
function saveSettings(){ function saveSettings() {
lastSettings = {...settingsTab.settings} lastSettings = { ...settingsTab.settings }
socket.emit("saveSettings", lastSettings) socket.emit('saveSettings', lastSettings)
} }
// tabs stuff // tabs stuff
function changeTab(evt, section, tabName) { function changeTab(evt, section, tabName) {
var i, tabcontent, tablinks; console.log( {evt, section, tabName} );
tabcontent = document.getElementsByClassName(section+"_tabcontent");
for (i = 0; i < tabcontent.length; i++) { var i, tabcontent, tablinks
tabcontent[i].style.display = "none"; tabcontent = document.getElementsByClassName(section + '_tabcontent')
} for (i = 0; i < tabcontent.length; i++) {
tablinks = document.getElementsByClassName(section+"_tablinks"); tabcontent[i].style.display = 'none'
for (i = 0; i < tablinks.length; i++) {
tablinks[i].className = tablinks[i].className.replace(" active", "");
}
if (tabName == "settings_tab" && main_selected != "settings_tab"){
settingsTab.settings = {...lastSettings}
} }
document.getElementById(tabName).style.display = "block"; tablinks = document.getElementsByClassName(section + '_tablinks')
window[section+"_selected"] = tabName for (i = 0; i < tablinks.length; i++) {
evt.currentTarget.className += " active"; tablinks[i].className = tablinks[i].className.replace(' active', '')
}
if (tabName == 'settings_tab' && main_selected != 'settings_tab') {
settingsTab.settings = { ...lastSettings }
}
document.getElementById(tabName).style.display = 'block'
window[section + '_selected'] = tabName
evt.currentTarget.className += ' active'
// Check if you need to load more content in the search tab // Check if you need to load more content in the search tab
if (document.getElementById("content").offsetHeight >= document.getElementById("content").scrollHeight && main_selected == "search_tab" && ["track_search", "album_search", "artist_search", "playlist_search"].indexOf(search_selected) != -1){ if (
scrolledSearch(window[search_selected.split("_")[0]+"Search"]) document.getElementById('content').offsetHeight >= document.getElementById('content').scrollHeight &&
main_selected == 'search_tab' &&
['track_search', 'album_search', 'artist_search', 'playlist_search'].indexOf(search_selected) != -1
) {
scrolledSearch(window[search_selected.split('_')[0] + 'Search'])
} }
} }

View File

@ -0,0 +1,20 @@
<template>
<div></div>
</template>
<script>
// const Import = httpVueLoader('./Import.vue')
module.exports = {
data: () => ({
who: 'world'
}),
mounted() {
console.log( 'First Vue SFC try' );
}
}
</script>
<style>
</style>

View File

@ -2,29 +2,27 @@ var queueList = {}
var queue = [] var queue = []
var queueComplete = [] var queueComplete = []
socket.on("init_downloadQueue", function(data){ socket.on('init_downloadQueue', function (data) {
console.log(data) console.log(data)
if (data.queueComplete.length){ if (data.queueComplete.length) {
data.queueComplete.forEach(item=>{ data.queueComplete.forEach(item => {
addToQueue(data.queueList[item]) addToQueue(data.queueList[item])
}) })
} }
if (data.currentItem){ if (data.currentItem) {
addToQueue(data['queueList'][data.currentItem]) addToQueue(data['queueList'][data.currentItem])
} }
data.queue.forEach(item=>{ data.queue.forEach(item => {
addToQueue(data.queueList[item]) addToQueue(data.queueList[item])
}) })
}) })
function addToQueue(queueItem){ function addToQueue(queueItem) {
queueList[queueItem.uuid] = queueItem queueList[queueItem.uuid] = queueItem
if ((queueItem.downloaded + queueItem.failed) == queueItem.size) if (queueItem.downloaded + queueItem.failed == queueItem.size) queueComplete.push(queueItem.uuid)
queueComplete.push(queueItem.uuid) else queue.push(queueItem.uuid)
else $('#download_list').append(
queue.push(queueItem.uuid) `<div class="download_object" id="download_${queueItem.uuid}" data-deezerid="${queueItem.id}">
$("#download_list").append(
`<div class="download_object" id="download_${queueItem.uuid}" data-deezerid="${queueItem.id}">
<div class="download_info"> <div class="download_info">
<img width="75px" class="rounded coverart" src="${queueItem.cover}" alt="Cover ${queueItem.title}"/> <img width="75px" class="rounded coverart" src="${queueItem.cover}" alt="Cover ${queueItem.title}"/>
<div class="download_info_data"> <div class="download_info_data">
@ -32,133 +30,147 @@ function addToQueue(queueItem){
<span class="secondary-text">${queueItem.artist}</span> <span class="secondary-text">${queueItem.artist}</span>
</div> </div>
<div class="download_info_status"> <div class="download_info_status">
<span class="download_line"><span class="queue_downloaded">${queueItem.downloaded + queueItem.failed}</span>/${queueItem.size}</span> <span class="download_line"><span class="queue_downloaded">${queueItem.downloaded + queueItem.failed}</span>/${
queueItem.size
}</span>
</div> </div>
</div> </div>
<div class="download_bar"> <div class="download_bar">
<div class="progress"><div id="bar_${queueItem.uuid}" class="indeterminate"></div></div> <div class="progress"><div id="bar_${queueItem.uuid}" class="indeterminate"></div></div>
<i onclick="downloadAction(event)" class="material-icons queue_icon" data-uuid="${queueItem.uuid}">remove</i> <i onclick="downloadAction(event)" class="material-icons queue_icon" data-uuid="${queueItem.uuid}">remove</i>
</div> </div>
</div>`) </div>`
if (queueItem.progress>0){ )
$('#bar_' + queueItem.uuid).removeClass('indeterminate').addClass('determinate') if (queueItem.progress > 0) {
$('#bar_' + queueItem.uuid)
.removeClass('indeterminate')
.addClass('determinate')
} }
$('#bar_' +queueItem.uuid).css('width', queueItem.progress + '%') $('#bar_' + queueItem.uuid).css('width', queueItem.progress + '%')
if (queueItem.failed >= 1){ if (queueItem.failed >= 1) {
$("#download_"+queueItem.uuid+" .download_info_status").append(`<span class="secondary-text inline-flex"><span class="download_slim_separator">(</span><span class="queue_failed">${queueItem.failed}</span><i class="material-icons">error_outline</i><span class="download_slim_separator">)</span></span>`) $('#download_' + queueItem.uuid + ' .download_info_status').append(
`<span class="secondary-text inline-flex"><span class="download_slim_separator">(</span><span class="queue_failed">${queueItem.failed}</span><i class="material-icons">error_outline</i><span class="download_slim_separator">)</span></span>`
)
} }
if ((queueItem.downloaded + queueItem.failed) == queueItem.size){ if (queueItem.downloaded + queueItem.failed == queueItem.size) {
let result_icon = $('#download_'+queueItem.uuid).find('.queue_icon') let result_icon = $('#download_' + queueItem.uuid).find('.queue_icon')
if (queueItem.failed == 0){ if (queueItem.failed == 0) {
result_icon.text("done") result_icon.text('done')
}else if (queueItem.failed == queueItem.size){ } else if (queueItem.failed == queueItem.size) {
result_icon.text("error") result_icon.text('error')
}else{ } else {
result_icon.text("warning") result_icon.text('warning')
} }
} }
} }
socket.on("addedToQueue", function(queueItem){ socket.on('addedToQueue', function (queueItem) {
addToQueue(queueItem) addToQueue(queueItem)
}) })
function downloadAction(evt){ function downloadAction(evt) {
let icon = $(evt.currentTarget).text() let icon = $(evt.currentTarget).text()
let uuid = $(evt.currentTarget).data("uuid") let uuid = $(evt.currentTarget).data('uuid')
switch (icon) { switch (icon) {
case 'remove': case 'remove':
socket.emit('removeFromQueue', uuid) socket.emit('removeFromQueue', uuid)
break; break
default: default:
} }
} }
socket.on("removedFromQueue", function(uuid){ socket.on('removedFromQueue', function (uuid) {
let index = queue.indexOf(uuid) let index = queue.indexOf(uuid)
if (index > -1){ if (index > -1) {
queue.splice(index, 1) queue.splice(index, 1)
$(`#download_${queueList[uuid].uuid}`).remove() $(`#download_${queueList[uuid].uuid}`).remove()
delete queueList[uuid] delete queueList[uuid]
} }
}) })
socket.on("startDownload", function(uuid){ socket.on('startDownload', function (uuid) {
$('#bar_' + uuid).removeClass('indeterminate').addClass('determinate') $('#bar_' + uuid)
.removeClass('indeterminate')
.addClass('determinate')
}) })
socket.on("finishDownload", function(uuid){ socket.on('finishDownload', function (uuid) {
if (queue.indexOf(uuid) > -1){ if (queue.indexOf(uuid) > -1) {
toast(`${queueList[uuid].title} finished downloading.`, 'done') toast(`${queueList[uuid].title} finished downloading.`, 'done')
$('#bar_' + uuid).css('width', '100%') $('#bar_' + uuid).css('width', '100%')
let result_icon = $('#download_'+uuid).find('.queue_icon') let result_icon = $('#download_' + uuid).find('.queue_icon')
if (queueList[uuid].failed == 0){ if (queueList[uuid].failed == 0) {
result_icon.text("done") result_icon.text('done')
}else if (queueList[uuid].failed >= queueList[uuid].size){ } else if (queueList[uuid].failed >= queueList[uuid].size) {
result_icon.text("error") result_icon.text('error')
}else{ } else {
result_icon.text("warning") result_icon.text('warning')
} }
let index = queue.indexOf(uuid) let index = queue.indexOf(uuid)
if (index > -1){ if (index > -1) {
queue.splice(index, 1) queue.splice(index, 1)
queueComplete.push(uuid) queueComplete.push(uuid)
} }
if (queue.length <= 0){ if (queue.length <= 0) {
toast('All downloads completed!', 'done_all') toast('All downloads completed!', 'done_all')
} }
} }
}) })
socket.on("removedAllDownloads", function(currentItem){ socket.on('removedAllDownloads', function (currentItem) {
queueComplete = [] queueComplete = []
if (currentItem == ""){ if (currentItem == '') {
queue = [] queue = []
queueList = {} queueList = {}
$("#download_list").html("") $('#download_list').html('')
}else{ } else {
queue = [currentItem, ] queue = [currentItem]
tempQueueItem = queueList[currentItem] tempQueueItem = queueList[currentItem]
queueList = {} queueList = {}
queueList[currentItem] = tempQueueItem queueList[currentItem] = tempQueueItem
$(".download_object").each(function(index){ $('.download_object').each(function (index) {
if ($(this).attr('id') != "download_"+currentItem) if ($(this).attr('id') != 'download_' + currentItem) $(this).remove()
$(this).remove()
}) })
} }
}) })
socket.on("removedFinishedDownloads", function(){ socket.on('removedFinishedDownloads', function () {
queueComplete.forEach((item) => { queueComplete.forEach(item => {
$("#download_"+item).remove() $('#download_' + item).remove()
}) })
queueComplete = [] queueComplete = []
}) })
$("#clean_queue").on("click", function(){ $('#clean_queue').on('click', function () {
socket.emit("removeFinishedDownloads") socket.emit('removeFinishedDownloads')
}) })
$("#cancel_queue").on("click", function(){ $('#cancel_queue').on('click', function () {
socket.emit("cancelAllDownloads") socket.emit('cancelAllDownloads')
}) })
socket.on("updateQueue", function(update){ socket.on('updateQueue', function (update) {
if (update.uuid && queue.indexOf(update.uuid) > -1){ if (update.uuid && queue.indexOf(update.uuid) > -1) {
if (update.downloaded){ if (update.downloaded) {
queueList[update.uuid].downloaded++ queueList[update.uuid].downloaded++
$("#download_"+update.uuid+" .queue_downloaded").text(queueList[update.uuid].downloaded + queueList[update.uuid].failed) $('#download_' + update.uuid + ' .queue_downloaded').text(
queueList[update.uuid].downloaded + queueList[update.uuid].failed
)
} }
if (update.failed){ if (update.failed) {
queueList[update.uuid].failed++ queueList[update.uuid].failed++
$("#download_"+update.uuid+" .queue_downloaded").text(queueList[update.uuid].downloaded + queueList[update.uuid].failed) $('#download_' + update.uuid + ' .queue_downloaded').text(
if (queueList[update.uuid].failed == 1){ queueList[update.uuid].downloaded + queueList[update.uuid].failed
$("#download_"+update.uuid+" .download_info_status").append(`<span class="secondary-text inline-flex"><span class="download_slim_separator">(</span><span class="queue_failed">1</span> <i class="material-icons">error_outline</i><span class="download_slim_separator">)</span></span>`) )
}else{ if (queueList[update.uuid].failed == 1) {
$("#download_"+update.uuid+" .queue_failed").text(queueList[update.uuid].failed) $('#download_' + update.uuid + ' .download_info_status').append(
`<span class="secondary-text inline-flex"><span class="download_slim_separator">(</span><span class="queue_failed">1</span> <i class="material-icons">error_outline</i><span class="download_slim_separator">)</span></span>`
)
} else {
$('#download_' + update.uuid + ' .queue_failed').text(queueList[update.uuid].failed)
} }
} }
if (update.progress){ if (update.progress) {
queueList[update.uuid].progress = update.progress queueList[update.uuid].progress = update.progress
$('#bar_' + update.uuid).css('width', update.progress + '%') $('#bar_' + update.uuid).css('width', update.progress + '%')
} }

View File

@ -1,165 +1,186 @@
// Load more content when the search page is at the end // Load more content when the search page is at the end
$('#content').on('scroll', function() { $('#content').on('scroll', function () {
if($(this).scrollTop() + $(this).innerHeight() >= $(this)[0].scrollHeight) { if ($(this).scrollTop() + $(this).innerHeight() >= $(this)[0].scrollHeight) {
if (main_selected == "search_tab" && ["track_search", "album_search", "artist_search", "playlist_search"].indexOf(search_selected) != -1){ if (
scrolledSearch(window[search_selected.split("_")[0]+"Search"]) main_selected == 'search_tab' &&
['track_search', 'album_search', 'artist_search', 'playlist_search'].indexOf(search_selected) != -1
) {
scrolledSearch(window[search_selected.split('_')[0] + 'Search'])
} }
} }
}) })
function scrolledSearch(vueTab){ function scrolledSearch(vueTab) {
query = vueTab.query query = vueTab.query
if (vueTab.results.next < vueTab.results.total){ if (vueTab.results.next < vueTab.results.total) {
socket.emit("search", {term: vueTab.query, type: vueTab.type, start: vueTab.results.next, nb: vueTab.nb}); socket.emit('search', {
term: vueTab.query,
type: vueTab.type,
start: vueTab.results.next,
nb: vueTab.nb
})
} }
} }
function searchUpadate(result){ function searchUpadate(result) {
console.log(result) console.log(result)
vueTab = null; vueTab = null
switch (result.type) { switch (result.type) {
case "TRACK": case 'TRACK':
vueTab = trackSearch; vueTab = trackSearch
break; break
case "ALBUM": case 'ALBUM':
vueTab = albumSearch; vueTab = albumSearch
break; break
case "ARTIST": case 'ARTIST':
vueTab = artistSearch; vueTab = artistSearch
break; break
case "PLAYLIST": case 'PLAYLIST':
vueTab = playlistSearch; vueTab = playlistSearch
break; break
} }
if (vueTab && vueTab.results.next != result.next){ if (vueTab && vueTab.results.next != result.next) {
vueTab.results.next = result.next vueTab.results.next = result.next
vueTab.results.data = vueTab.results.data.concat(result.data) vueTab.results.data = vueTab.results.data.concat(result.data)
} }
} }
socket.on("search", function(result){searchUpadate(result)}) socket.on('search', function (result) {
searchUpadate(result)
})
function clickElement(button){ function clickElement(button) {
return document.getElementById(button).click() return document.getElementById(button).click()
} }
function sendAddToQueue(url, bitrate = null){ function sendAddToQueue(url, bitrate = null) {
socket.emit("addToQueue", {url: url, bitrate:bitrate}) socket.emit('addToQueue', { url: url, bitrate: bitrate })
} }
var mainSearch = new Vue({ let MainSearch = new Vue({
el: '#main_search', el: '#main_search',
data: { data() {
names: { return {
"TOP_RESULT": "Top Result", names: {
"TRACK": "Tracks", TOP_RESULT: 'Top Result',
"ARTIST": "Artists", TRACK: 'Tracks',
"ALBUM": "Albums", ARTIST: 'Artists',
"PLAYLIST": "Playlists" ALBUM: 'Albums',
}, PLAYLIST: 'Playlists'
results: { },
QUERY: "", results: {
ORDER: [], QUERY: '',
ALBUM: {}, ORDER: [],
ARTIST: {}, ALBUM: {},
TRACK: {}, ARTIST: {},
TOP_RESULT: [], TRACK: {},
PLAYLIST: {} TOP_RESULT: [],
}, PLAYLIST: {}
}, }
}
},
methods: { methods: {
changeSearchTab: function (section) { changeSearchTab(section) {
if (section != "TOP_RESULT") if (section != 'TOP_RESULT') clickElement('search_' + section.toLowerCase() + '_tab')
clickElement('search_'+section.toLowerCase()+'_tab')
}, },
addToQueue: function(url){sendAddToQueue(url)} addToQueue(url) {
sendAddToQueue(url)
}
} }
}) })
var trackSearch = new Vue({ var trackSearch = new Vue({
el: '#track_search', el: '#track_search',
data: { data: {
type: "TRACK", type: 'TRACK',
nb: 40, nb: 40,
query: "", query: '',
results: { results: {
data: [], data: [],
next: 0, next: 0,
total: 0 total: 0
} }
}, },
methods: { methods: {
addToQueue: function(url){sendAddToQueue(url)} addToQueue: function (url) {
sendAddToQueue(url)
}
} }
}) })
var albumSearch = new Vue({ var albumSearch = new Vue({
el: '#album_search', el: '#album_search',
data: { data: {
type: "ALBUM", type: 'ALBUM',
nb: 20, nb: 20,
query: "", query: '',
results: { results: {
data: [], data: [],
next: 0, next: 0,
total: 0 total: 0
} }
}, },
methods: { methods: {
addToQueue: function(url){sendAddToQueue(url)} addToQueue: function (url) {
sendAddToQueue(url)
}
} }
}) })
var artistSearch = new Vue({ var artistSearch = new Vue({
el: '#artist_search', el: '#artist_search',
data: { data: {
type: "ARTIST", type: 'ARTIST',
nb: 20, nb: 20,
query: "", query: '',
results: { results: {
data: [], data: [],
next: 0, next: 0,
total: 0 total: 0
} }
}, },
methods: { methods: {
addToQueue: function(url){sendAddToQueue(url)} addToQueue: function (url) {
sendAddToQueue(url)
}
} }
}) })
var playlistSearch = new Vue({ var playlistSearch = new Vue({
el: '#playlist_search', el: '#playlist_search',
data: { data: {
type: "PLAYLIST", type: 'PLAYLIST',
nb: 20, nb: 20,
query: "", query: '',
results: { results: {
data: [], data: [],
next: 0, next: 0,
total: 0 total: 0
} }
}, },
methods: { methods: {
addToQueue: function(url){sendAddToQueue(url)} addToQueue: function (url) {
sendAddToQueue(url)
}
} }
}) })
let term = null
// Search section // Search section
$("#searchbar").keyup(function(e){ $('#searchbar').keyup(function (e) {
if(e.keyCode == 13){ if (e.keyCode == 13) {
term = this.value term = this.value
console.log(term) console.log(term)
if (isValidURL(term)) if (isValidURL(term)) socket.emit('addToQueue', { url: term })
socket.emit("addToQueue", {url: term}); else {
else{ document.getElementById('search_tab_content').style.display = 'none'
document.getElementById("search_tab_content").style.display = "none"; socket.emit('mainSearch', { term: term })
socket.emit("mainSearch", {term: term});
} }
} }
}) })
function mainSearchHandler(result){ function mainSearchHandler(result) {
console.log(result) MainSearch.results = result
mainSearch.results = result
trackSearch.results = result.TRACK trackSearch.results = result.TRACK
albumSearch.results = result.ALBUM albumSearch.results = result.ALBUM
artistSearch.results = result.ARTIST artistSearch.results = result.ARTIST
@ -168,8 +189,10 @@ function mainSearchHandler(result){
albumSearch.query = result.QUERY albumSearch.query = result.QUERY
artistSearch.query = result.QUERY artistSearch.query = result.QUERY
playlistSearch.query = result.QUERY playlistSearch.query = result.QUERY
document.getElementById("search_all_tab").click(); document.getElementById('search_all_tab').click()
document.getElementById("search_tab_content").style.display = "block"; document.getElementById('search_tab_content').style.display = 'block'
document.getElementById("main_search_tablink").click(); document.getElementById('main_search_tablink').click()
} }
socket.on("mainSearch", function(result){mainSearchHandler(result)}) socket.on('mainSearch', function (result) {
mainSearchHandler(result)
})

View File

@ -1,33 +1,32 @@
function isValidURL(text){ function isValidURL(text) {
if (text.toLowerCase().startsWith("http")){ if (text.toLowerCase().startsWith('http')) {
if (text.toLowerCase().indexOf("deezer.com") >= 0 || text.toLowerCase().indexOf("open.spotify.com") >= 0) if (text.toLowerCase().indexOf('deezer.com') >= 0 || text.toLowerCase().indexOf('open.spotify.com') >= 0)
return true return true
}else if (text.toLowerCase().startsWith("spotify:")) } else if (text.toLowerCase().startsWith('spotify:')) return true
return true
return false return false
} }
function convertDuration(duration) { function convertDuration(duration) {
//convert from seconds only to mm:ss format //convert from seconds only to mm:ss format
var mm, ss let mm, ss
mm = Math.floor(duration / 60) mm = Math.floor(duration / 60)
ss = duration - (mm * 60) ss = duration - mm * 60
//add leading zero if ss < 0 //add leading zero if ss < 0
if (ss < 10) { if (ss < 10) {
ss = "0" + ss ss = '0' + ss
} }
return mm + ":" + ss return mm + ':' + ss
} }
function convertDurationSeparated(duration){ function convertDurationSeparated(duration) {
var hh, mm, ss let hh, mm, ss
mm = Math.floor(duration / 60) mm = Math.floor(duration / 60)
hh = Math.floor(mm / 60) hh = Math.floor(mm / 60)
ss = duration - (mm * 60) ss = duration - mm * 60
mm -= hh*60 mm -= hh * 60
return [hh, mm, ss] return [hh, mm, ss]
} }
function numberWithDots(x) { function numberWithDots(x) {
return x.toString().replace(/\B(?=(\d{3})+(?!\d))/g, "."); return x.toString().replace(/\B(?=(\d{3})+(?!\d))/g, '.')
} }

5
public/js/app/v-app.js Normal file
View File

@ -0,0 +1,5 @@
new Vue({
components: {
'app': httpVueLoader('./public/js/app/components/App.vue')
}
}).$mount('#v-app');

478
public/js/vendor/httpVueLoader.js vendored Normal file
View File

@ -0,0 +1,478 @@
(function umd(root,factory){
if(typeof module==='object' && typeof exports === 'object' )
module.exports=factory()
else if(typeof define==='function' && define.amd)
define([],factory)
else
root.httpVueLoader=factory()
})(this,function factory() {
'use strict';
var scopeIndex = 0;
StyleContext.prototype = {
withBase: function(callback) {
var tmpBaseElt;
if ( this.component.baseURI ) {
// firefox and chrome need the <base> to be set while inserting or modifying <style> in a document.
tmpBaseElt = document.createElement('base');
tmpBaseElt.href = this.component.baseURI;
var headElt = this.component.getHead();
headElt.insertBefore(tmpBaseElt, headElt.firstChild);
}
callback.call(this);
if ( tmpBaseElt )
this.component.getHead().removeChild(tmpBaseElt);
},
scopeStyles: function(styleElt, scopeName) {
function process() {
var sheet = styleElt.sheet;
var rules = sheet.cssRules;
for ( var i = 0; i < rules.length; ++i ) {
var rule = rules[i];
if ( rule.type !== 1 )
continue;
var scopedSelectors = [];
rule.selectorText.split(/\s*,\s*/).forEach(function(sel) {
scopedSelectors.push(scopeName+' '+sel);
var segments = sel.match(/([^ :]+)(.+)?/);
scopedSelectors.push(segments[1] + scopeName + (segments[2]||''));
});
var scopedRule = scopedSelectors.join(',') + rule.cssText.substr(rule.selectorText.length);
sheet.deleteRule(i);
sheet.insertRule(scopedRule, i);
}
}
try {
// firefox may fail sheet.cssRules with InvalidAccessError
process();
} catch (ex) {
if ( ex instanceof DOMException && ex.code === DOMException.INVALID_ACCESS_ERR ) {
styleElt.sheet.disabled = true;
styleElt.addEventListener('load', function onStyleLoaded() {
styleElt.removeEventListener('load', onStyleLoaded);
// firefox need this timeout otherwise we have to use document.importNode(style, true)
setTimeout(function() {
process();
styleElt.sheet.disabled = false;
});
});
return;
}
throw ex;
}
},
compile: function() {
var hasTemplate = this.template !== null;
var scoped = this.elt.hasAttribute('scoped');
if ( scoped ) {
// no template, no scopable style needed
if ( !hasTemplate )
return;
// firefox does not tolerate this attribute
this.elt.removeAttribute('scoped');
}
this.withBase(function() {
this.component.getHead().appendChild(this.elt);
});
if ( scoped )
this.scopeStyles(this.elt, '['+this.component.getScopeId()+']');
return Promise.resolve();
},
getContent: function() {
return this.elt.textContent;
},
setContent: function(content) {
this.withBase(function() {
this.elt.textContent = content;
});
}
};
function StyleContext(component, elt) {
this.component = component;
this.elt = elt;
}
ScriptContext.prototype = {
getContent: function() {
return this.elt.textContent;
},
setContent: function(content) {
this.elt.textContent = content;
},
compile: function(module) {
var childModuleRequire = function(childURL) {
return httpVueLoader.require(resolveURL(this.component.baseURI, childURL));
}.bind(this);
var childLoader = function(childURL, childName) {
return httpVueLoader(resolveURL(this.component.baseURI, childURL), childName);
}.bind(this);
try {
Function('exports', 'require', 'httpVueLoader', 'module', this.getContent()).call(this.module.exports, this.module.exports, childModuleRequire, childLoader, this.module);
} catch(ex) {
if ( !('lineNumber' in ex) ) {
return Promise.reject(ex);
}
var vueFileData = responseText.replace(/\r?\n/g, '\n');
var lineNumber = vueFileData.substr(0, vueFileData.indexOf(script)).split('\n').length + ex.lineNumber - 1;
throw new (ex.constructor)(ex.message, url, lineNumber);
}
return Promise.resolve(this.module.exports)
.then(httpVueLoader.scriptExportsHandler.bind(this))
.then(function(exports) {
this.module.exports = exports;
}.bind(this));
}
};
function ScriptContext(component, elt) {
this.component = component;
this.elt = elt;
this.module = { exports:{} };
}
TemplateContext.prototype = {
getContent: function() {
return this.elt.innerHTML;
},
setContent: function(content) {
this.elt.innerHTML = content;
},
getRootElt: function() {
var tplElt = this.elt.content || this.elt;
if ( 'firstElementChild' in tplElt )
return tplElt.firstElementChild;
for ( tplElt = tplElt.firstChild; tplElt !== null; tplElt = tplElt.nextSibling )
if ( tplElt.nodeType === Node.ELEMENT_NODE )
return tplElt;
return null;
},
compile: function() {
return Promise.resolve();
}
};
function TemplateContext(component, elt) {
this.component = component;
this.elt = elt;
}
Component.prototype = {
getHead: function() {
return document.head || document.getElementsByTagName('head')[0];
},
getScopeId: function() {
if ( this._scopeId === '' ) {
this._scopeId = 'data-s-' + (scopeIndex++).toString(36);
this.template.getRootElt().setAttribute(this._scopeId, '');
}
return this._scopeId;
},
load: function(componentURL) {
return httpVueLoader.httpRequest(componentURL)
.then(function(responseText) {
this.baseURI = componentURL.substr(0, componentURL.lastIndexOf('/')+1);
var doc = document.implementation.createHTMLDocument('');
// IE requires the <base> to come with <style>
doc.body.innerHTML = (this.baseURI ? '<base href="'+this.baseURI+'">' : '') + responseText;
for ( var it = doc.body.firstChild; it; it = it.nextSibling ) {
switch ( it.nodeName ) {
case 'TEMPLATE':
this.template = new TemplateContext(this, it);
break;
case 'SCRIPT':
this.script = new ScriptContext(this, it);
break;
case 'STYLE':
this.styles.push(new StyleContext(this, it));
break;
}
}
return this;
}.bind(this));
},
_normalizeSection: function(eltCx) {
var p;
if ( eltCx === null || !eltCx.elt.hasAttribute('src') ) {
p = Promise.resolve(null);
} else {
p = httpVueLoader.httpRequest(eltCx.elt.getAttribute('src'))
.then(function(content) {
eltCx.elt.removeAttribute('src');
return content;
});
}
return p
.then(function(content) {
if ( eltCx !== null && eltCx.elt.hasAttribute('lang') ) {
var lang = eltCx.elt.getAttribute('lang');
eltCx.elt.removeAttribute('lang');
return httpVueLoader.langProcessor[lang.toLowerCase()].call(this, content === null ? eltCx.getContent() : content);
}
return content;
}.bind(this))
.then(function(content) {
if ( content !== null )
eltCx.setContent(content);
});
},
normalize: function() {
return Promise.all(Array.prototype.concat(
this._normalizeSection(this.template),
this._normalizeSection(this.script),
this.styles.map(this._normalizeSection)
))
.then(function() {
return this;
}.bind(this));
},
compile: function() {
return Promise.all(Array.prototype.concat(
this.template && this.template.compile(),
this.script && this.script.compile(),
this.styles.map(function(style) { return style.compile(); })
))
.then(function() {
return this;
}.bind(this));
}
};
function Component(name) {
this.name = name;
this.template = null;
this.script = null;
this.styles = [];
this._scopeId = '';
}
function identity(value) {
return value;
}
function parseComponentURL(url) {
var comp = url.match(/(.*?)([^/]+?)\/?(\.vue)?(\?.*|#.*|$)/);
return {
name: comp[2],
url: comp[1] + comp[2] + (comp[3] === undefined ? '/index.vue' : comp[3]) + comp[4]
};
}
function resolveURL(baseURL, url) {
if (url.substr(0, 2) === './' || url.substr(0, 3) === '../') {
return baseURL + url;
}
return url;
}
httpVueLoader.load = function(url, name) {
return function() {
return new Component(name).load(url)
.then(function(component) {
return component.normalize();
})
.then(function(component) {
return component.compile();
})
.then(function(component) {
var exports = component.script !== null ? component.script.module.exports : {};
if ( component.template !== null )
exports.template = component.template.getContent();
if ( exports.name === undefined )
if ( component.name !== undefined )
exports.name = component.name;
exports._baseURI = component.baseURI;
return exports;
});
};
};
httpVueLoader.register = function(Vue, url) {
var comp = parseComponentURL(url);
Vue.component(comp.name, httpVueLoader.load(comp.url));
};
httpVueLoader.install = function(Vue) {
Vue.mixin({
beforeCreate: function () {
var components = this.$options.components;
for ( var componentName in components ) {
if ( typeof(components[componentName]) === 'string' && components[componentName].substr(0, 4) === 'url:' ) {
var comp = parseComponentURL(components[componentName].substr(4));
var componentURL = ('_baseURI' in this.$options) ? resolveURL(this.$options._baseURI, comp.url) : comp.url;
if ( isNaN(componentName) )
components[componentName] = httpVueLoader.load(componentURL, componentName);
else
components[componentName] = Vue.component(comp.name, httpVueLoader.load(componentURL, comp.name));
}
}
}
});
};
httpVueLoader.require = function(moduleName) {
return window[moduleName];
};
httpVueLoader.httpRequest = function(url) {
return new Promise(function(resolve, reject) {
var xhr = new XMLHttpRequest();
xhr.open('GET', url);
xhr.responseType = 'text';
xhr.onreadystatechange = function() {
if ( xhr.readyState === 4 ) {
if ( xhr.status >= 200 && xhr.status < 300 )
resolve(xhr.responseText);
else
reject(xhr.status);
}
};
xhr.send(null);
});
};
httpVueLoader.langProcessor = {
html: identity,
js: identity,
css: identity
};
httpVueLoader.scriptExportsHandler = identity;
function httpVueLoader(url, name) {
var comp = parseComponentURL(url);
return httpVueLoader.load(comp.url, name);
}
return httpVueLoader;
});

View File

0
public/js/socket.io.js.map → public/js/vendor/socket.io.js.map generated vendored Executable file → Normal file
View File

0
public/js/vue.min.js → public/js/vendor/vue.min.js vendored Executable file → Normal file
View File