function VotingControl(initial_page) {
  var current_page = initial_page;
  var total_pages = initial_page;
  
  var voting_page_info = "#voting_page_info";
  var vote_button_first = "#vote_button_first";
  var vote_button_previous = "#vote_button_previous";
  var vote_button_next = "#vote_button_next";
  var vote_button_last = "#vote_button_last";
  var voting_list = "#voting_list";

  var image_first = "/static/resultset_first";
  var image_previous = "/static/resultset_previous";
  var image_next = "/static/resultset_next";
  var image_last = "/static/resultset_last";
  
  function getButtonUrl(base_url, enabled) {
    var disabled_text = "_disabled.png";
    var enabled_text = "_enabled.png";
    
    if(enabled) {
      return base_url + enabled_text;
    }
    else {
      return base_url + disabled_text;
    }
  }

  $(vote_button_first).click(function() {
    gotoFirstPage();
  });
  
  $(vote_button_previous).click(function() {
    gotoPreviousPage();
  });
  
  $(vote_button_next).click(function() {
    gotoNextPage();
  });
  
  $(vote_button_last).click(function() {
    gotoLastPage();
  });
  
  function gotoFirstPage() {
    if(current_page == 1) {
      return;
    }
    else {
      getPage(1);
    }
  }
  
  function gotoPreviousPage() {
    if(current_page == 1) {
      return;
    }
    else {
      getPage(current_page - 1);
    }
  }
  
  function gotoNextPage() {
    if(current_page == total_pages) {
      return;
    }
    else {
      getPage(current_page + 1);
    }
  }
  
  function gotoLastPage() {
    if(current_page == total_pages) {
      return;
    }
    else {
      getPage(total_pages);
    }
  }
  
  function updateContainer(data) {
    $(voting_list).empty();
    $.each(data.result_set, function(idx) {
      //create the list
      var el = data.result_set[idx];
      var header = "<div><span>";
      var vote_up_id = "vote_up_" + el.id;
      var vote_down_id = "vote_down_" + el.id;
      var vote_count_id = "vote_count_" + el.id;
      header += '<img id="' + vote_up_id + '" src="/static/tick.png" />';
      header += '<img id="' + vote_down_id + '" src="/static/cross.png" />';
      header += '(<span id="' + vote_count_id + '">' + el.vote_count + '</span> Votes)';
      header += "</span></div>";
      var joke_text = "<div>" + el.joke_text + "</div>";
      $(voting_list).append("<li>" + header + joke_text + "</li>");
      
      //add event handlers to the list
      var updating_joke = false;
      function updateVote(data) {
        if(updating_joke) return;
        
        if(data.success) {
          $("#"+vote_count_id).html(data.vote_count);
        }
        else {
          if(data.message == "joke_id does not exist") {
            getPage(current_page);
            return;
          }
          updating_joke = true;
          $("#vote_message_box").html(data.message)
            .slideDown(1000)
            .animate({opacity: 1.0}, 2000)
            .slideUp(1000, function(){
              updating_joke = false;
            });
        }
      }
      
      $("#"+vote_up_id).click(function() {
        $.post("/joke/vote", {"action":"upvote", "joke_id":el.id}, function(data) {
          updateVote(data);
        }, "json");
      });
      
      $("#"+vote_down_id).click(function() {
        $.post("/joke/vote", {"action":"downvote", "joke_id":el.id}, function(data) {
          updateVote(data);
        }, "json");
      });
    });
  }
  
  function updateButtons(data) {
    //update the buttons
    $(vote_button_first + " > img").attr('src', getButtonUrl(image_first, current_page > 1));
    $(vote_button_previous + " > img").attr('src', getButtonUrl(image_previous, current_page > 1));
    $(vote_button_next + " > img").attr('src', getButtonUrl(image_next, current_page < total_pages));
    $(vote_button_last + " > img").attr('src', getButtonUrl(image_last, current_page < total_pages));
    
    //update the page counts
    $(voting_page_info).html(current_page + " of " + total_pages);
  }
  
  function update(data) {
    updateContainer(data);
    updateButtons(data);
  }
  
  function getPage(page) {
    $.getJSON("/joke/page/" + page, function(data) {
      if(data.success) {
        //update the internal vars with server data
        current_page = data.page_number;
        total_pages = data.total_pages;
        update(data);
      }
      else {
        //just go to the first page if the page does not exist
        getPage(1);
      }
    });
  }

  function init() {
    getPage(initial_page);
  }
  
  init();
}