Play uploaded music in Rails - javascript

I have an app which allows users to upload music, but I'm having trouble setting up a player which allows them to then play that music.
On a user's page, this is a simplified example of his/her top tracks:
<% #top_tracks.each do |track| %>
<div class="top-track">
<button class="btn-play">
<i class="icon-play"></i>
</button>
<span><%= track.title %></span>
</div>
<% end %>
Each track has several properties, including but not limited to: title (self-explanatory), album_id (every track belongs to an album), file_url (URL of the MP3 file for the track), and album_position (order of the track within the album).
I would like to be able to click the .btn-play button for each track and have the corresponding audio play. Ideally, I would also have a dedicated player at the bottom of the page with full controls to pause, seek, adjust volume, and display the currently-playing song's information.
A simplified version of that player would look like this:
<div class="player">
<button class="play">
<i class="icon-play"></i>
</button>
<button class="pause">
<i class="icon-pause"></i>
</button>
<div>
<div class="now-playing">[currently playing track title would go here]</div>
<div class="seekbar"></div>
</div>
<div>
<button class="mute">
<i class="icon-mute"></div>
</button>
</div>
</div>
I'm not overly familiar with Javascript, or how to use methods such as .play() or .pause(). I have looked into the mediaelement_rails gem, but I'm not sure if that would be useful in this case. To summarize, how would I hook up the tracks so that:
1) when I click the .btn-play button it plays the track
2) the track's info would populate the appropriate info in the player
3) the player's controls would control the currently-playing track

If you want a full-featured player, then mediaelement.js is a good way to go, as it has fallback players for older browsers. Note that you do not have to use the rails, it's essentially just a wrapper for the js itself. That's up to you and how you want your application assets to be used/stored/called.
For BASIC html5 audio output, this is what I would:
Create a button with a data attribute of file source
Use jquery to grab the click event when a user clicks the button
Build an audio tag using the data attribute url with the autoplay option enabled (so it starts playing as soon as it's loaded)
So for a code example:
<button class="audioplay au-<%= upload.id %> btn btn-default" data-audiofile="/music.mp3">
Play Now
</button>
<script>
$(".audioplay").on("click", function(){
var source = $(this).data("audiofile");
var player = '<audio class="audioplayer" src="'+source+'" controls autoplay></audio>';
$(this).after(player);
});
</script>
Obviously, this is really really bare bones... it doesn't protect from clicking play multiple times, or removing any other players when a different song is selected, but those are things you can handle in javascript.

In addition to using audio_tag as Antarr Byrd has suggested, you can use Javascript to manipulate the media as described here.
For example, you could use the following:
<%= audio_tag #track.path, id: 'player' %>
<button id="play">Play</button>
<button id="pause">Pause</button>
With this accompanying Javascript:
$('#play').click(function() {
$('#player').get(0).play();
});
$('#pause').click(function() {
$('#player').get(0).pause();
});
One thing to note is that in the case of my example, #track.path refers to the name of the file in the /public/audios/ directory.

Related

Custom Audio Player play and pause button

I am creating an audio playlist. I have created the custom audio player using the code below. It works fine although the issue is that i have auto play on which means that when the first song is over it automatically goes into the next song. This causes the play pause button to be all messed up. It is kind of hard to explain though if you go to this link and go the very end of a song you will know what i mean. Please help me, this is really holding me back.
<!--HTML5 audio-->
<audio id="audioPlayer" preload="true">
<source src="oh-my.mp3">
</audio>
<div id="wrapper">
<!--Audio Player Interface-->
<div id="audioplayer">
<button id="pButton" class="play"></button>
<div id="timeline">
<div id="playhead"></div>
</div>
</div>
</div>
<script src="js/html5audio.js" type="text/javascript"></script>
I'd recommend listening to the onplay event in your JavaScript. This event is raised when the audio starts playing. Here's an example:
document.getElementById('audioPlayer').onplay = function(){
document.getElementById('pButton').style.background = "url(pause.png)"
}
This causes the button to be changed to a pause button whenever the audio plays, regardless of whether is was started by a user click. I hope this helps!
EDIT
I've looked at your code some more, and I've discovered that this works:
$("#audioPlayer").on("ended play", function(){
$("#pButton").addClass("pause").removeClass("play")
})

Access to repetitive tags in jQuery

So I've got this piece of HTML (it's mp3 player):
<div id="player-body_0" class="player-body">
<audio id="player_0" class="player">
<source src="http://www.noiseaddicts.com/samples_1w72b820/2543.mp3" type="audio/mpeg" />
</audio>
<div id="audio-player_0" class="audio-player">
<div id="controls_0" class="controls">
<i id="play_0" class="fa fa-play play"></i>
<span id="start-time_0" class="time start-time">00:00</span>
<div id="progressbar_0" class="progressbar"></div>
<span id="time_0" class="time">00:00</span>
<i id="mute_0" class="fa fa-volume-up mute" onclick=""></i>
<div id="volume_0" class="volume"></div>
</div>
</div>
</div>
code is automatically generated, so I could have 30+ players like this all on the same website. Ids in tags of course will increment in every next player-body.
How could I manage all this players with generic methods in jQuery?
To manage player mute button I could have something like this:
var mute_button = $('.mute');
var player = document.getElementById('player_0');
mute_button.click(function() {
$(this); //clicked mute button
//how to easily access proper audio tag without using its id?
});
But how in above function I could access audio player tag without using its id? As I said I want methods to be generic I can't just repeat them like 30+ times.
From the .mute icon... Lookup for the parent matching the .player-body... Then lookdown, using .find(), for the <audio> tag using the .player class...
You now have the target element!
Then simply mute it... Okay... You need the DOM element, not the jQuery object. But you have it using [0] against a jQuery object because the DOM element is the first property.
Concretely, it's a one liner:
$('.mute').on('click', function(){
$(this).parents(".player-body").find(".player")[0].muted = true;
});
That is what's called "traversing" DOM elements...
You just have to know a couple jQuery methods to navigate. ;)
You can use closest method to target the container that encompasses the controls and the player.
$('.mute').on('click', function() {
const $player = $(this).closest('.player-body').find('.player');
});
Another alternative to closest(), but only if id are consistent within the same audio player, could be getting that id and use it to target the related audio player:
Example:
$('.mute').on('click', function()
{
let id = $(this).attr("id").split("_")[1];
let audPlayer = $('#player_' + id);
});

