it-swarm.com.ru

jQuery $ (документ) .ready и UpdatePanels?

Я использую jQuery для подключения некоторых эффектов наведения мыши на элементах внутри UpdatePanel. События связаны в $(document).ready. Например:

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

Конечно, это работает нормально при первой загрузке страницы, но когда UpdatePanel выполняет частичное обновление страницы, он не запускается и эффекты наведения мыши больше не работают внутри UpdatePanel. 

Каков рекомендуемый подход для подключения компонентов в jQuery не только при первой загрузке страницы, но и каждый раз, когда UpdatePanel запускает частичное обновление страницы? Должен ли я использовать жизненный цикл ASP.NET ajax вместо $(document).ready?

461
Herb Caudill

UpdatePanel полностью заменяет содержимое панели обновления при обновлении. Это означает, что те события, на которые вы подписались, больше не подписываются, потому что на этой панели обновлений есть новые элементы.

Чтобы обойти это, я переподписывался на события, которые мне нужны после каждого обновления. Я использую $(document).ready() для начальной загрузки, затем использую Microsoft PageRequestManager (доступно, если на вашей странице есть панель обновлений), чтобы повторно подписаться на каждое обновление. 

$(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 - это объект javascript, который автоматически доступен, если на странице находится панель обновления. Вам не нужно делать ничего, кроме приведенного выше кода, чтобы использовать его, пока UpdatePanel находится на странице.

Если вам нужен более подробный контроль, это событие передает аргументы, аналогичные тому, как события .NET передаются аргументам (sender, eventArgs), чтобы вы могли видеть, что вызвало событие, и выполнять повторную привязку только при необходимости.

Вот последняя версия документации от Microsoft: msdn.Microsoft.com/.../bb383810.aspx


Лучший вариант, который вы можете иметь, в зависимости от ваших потребностей, это использовать jQuery's .on() . Эти методы более эффективны, чем повторная подписка на элементы DOM при каждом обновлении. Однако, прежде чем использовать этот подход, прочитайте всю документацию, так как он может соответствовать или не соответствовать вашим потребностям. Существует множество плагинов jQuery, которые было бы неразумно реорганизовывать для использования .delegate() или .on(), поэтому в этих случаях вам лучше переподписаться.

527
Dan Herbert
<script type="text/javascript">

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

Площадь, которая будет обновляться.

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

Пользовательский элемент управления с jQuery внутри UpdatePanel

Это не прямой ответ на вопрос, но я соединил это решение, прочитав ответы, которые нашел здесь, и подумал, что кто-то может найти его полезным.

Я пытался использовать ограничитель текстовой области jQuery внутри пользовательского элемента управления. Это было сложно, потому что пользовательский элемент управления работает внутри UpdatePanel, и он терял свои привязки при обратном вызове.

Если бы это была просто страница, ответы здесь были бы применены напрямую. Однако пользовательские элементы управления не имеют прямого доступа к тегу head и не имеют прямого доступа к UpdatePanel, как предполагают некоторые ответы. 

Я закончил тем, что поместил этот блок сценария прямо в разметку моего пользовательского элемента управления. Для начального связывания он использует $ (document) .ready, а затем использует prm.add_endRequest оттуда:

<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>

Так что ... Просто подумал, что кто-то хотел бы знать, что это работает.

62
Brian MacKay

Обновитесь до jQuery 1.3 и используйте:

$(function() {

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

});

Примечание: live работает с большинством событий, но не со всеми. Полный список в документации .

33
svinto

Вы также можете попробовать:

<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>

, поскольку pageLoad () является ajax-событием ASP.NET, которое выполняется каждый раз, когда страница загружается на стороне клиента.

20
Daniel Hursan

Мой ответ? 

function pageLoad() {

  $(document).ready(function(){

и т.п.

Работал как шарм, где ряд других решений с треском провалились.

16
Jono

Это сработало для меня:

$(document).ready(function() {

    // Do something exciting

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

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

});
7
Turbojohan

Я бы использовал один из следующих подходов:

  1. Инкапсулируйте привязку события в функцию и запускайте ее каждый раз, когда вы обновляете страницу. Вы всегда можете содержать привязку события к конкретным элементам, чтобы не связывать события несколько раз с одними и теми же элементами.

  2. Используйте плагин livequery , который автоматически выполняет первый метод для вас. Ваше предпочтение может варьироваться в зависимости от степени контроля, который вы хотите иметь для привязки события.

7
Eran Galperin

Если функция $(document).ready(function (){...}) не работает после постраничной публикации, используйте функцию JavaScript pageLoad в Asp.page следующим образом: 

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

функция pageLoad () очень опасна для использования в этой ситуации. Вы можете сделать события проводными несколько раз. Я бы также держался подальше от .live (), так как он присоединяется к элементу документа и должен пересекать всю страницу (медленно и дрянно). 

Лучшее решение, которое я видел до сих пор, - это использовать функцию jQuery .delegate () на оболочке за пределами панели обновления и использовать всплывающее окно. Кроме того, вы всегда можете подключить обработчики, используя библиотеку Microsoft Ajax, которая была разработана для работы с UpdatePanels. 

6
Norm

FWIW, у меня возникла похожая проблема с mootools. Повторное присоединение моих событий было правильным ходом, но это нужно было сделать в конце запроса .. например

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

Просто стоит иметь в виду, что beginRequest заставляет вас получать исключения JS с нулевой ссылкой.

Ура

4
SanjayU

Это отличный плагин для использования с панелями обновления:

http://updatepanelplugin.codeplex.com/

4
A_Surtees

У меня была похожая проблема, и я нашел способ, который работал лучше всего, - это использовать Event Bubbling и делегирование событий для ее решения. Хорошая вещь в делегировании событий заключается в том, что после настройки вам не нужно перепривязывать события после обновления AJAX.

В моем коде я настраиваю делегата на родительском элементе панели обновлений. Этот родительский элемент не заменяется при обновлении, и, следовательно, привязка события не затрагивается.

Существует множество хороших статей и плагинов для обработки делегирования событий в jQuery, и эта функция, вероятно, будет включена в версию 1.3. Статья/плагин, который я использую для справки:

http://www.danwebb.net/2008/2/8/event-delegation-made-easy-in-jquery

Как только вы поймете, что происходит, я думаю, вы найдете это гораздо более элегантное решение, которое будет более надежным, чем повторная привязка событий после каждого обновления. Это также дает дополнительное преимущество, так как дает вам одно событие для отмены привязки, когда страница выгружается.

4
Joe Brinkman
pageLoad = function () {
    $('#div').unbind();
    //jquery here
}

Функция pageLoad идеально подходит для этого случая, так как она запускается при начальной загрузке страницы и каждой асинхронной обратной передаче панели обновления. Мне просто нужно было добавить метод unbind, чтобы jquery работал с постбэками updatepanel.

http://encosia.com/document-ready-and-pageload-are-not-the-same/

3
Duane

Мой ответ основан на всех комментариях экспертов, приведенных выше, но ниже приведен следующий код, который любой может использовать, чтобы убедиться, что при каждой обратной передаче и при каждой асинхронной обратной передаче все еще будет выполняться код JavaScript.

В моем случае у меня был пользовательский элемент управления на странице. Просто вставьте приведенный ниже код в свой пользовательский элемент управления.

<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>
2
Abhishek Shrivastava

Панель обновления всегда заменяет ваш Jquery встроенными скриптами Scriptmanager после каждой загрузки. Лучше, если вы используете методы экземпляра pageRequestManager, как это ...

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

это будет работать нормально ... 

2
Rohit Sharma

В ответ на ответ Брайана Маккея:

Я вставляю JavaScript в свою страницу через ScriptManager вместо того, чтобы помещать его прямо в HTML-код UserControl. В моем случае мне нужно прокрутить до формы, которая станет видимой после того, как UpdatePanel завершит работу и вернется. Это идет в коде файла. В моем примере я уже создал переменную prm на главной странице содержимого.

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;
}
0
fujiiface
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
        });
}
0
Tony Dong

Используйте скрипт ниже и измените тело скрипта соответственно.

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