2010-05-20 20 views
5

¿Es posible automatizar la presentación/ocultación de un gif de carga de AJAX, y la desactivación/habilitación del botón de enviar al mismo tiempo? (Cuando el botón de envío es un estilo < a> no es un input type = submit)Jquery GIF de carga automática y botón desactivar al enviar clic

Actualmente el momento de presentar hago esto:

$("#save_button_id").click(function() { 
     if ($('#save_button_id').hasClass('ui-state-disabled')) return false; 
     Save(); 
}); 

function Save() { 
StartAjax($("#save_button_id")); 
$.ajax({ 
     success: function (data) { 
      EndAjax($("#save_button_id")); 
      // etc... 
     }, 
     error: function (xhr, status, error) { 
      EndAjax($("#save_button_id")); 
      // etc ... 
     } 
}); 
} 

function StartAjax(button) { 
    DisableButtonClick(button); 
    $("#ajaxLoad").show(); 
} 

function EndAjax(button) { 
    EnableButtonClick(button); 
    $("#ajaxLoad").hide(); 
} 

que he visto en algunos lugares se habla de cómo utilizar .ajaxStart() para mostrar automáticamente el gif de carga, pero ¿es posible encontrar también una referencia al botón (una etiqueta de estilo < a>) en la que se hizo clic, y también desactivarlo/habilitarlo automáticamente?

El objetivo de esto es no tener que escribir manualmente Start/EndAjax cada vez y asegurarse de que la aplicación sea coherente en todas partes.

EDITAR

Ninguna de las respuestas hasta el momento la oferta de automatización - Cualquier solución (como mi actual) por encima de donde se tiene que escribir manualmente inicio/final, antes y después de cada $ .ajax sola() produce un problema de mantenimiento : Es fácil olvidarse de ubicar el inicio/fin al lado de algunas llamadas $ .ajax(), y si desea cambiar la forma en que funciona más adelante, debe revisar cada una de ellas para realizar el cambio.

EDIT 2 - para aclarar el punto re el .delegate() sugerencia

Dijiste "Puede conectar el controlador de eventos para cualquier elemento " - pero quiero adjuntar a cada elemento botón (DRY): por lo que he modificado la primera parte de su sugerencia sea:

$('div#buttons a.ui-icon').each(function(index) { 
    $(this).ajaxStart(function() { 
     $("#ajaxLoad").show(); 
    }); 
}); 

Esto resuelve el primer problema, que es la forma de mostrar la .gif de carga para cualquier botón, sin tener que escribir de forma repetitiva " $ ("# ajaxLoad"). show() "en todas partes hay una llamada $ .ajax().

La siguiente parte es cómo desactivar cualquier botón cuando se hace clic (de nuevo sin ningún código repetitivo): sugirió .delegate(). Pero en su ejemplo, cada clic de botón llamará al método Save(). (He cambiado el selector para que coincida con mi html)

$('div#buttons a.ui-icon').delegate('button:not(.ui-state-disabled)', 'click', function() { 
    $(this).toggleClass('ui-state-disabled'); 
    Save(); // this line needs replacing with a call to $(this).something 
}); 

El problema con esto es que $ (esto) no siempre es el botón de guardar (el selector devuelve todos los botones), que podría ser el botón de borrar o el botón de cancelar o etc. Así que llamar a $ (this) .toggleClass está bien, pero al llamar a Save() significa que está llamando a la función incorrecta. Todos estos botones tienen ya un método .click:

$("#SaveButton").click(function() { 
    Save(); 
}); 

$("#DeleteButton").click(function() { 
    Delete(); 
}); 

Así que esta es la función de metrónomo original que necesita ser llamada donde dice $ (this) .something anteriormente. En este punto, debería estar llamando al clic original, o tal vez sea más correcto decir que debería burbujear hasta el clic original. El .delegate debe ser más genérico y el .click original proporcionará la implementación específica.

+0

Como responsable de su edición: tendrá que definir estas cosas en un punto u otro; no hay escapatoria. Una posible solución sería crear una función de ajax superpuesta, digamos 'doAjax (..., ...)', incluyendo '$ .ajax' de jQuery y las acciones de los botones. Pero realmente depende de qué (tipo de cosas diferentes) intente hacer aquí, de si esta función de superposición puede ser simple o hacerse increíblemente compleja y perder todas sus ventajas. – Alec

Respuesta

7

En realidad resultó ser muy sencillo: He incluido esto en mi archivo helper.js que se ejecuta para cada página:

$(document).ready(function() { 
    $('div#buttons a.fm-button').each(function (index) { 
     $(this).ajaxStart(function() { 
      $("#ajaxLoad").show(); 
      DisableButtonClick($(this)); 
     }); 
     $(this).ajaxStop(function() { 
      $("#ajaxLoad").hide(); 
      EnableButtonClick($(this)); 
     }); 
    }); 
}); 

