Lompat ke konten
dokumentasi.id
Commit 83fc07e
v2
Star3,5 rb

4

Alur Efek Klik dari Event ke Elemen

Waves.init tidak memasang listener pada setiap elemen yang bisa diklik. Fungsi itu hanya memasang listener global di document.body, lalu membiarkan event naik sendiri ke sana src/js/waves.js:467-487. Karena pengenalan elemen terjadi saat event berlangsung, urutan pemanggilan Waves.attach() dan Waves.init() tidak mengikat docs/_pages/getting-started.html:61-71.

Diagram berikut menyusuri satu event dari document.body sampai Effect.show.

sequenceDiagram
    autonumber
    participant U as Pengguna
    participant B as document.body
    participant S as showEffect
    participant G as getWavesEffectElement
    participant T as TouchHandler
    participant E as Effect
    U->>B: mousedown atau touchstart naik ke body
    B->>S: showEffect e
    S->>G: getWavesEffectElement e
    G->>T: allowEvent e
    alt touches masih terhitung dan event mousedown
        T-->>G: false
        G-->>S: null
        Note over S: tidak ada ripple
    else event diizinkan
        T-->>G: true
        loop selama target.parentElement ada
            G->>G: uji classList waves-effect
        end
        G-->>S: element atau null
    end
    alt element terisi dan tidak disabled
        S->>T: registerEvent e
        alt touchstart dan Effect.delay aktif
            S->>E: Effect.show tertunda Effect.delay
        else mousedown atau delay nol
            S->>E: Effect.show e, element
            S->>S: pasang mouseup, mouseleave, touchend, touchcancel
        end
    else element null atau disabled
        Note over S: kembali tanpa ripple
    end
%% fig: Perjalanan satu event klik ke Effect.show
%% desc: Event dari dalam halaman naik ke document.body, disaring oleh TouchHandler, dicocokkan ke elemen .waves-effect terdekat, lalu diteruskan ke Effect.show lewat cabang timer atau cabang langsung.
Fig. 1: Perjalanan satu event klik ke Effect.showEvent dari dalam halaman naik ke document.body, disaring oleh TouchHandler, dicocokkan ke elemen .waves-effect terdekat, lalu diteruskan ke Effect.show lewat cabang timer atau cabang langsung.

Listener yang dipasang Waves.init

Sebelum memasang apa pun, Waves.init membaca options.duration dan options.delay dan menimpa default yang tersimpan di objek Effect src/js/waves.js:472-478. Sesudah itu listener dipasang menurut kemampuan perangkat. Nilai isTouchAvailable dihitung sekali saat modul dimuat dari ekspresi 'ontouchstart' in window src/js/waves.js:38.

EventHandlerKapan dipasang
touchstartshowEffecthanya bila isTouchAvailable
touchcancelTouchHandler.registerEventhanya bila isTouchAvailable
touchendTouchHandler.registerEventhanya bila isTouchAvailable
mousedownshowEffectselalu

Tiga listener pertama berada di dalam blok if (isTouchAvailable), sedangkan mousedown dipasang di luar blok itu sehingga perangkat tanpa touch tetap mendapat efek src/js/waves.js:480-486.

Penyaringan awal oleh TouchHandler.allowEvent

Baris pertama getWavesEffectElement adalah panggilan TouchHandler.allowEvent. Bila hasilnya false, fungsi langsung mengembalikan null dan tidak ada elemen yang diproses src/js/waves.js:366-370. allowEvent menolak event yang cocok dengan /^(mousedown|mousemove)$/ selama TouchHandler.touches belum kembali ke nol src/js/waves.js:332-341. Cara penghitung itu naik dan turun dijelaskan di Penanganan Perangkat Touch.

Penelusuran ke .waves-effect terdekat

Sasaran awal penelusuran adalah e.target || e.srcElement. Setiap iterasi menguji satu elemen: bila elemen itu bukan SVGElement dan classList.contains('waves-effect') bernilai benar, elemen tersebut disimpan dan loop berhenti. Bila tidak cocok, target diganti dengan target.parentElement. Loop berjalan selama target.parentElement masih ada, jadi elemen yang tidak punya parent tidak pernah diuji, dan bila tidak ada satu pun elemen cocok fungsi mengembalikan null src/js/waves.js:375-383.