Stop CSS-animation when embedded YT is played

I've been trying to find some good ways of fixing this, but with no avail.
I've got a profile website I'm working on that uses a carousel to show of some of my previous work.
One of the items of the carousel is a YT iFrame. The carousel has two main functionalities:
A next and a previous buttons to navigate the carousel and
An animation that gets triggered when you mouse over an item of the carousel; much like flipping a card it turns over and displays some details of the project.
The items in the carousel are mainly images, but I've also added a YT iFrame. The problem I'm facing is quite obvious; when you hover over the item containing the iFrame it starts the flip-animation.
So what I need to do is check when the video is being played and then disable the animation (preferably for that item only)...
Any advice on how I could do that?
This is a codepen taken straight from my local machine (hence the script references).
https://codepen.io/Todai/pen/GqGJxR
Some sample code:
<div class="item c">
<div id="f1_container">
<div id="f1_card" class="shadow">
<div class="front face">
<iframe width="250" height="200" src="https://www.youtube.com/embed/92i9TvuVtQc" frameborder="0" allowfullscreen></iframe>
</div>
<div class="back face center">
<p>A distributed software built in Erlang, using a MSSQL instance and
a C# Web Api end-point.</p>
<p>I was in charge with working on the Android and web front-end.</p>
<span> <i class="fa fa-github fa-2x"> </i> </span>
</div>
</div>
</div>
</div>
I think you should use IFrame player API. So you can embed a YouTube video player into your page and control player using JavaScript. The API will calls the onPlayerStateChange function when the player's state changed. And you will know when the video is playing and then remove the animation. You can see the following code below: The animation will add again until the video finish playing.
var done = false;
function onPlayerStateChange(event) {
if (event.data == YT.PlayerState.PLAYING && !done) {
stopAnimation();
done = true;
}else{
startAnimation();
done=false;
}
}
function stopAnimation() { $("#player").parent().parent().addClass('notransition');
} function startAnimation(){ $("#player").parent().parent().removeClass('notransition');
}
You will need the YouTube API for this, then use JS to detect if the video is playing and then only prevent flipping of the tile by ID.

How do I make my back button link to the previous page the user has been on?

