javascript cshtml - jQuery $(documento).ready e UpdatePanels?




run partial (17)

Sto usando jQuery per collegare alcuni effetti mouseover su elementi che si trovano all'interno di un UpdatePanel. Gli eventi sono associati a $(document).ready . Per esempio:

$(function() {    
    $('div._Foo').bind("mouseover", function(e) {
        // Do something exciting
    });    
});

Naturalmente, questo funziona bene la prima volta che viene caricata la pagina, ma quando UpdatePanel esegue un aggiornamento parziale della pagina, non viene eseguito e gli effetti mouseover non funzionano più all'interno di UpdatePanel.

Qual è l'approccio consigliato per il cablaggio di jQuery non solo sul caricamento della prima pagina, ma ogni volta che UpdatePanel attiva un aggiornamento parziale della pagina? Dovrei usare il ciclo di vita di ajax di ASP.NET invece di $(document).ready ?


Answers

FWIW, ho riscontrato un problema simile con mootools. Riattaccare i miei eventi era la mossa corretta, ma doveva essere fatta alla fine della richiesta ...

var prm = Sys.WebForms.PageRequestManager.getInstance();
prm.add_endRequest(function() {... 

Solo qualcosa da tenere a mente se beginRequest ti fa ottenere eccezioni JS di riferimento null.

Saluti


Quando $(document).ready(function (){...}) non funziona dopo il post della pagina, usa la funzione JavaScript pageLoad in Asp.page come segue:

<script type="text/javascript" language="javascript">
function pageLoad() {
// Initialization code here, meant to run once. 
}
</script>

function pageLoad () è molto pericoloso da usare in questa situazione. Potresti avere eventi collegati più volte. Vorrei anche stare lontano da .live () mentre si collega all'elemento del documento e deve attraversare l'intera pagina (lento e schifoso).

La soluzione migliore che ho visto finora è usare la funzione jQuery .delegate () su un wrapper al di fuori del pannello di aggiornamento e fare uso di bubbling. Altrimenti, è sempre possibile collegare i gestori usando la libreria Ajax di Microsoft, progettata per funzionare con UpdatePanel.


Usa sotto lo script e modifica il corpo del copione di conseguenza.

       <script>
        //Re-Create for on page postbacks
        var prm = Sys.WebForms.PageRequestManager.getInstance();
        prm.add_endRequest(function () {
           //your codes here!
        });
    </script>

<script type="text/javascript">

        function BindEvents() {
            $(document).ready(function() {
                $(".tr-base").mouseover(function() {
                    $(this).toggleClass("trHover");
                }).mouseout(function() {
                    $(this).removeClass("trHover");
                });
         }
</script>

L'area che verrà aggiornata.

<asp:UpdatePanel...
<ContentTemplate
     <script type="text/javascript">
                    Sys.Application.add_load(BindEvents);
     </script>
 *// Staff*
</ContentTemplate>
    </asp:UpdatePanel>


Controllo utente con jQuery all'interno di un UpdatePanel

Questa non è una risposta diretta alla domanda, ma ho messo insieme questa soluzione leggendo le risposte che ho trovato qui, e ho pensato che qualcuno potrebbe trovare utile.

Stavo cercando di usare un limitatore di textarea jQuery all'interno di un controllo utente. Questo è stato complicato, perché il Controllo Utente viene eseguito all'interno di un UpdatePanel e stava perdendo i suoi binding durante la richiamata.

Se questa fosse solo una pagina, le risposte qui avrebbero applicato direttamente. Tuttavia, i controlli utente non hanno accesso diretto al tag head, né hanno accesso diretto a UpdatePanel come alcune delle risposte assumono.

Ho finito per mettere questo blocco di script direttamente nella parte superiore del markup del mio controllo utente. Per il bind iniziale, utilizza $ (document) .ready, quindi utilizza prm.add_endRequest da lì:

<script type="text/javascript">
    function BindControlEvents() {
        //jQuery is wrapped in BindEvents function so it can be re-bound after each callback.
        //Your code would replace the following line:
            $('#<%= TextProtocolDrugInstructions.ClientID %>').limit('100', '#charsLeft_Instructions');            
    }

    //Initial bind
    $(document).ready(function () {
        BindControlEvents();
    });

    //Re-bind for callbacks
    var prm = Sys.WebForms.PageRequestManager.getInstance(); 

    prm.add_endRequest(function() { 
        BindControlEvents();
    }); 

</script>

Quindi ... Pensavo che qualcuno potrebbe piacere sapere che questo funziona.


In risposta alla risposta di Brian MacKay:

Inserisco il codice JavaScript nella mia pagina tramite ScriptManager invece di inserirlo direttamente nell'HTML di UserControl. Nel mio caso, ho bisogno di scorrere fino a un modulo reso visibile dopo che UpdatePanel ha terminato e restituito. Questo va nel codice dietro il file. Nel mio esempio, ho già creato la variabile prm nella pagina di contenuto principale.

private void ShowForm(bool pShowForm) {
    //other code here...
    if (pShowForm) {
        FocusOnControl(GetFocusOnFormScript(yourControl.ClientID), yourControl.ClientID);
    }
}

private void FocusOnControl(string pScript, string pControlId) {
    ScriptManager.RegisterStartupScript(this.Page, this.Page.GetType(), "focusControl_" + pControlId, pScript, true);
}

/// <summary>
/// Scrolls to the form that is made visible
/// </summary>
/// <param name="pControlId">The ClientID of the control to focus on after the form is made visible</param>
/// <returns></returns>
private string GetFocusOnFormScript(string pControlId) {
    string script = @"
    function FocusOnForm() {
        var scrollToForm = $('#" + pControlId + @"').offset().top;
        $('html, body').animate({ 
            scrollTop: scrollToForm}, 
            'slow'
        );
        /* This removes the event from the PageRequestManager immediately after the desired functionality is completed so that multiple events are not added */
        prm.remove_endRequest(ScrollFocusToFormCaller);
    }
    prm.add_endRequest(ScrollFocusToFormCaller);
    function ScrollFocusToFormCaller(sender, args) {
        if (args.get_error() == undefined) {
            FocusOnForm();
        }
    }";
    return script;
}

La mia risposta?

function pageLoad() {

  $(document).ready(function(){

eccetera.

Ha funzionato come un incantesimo, dove molte altre soluzioni hanno fallito miseramente.


Un UpdatePanel sostituisce completamente il contenuto del pannello di aggiornamento su un aggiornamento. Ciò significa che gli eventi a cui sei iscritto non sono più iscritti perché ci sono nuovi elementi in quel pannello di aggiornamento.

Quello che ho fatto per ovviare a questo è ri-iscriversi agli eventi di cui ho bisogno dopo ogni aggiornamento. Uso $(document).ready() per il caricamento iniziale, quindi uso il PageRequestManager di Microsoft (disponibile se si dispone di un pannello di aggiornamento sulla pagina) per ri-sottoscrivere ogni aggiornamento.

$(document).ready(function() {
    // bind your jQuery events here initially
});

var prm = Sys.WebForms.PageRequestManager.getInstance();

prm.add_endRequest(function() {
    // re-bind your jQuery events here
});

PageRequestManager è un oggetto javascript che è automaticamente disponibile se nella pagina è presente un pannello di aggiornamento. Non dovresti aver bisogno di fare nient'altro che il codice sopra per poterlo utilizzare purché UpdatePanel sia nella pagina.

Se hai bisogno di un controllo più dettagliato, questo evento passa argomenti simili a come gli eventi .NET vengono passati argomenti (sender, eventArgs) modo da poter vedere cosa ha generato l'evento e re-associare solo se necessario.

Ecco l'ultima versione della documentazione di Microsoft: msdn.microsoft.com/.../bb383810.aspx

Un'opzione migliore che potresti avere, a seconda delle tue esigenze, è usare .on() di jQuery. Questi metodi sono più efficienti della ri-sottoscrizione agli elementi DOM su ogni aggiornamento. Leggi tutta la documentazione prima di usare questo approccio, poiché potrebbe o meno soddisfare le tue esigenze. Ci sono molti plugin jQuery che sarebbero irragionevoli da rifattori usare .delegate() o .on() , quindi in questi casi, è meglio iscriversi nuovamente.


Sys.Application.add_load(LoadHandler); //This load handler solved update panel did not bind control after partial postback
function LoadHandler() {
        $(document).ready(function () {
        //rebind any events here for controls under update panel
        });
}

La mia risposta si basa su tutti i commenti degli esperti di cui sopra, ma di seguito è riportato il codice seguente che chiunque può utilizzare per accertarsi di ogni postback e su ciascun postback asincrono il codice JavaScript verrà comunque eseguito.

Nel mio caso, ho avuto un controllo utente all'interno di una pagina. Basta incollare il codice qui sotto nel controllo utente.

<script type="text/javascript"> 
        var prm = Sys.WebForms.PageRequestManager.getInstance();
    prm.add_endRequest(EndRequestHandler);
    function EndRequestHandler(sender, args) {
        if (args.get_error() == undefined) {
            UPDATEPANELFUNCTION();
        }                   
    }

    function UPDATEPANELFUNCTION() {
        jQuery(document).ready(function ($) {
            /* Insert all your jQuery events and function calls */
        });
    }

    UPDATEPANELFUNCTION(); 

</script>

Puoi anche provare:

<asp:UpdatePanel runat="server" ID="myUpdatePanel">
    <ContentTemplate>

        <script type="text/javascript" language="javascript">
        function pageLoad() {
           $('div._Foo').bind("mouseover", function(e) {
               // Do something exciting
           });
        }
        </script>

    </ContentTemplate>
</asp:UpdatePanel>

, poiché pageLoad () è un evento ajax di ASP.NET che viene eseguito ogni volta che la pagina viene caricata sul lato client.


Pannello di aggiornamento sostituisce sempre il tuo Jquery con gli script di Scriptmanager incorporati dopo ogni caricamento. È meglio se usi i metodi di istanza di pageRequestManager come questo ...

Sys.WebForms.PageRequestManager.getInstance().add_endRequest(onEndRequest)
    function onEndRequest(sender, args) {
       // your jquery code here
      });

funzionerà bene ...


Vorrei utilizzare uno dei seguenti approcci:

  1. Incapsula l'associazione eventi in una funzione ed eseguila ogni volta che aggiorni la pagina. È sempre possibile contenere l'associazione degli eventi a elementi specifici in modo da non associare più volte gli eventi agli stessi elementi.

  2. Usa il plug-in livequery , che fondamentalmente esegue il metodo uno per te automaticamente. Le tue preferenze potrebbero variare in base alla quantità di controllo che desideri avere sul bind dell'evento.


Esegui l'upgrade a jQuery 1.3 e utilizza:

$(function() {

    $('div._Foo').live("mouseover", function(e) {
        // Do something exciting
    });

});

Nota: il live funziona con la maggior parte degli eventi, ma non tutti. C'è una lista completa nella documentazione .


questo è molto simile a tutte le risposte, ma perché non usare il ! operatore due volte in modo da poter ottenere un booleano:

jQuery.fn.exists = function(){return !!this.length};

if ($(selector).exists()) {
    // the element exists, now what?...
}




javascript jquery asp.net javascript-events asp.net-ajax