Kelas .waves-effect sendiri tidak datang dari Waves.init. Waves.attach menambahkannya ketika element.className belum memuat kelas itu src/js/waves.js:517-519. Daftar parameter dan perilaku Waves.attach ada di API Publik dan Tipings TypeScript, sedangkan perlakuan khusus untuk tag input dan img ada di Pembungkusan Elemen input dan img.

Gerbang disabled

showEffect tidak langsung memakai elemen yang ditemukan. Elemen dianggap tidak boleh memicu efek bila element.disabled, element.getAttribute('disabled'), atau element.classList.contains('disabled') bernilai benar, dan dalam kasus itu fungsi langsung return src/js/waves.js:397-404. Pemeriksaan versi lama yang hanya melihat atribut disabled pada e.target masih tertulis di berkas, tetapi sudah dikomentari src/js/waves.js:391-395.

Dua cabang sesudah gerbang

Setelah elemen lolos, showEffect mencatat event ke TouchHandler, lalu memilih satu dari dua jalur tampil.

KondisiYang dijalankanRentang baris
selalu, sesudah lolos gerbangTouchHandler.registerEvent(e)src/js/waves.js:406
e.type === 'touchstart' dan Effect.delay bernilai benarsetTimeout ke Effect.show selama Effect.delay, ditambah listener touchmove, touchend, touchcancelsrc/js/waves.js:408-451
selain ituEffect.show(e, element) langsung, ditambah listener touchend, touchcancel, mouseup, mouseleavesrc/js/waves.js:452-463

Nilai default yang dipakai kedua cabang adalah Effect.delay 200 dan Effect.duration 750 src/js/waves.js:105-108. Pada cabang langsung, Effect.show menerima event asli dari mousedown, sehingga klik kanan tetap tersaring di dalam Effect.show lewat pemeriksaan e.button === 2 src/js/waves.js:112-115.

Rangkaian gerbang di atas dapat dibaca sebagai pohon keputusan.

graph TD
    A["event mousedown / touchstart"] --> B{"TouchHandler.allowEvent"}
    B -->|false| Z["getWavesEffectElement return null"]
    B -->|true| C["target = e.target || e.srcElement"]
    C --> D{"classList has waves-effect?"}
    D -->|belum| E["target = target.parentElement"]
    E --> D
    D -->|ketemu| F{"disabled atau class disabled?"}
    F -->|ya| Y["return tanpa ripple"]
    F -->|tidak| G["TouchHandler.registerEvent"]
    G --> H["Effect.show"]
    style A fill:#f59e0b,color:#000
    style B fill:#f59e0b,color:#000
    style D fill:#8b5cf6,color:#fff
    style F fill:#f59e0b,color:#000
    style G fill:#2d7d46,color:#fff
    style H fill:#2d7d46,color:#fff
    style Z fill:#dc2626,color:#fff
    style Y fill:#dc2626,color:#fff
%% fig: Gerbang keputusan dari event ke Effect.show
%% desc: Dua titik penolakan menghentikan alur, yaitu allowEvent yang bernilai false dan elemen berstatus disabled; jalur yang lolos berakhir di Effect.show.
Fig. 2: Gerbang keputusan dari event ke Effect.showDua titik penolakan menghentikan alur, yaitu allowEvent yang bernilai false dan elemen berstatus disabled; jalur yang lolos berakhir di Effect.show.

⚠️ Tidak ada efek bila tidak satu pun leluhur elemen yang diklik memakai kelas waves-effect. Dalam keadaan itu getWavesEffectElement mengembalikan null, showEffect tidak melakukan apa pun, dan tidak ada pesan error yang muncul src/js/waves.js:375-383.

Setelah elemen ditemukan

Effect.show menerima pasangan e dan element yang sama seperti yang dipakai pada cabang timer maupun cabang langsung. Pembuatan node waves-ripple, penempatannya, dan penghapusannya dibahas di Siklus Hidup Ripple; pemicu manual lewat Waves.ripple dan Waves.calm dijelaskan di API Publik dan Tipings TypeScript.