문제

I have a click handler bound to a list of radio buttons.

When someone clicks any of these buttons, an ajax request is performed, which goes away to a server, and comes back with some data, which is injected into the page.

    $('ul#tag_picker').find('input').click(function(e){
    var type = ($(this).attr('type') == 'radio') ? 'radio' : 'checkbox';
    if($('ul#tag_picker input[type="radio"]:checked').length < 1 && type === 'checkbox'){   
        e.preventDefault();
        return false;
    }
    var value = $(this).val();
    var word = $(this).siblings('label').text();
    tag = {};
    tag.tag_id = value;
    tag.tag_word = word;
    tag.jumper = di.tags.jumpers[0];
    //tag.privilege = ui.item.privilege;
    args = {};
    args['jumper']  = di.tags.jumpers[0];
    args['name'] = 'selected_tags[]';
    //args['class'] = 'tag genre_tag';
    tag.privilege = 'genre';

    if (type === 'radio'){
        args['main_tag'] = true;
    }
    else if ( $(this).siblings('input[type="radio"]:first').is(':checked') ){
        $(this).attr('checked','checked');
        return false;                                   
    }
    action = ($(this).is(':checked')) ? 'add' : 'remove';
    user_select_tag(tag, action, args);  // <<< This is the ajax request.       
})

This ajax request can take some time (2-3 seconds) to complete.

During the request, the radio button remains in its 'depressed' state. Once the data is returned from the remote server, the page is updated, and the button is shown as selected.

I would like to make the button appear selected, and execute the ajax request 'out of band'.

I have been thinking I should be using the 'deferred' method, or a callback, but I am unsure how to do this.

Any suggestions as to how I can make the request happen more 'out-of-band' would be great! I have the jquery ajax option 'async' set to true.

Edited to add the ajax request under here:

function user_select_tag(tag, operation, overrides) {
var args = [];
args['tag_box'] = 'ul#user_selected_tags';
if ($(args['tag_box']).length < 1 && $('ul#selected_tags').length > 0){
    args['tag_box'] = 'ul#selected_tags';
}
args['name'] = '';
args['class'] = 'tag';
args['jumper'] = false;
args['main_tag'] = false;
args['getSuggestedTags'] = 1;
if(typeof di.tags.max_tags !== 'undefined'){
    args['max_tags'] = parseInt(di.tags.max_tags);
}
else{
    args['max_tags'] = 5;   
}
args['privilege'] = false;
var main_tag_attr = '';
var main_tag_class = '';
var append = 'append';
var tag_privilege = '';
var tag_picker = false
if ($('ul#tag_picker').length>0){
    tag_picker=$('ul#tag_picker');    
}
if (typeof(overrides) === 'object') {
    $.each(overrides,
    function(index, value) {
        if ($.inArray(index, args)) {
            args[index] = value;
        }
    });
}
if (args['jumper'] === false && operation === 'select') {
    log('This jumper was called without a jumper, is cold, and will now exit.');
    return false;
}
var j_id = tag.jumper.id;
var jumper = di.tags.jumpers[j_id];
var tag_box = $(args['tag_box']);
var tag_array = jumper.pre_selected_tags;
var tag_ref = 'ust_' + j_id + '_' + tag.tag_id;
if (operation == 'add') {
    if ($.inArray(tag.tag_id, tag_array) != -1 && args['main_tag'] == false) {
        log('The tag was already selected, so I\'m returning.');
        return false;
    }
    if (tag_array.length + 1 > args['max_tags'] && args['main_tag'] == false && !admin()) {
        alert(args['max_tags'] + ' tags are already selected. Please remove a tag if you would like to replace it with this one.');
        return false;
    }
    if (args['main_tag'] !== false) {
        console.log('main tag was not false ',args,'jumper id is: ',j_id);
        var append = 'prepend';
        $('.main_tag[data-jumper_id="' + j_id + '"]').each(function() {
            var removetag = {};
            removetag.tag_id = $(this).attr('data-tag_id');
            removetag.tag_word = $(this).text();
            removetag.jumper = di.tags.jumpers[j_id];
            var rtargs = {};
            rtargs['jumper'] = di.tags.jumpers[j_id];
            rtargs['getSuggestedTags'] = 0;
            //rtargs['main_tag']  = true;
            console.log('removing ',$(this),' tag',rtargs);
            user_select_tag(removetag, 'remove', rtargs);
            if(admin()){
                removetag['privilege'] = 'genre';
                user_select_tag(removetag, 'add', rtargs);
            }
        });
        //user_select_tag(tag,'remove');
        $('.' + tag_ref).remove();
        main_tag_attr = 'data-main_tag="true"';
        main_tag_class = 'main_tag';
    }
    tag_array.push(tag.tag_id);
    if (typeof  tag.privilege != 'undefined') {
        args['class'] += ' ' + tag.privilege + '_tag';
        tag_privilege = 'data-tag_privilege="' + tag.privilege + '"';
    }
    tag_box[append]('<li id="' + tag_ref + '" name="' + args['name'] + '" class="' + args['class'] + ' ' + main_tag_class + ' ' + tag_ref + '" data-tag_id="' + tag.tag_id + '" data-jumper_id="' + j_id + '"' + main_tag_attr + ' ' + tag_privilege + '><span class="tag_word">' + tag.tag_word + ' </span><img id="x_ust_' + tag.tag_id + '" class="x_ust" src="http://www.dailyinfo.co.uk/dimages/remove_tag.gif" alt="Remove this tag"></li>');
    if (tag_picker){
        tag_picker.find('input[type="checkbox"][value="'+tag.tag_id+'"]').attr('checked','checked');
    }
    var hidden_input = '<input type="hidden" name="' + args['name'] + '" class="' + tag_ref + '" value="' + tag.tag_id + '" />';
    if (jumper.form.length > 0) {
        $(hidden_input).appendTo(jumper.form);
    } else {
        $(hidden_input).appendTo(tag_box);
    }
    if (args['getSuggestedTags'] == 1){
        console.log('getting suggested tags',args)
        getSuggestedTags();   
    }
    else{
        console.log('not getting suggested tags',args)
    }
} else {
    // operation assumed to be remove
    $('.' + tag_ref).remove();
    if (tag_picker){
        tag_picker.find('input[type="checkbox"][value="'+tag.tag_id+'"]').attr('checked','');           
    }
    if (tag_array.length > 0) {

        }
    tag_array.splice($.inArray(tag.tag_id, tag_array), 1);
}
// copy the contents of the tag_box into the tag section of the live event preview
var tag_html = $(args['tag_box']).html();  
if (tag_html.length < 1) {
    tag_html = 'not tagged yet';
}
$('p.event_live_preview[data-handle="tags"]').html(tag_html);
return true;

}

