views:

243

answers:

3

Hi folks, I'm new here, but I love the site. I checked through the other similar questions, but I didn't see what I'm looking for.

I'm a musician, and I've been doing a "song of the day" thing for a while where I write a little song every day. I want to post the songs as <div>s inside <li>. In the divs, I just want a simple mp3 player and a "like" or "dislike" button. The user can vote and the song will move up or down the <li> based on the number of votes.

I want to keep this simple with the math-just subtracting the dislikes from the likes in the <li> array and ordering them from highest to lowest.

It'd be good to have a simple cookie system in place to at least keep someone from voting a lot all in one sitting, but I'm not too concerned about it.

I've been looking for a simple PHP or Javascript tutorial on this. Can anyone point me in the right directions? Thanks!

+3  A: 

You're going to need a central location to store this song information, mainly the votes, but you might as well through the other song information (like title, path to music file, etc) in there as well. I suggest a simple MySQL table as follows

CREATE TABLE daily_song (
    daily_song_id SMALLINT UNSIGNED NOT NULL AUTO_INCREMENT,
    vote          INT          NOT NULL DEFAULT 0,
    title         VARCHAR(255) NOT NULL DEFAULT "" COMMENT "Name of the song",
    path          VARCHAR(255) NOT NULL DEFAULT "" COMMENT "Path to the song on the server",
    ctime         DATETIME     NOT NULL            COMMENT "Datetime the song was added",
    PRIMARY KEY(daily_song_id)
);

I used the following HTML structure:

<ul id="daily-songs">
    <li id="song-id-1">
        <h3>Song 1</h3>
        <div class="voting-controls">
            <a href="#" class="vote-up">Up</a>
            <div class="votes">8</div>
            <a href="#" class="vote-down">Down</a>
        </div>
        <div class="player"></div>
    </li>
    <li id="song-id-2">
        <h3>Song 2</h3>
        <div class="player"></div>
        <div class="voting-controls">
            <a href="#" class="vote-up">Up</a>
            <div class="votes">5</div>
            <a href="#" class="vote-down">Down</a>
        </div>
    </li>
    <li id="song-id-3">
        <h3>Song 3</h3>
        <div class="player"></div>
        <div class="voting-controls">
            <a href="#" class="vote-up">Up</a>
            <div class="votes">4</div>
            <a href="#" class="vote-down">Down</a>
        </div>
    </li>
</ul>

And a touch of CSS

#daily-songs li { clear: both; list-style: none; }
#daily-songs h3 { margin: 0 10px 0 0; float: left; }
#daily-songs .voting-controls { height: 1em; }
#daily-songs .voting-controls * { float: left; }
#daily-songs .voting-controls .votes { padding: 0 10px; }

Here's the JavaScript, using jQuery

$(function() {
    var listContainer = $("#daily-songs"),
        songs         = [];
    var songSort = function(a, b) {
        return +b.vote.text() - +a.vote.text();
    };

    var submitVote = function(song, delta) {
        $.post("vote.php", 
            {
                id:    song.node.attr("id").match(/\d+$/)[0],
                delta: delta,
                votes: song.vote.text() // temporary
            }, 
            function(data) {
                if ( isNaN(data) ) { return; }
                song.vote.text(data);

                // Re-order the song list
                $.each(songs.sort(songSort), function() {
                    listContainer.append(this.node);
                });
            }
        );
    };

    listContainer.find("li").each(function() {
        var $this = $(this); 
        var song  = {
            node: $this,
            vote: $this.find(".votes")
        };
        $this.find(".vote-up").click(function() {
            submitVote(song, 1);
        });
        $this.find(".vote-down").click(function() {
            submitVote(song, -1);
        });

        songs.push(song);
    });
});

And some stub PHP for vote.php:

<?php

$songId = !empty($_POST['id'])    ? (int)$_POST['id']    : 0;
$delta  = !empty($_POST['delta']) ? (int)$_POST['delta'] : 0;

if ( !$songId || !$delta ) {
    die("Invalid parameters");
}

// Make sure the voting value is within the valid rang
$delta = $delta > 0 ? 1 : -1;

// Check to see if user has already voted for this song,

// If they haven't voted yet, connect to the database

// If the database connection is succesful, update song entry
// UPDATE daily_song SET votes=votes+$delta WHERE daily_song_id=$songId

// If the UPDATE is successful, SELECT the new vote value
// SELECT vote FROM daily_song WHERE daily_song_id=$songId

// Output the new vote value

// But for now, just accept the current vote and apply the delta
echo $_POST['votes'] + $delta;

I'll leave the PHP for you to fill in. Shouldn't be too much of a stretch. Let me know if you have any questions.

Justin Johnson
Thanks Justin. I'm afraid I'm stuck. I'm really quite a noob at this stuff, so please bare with me. I have my daily_songs.php page with this basic structure, is this correct?<head><css include><script><jquery include></script><script><your javascript function inline></script></head><body><html form></body>Is that correct? I'm also looking at the html, and I will need to replace some of that with php variables pulled from the db, right? like <h3>Song 1</h3> would be <h3><?php the name of the song that has the most votes, etc ?>
Joel
You're on the right track with the PHP variables, but don't forget to include a doctype and `html` tags in your HTML page. Take a look at http://jsbin.com/eriwa so you can get the idea (put ignore the google tracking scripts at the bottom).
Justin Johnson
Hi Justin...doctype and tags don't matter at this point when just trying to get this to work...I'm still just stuck trying to get this example happening.
Joel
A: 

Yeah, a MySQL table seems critical, to maintain the votes as you collect them. Then a function to return or output the <li>'s in sorted order, as you are constructing the page. If Justin doesn't come back with more, I will add more later.

Dave
A: 

ugh-I'm trying to reply with code snips but it's telling me I'm using hyperlinks (though I'm not...)

This is looking really great. I can get the javascript to move the song titles up and down, but I'm having trouble when I try and include vote.php

Am I supposed to be including that? I have it as an include in the head section, and I get the Invalid parameters error.

I am connecting to the db.

Cheers, joel

Joel
This is more of an edit (to your original question) or as a comment to Justin's answer. If you're having trouble posting something, leave it in it's original form and someone will edit your post to get it looking right.
Nick Presta
Let me see if I can post this one link-here is what I have so far-please note, I took out vote.php so you can view the surrce so far...can you tell me where to include it?http://mbira.me/daily_song.phpPlease also note that in the vote div, I have this code:<div class="votes">5<?php echo $_POST['votes'] + $delta; ?></div>
Joel
Hi Nick-It wouldn't let me post because of the link. :( I removed the link and tried again, but it kept saying I couldn't post links until I have more posts...not sure why?
Joel
@Joel You've moved the sorting logic outside of the AJAX callback, which you don't want to do since it executes asynchronously.
Justin Johnson
Justin-Can you please clarify what you mean? I'm afraid that is over my head.
Joel