Не работает повторная привязка событий с помощью jquery

#javascript #jquery #ajax #bpopup

#javascript #jquery #ajax #bpopup

Вопрос:

У меня есть настройка страницы для макета презентации:

  ------------------------ 
|prev                next|
| ---------------------- |
||         page         ||
||   dynamic content    ||
||                      ||
| ---------------------- |
 ------------------------ 
  

В приведенном выше примере next / prev — это навигационные кнопки, которые управляют динамическим содержимым с помощью $("page").load(url);

На одной из страниц у меня есть всплывающее окно, в котором есть кнопки, связанные с вызовом ajax, который управляет содержимым всплывающего окна.

Эти кнопки прекрасно выполняют свою работу при первой загрузке страницы. Если страница была изменена (с помощью кнопок навигации), а затем изменена обратно, всплывающее окно откроется, но кнопки не работают. Если вы нажмете кнопки, закройте всплывающее окно, а затем снова откроете всплывающее окно, отобразится информация, запрошенная вами при первом нажатии, но кнопки по-прежнему не работают.

Это говорит мне о том, что запрос ajax в порядке, где-то есть проблема с привязкой элементов. Вот мой Javascript:

 $('#resTable').on('click',this,function() {
    $('#ayAvgDPm').html("");
    $('#aoAvgDPm').html("");
    $('#ayTotProfit').html("");
    $('#aoTotProfit').html("");
    $('#ayAvgPcPm').html("");
    $('#aoAvgPcPm').html("");
    $('#ayTotPcProfit').html("");
    $('#aoTotPcProfit').html("");
    $('#ayrRes').html("");
    $('#etfProductPopup').bPopup();
});

$('div[class^="sideNav"]').on('click',this,function() {

    $('#yrSummary').fadeIn(200);

    $('#yAvgDPm').html("");
    $('#oAvgDPm').html("");
    $('#yTotProfit').html("");
    $('#oTotProfit').html("");
    $('#yAvgPcPm').html("");
    $('#oAvgPcPm').html("");
    $('#yTotPcProfit').html("");
    $('#oTotPcProfit').html("");
    $('#yrRes').html("");

    var yr = "20" $(this).attr('class').substr(-2);

    var req = $.ajax({
        url : '../includes/prod_results.php',
        type : 'POST',
        dataType : "json",
        data : {
            y : yr,
            t : 'ETF'
        },
        success : function(j) {
            var table = "<table cellspacing='0'><tr><th>Year</th><th>Returns</th></tr>";
            for(var i = 0; i < 12; i  ) {
                if (i === 5 amp;amp; yr === '2014'){
                    break;
                }
                var obj = j[i];
                var month = obj['month'];
                var profit = obj['profit'];
                var bal = obj['bal'];
                table  = "<tr><td style='width:75px'>" month "</td><td style='padding: 0 15px'>" parseFloat(profit).toFixed(2) "%</td><td style='width:75px'>$" comma(parseFloat(bal).toFixed(2)) "</td></tr>";
                if (i === (11)) {
                    table  = "</table>";
                }
            }
            var YAvgDPm = comma(parseFloat(j.YAvgDPm).toFixed(2));
            var OAvgDPm = comma(parseFloat(j.OAvgDPm).toFixed(2));
            var YTotProfit = comma(parseFloat(j.YTotProfit).toFixed(2));
            var OTotProfit = comma(parseFloat(j.OTotProfit).toFixed(2));
            var YAvgPcPm = comma(parseFloat(j.YAvgPcPm).toFixed(2));
            var OAvgPcPm = comma(parseFloat(j.OAvgPcPm).toFixed(2));
            var YTotPcProfit = comma(parseFloat(j.YTotPcProfit).toFixed(2));
            var OTotPcProfit = comma(parseFloat(j.OTotPcProfit).toFixed(2));

            $('#yAvgDPm').html("$" YAvgDPm);
            $('#oAvgDPm').html("$" OAvgDPm);
            $('#yTotProfit').html("$" YTotProfit);
            $('#oTotProfit').html("$" OTotProfit);
            $('#yAvgPcPm').html(YAvgPcPm "%");
            $('#oAvgPcPm').html(OAvgPcPm "%");
            $('#yTotPcProfit').html(YTotPcProfit "%");
            $('#oTotPcProfit').html(OTotPcProfit "%");
            $('#yrRes').html(table);
            $('#yrGraph').html("<img src='../images/graphs/etf_" yr ".jpg'>");
            return false;
        }
    });
    return false;
});
  