function getSuggestedTags(overrides) {
var args = {};
args['jumper_id'] = 0;
if (typeof(overrides) === 'object') {
    $.each(overrides,
    function(index, value) {
        if ($.inArray(index, args)) {
            args[index] = value;
        }
    });
}
var json = {};
json.action = 'getSuggestedTags';
json.arguments = {};
var options = {};
options['chosen_tags'] = di.tags.jumpers[args['jumper_id']].pre_selected_tags;
options['return'] = 'id_key_word';
options['aliases'] = true;
options['related'] = true;
options['text'] = '';
options['location'] = null;
var det_names = ['name', 'description'];
var det_arr = [];
$('.evt_text').each(function() {
    var v = $(this).val();
    if (v.length > 0) {
        det_arr.push(v);
    }
});
if (typeof di.event.defaults.free === 'boolean' && di.event.defaults.free){
    det_arr.push($('input#di_cal_event_times_prices_window_prices').val());
}
if (det_arr.length > 0) {
    options['text'] = det_arr.join(' ');
}
var hid = $('input#hidden_venue_id');
var cv = $('input#custom_venue');
if (hid.length > 0 && cv.length > 0) {
    if (hid.val().length > 0 && cv.val().length < 1) {
        options['location'] = hid.val();
    }
}
json.arguments = options;
var a = ajax_request({
    url: '/ajax/get_suggested_tags.php',
    async: false,
    dataType: 'html',
    data: {
        json: JSON.stringify(json)
    },
    success: function(data) {
        if (data.length > 0) {
            $('ul#suggested_tags').replaceWith(data);
        }
    },
    type: 'GET'
});

}

ajax_request is a wrapper:

function ajax_request(override_options){
var options={
    "async":true,
    "cache":false,
    //"data":{Xaction and Xquery/Xcode},
    "dataType":"json",
    "error":errorCallback,
    "success":function (data,textStatus){
        //alert("A specific success callback was not specified!\n"+data+"\n"+textStatus)
    },
    "timeout":9000,
    "type":"POST"
}
var option_name
for(option_name in override_options){
    options[option_name]=override_options[option_name]
}
return jQuery.ajax(options)

}

Patrick

도움이 되었습니까?

해결책

Just inside your click, do something to your button. I set use jQuery UI buttons (which are great) so in my app I just set attr to disabled....you could handle this detail any way you wanted.

Next, under the ajax success, simply change your initially set button state. It also helps to add a loader notice at the top and remove it here. Jquery's dialogs with an animated gif from ajaxload.info are perfect.

BTW, jQuery's ajax function is async by default, no need to define it.

다른 팁

I'd really need to see your ajax code, but by default, it should be asynchronous. Here's callbacks 101 for you, though:

This assumes jQuery syntax, by the way. If you need it in another format let me know.

$.ajax({
    type: 'POST',
    url: yourUrl,
    async: true, //not necessary -- its the default behavior, but I put it in there in case you had it set to false currently
    //here are your callbacks: success will be called when your ajax function returns, and error will be called if any errors are thrown
    success: function(results) {                   
             //do something with your results       
             }                                    
    error: function(e) {
             //do something with your error
           }
});
라이센스 : CC-BY-SA ~와 함께 속성
제휴하지 않습니다 StackOverflow
scroll top