# Trying to improve my jQuery animation queue

So I built a little baseball "scouting report" graphic that shows stats for players. As you page through the players, their images slide in and out of the graphic. I worked out a way to do this using a jQuery queue, and it works fairly well.

The one hitch is when the graphic is changing from a player on one side of the plate to the other (from a lefty to a righty, for example). Rather than smoothly sliding in, the player just appears there.

I can't work out why that is happening. The transitions are always smooth when they are between players who bat on the same side.

I have stripped this code down to essentially just the parts that deal with the animation queue/sliding. Could you take a look and show me areas where it could be improved?

You can see it in action here: http://dl.dropbox.com/u/27409695/mlb-scouting/baseball-test.html

testArray = [];
testArray[0]  = ['Andrus','XXX','R'];
testArray[1]  = ['Beltre','XXX','R'];
testArray[2]  = ['Chavez','XXX','L'];
testArray[3]  = ['Hamilton','XXX','L'];

jQuery(document).ready(function($) { buildSelectList();$('playerPhoto').hide();

$('#scoutSelect').live('change', function(event) { var userChoice =$(this).val();
if ( userChoice === 'Choose player' ) {
return false;
}
else if (!$('*').is(':animated')) { playerQueue(userChoice); } });$('.arrow').live('click', function(event) {
var player = $(this).attr('player'); if (player !== null && !$('*').is(':animated') ) {
playerQueue(player);
}
});

startUp();
});

});

function buildSelectList() {
var playerLength = testArray.length;
for (i=0; i < playerLength; i++ ) {
jQuery('<option value="'+i+'">'+testArray[i][1]+' '+testArray[i][0]+'</option>').appendTo('#scoutSelect');
}
}

function startUp() {
var theQueue = jQuery('#scouting');
var thisPlayerL = jQuery('#playerPhotoL');
var thisPlayerR = jQuery('#playerPhotoR');
var playerHand = testArray[0][2];
theQueue.queue('josh', function() {
buildPlayer(0);
theQueue.dequeue('josh');
});
theQueue.queue('josh', function() {
if (playerHand === 'R') {
thisPlayerR.switchClass('offstage','onstage',1500);
}
else if (playerHand === 'L') {
thisPlayerL.switchClass('offstage','onstage',1500);
}
theQueue.dequeue('josh');
});
theQueue.dequeue('josh');
}

function playerQueue(playerID) {
var theQueue = jQuery('#scouting');
var thisPlayerL = jQuery('#playerPhotoL');
var thisPlayerR = jQuery('#playerPhotoR');
var playerHand = testArray[playerID][2];
theQueue.queue('josh', function() {
if (thisPlayerL.hasClass('onstage') ) {
thisPlayerL.switchClass('onstage','offstage',1500);
}
else if (thisPlayerR.hasClass('onstage') ) {
thisPlayerR.switchClass('onstage','offstage',1500);
}
theQueue.dequeue('josh');
});
theQueue.queue('josh', function() {
setTimeout("buildPlayer("+playerID+")",1500);

theQueue.dequeue('josh');
});
theQueue.queue('josh', function() {
if (playerHand === 'R') {
thisPlayerR.switchClass('offstage','onstage',1500);
}
else if (playerHand === 'L') {
thisPlayerL.switchClass('offstage','onstage',1500);
}
theQueue.dequeue('josh');
});
theQueue.dequeue('josh');
}

function buildPlayer(playerID) {
var testArraySize = testArray.length;
// make sure playerID is an integer not a string
playerID = parseInt(playerID,10);

// update the arrows' player IDs
var prevPlayer = '';
var nextPlayer = '';
if ((playerID > 0) && (playerID < testArraySize-1)) {
prevPlayer = playerID - 1;
nextPlayer = playerID + 1;
}
else if (playerID === 0) {
prevPlayer = testArraySize-1;
nextPlayer = 1;
}
else if (playerID === testArraySize-1) {
prevPlayer = playerID - 1;
nextPlayer = 0;
}
jQuery('#prevArrow').attr('player',prevPlayer);
jQuery('#nextArrow').attr('player',nextPlayer);

// player info
jQuery('#scouting h1').text(testArray[playerID][0]);

showPlayer(playerID);
}