Я знаю, что это довольно долго…

Я пробовал приведенный выше сценарий как внутри, так и вне $(document).ready() обработчика.

Может кто-нибудь, пожалуйста, помочь мне относительно того, что я не делаю?

РЕДАКТИРОВАТЬ по запросу, HTML:

 <table id="resTable" cellspacing="0">
    <tr>
        <th>Year</th>
        <th> 1st Quarter</th>
        <th>2nd Quarter</th>
        <th>3rd Quarter</th>
        <th>4th Quarter</th>
        <th>Year Total</th>
        <th>Month Avg</th>
    </tr>
...
</table>

<div id="etfProductPopup">
<h1 style="text-align:center">ETF - Compounded Results</h1>
<div id="popupLeftBar">
    <div class="sideNav14">
        2014
    </div>
    <div class="sideNav13">
        2013
    </div>
    <div class="sideNav12">
        2012
    </div>
    <div class="sideNav11">
        2011
    </div>
    <div class="sideNav10">
        2010
    </div>
    <div class="sideNav09">
        2009
    </div>
    <div class="sideNav08">
        2008
    </div>
    <div class="sideNav07">
        2007
    </div>
    <div class="sideNav06">
        2006
    </div>
    <div class="sideNav05">
        2005
    </div>
    <div class="sideNav04">
        2004
    </div>
    <div class="sideNav03">
        2003
    </div>
</div>
<div id="popupMain">
    <div id="yrSummary">
        <table cellspacing="0">
            <tr>
                <th></th>
                <th>Avg<br>$/Mth</th>
                <th>Total<br>$ Profit</th>
                <th>Avg<br>%/Mth</th>
                <th>Total<br>% Profit</th>
            </tr>
            <tr>
                <th>Year</th>
                <td id="yAvgDPm"></td>
                <td id="yTotProfit"></td>
                <td id="yAvgPcPm"></td>
                <td id="yTotPcProfit"></td>
            </tr>
            <tr>
                <th>Overall</th>
                <td id="oAvgDPm"></td>
                <td id="oTotProfit"></td>
                <td id="oAvgPcPm"></td>
                <td id="oTotPcProfit"></td>
            </tr>
        </table>
    </div>
    <div id="yrGraph"></div>
    <div id="yrRes"></div>
</div>
  

Really? No body got any other ideas on this? I really need you guys to come through for me on this!

Code for nav buttons:

 function nav(d) {
n = page   d;
$('#slide').load('p/' n '.php');
  

}

HTML:

 <div class="prev" onClick="nav(-1)" title="Previous Page">amp;<amp;< Previous</div>
<div class="next" onClick="nav(1)" title="Next Page">Next amp;>amp;></div>
  

EDIT

So I have tried all 3 of the (current) answers and am getting nowhere! This is very frustrating!

I am starting to think there may be some underlying issues and that the bindings are not the complete problem.

The page obviously nees to be loaded as if it was refreshed by the browser. The fact that the page works fine the 1st time it is loaded, regardless of how it is loaded, says to me that the bindings are all fine.

The page also works fine without the popup.

Are there any ideas, other than the bindings, what the underlying issue could be?

Also, I know it is against the rules of SO for me to publish a link to the webpage in question, but if anyone would like a link, I am desperate enough to provide it privately. Please ask.

EDIT