I'm making a wedding website, basically the site is one big nav optimised for touch and there are 3 main sections: The Wedding, Travel and The Town. Each section then has sub-sections inside it, The Wedding has The Ceremony and Reception, Travel has Flights, Transfers and Accommodation and The Town has About Malcesine, Things To Do and Weather.
Now, on all of those pages is also a link to the RSVP page and there are also home & back buttons. On the RSVP page I need the back button to go back to whatever page the user was on but I can't figure out how to get it to link to more than one page? I've looked here and on Google but can't find anything
Here's my code for the header section of the RSVP page which involves the home & back buttons:
<header class="mainHeader">
<h1>RSVP</h1>
<nav class="secondaryNav">
<img class="backButton" src="img/back2.png" alt="Back Button">
<img class="homeButton" src="img/home.png" alt="Home Button">
</nav>
<aside><p id="countdown"></p></aside>
</header>
<!-- end .mainHeader -->
The back button is currently linking to just the Town sub-section. The countdown paragraph is a countdown timer. Am I right in thinking i'll need to use some form of javascript?
history.go(-1); does it, so I guess the easiest implementation would be inline:
<img class="backButton" src="img/back2.png" alt="Back Button" onclick="history.go(-1);" />
Though you'd probably want to remove that anchor, or at least its href attribute.
There's a way to do this in href, but it's not the best approch:
...
If you are ok with using JavaScript then you can:
Back

Vimeo Gallery - separate title div - to change dynamically

Hi I am trying to build a gallery of videos on our website, and I have already done 90% of it, using the help from the following topic
Javascript Vimeo Gallery Basics
<div class="vimeo-container">
<iframe id="vplayer"
src="http://player.vimeo.com/video/.." frameborder="0" webkitallowfullscreen mozallowfullscreen allowfullscreen></iframe>
</div><!--vimeo-container-->
<div id="vplayer_title">
<p>INSERT VIMEO VIDEO TITLE HERE FOR EACH VIDEO<p>
</div><!--vplayer_title-->
<div class="bucketthumbs">
<a class="video-thumbnail" href="http://player.vimeo.com/video/.." video-uri="http://player.vimeo.com/video/..">
<div class="bucket">
<img class="gt_orrery" src="images/thumb_1.jpg">
<div class="title_bucket" id="thumb1_title">
<p>VIDEO TITLE HERE FOR THIS VIDEO<p>
</div><!--title_bucket-->
</div><!--bucket1-->
</a>
<a class="video-thumbnail" href="http://player.vimeo.com/video/.." video-uri="http://player.vimeo.com/video/..">
<div class="bucket">
<img class="gt_orrery" src="images/thumb_2.jpg">
<div class="title_bucket" id="thumb2_title">
<p>VIDEO TITLE HERE FOR THIS VIDEO<p>
</div><!--title_bucket-->
</div><!--bucket1-->
</a>
<a class="video-thumbnail" href="http://player.vimeo.com/video/.." video-uri="http://player.vimeo.com/video/..">
<div class="bucket">
<img class="gt_orrery" src="images/thumb_3.jpg">
<div class="title_bucket" id="thumb3_title">
<p>VIDEO TITLE HERE FOR THIS VIDEO<p>
</div><!--title_bucket-->
</div><!--bucket1-->
</a>
</div><!--bucketthumbs-->
This is my html. Using the above topic. I am successfully able to target the thumbnails to change the video in the iframe.
<script>
$(function() {
// Add an event listener to the click event for each of your thumbnails
$('.video-thumbnail').click(function(e) {
// changes src of the iframe to the one we stored in the clicked thumbnail
$('#vplayer').get(0).src = this.getAttribute('video-uri');
// stops default browser behaviour of loading a new page
e.preventDefault();
});
});
</script>
But I dont want to use the title that vimeo has on the video.
Instead I want to display it below the main video and have it change with the video, pulling the titles from vimeo.
I am only a front end developer and my knowledge of javascript and API is extremely limited. I tried to use the same code to get the titles to change too but since that uses src, and attribute i dont think i know how to make it work.
Could someone pls help!? :(
I believe Vimeo has oEmbed that can make it easier. But I cant really understand much of the API, its too basic for me, If its too complicated to solve this issue by using vimeo video titles, a second aleternative would be for me to manually enter the titles on the respect bucket divs, all i need to know is how to dynamically change the title in the main vplayer_title div
You might want to use the player's JS API: https://developer.vimeo.com/player/js-api
Something like this in your thumbnail click event:
var player = $f(iframe);
player.addEvent('ready', function() {
player.api('getVideoTitle', function(title) {
// set the title contents here
$('#vplayer_title').html('<p>' + title + '</p>');
});
});

Categories