2013-02-27 2 views
2

У меня довольно простая функция, как показано ниже. Это приведет к удалению пользователя после подтверждения того, что они хотят сделать (обратите внимание на пользовательский confirm). Внутри функции обратного вызова при подтверждении, id устанавливается правильно в первый раз, но после этого он не обновляется.Значение внутри обратного вызова не обновляется при каждом вызове функции

Если я console.log внутри функции deleteSlip, id всегда правилен. Если I console.log внутри обратного вызова, это всегда первый id Я отправляю его. Я вижу то же самое, когда отлаживаю javascript. Значение правильное в первый раз, но после этого оно не обновляется.

Что нужно сделать, чтобы получить значение внутри функции обратного вызова для обновления, когда оно обновляется в deleteSlip?

function deleteSlip(id){ 
    // id is correct right here 
    confirm('This will delete your slip. Are you sure you want to do this?', function(confirmed){ 
     // id here is always the first value from deleteSlip, and never changes 
     if (confirmed) 
     { 
      // do stuff 
     } 
    }); 
} 

confirm называют это обычай и определяется следующим образом:

window._originalConfirm = window.confirm; 
window.confirm = function(text, cb) { 
    bootStrapConfirm = function() { 
    if(! $.fn.modal.Constructor) 
     return false; 
    if($('#windowConfirmModal').length == 1) 
     return true; 
    $('body').append(' \ 
    <div id="windowConfirmModal" class="modal hide fade" tabindex="-1" role="dialog" aria-hidden="true"> \ 
     <div class="modal-body"> \ 
     <button type="button" class="close" data-dismiss="modal" aria-hidden="true">×</button> \ 
     <p> alert text </p> \ 
     </div> \ 
     <div class="modal-footer"> \ 
     <button class="btn btn-danger" data-dismiss="modal" aria-hidden="true">No</button> \ 
     <button class="btn btn-primary" data-dismiss="modal" aria-hidden="true">Yes</button> \ 
     </div> \ 
    </div> \ 
    '); 
    function unbind() { 
     $("#windowConfirmModal .btn-primary").unbind('click', confirm); 
     $("#windowConfirmModal .btn-danger").unbind('click', deny); 
    } 
    function confirm() { cb(true); delete cb;} 
    function deny() { cb(false); delete cb;} 
    $("#windowConfirmModal .btn-primary").bind('click', confirm); 
    $("#windowConfirmModal .btn-danger").bind('click', deny); 
    return true; 
    } 
    if (bootStrapConfirm()){ 
    $('#windowConfirmModal .modal-body p').text(text); 
    $('#windowConfirmModal').modal(); 
    } else { 
    console.log('bootstrap was not found'); 
    window._originalConfirm(text); 
    } 
} 

deleteSlip является атрибутом onclick HTML на кнопке. Как так:

onclick="deleteSlip(1234)" 

Опять же, чтобы подтвердить, то id внутри deleteSlip правильно. id внутри обратного вызова на confirm - это то, что он получает первым и никогда не меняется. Обратный вызов может быть асинхронным, но я вызываю его только один раз в любой момент времени. deleteSlip уволен нажатием кнопки.

Я разместил этот вопрос раньше и ему сказали, что это слишком неоднозначно. Пожалуйста, дайте мне знать, что вам нужно, чтобы помочь мне в этом. Область «do stuff» имеет вызов ajax, но перед этим значение не так (поэтому не показывать его для людей, которые не читают весь вопрос).

Обновление: Похоже, что это проблема с обычным confirm. Изменить пользовательские confirm быть следующее:

window.confirm = function(text, cb) { 
    bootStrapConfirm = function() { 
    if(! $.fn.modal.Constructor) 
     return false; 
    if($('#windowConfirmModal').length == 1) 
     return true; 
    $('body').append(' \ 
     <div id="windowConfirmModal" class="modal hide fade" tabindex="-1" role="dialog" aria-hidden="true"> \ 
     <div class="modal-body"> \ 
     <button type="button" class="close" data-dismiss="modal" aria-hidden="true">×</button> \ 
     <p> alert text </p> \ 
     </div> \ 
     <div class="modal-footer"> \ 
     <button class="btn btn-danger" data-dismiss="modal" aria-hidden="true">No</button> \ 
     <button class="btn btn-primary" data-dismiss="modal" aria-hidden="true">Yes</button> \ 
     </div> \ 
     </div> \ 
    '); 
    return true; 
    } 
    if (bootStrapConfirm()){ 
    function confirm() { cb(true); } 
    function deny() { cb(false); } 
    $("#windowConfirmModal .btn-primary").unbind('click', confirm); 
    $("#windowConfirmModal .btn-danger").unbind('click', deny); 
    $("#windowConfirmModal .btn-primary").bind('click', confirm); 
    $("#windowConfirmModal .btn-danger").bind('click', deny); 
    $('#windowConfirmModal .modal-body p').text(text); 
    $('#windowConfirmModal').modal(); 
    } else { 
    console.log('bootstrap was not found'); 
    window._originalConfirm(text); 
    } 
} 

Теперь, когда confirm называется, он называет ВСЕ id «S это когда-либо видел. Что-то я не unbind правильно?

+0

Почему вы только что удалили этот вопрос и повторно разместили его? –

+0

Мне сказали, что это было слишком неоднозначно. Я обновил вопрос с гораздо большей информацией. – tubaguy50035

+1

Я просто рад, что сделал копию своего комментария, который я не мог опубликовать, поэтому вот оно ... –

ответ

1

У вас проблема с прицелом. id определяется в deleteSlip(), а не в обратном вызове. Поэтому вы должны передать id в качестве параметра для обратного вызова.

В встроенном jquery это будет сделано путем добавления параметров непосредственно перед тем, как функция обратного вызова будет присвоена confirm(). Не знаете, как бы вам пришлось это делать.

В вашем случае я бы сделал это так:

function deleteSlip(id){ 
    // id is correct right here 
    confirm('This will delete your slip. Are you sure you want to do this?', id, function(cb_id, confirmed){ 
     // id here is always the first value from deleteSlip, and never changes 
     if (confirmed) 
     { 
     // do stuff 
     } 
    }); 
} 

И:

window._originalConfirm = window.confirm; 
window.confirm = function(text, id, cb) { 
    bootStrapConfirm = function() { 
    if(! $.fn.modal.Constructor) 
     return false; 
    if($('#windowConfirmModal').length == 1) 
     return true; 
    $('body').append(' \ 
     <div id="windowConfirmModal" class="modal hide fade" tabindex="-1" role="dialog" aria-hidden="true"> \ 
     <div class="modal-body"> \ 
     <button type="button" class="close" data-dismiss="modal" aria-hidden="true">×</button> \ 
     <p> alert text </p> \ 
     </div> \ 
     <div class="modal-footer"> \ 
     <button class="btn btn-danger" data-dismiss="modal" aria-hidden="true">No</button> \ 
     <button class="btn btn-primary" data-dismiss="modal" aria-hidden="true">Yes</button> \ 
     </div> \ 
    </div> \ 
    '); 
    function unbind() { 
     $("#windowConfirmModal .btn-primary").unbind('click', confirm); 
     $("#windowConfirmModal .btn-danger").unbind('click', deny); 
    } 
    function confirm() { cb(id, true); delete cb;} 
    function deny() { cb(id, false); delete cb;} 
    $("#windowConfirmModal .btn-primary").bind('click', confirm); 
    $("#windowConfirmModal .btn-danger").bind('click', deny); 
    return true; 
    } 
    if (bootStrapConfirm()){ 
    $('#windowConfirmModal .modal-body p').text(text); 
    $('#windowConfirmModal').modal(); 
    } else { 
    console.log('bootstrap was not found'); 
    window._originalConfirm(text); 
    } 
} 

Отказ от ответственности: havn't запустить код, так что может быть какая-то ошибка есть. Но идея должна быть надежной.

+0

Но идентификатор существует в обратном вызове ... – tubaguy50035

+0

Да, но самое близкое пространство имеет приоритет. Вы можете назвать его cb_id, которым хотите быть уверенным. – fredrik

+0

@fredrik: он не объявляется в обратном вызове OP, поэтому, когда в обратном вызове используется 'id', он будет использовать тот, который входит в область« deleteSlip ». –

-1

Вы должны явно передать идентификатор функции обратного вызова.

function deleteSlip(id){ 
     // id is correct right here 
     confirm('This will delete your slip. Are you sure you want to do this?',  function(confirmed,id){ 
      var newId = id; 
      alert(newId); 
      // id here is always the first value from deleteSlip, and never changes 
      if (confirmed) 
      { 
       // do stuff 
      } 
     }); } 
+1

Нет, функции в JavaScript создают закрытие, поэтому обратный вызов несет в себе свою охватывающую область переменных, включая параметр id. Чтобы сделать то, что вы хотите, 'id' нужно будет передать' confirm', а затем 'confirm' нужно будет передать его на обратный вызов. Но все это не обязательно. –

+0

@thesystem Купите свой аргумент. Но, не передаст ли это как параметр решить проблему? Было ли это решение? – hop

+0

Нет, проблема в том, что функция обратного вызова постоянно связана с диалогом с помощью новой функции, созданной внутри функции 'window.confirm', которая ссылается на нее. Пропуская «id», все равно будет та же проблема. Новая функция теперь будет ссылаться на исходную функцию * и * на исходный идентификатор. Кроме того, функция 'confirm' должна быть общей.получая и передавая «id», делает его конкретным для ситуации, когда вы хотите это сделать. Использование закрытий позволяет вашей функции обратного вызова ссылаться на любые переменные, которые она хочет, без необходимости передавать их при вызове обратного вызова. –

Смежные вопросы