views:

703

answers:

2

Hello jQuery Ninjas! I am trying, in vain it seems, to be able to pass additional parameters back to the success callback method that I have created for a successful ajax call. A little background. I have a page with a number of dynamically created textbox / selectbox pairs. Each pair having a dynamically assigned unique name such as name="unique-pair-1_txt-url" and name="unique-pair-1_selectBox" then the second pair has the same but the prefix is different.

In an effort to reuse code, I have crafted the callback to take the data and a reference to the selectbox. However when the callback is fired the reference to the selectbox comes back as 'undefined'. I read here that it should be doable. I have even tried taking advantage of the 'context' option but still nothing. Here is the script block that I am trying to use:

<script type="text/javascript" language="javascript">
$j = jQuery.noConflict();
function getImages(urlValue, selectBox) {
    $j.ajax({
        type: "GET",
        url: $j(urlValue).val(),
        dataType: "jsonp",
        context: selectBox,
        success:function(data){
         loadImagesInSelect(data)
        } ,
        error:function (xhr, ajaxOptions, thrownError) {
            alert(xhr.status);
            alert(thrownError);
        }

    });
}

function loadImagesInSelect(data) {
var select = $j(this);
select.empty();
$j(data).each(function() {
    var theValue = $j(this)[0]["@value"];
    var theId = $j(this)[0]["@name"];
    select.append("<option value='" + theId + "'>" + theValue + "</option>");
});
select.children(":first").attr("selected", true);

}

From what I have read, I feel I am close but I just cant put my finger on the missing link. Please help in your typical ninja stealthy ways. TIA

*UPDATE* Nick is a true Ninja. They should invent a new badge for that! His answer below does the trick. As he mentions it's 1.4 specific but I can live with that. Here is my final code that is working for any Ninjas in training (and my future reference):

<script type="text/javascript" language="javascript">
$j = jQuery.noConflict();
function getImages(urlValue, selectBox) {
    $j.ajax({
        type: "GET",
        url: urlValue+ '?callback=?',
        dataType: "jsonp",
        context: selectBox,
        success: jQuery.proxy(function (data) {
            var select = $j(this);
            select.empty();
            $j(data).each(function() {
                var theValue = $j(this)[0]["@value"];
                var theId = $j(this)[0]["@name"];
                select.append("<option value='" + theId + "'>" + theValue + "</option>");
            });
            select.children(":first").attr("selected", true);
        }, selectBox),
        error:function (xhr, ajaxOptions, thrownError) {
            alert(xhr.status);
            alert(thrownError);
        }
    });
}
</script>
+2  A: 

Updated: If you're using jQuery 1.4 use this to simplify things a bit:

success: jQuery.proxy(function (data) {
    var select = $j(this);
    select.empty();
    $j(data).each(function() {
        var theValue = $j(this)[0]["@value"];
        var theId = $j(this)[0]["@name"];
        select.append("<option value='" + theId + "'>" + theValue + "</option>");
    });
    select.children(":first").attr("selected", true);
}, selectBox)
Nick Craver
Nick, This does not seem to work. I first tried with the anonymous method and still nothing. I can see the method getting invoked but cannot step into the anonymous method. So I changed it to use the external method so I could break on it. It then comes back undefined.
dotnetgeek
@dotnetgeek - How are you calling the external method? It should just be `success: externalMethodName` with a signature like this: `function externalMethodName(data)`
Nick Craver
@Nick, I updated the original code with how I currently have it setup. It looks like this: loadImagesInSelect(data, $j(this)).Wether I pass it the reference or not, $j(this) returns back a Window object.
dotnetgeek
@dotnetgeek - That's the part I'm trying to convey, you don't control which arguments are passed to that function, the format is always `function(data, textStatus, XMLHttpRequest)`, but you can determine what `this` refers to inside that function by setting `context: something`, that `something` will be `this` when the function runs.
Nick Craver
When I do what you suggest, change the callbacck method format to:loadImagesInSelect(data)and change the loadImagesInSelect method to:function loadImagesInSelect(data) { var select = $j(this); select.empty(); $j(data).each(function() { var theValue = $j(this)[0]["@value"]; var theId = $j(this)[0]["@name"]; select.append("<option value='" + theId + "'>" + theValue + "</option>"); }); select.children(":first").attr("selected", true);}$(this)'s type is NOT the dropdown. In IE it shows as DispHTMLWindow2. In FF its a Window
dotnetgeek
@dotnetgeek - In hopes you're using jQuery 1.4, updated the answer with a more reliable method to go about it, see if it gives you any trouble.
Nick Craver
@Nick, you da man! This example is working perfectly. I think the previous would have worked too. The key change in addition to your suggestion was changing the param that I passed to the JSONP service. I originally had: "http://<url>:<port>?callback=loadImagesInSelect" I changed that to "http://<url>:<port>?callback=?". Thanks a million for your persistence and patience! I will update my question with the full proper code.
dotnetgeek
@dotnetgeek - Welcome :) Glad this version's working, easier to understand as well I think, once you use proxy just a handful of times.
Nick Craver
A: 

Put this into your $.ajax parameters.

invokedata: {
    data1: "yourdata",
    data2: "moredata"
}

In the success function use it like this

this.invokedata.data1;
this.invokedata.data2;

Your $.ajax call and the success function must also be a part of the same object. Put your functions in an object and define them like this

function myObject {
    var getImage = function(..) { }
    var loadImagesInSelect = function(..) { }
}
HeavyWave
can you tell me what you mean by: Your $.ajax call and the success function must also be a part of the same object? Also I do not see invokeData as a parameter on the jQuery site. Can you elaborate on the values? Do they need to be strings or can they be an object reference?
dotnetgeek
I have updated my answer. invokedata is stored in your object, not in jquery. Data can be anything.
HeavyWave
@HeavyWave, I was not able to get this working but @Nick's final answer seemed to work. Thanks for the help though. Your solution has given me a couple more ideas to try out to clean things up a bit.
dotnetgeek
Check this answer, which worked for me http://stackoverflow.com/questions/2542208/how-to-refactor-this-javascript-anonymous-function/2542323#2542323. I was trying to do the same thing.
HeavyWave