views:

213

answers:

9

Hello all,
I've got a confusing problem. I'm working on a music catalog/playlist/player. When a user drags a song into the playlist a request is sent to php (via javascript/ajax) which finds the song in the database and returns song information which is then organized and displayed in the playlist. This works great. The problem I'm having is when an album is dropped on the playlist (which just calls the song processing function recursively). If I have an alert before each song is processed it works perfect; of course I don't want the user to have to click through 20 alerts just to add an album, they should just see the finished product. When I take the alert out, only the last song is displayed. I'm guessing the sever needs more time maybe? The javascript maybe? I don't know,I'm grasping at straws. Has anyone ran into a similar problem?? All help is greatly appreciated...

A: 

Fairly hard to answer this without seeing how you interact with the server. PHP+Mysql should not need more time - that is, if you're waiting for the return message from the server. If, on the other hand, your javascript determines that it wants to do something regardless of whether it has heard back from the server, then you might very well run into race condition problems. Post some code detailing how you communicate between server and script, should make it possible to figure out what goes wrong.

Fake51
+1  A: 

This seems like you might have some race condition somewhere. unfortunately, these are really hard to diagnose without seeing some code. of course, if your code is quite long, it would be very difficult for someone here to figure it out quick enough to want to answer your question and/or solve your problem.

I'd suggest reproducing your problem on a smaller test page. You'd probably solve it in the process, but if you can reproduce it, we can help :-)

Joel Martinez
A: 

Once the song processing function cleans a few things up it does...

if(xmlHttp){
try{
  var params = ("elementId=" + elementId);
  //alert(params);
  xmlHttp.open("GET", "php/p_songInfoRetrevial.php?" + params, true);
  //the weird function stuff is because you're assigning a function to a variable
  xmlHttp.onreadystatechange = function(){p_handleRequestStateChange(elementId, elmVertPosition);};
  xmlHttp.send(null);
}//end try
catch(e){
  alert("Can't connect to server: \n" + e.toString());
}//end catch
}//end if(xmlHttp)
danwoods
A: 

entire initial function (called when anything is dropped on the playlist):

function p_process(elementId){

//alert("entered p_process");
//check if the element dropped is a single song
var newSong = document.getElementById(elementId);
//alert("newSong id = " + newSong.getAttribute('id'));
if(newSong.hasAttribute('class')){
  //alert("newSong has attribute class");
  if(newSong.getAttribute('class') === 'song'|| newSong.getAttribute('class') === 'row-even'||newSong.getAttribute('class') === 'row-odd'){
  alert("newSong is a song");
  //set elements vertical position
  var aryPosition = ObjectPosition(document.getElementById(elementId));
  var elmVertPosition = aryPosition[1];

  //account for clones
  if(elementId.match("clone_")){
   elementId = elementId.substr(6);
   }

  //remove items already in playlist and fix elementId
  if(elementId.match(/\b\d{4}/)){
    //CALL REORDER
    oldNode = document.getElementById(elementId);
    oldNode.parentNode.removeChild(oldNode);

    //snyc player and playlist (decrement)
    //alert("sending " + elementId + " updateFlashPlrIndex");
    updateFlashPlrIndex(elementId, 'dec');
    //alert("returned from syncplrsub");

    //remove leading playlist number (####)
    elementId = elementId.substr(4);
  }//end if

  if(xmlHttp){
    try{
      var params = ("elementId=" + elementId);
      //alert(params);
      xmlHttp.open("GET", "php/p_songInfoRetrevial.php?" + params, true);
      //the weird function stuff is because you're assigning a function to a variable
      xmlHttp.onreadystatechange = function(){p_handleRequestStateChange(elementId, elmVertPosition);};
      xmlHttp.send(null);
    }//end try
    catch(e){
    alert("Can't connect to server: \n" + e.toString());
  }//end catch
}//end if(xmlHttp)
}//end inner if

//new element is not a song
else if(newSong.getAttribute('class') === 'show'){
//alert("entered else");
var newElm = newSong;
for(var currElm = newElm.firstChild.nextSibling.nextSibling; currElm !== null; currElm = currElm.nextSibling){
//alert("currElm being sent to p_process = " + currElm.getAttribute('id'));
p_process(currElm.getAttribute('id'));
}//end for
}

else{//need to skip over <ol>s, this will only work for sets/encores
alert("entered else");
var newElm = newSong;
for(var currElm = newElm.firstChild.nextSibling; currElm !== null; currElm = currElm.nextSibling){
//alert("currElm being sent to p_process = " + currElm.getAttribute('id'));
p_process(currElm.getAttribute('id'));
}//end for
}//end else
}//end outer if
}
danwoods
which all works perfect as long as I have an 'alert' somewhere in the song section..
danwoods
and only shoows the last song on the album if I take it out...
danwoods
A: 

This may be to javascript threading that does not exist.

My tip is to run it with setTimeout('p_process(elementId):',0); on your dropevent Then browser will not be blocked by javascript.

.. also maybe you should also take a look at jQuery to make ajax a little easier ;)

walming
A: 

Did you check your DOM tree and/or your access_log? Maybe your songs are actually present, but something in your process prevents them from being displayed properly.

Alsciende
A: 

I do belive that you have a bug on your js code. You may overwrite the contents of the container containing the dropped items, or all the items get rewritten in the same place.

Try logging every move you make and make some heavy use of firebug if you cant spot anything wrong with your js code on the first sight.

Quamis
A: 

Have the script be able to send multiple song requests, and then return one response. If you look at firebug you are probably sending multiple requests and receiving multiple back.

Either javascript is overwritting itself OR what is more likely, the last song is the first processed but the last returned, so the other songs are added after the last song is.

So honestly just have them all in one request, you have a server-side race condition with client-side latency.

Gus
A: 

What is this piece doing?

   //remove items already in playlist and fix elementId
   if(elementId.match(/\b\d{4}/))
   {
    //CALL REORDER
    oldNode = document.getElementById(elementId);
    oldNode.parentNode.removeChild(oldNode);

    //snyc player and playlist (decrement)\
    updateFlashPlrIndex(elementId, 'dec');

    //remove leading playlist number (####)
    elementId = elementId.substr(4);
   } // end if( elementId.match(/\b\d{4}/) )

Your comment says it is removing the items in the playlist, could this be part of your issue?

Also you should send the full array of id's to the server in one call and retrieve the data as an array and process it all at once. If you do something like this for your parameters:

var params = "elementIDs=[" + elementIDs.join() + "]";

You will have a json encoded array of elementIDs. Of course elementIDs will need to be an array of all the id's that were sent in. Then in your php decode it using the json_decode function like this:

//  Parameter checking goes here
$elementIDs = json_decode($_GET['elementIDs']);

Then you'll have an array to work with in your php. Once you are done processing it be sure that whatever form you return the data in also supports arrays. Another advantage here is that you wont have any special case processing for only one item which will get rid of some of the bulk of your code and remove any recursion.

Oz