function showPlayer(playerID) {
jQuery('#playerPhotoL img').remove();
jQuery('#playerPhotoR img').remove();

var playerName = testArray[playerID][0];
var playerHand = testArray[playerID][2];

jQuery('<img src="http://dl.dropbox.com/u/27409695/mlb-scouting/lineup/Rangers/'+playerName+'.png" />')
.appendTo('#playerPhoto'+playerHand);

}


I think you need to keep it simple. This seems much more complicated than need be.

For example why are you removing and then creating again?:

jQuery('#playerPhotoL img').remove();
jQuery('#playerPhotoR img').remove();

var playerName = testArray[playerID][0];
var playerHand = testArray[playerID][2];

jQuery('<img src="http://dl.dropbox.com/u/27409695/mlb-scouting/lineup/Rangers/'+playerName+'.png" />')
.appendTo('#playerPhoto'+playerHand);


I would approach this differently. Firstly make your players into literal objects:

var players = [{
'name': 'Andrus',
'somethingelse': 'XXX',
'hand': 'R'
},
{
'name': 'Beltre',
'somethingelse': 'XXX',
'hand': 'R'
},
{
'name': 'Chavez',
'somethingelse': 'XXX',
'hand': 'L'
},
{
'name': 'Hamilton',
'somethingelse': 'XXX',
'hand': 'L'
}
];


This way you don't have to remember what information is in what element of the list.

Then creat functions:

• next arrow click: moveNextPlayer
• prev arrow click: movePrevPlayer
• Select on change: moveToPlayer

and one to animate called _movePlayers(toPlayerIndex)

here is a jsfiddle to get you started: http://jsfiddle.net/Skt6F/

EDIT:- further on the objects issue ... you have:

testArray = [];
testArray[0]  = ['R',0.169,0.311,0.236,0.288,0.436,0.314,0.27,0.35,0.232,20,26,15,27,null,15,26,31,16,0.253,0.443,0.268,0.353,0.473,0.357,0.348,0.447,0.232,28.9,12.4,14.7,9.6,14.3,20.1,0.288,0.283,0.303,0.225,0.229,0.214,0.254,0.241,0.348,0.231,0.242,0.219,59.9,42.2,12.5];
testArray[2]  = ...


Its still better to have:

var playerData = [{ 'firstName': 'Andrus', 'lastName':'Elvis', 'hand': 'R', 'stats':
[0.263,0.372,0.285,0.337,0.527,0.302,0.323,0.344,0.329,28,40,31,35,null,38,29,45,34,0.491,0.755,0.416,0.742,1.194,0.55,0.569,0.689,0.519,23.5,7.6,8,22.3,17.8,20.7,0.325,0.323,0.33,0.245,0.267,0.174,0.275,0.269,0.318,0.293,0.205,0.358,38.5,60.4,12.1]
},
{ 'firstName': etc
}

];

• You have some good ideas here. I am somewhat new to scripting, so the idea of objects didn't occur to me. They make perfect sense here. The only problem I can see is that the actual application involves more than just the players' names and handedness. There are about 30 different statistical categories in each of the player's arrays (as it exists now). – Kirkman14 Oct 18 '11 at 1:31
• I did embrace your suggestion of not removing and creating the images, and the solution I came up with has eliminated the "sudden appearance" problem I described above. Now all the animation is smooth as silk. You can see it here: dl.dropbox.com/u/27409695/mlb-scouting/baseball-test.html – Kirkman14 Oct 18 '11 at 1:34
• @Kirkman14 you still have the data in lists instead of objects. This is going to be a big problem when you need to revise this six months down the track. Its a very good idea to turn them into objects early on. You can even put categories and their stats in a list inside a property. Check out my edit. – James Khoury Oct 18 '11 at 2:38