Ahora siempre que cualquiera de los botones ajax-y se hace clic en cualquier página, los botones están deshabilitados y se muestra ajax cargando gif. Cuando finaliza la llamada ajax, vuelven a su estado normal. Y todo hecho sin escribir código repetitivamente cada vez que se llama aajax().

0
$("#save_button_id").click(function() { 
    if ($('#save_button_id').hasClass('ui-state-disabled')) { 
    return false; 
    } else { 
    // add disabled class 
    $('#save_button_id').addClass('ui-state-disabled'); 

    // optionally disable the button if it's an input button 
    $('#save_button_id').attr('disabled','disabled'); 

    // show ajax loader 
    $("#ajaxLoad").show(); 

    $.ajax({ 
     url: 'ajax/stuff.html', 
     success: function(data) { 
     // do stuff 

     // re-enable button 
     $('#save_button_id').removeClass('ui-state-disabled'); 

     // optionally re-enable the button if it's an input button 
     $('#save_button_id').attr('disabled',''); 

     // hide ajax loader 
     $("#ajaxLoad").hide(); 
     }, 
     error: function (xhr, status, error) { 
     // do stuff 

     // re-enable button 
     $('#save_button_id').removeClass('ui-state-disabled'); 

     // optionally re-enable the button if it's an input button 
     $('#save_button_id').attr('disabled',''); 

     // hide ajax loader 
     $("#ajaxLoad").hide(); 
     }); 
    } 

    // prevent default action, if any 
    return false; 
});

Editar: y poner los de una función:


function processing(status) { 
    if (status == 1) { 
    // add disabled class 
    $('#save_button_id').addClass('ui-state-disabled'); 

    // optionally disable the button if it's an input button 
    $('#save_button_id').attr('disabled','disabled'); 

    // show ajax loader 
    $("#ajaxLoad").show(); 
    } else { 
    // re-enable button 
    $('#save_button_id').removeClass('ui-state-disabled'); 

    // optionally re-enable the button if it's an input button 
    $('#save_button_id').attr('disabled',''); 

    // hide ajax loader 
    $("#ajaxLoad").hide(); 
    } 
}

Y luego llamar a esa función:

$("#save_button_id").click(function() { 
    if ($('#save_button_id').hasClass('ui-state-disabled')) { 
    return false; 
    } else { 
    processing(1); 

    $.ajax({ 
     url: 'ajax/stuff.html', 
     success: function(data) { 
     // do stuff 

     processing(0); 
     }, 
     error: function (xhr, status, error) { 
     // do stuff 

     processing(0); 
     }); 
    } 

    // prevent default action, if any 
    return false; 
});
2

Puede conectar el controlador de eventos a cualquier elemento; Así que para su botón de guardar:

$(this).ajaxStart(function() { 
    $("#ajaxLoad").show(); 
}); 

Ahora, se puede detectar el evento clic para cada botón en su página y llamar a la función ajax de ese elemento:

$('div').delegate('button:not(.ui-state-disabled)', 'click', function() { 
    $(this).toggleClass('ui-state-disabled'); 
    Save(); 
}); 

La función $.delegate() escucha clic eventos para cada elemento que no tiene la clase .ui-state-disabled. Cuando se activa un evento, alternará la clase de ese botón para deshabilitarlo, llamará a su función Guardar y se activará el evento $ .ajaxStart(). Ese evento mostrará tu gif animado ajax.

Supuse que sus botones están todos contenidos en un div para este ejemplo. Muchos desean modificar el código para que realmente especifique el elemento que contiene sus botones. También estoy asumiendo que estás usando jQuery 1.4.2.

Debería poder usar la función $.ajaxStop() para revertir todo de nuevo.

+0

Eso se ve bien. ¿Es posible llamar a los botones la función de clic original, en lugar de a la codificación de Guardar()? porque, por supuesto, solo 1 botón llama a Save(), otros botones llaman Delete(), DoSomethingElse(), etc. (y eso es un sí a usar 1.4.2) –

+0

¿Puede proporcionar más explicaciones? ¿Desde dónde quieres llamar al botón clic en evento? –

+0

Quiero decir que, donde tiene "Guardar()" en su ejemplo de delegado, es posible reemplazarlo con una llamada a la función de clic actual del objeto seleccionado. por ejemplo $ (this) .call_original_click_function(); - No sé cuál podría ser la sintaxis. (Por cierto, como lo entiendo .delegate() reemplazará el .click actual con uno nuevo - ¿es correcto? –

Cuestiones relacionadas