I’m trying to pass local variables to an inline function in javascript and have that (inline) function manipulate those variables, then be able to access the changed variable values in the containing function. Is this even possible? Here’s a sample of the code I’m working with:
function addArtists(artist, request, origElm, xml){
//variables
var artistIdArray = [];
/*coding*/
//traverse xml
$('element', xml).each(function(){
/*coding*/
$.ajax({
/*parameters*/
success: function(html) {
var artistAbb = html;
/*coding*/
//add this element's id to the array of ids to make it draggable later
artistIdArray.push(artistAbb);
alert(artistIdArray[artistIdArray.length - 1]);
}//end on success
});//end ajax call
});//end each(function()
alert(artistIdArray.length);
}
The problem is I keep getting artistIdArray.length = 0, even though elements are several elements are ‘alerted’ after they’re added to the array.
Like I said, I don’t know if it’s even possible without global variables or objects. Any ideas? Am I totally wrong?
Edit: Entire function
function addArtists(artist, request, origElm, xml){
//variables
var artistIdArray = [];
//create ordered list
//set new <ol>s class
var olClass = "artists"; //holds the class of new <ol>
//create id for new <ol>
var olId = "artists"; //holds the id of new <ol>
//create actual <ol> element
var ol = $('<ol></ol>').attr('id',olId)
.addClass(olClass)
.appendTo(origElm);
//create the <li> elements from the returned xml
//create class for new <li>s, (just the request minus the 's')
var liClass = request.substring(0, request.length-1);
//traverse xml
$('element', xml).each(function(){
//create id for new <li> based on artist abbreviation
var artist = $(this).text();
$.ajax({
url: "php/artistToAbb.php",
data: {artist: artist},
dataType: "html",
async: true,
success: function(html) {
var artistAbb = html;
//create li
var li = $('<li></li>').attr('id', artistAbb)
.addClass(liClass)
.appendTo(ol);
//create arrow icon/button for li
var img = $('<img />').attr('id', artistAbb + 'ArrowImg')
.attr("src","images/16-arrow-right.png")
.attr('onclick', "expand(this, '" + artistAbb + "', 'years', 'danwoods')")
.addClass("expImg")
.appendTo(li);
var artistTxt = $('<h2>' + artist + '</h2>')
.addClass("artist_txt")
.attr('onMouseOver', 'catMouseOver(this)')
.attr('onMouseOut', 'catMouseOut(this)')
.appendTo(li);
//tag the ol element's class
$($(origElm)[0]).addClass('expanded');
//add this element's id to the array of ids to make it draggable later
artistIdArray.push(artistAbb);
alert(artistIdArray[artistIdArray.length - 1]);
}//end on success
});//end ajax call
});//end each(function()
//make newly added artist elements draggable
for(var n = 0; n < artistIdArray.length; n++){
//new Draggable(artistIdArray[n], {superghosting: true, detached: true, onEnd: catClearHighlight});
alert(artistIdArray[n]);
}
alert(artistIdArray.length);
}
UPDATED: Now that you’ve posted your entire code. The answer is that you shouldn’t store the elements in the temporary array at all, but create the draggable for each element as the AJAX call returns.
The problem is that while the array is accessible inside the AJAX callback the code at the end of the function (outside the each) executes before the AJAX calls have completed and so the array is empty. If you create each draggable as the call returns, you don’t need the intermediate storage variable and the draggable is created as it is inserted into the DOM. The other alternative, would be to make your AJAX calls synchronous
{aSync: false}, but this would also potentially tie up the browser until all of the elements have returned. Better, IMO, to live with the asynchronous nature of the AJAX call and handle each element as it is created.