Quantcast
Channel: Peter of the Norse Thinks He’s Smarter than You
Viewing all articles
Browse latest Browse all 54

Long time no post

$
0
0

It’s been forever since I added anything here. Life got in the way I suppose.


I thought I had written about the way songs are added to the current playlist, but it looks like I was wrong.

There are three ways to set the song:

  1. Click the “edit” button, and two text fields show up for the artist and song. Fill them in and then either hit return or the edit button again to make them stick.
  2. From the search window, click on the “play” button next to a song. If the edit boxes are on a line change that one, otherwise, change the next.
  3. Songs in rotation can be “Dj Pick”. That means instead of having to play a specific song, the DJ chooses from the entire album. The song is chosen from a pop-up menu.

All three use the same code. We’ll start with the first since it’s the most direct.

We start by making a form with two text fields and two hidden. When we click the edit button, the artist and song fields are made visible and moved and resized to cover the artist and song info on that line of the playlist. The working line is stored one of the hidden fields. The artist and song fields are autocompleting. While the artist field is straightforward, the song field has to send the artist to the server and retrieves the database id with the song name.

As an aside, | is a fucking stupid separator. I changed the code to use <> since it’s invalid HTML and thus should never be a valid value.

The database id is put in the other hidden field. Then when it’s time to set the song, only the the two hidden fields are necessary. The new playlist line is returned and replaces the old one. Here’s the javscript:

function edit(id){
    if (form[0].line.value == id) {
        change();
        return;
    }
    
    var form = $('#edit_form');
    var art = form.children('[name=artist]');
    var son = form.children('[name=song]');
    var line = $('#line_' id).children('.info');
    
    //Overlay the form on the song
    -- Snip CSS code that’s going to change anyways --
    
    form.show();
    art.show();
    son.show();
    art.focus();
    
    form[0].line.value = id;
    form[0].artist.value = line.children('.artist').text();
    form[0].song.value = line.children('.song').text();
    form[0].song_id.value = null;

    art.select();
}

function change(){
    // Less code and faster without jQuery.
    var form = document.getElementById('edit_form');
    
    var callback = function(data, status) {
        $('#line_' data.id).children('.info').html(data.song);
        $('#line_' data.id).children('.concert').html(data.concert);
        
        $(form).hide();
        form.song_id.value = null;
        form.line.value = null;
    }
    
    // Well, some jQuery
    $.post('change/', {id:form.line.value, song_id:form.song_id.value}, callback, 'json');
    
    return false;
}

The artist and song are spans inside a div with class info. The Django code is:

def change(request):
    if request.method == "POST":
        id = int(request.POST['id'])
        line = models.Playlist.objects.get(pk=id)
        
        song_id = int(request.POST['song_id'])
        line.song_id = song_id
        line.save()
            
        return render_to_response('on_air/changed_song.json', {'id':id, 'song':line.song}, mimetype="application/json")

There’s no default return statement since if it’s not a POST with both id and song_id as int, we need to log the false call.


On to the second condition. The search window is called with window.open() so we can make callbacks like this:

function add_to_playlist(id) {
    var form = window.opener.document.forms['edit_form']
    form['song_id'].value = id;
    form.submit();
    window.close();
}

Simple, no? But wait! What if there is no playlist line selected? Then the id the view function will be empty and we’ll get an error. We’ll have to update the view so that it uses the “next” line in that instance.

        if request.POST.get('id'):
            id = int(request.POST['id'])
            line = models.Playlist.objects.get(pk=id)
        else:
            # No id? Get the next blank line
            last_line_played = models.Playlist.objects.filter(played_at__isnull=False).order_by('-order')[0]
            line = models.Playlist.objects.filter(order__gt=last_line_played.order, song__isnull=True).order_by('order')[0]
            id = line.id

So we get the first blank line after all of the ones that have been played. Works for me. And it’s not much more complicated than before we added this feature.


The third option is even easier to add. The pop-up menu is quietly wrapped in a form with a hidden field that has the line id. There’s no fear of it accidentally being sent. <select onchange="change(this.form)">... and

function change(form){
    
    if (!form) form = document.getElementById('edit_form');

That’s right. Only two lines of existing code needs to be changed. Of course, the original code was built with this in mind. Part of my reason for rewriting DJ Pro is to hide the kludge I wrote when I added DJ Picks to the old one.


Viewing all articles
Browse latest Browse all 54

Trending Articles