So, I’m thinking, the hidded div (for the popup) is staying populated even after I use the following script:

 $('#etfProductPopup').bPopup({
        onClose : function() {
            postLoadBindings();
            $('#ayAvgDPm').html("");
            $('#aoAvgDPm').html("");
            $('#ayTotProfit').html("");
            $('#aoTotProfit').html("");
            $('#ayAvgPcPm').html("");
            $('#aoAvgPcPm').html("");
            $('#ayTotPcProfit').html("");
            $('#aoTotPcProfit').html("");
            $('#ayrRes').html("");
        }
    });
  

I’m thinking the issue may be with the popup script…

https://raw.githubusercontent.com/dinbror/bpopup/master/jquery.bpopup.min.js

EDIT

Also just noticed that the popup div is being duplicated on page load. From the console:

 <div id="etfProductPopup" style="display: none; left: 440px; position: absolute; top: 156px; z-index: 2147483650; opacity: 0;">...</div>

<div id="etfProductPopup" style="display: none; left: 440px; position: absolute; top: 156px; z-index: 2147483650; opacity: 0;">...</div>
  

Редактировать

(Да, я понимаю, что если бы был значок «Большинство изменений в собственном вопросе», тогда я бы выиграл, но я думаю, что чем больше данных я предоставляю, тем больше шансов на ответ)

Я создал #resTable элемент на другой странице (загруженный так же, как и предыдущий). Я заметил, что даже при использовании $('#resTable').unbind() в обработчике готовности документа щелчок по элементу вызывает всплывающее окно с предыдущей страницы!

КАК ЭТО ВОЗМОЖНО, КОГДА СЦЕНАРИЙ ДЛЯ ВСПЛЫВАЮЩЕГО ОКНА ДАЖЕ НЕ СУЩЕСТВУЕТ НА ЭТОЙ СТРАНИЦЕ, НЕ ГОВОРЯ УЖЕ О СОДЕРЖИМОМ??

Кто-нибудь, ПОЖАЛУЙСТА! Этому ДОЛЖНО быть рациональное объяснение! Я не пытаюсь программировать людей, это компьютерный код, он работает с битами данных и не может просто составлять его по ходу дела!

Может кто-нибудь, пожалуйста, помочь мне с этим?

Зашел так далеко: всплывающее окно создает дубликат div внутри внешней страницы (той, на которой расположены кнопки навигации). Я предполагаю, что он делает это так, чтобы он правильно накладывался на всю страницу, а не только на страницу, содержащую исходный код для div.

Редактировать

Более подробный взгляд на то, что происходит. Очевидно, что div для всплывающего окна находится внутри страницы, а не контейнера. bPopup перемещает div в <body> теги содержащей страницы. Это означает, что div доступен на всех страницах, на которые переходили после вызова bPopup. Закрытие всплывающего окна не перемещает div обратно, поэтому при перезагрузке страницы с помощью кнопок навигации div дублируется.

Последний прогресс

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

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

Я не уверен, есть ли способ удалить элемент на странице? Проблема в том, что если элемент можно удалить, копия, которую создает bpopup, точно такая же, как и оригинал, поэтому любой скрипт, предназначенный для дубликата, также будет нацелен на оригинал

Комментарии:

1. Соответствующий HTML тоже был бы полезен. Просто в качестве исключения, вы могли бы присвоить всем этим элементам один и тот же класс и сделать $('.newclass').html(""); вместо этого 🙂

2. @intracept добавили html в соответствии с запросом

3. Я не хочу показаться нетерпеливым, но если кто-нибудь может дать отзыв, я был бы очень благодарен!

4. Каков код для ваших навигационных кнопок?

5. Было бы гораздо удобнее добавлять к вопросу.

Ответ №1:

изменить:

 $('#resTable').on('click',this,function() {
...
  

Для

 $(document).on('click','#resTable',function() {
...
  

и

 $('div[class^="sideNav"]').on('click',this,function() {
...
  

Для

 $(document).on('click','div[class^="sideNav"]',function() {
...
  

Комментарии:

1. Как вы думаете, было бы много разницы, были ли они в $(document).ready() обработчике или нет? Или, может быть, даже размещены на внешней странице, а не на динамической странице?

2. это будет иметь значение, если его поместить в обработчик .ready(), правильный способ — поместить его в обработчик .ready()

3. Это то, что я подумал. До сих пор он провел там большую часть своей жизни, и именно там он и останется 🙂

4. это не обязательно должно быть готово, это похоже на устаревший $.live(), поэтому он может быть где угодно, поскольку вы привязываетесь к $ (document)

Ответ №2:

Делегирование событий, о котором упоминал @Sudhir, должно было сработать, но все же, если вы столкнулись с проблемой, вы можете попробовать принудительно привязывать новые события при каждой загрузке страницы. Что-то вроде —

На главной странице, на которой есть кнопка Prev и Next , определите все ваши функции —

 var bindEvents = function(){
    //we are unbinding to make 
    //sure we are not attaching more than once since
    //instead of on, I am using direct CLICK binding.
    $('#resTable').unbind("click").click(function() { 
        ....
    });

    $('div[class^="sideNav"]').unbind("click").click(function() {
        ....
    });
};

var nav = function(d) {
    n = page   d;
    $('#slide').empty();
    $('#slide').load('p/' n '.php', function(){
         //bind events
         bindEvents();
    });
}

$(function(){
    //the first page call, when page loads
    nav(0);
});
  

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

Ответ №3:

Я не пробовал ничего делать с этим, но вы пробовали помещать привязку событий всплывающих кнопок в «завершенный» вариант запроса ajax? Кажется, это более безопасный способ обеспечить привязку к одному элементу:

 var req = $.ajax({
    url : '../includes/prod_results.php',
    type : 'POST',
    dataType : "json",
    data : {
        y : yr,
        t : 'ETF'
    },
    success : function(j) {
        var table = "<table cellspacing='0'><tr><th>Year</th><th>Returns</th></tr>";
        for(var i = 0; i < 12; i  ) {
            if (i === 5 amp;amp; yr === '2014'){
                break;
            }
            var obj = j[i];
            var month = obj['month'];
            var profit = obj['profit'];
            var bal = obj['bal'];
            table  = "<tr><td style='width:75px'>" month "</td><td style='padding: 0 15px'>" parseFloat(profit).toFixed(2) "%</td><td style='width:75px'>$" comma(parseFloat(bal).toFixed(2)) "</td></tr>";
            if (i === (11)) {
                table  = "</table>";
            }
        }
        var YAvgDPm = comma(parseFloat(j.YAvgDPm).toFixed(2));
        var OAvgDPm = comma(parseFloat(j.OAvgDPm).toFixed(2));
        var YTotProfit = comma(parseFloat(j.YTotProfit).toFixed(2));
        var OTotProfit = comma(parseFloat(j.OTotProfit).toFixed(2));
        var YAvgPcPm = comma(parseFloat(j.YAvgPcPm).toFixed(2));
        var OAvgPcPm = comma(parseFloat(j.OAvgPcPm).toFixed(2));
        var YTotPcProfit = comma(parseFloat(j.YTotPcProfit).toFixed(2));
        var OTotPcProfit = comma(parseFloat(j.OTotPcProfit).toFixed(2));

        $('#yAvgDPm').html("$" YAvgDPm);
        $('#oAvgDPm').html("$" OAvgDPm);
        $('#yTotProfit').html("$" YTotProfit);
        $('#oTotProfit').html("$" OTotProfit);
        $('#yAvgPcPm').html(YAvgPcPm "%");
        $('#oAvgPcPm').html(OAvgPcPm "%");
        $('#yTotPcProfit').html(YTotPcProfit "%");
        $('#oTotPcProfit').html(OTotPcProfit "%");
        $('#yrRes').html(table);
        $('#yrGraph').html("<img src='../images/graphs/etf_" yr ".jpg'>");
        return false;
    }, 
    complete:function(){
        //put the bindings to popup here
    }
});
  

Ответ №4:

попробуйте это

 $("body").delegate('#resTable','click',function() {
    //some codes
}


$("body").delegate('div[class^="sideNav"]','click',function() {
    //some codes
}
  

Комментарии:

1. Функция Delegate() была заменена функцией on(). Тем не менее, я уже пробовал delegate(), live() и on()