Editing User:Toad64/SandboxGive feedback
Jump to navigation
Jump to search
The edit can be undone.
Please check the comparison below to verify that this is what you want to do, and then publish the changes below to finish undoing the edit.
| Latest revision | Your text | ||
| Line 1: | Line 1: | ||
<div class="my-custom-player-wrapper"><syntaxhighlight lang="javascript"> | |||
<syntaxhighlight lang="javascript"> | |||
// gemini code | // gemini code | ||
// In your Common.js | // In your Common.js | ||
$(document).ready(function() { | $(document).ready(function() { | ||
// Find every native audio player generated by the wiki | |||
$('audio').each(function() { | $('audio').each(function() { | ||
const | // Create your custom component | ||
const myPlayer = document.createElement('audio-player'); | |||
// Transfer the source | |||
myPlayer.setAttribute('track', $(this).attr('src')); | |||
// | // Replace the native player with your custom one | ||
$(this).replaceWith(myPlayer); | |||
}); | }); | ||
}); | }); | ||
// audioplayer.js (pulled | // audioplayer.js (pulled from website) | ||
if (!customElements.get('audio-player')) { | if (!customElements.get('audio-player')) { | ||
class AudioPlayer extends HTMLElement { | |||
connectedCallback() { | |||
const ext = src.split(".").pop().toLowerCase(); | |||
const song = this.getAttribute("song") || ""; | |||
const artist = this.getAttribute("artist") || ""; | |||
const src = this.getAttribute("track") || ""; | |||
const cover = this.getAttribute("artcover") || ""; | |||
const originalArtist = | |||
this.getAttribute("originalartist") || ""; | |||
const originalSource = | |||
this.getAttribute("originalsource") || ""; | |||
const ext = src.split(".").pop().toLowerCase(); | |||
let mime = "audio/mpeg"; | |||
if (ext === "wav") { | |||
mime = "audio/wav"; | |||
} | |||
this.innerHTML = ` | |||
<style> | |||
.player { | |||
display: flex; | |||
width: 100%; | |||
max-width: 500px; | |||
min-height: 150px; | |||
background: var(--box-color); | |||
color: white; | |||
border-radius: 12px; | |||
overflow: hidden; | |||
font-family: Arial, sans-serif; | |||
} | |||
.cover { | |||
width: 40%; | |||
object-fit: cover; | |||
background-color: #333; | |||
display: block; | |||
} | |||
.info { | |||
width: 60%; | |||
padding: 12px; | |||
display: flex; | |||
flex-direction: column; | |||
justify-content: space-between; | |||
gap: 10px; | |||
} | |||
.meta { | |||
display: grid; | |||
grid-template-columns: 1fr 1fr; | |||
gap: 12px; | |||
} | |||
.leftmeta, | |||
.rightmeta { | |||
display: flex; | |||
flex-direction: column; | |||
gap: 4px; | |||
} | |||
h3 { | |||
margin: 0; | |||
font-size: 16px; | |||
} | |||
p { | |||
margin: 0; | |||
font-size: 12px; | |||
opacity: 0.7; | |||
} | |||
.credit { | |||
font-size: 11px; | |||
opacity: 0.6; | |||
line-height: 1.4; | |||
} | |||
.controls { | |||
display: flex; | |||
align-items: center; | |||
gap: 10px; | |||
width: 100%; | |||
} | |||
.playBtn { | |||
width: 24px; | |||
height: 24px; | |||
background: var(--green-color); | |||
border: none; | |||
color: white; | |||
padding: 3px 8px; | |||
border-radius: 50px; | |||
cursor: pointer; | |||
<div class="player | flex-shrink: 0; | ||
<audio class="audio"><source src="${src}" type="${mime}"></audio> | } | ||
.playBtn:hover { | |||
background: var(--green-hover); | |||
} | |||
.playBtn:active { | |||
background: var(--green-active); | |||
} | |||
.seek { | |||
-webkit-appearance: none; | |||
appearance: none; | |||
border-radius: 50px; | |||
flex: 1; | |||
background-color: #7e7e7e; | |||
height: 7px; | |||
min-width: 0; | |||
} | |||
.seek::-webkit-slider-thumb { | |||
-webkit-appearance: none; /* Override default look */ | |||
appearance: none; | |||
border-radius: 50px; | |||
width: 15px; | |||
height: 15px; | |||
background: var(--green-color); | |||
cursor: pointer; | |||
} | |||
.seek::-moz-range-thumb { | |||
border-radius: 50px; | |||
width: 15px; | |||
height: 15px; | |||
background: var(--green-color); | |||
cursor: pointer; | |||
} | |||
.time { | |||
font-size: 12px; | |||
opacity: 0.8; | |||
white-space: nowrap; | |||
} | |||
@media (max-width: 800px) { | |||
.player { | |||
flex-direction: column; | |||
} | |||
.cover { | |||
width: 100%; | |||
height: 180px; | |||
} | |||
.info { | |||
width: auto; | |||
} | |||
.meta { | |||
grid-template-columns: 1fr; | |||
} | |||
.controls { | |||
flex-wrap: wrap; | |||
} | |||
.time { | |||
width: 100%; | |||
} | |||
} | |||
</style> | |||
<div class="player"> | |||
<img class="cover" src="${cover}" alt="${song} cover art"> | |||
<div class="info"> | |||
<div class="meta"> | |||
<div class="leftmeta"> | |||
<h3>${song}</h3> | |||
<p>${artist}</p> | |||
</div> | |||
<div class="rightmeta"> | |||
<div class="credit"> | |||
Original Artist: ${originalArtist} | |||
</div> | |||
<div class="credit"> | |||
Original Source: ${originalSource} | |||
</div> | |||
</div> | |||
</div> | |||
<audio class="audio"> | |||
<source src="${src}" type="${mime}"> | |||
</audio> | |||
<div class="controls"> | |||
<button class="playBtn"><i class="fa-solid fa-play"></i></button> | <button class="playBtn"><i class="fa-solid fa-play"></i></button> | ||
<input class="seek" type="range" value="0" min="0" max="100"> | |||
<input | |||
class="seek" | |||
type="range" | |||
value="0" | |||
min="0" | |||
max="100"> | |||
<span class="time">0:00 / 0:00</span> | <span class="time">0:00 / 0:00</span> | ||
</div> | </div> | ||
const audio = this.querySelector(".audio"); | </div> | ||
</div> | |||
`; | |||
// component-local elements | |||
const audio = this.querySelector(".audio"); | |||
const playBtn = this.querySelector(".playBtn"); | |||
const seek = this.querySelector(".seek"); | |||
const time = this.querySelector(".time"); | |||
// play / pause | |||
playBtn.addEventListener("click", () => { | |||
if (audio.paused) { | |||
audio.play(); | |||
playBtn.innerHTML = '⏸'; | |||
} else { | |||
audio.pause(); | |||
playBtn.innerHTML = '▶'; | |||
} | } | ||
}); | |||
// update seek bar + time | |||
audio.addEventListener("timeupdate", () => { | |||
seek.value = | |||
(audio.currentTime / audio.duration) * 100 || 0; | |||
time.textContent = | |||
formatTime(audio.currentTime) | |||
+ " / " + | |||
formatTime(audio.duration); | |||
}); | |||
// seeking | |||
seek.addEventListener("input", () => { | |||
audio.currentTime = | |||
(seek.value / 100) * audio.duration; | |||
}); | |||
// reset button when song ends | |||
audio.addEventListener("ended", () => { | |||
playBtn.innerHTML = '▶'; | |||
}); | |||
// format time helper | |||
function formatTime(sec) { | |||
if (isNaN(sec)) return "0:00"; | |||
const m = Math.floor(sec / 60); | |||
const s = Math.floor(sec % 60) | |||
.toString() | |||
.padStart(2, "0"); | |||
return `${m}:${s}`; | |||
} | } | ||
} | } | ||
} | } | ||
customElements.define("audio-player", AudioPlayer); | |||
} | |||
[[File: | </syntaxhighlight>This code creates this (visually bugged but code is functional): | ||
[[File:Curio music.mp3]] | |||
</div> | |||