it-swarm-id.com

Bagaimana cara melanjutkan propagasi acara setelah membatalkan?

Ketika pengguna mengklik tautan tertentu, saya ingin menyajikan kepada mereka dialog konfirmasi. Jika mereka mengklik "Ya" saya ingin melanjutkan navigasi asli. Satu tangkapan: dialog konfirmasi saya dilaksanakan dengan mengembalikan objek jQuery.Deferred yang diselesaikan hanya ketika/jika pengguna mengklik tombol Ya. Jadi pada dasarnya dialog konfirmasi tidak sinkron.

Jadi pada dasarnya saya ingin sesuatu seperti ini:

$('a.my-link').click(function(e) {
  e.preventDefault(); e.stopPropogation();
  MyApp.confirm("Are you sure you want to navigate away?")
    .done(function() {
      //continue propogation of e
    })
})

Tentu saja saya bisa menetapkan bendera dan memicu kembali klik tapi itu berantakan. Adakah cara alami untuk melakukan ini?

52
George Mauer

Di bawah ini adalah bit dari kode yang benar-benar berfungsi di Chrome 13, yang mengejutkan saya.

function handler (evt ) {
    var t = evt.target;
    ...
    setTimeout( function() {
        t.dispatchEvent( evt )
    }, 1000);
    return false;
}

Ini bukan browser yang sangat lintas, dan mungkin akan diperbaiki di masa depan, karena rasanya seperti risiko keamanan, imho. 

Dan saya tidak tahu apa yang terjadi, jika Anda membatalkan propagasi acara. 

11
c69

Jika saya memahami masalahnya dengan benar, saya pikir Anda bisa memperbarui acara tersebut menjadi acara asli di penutupan yang Anda miliki di sana. Jadi cukup atur e = e.originalEvent dalam fungsi .done.

https://jsfiddle.net/oyetxu54/

MyApp.confirm("confirmation?")
.done(function(){ e = e.originalEvent;})

di sini ada biola dengan contoh yang berbeda (biarkan konsol tetap terbuka sehingga Anda dapat melihat pesan): .__ ini bekerja untuk saya di chrome dan firefox

3
user2977636

Saya memecahkan masalah dengan cara ini pada salah satu proyek saya. Contoh ini berfungsi dengan beberapa penanganan peristiwa dasar seperti klik, dll. Handler untuk konfirmasi harus terikat dengan handler pertama.

    // This example assumes clickFunction is first event handled.
    //
    // you have to preserve called function handler to ignore it 
    // when you continue calling.
    //
    // store it in object to preserve function reference     
    var ignoredHandler = {
        fn: false
    };

    // function which will continues processing        
    var go = function(e, el){
        // process href
        var href = $(el).attr('href');
        if (href) {
             window.location = href;
        }

        // process events
        var events = $(el).data('events');

        for (prop in events) {
            if (events.hasOwnProperty(prop)) {
                var event = events[prop];
                $.each(event, function(idx, handler){
                    // do not run for clickFunction
                    if (ignoredHandler.fn != handler.handler) {
                        handler.handler.call(el, e);
                    }
                });
            }
        }
    }

    // click handler
    var clickFunction = function(e){
        e.preventDefault();
        e.stopImmediatePropagation();
        MyApp.confirm("Are you sure you want to navigate away?")
           .done(go.apply(this, e));
    };

    // preserve ignored handler
    ignoredHandler.fn = clickFunction;
    $('.confirmable').click(clickFunction);

    // a little bit longer but it works :)
2
Jan Míšek

Kami memiliki persyaratan serupa dalam proyek kami dan ini berfungsi untuk saya. Diuji dalam chrome dan IE11.

$('a.my-link').click(function(e) {
  e.preventDefault(); 
  if (do_something === true) {
    e.stopPropogation();
    MyApp.confirm("Are you sure you want to navigate away?")
    .done(function() {
      do_something = false;
      // this allows user to navigate 
      $(e.target).click();
    })
  }

})
0
Karuna Lakshman

Saya mengedit kode Anda. Fitur baru yang saya tambahkan:

  1. Menambahkan namespace ke acara;
  2. Setelah mengklik pada elemen acara akan dihapus oleh namespace;
  3. Akhirnya, setelah selesai tindakan yang diperlukan di bagian "MyApp" melanjutkan propagasi dengan memicu elemen "klik" elemen lainnya.

Kode:

$('a.my-link').on("click.myEvent", function(e) {
  var $that = $(this);
  $that.off("click.myEvent");
  e.preventDefault();
  e.stopImmediatePropagation();
  MyApp.confirm("Are you sure you want to navigate away?")
    .done(function() {
        //continue propogation of e
        $that.trigger("click");
    });
});
0

Saya memecahkan ini dengan:

  1. menempatkan pendengar acara pada elemen induk
  2. menghapus kelas dari tautan SAJA ketika pengguna mengonfirmasi
  3. memilih kembali tautan setelah saya menghapus kelas.

function async() {
  var dfd = $.Deferred();
  
  // simulate async
  setTimeout(function () {
    if (confirm('Stackoverflow FTW')) {
      dfd.resolve();
    } else {
      dfd.reject();
    }
  }, 0);
  
  return dfd.promise();
};

$('.container').on('click', '.another-page', function (e) {
  e.stopPropagation();
  e.preventDefault();
  async().done(function () {
    $(e.currentTarget).removeClass('another-page').click();
  });
});

$('body').on('click', function (e) {
  alert('navigating somewhere else woot!')
});
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>

<div class="container">
  <a href="#" class="another-page">Somewhere else</a>
</div>

Alasan saya menambahkan pendengar acara ke induk dan bukan tautan itu sendiri adalah karena acara on jQuery akan mengikat elemen sampai diberitahu sebaliknya. Jadi meskipun elemen tidak memiliki kelas another-page masih memiliki pendengar acara terpasang sehingga Anda harus mengambil keuntungan dari event delegation untuk menyelesaikan masalah ini.

GOTCHA ini sangat berbasis negara. yaitu jika Anda perlu meminta pengguna SETIAP SAAT mereka mengklik tautan Anda harus menambahkan pendengar ke-2 untuk membaca kelas another-page kembali ke tautan. yaitu.:

$('body').on('click', function (e) {
  $(e.currentTarget).addClass('another-page');
});

catatan samping Anda juga dapat menghapus pendengar acara di container jika pengguna menerima, jika Anda melakukan ini pastikan Anda menggunakan namespace acara karena mungkin ada pendengar lain di wadah yang mungkin Anda hapus secara tidak sengaja. lihat https://api.jquery.com/event.namespace/ untuk lebih jelasnya.

0
devkaoru