6
Penanganan Perangkat Touch
TouchHandler adalah lapisan kecil di src/js/waves.js yang menahan efek mousedown selama dan sesudah interaksi sentuh. Lapisan ini hanya menyala ketika browser melaporkan dukungan sentuh: isTouchAvailable dihitung sekali dari 'ontouchstart' in window. src/js/waves.js:381
Pada perangkat tersebut, Waves.init memasang listener di document.body seperti tabel berikut. src/js/waves.js:480-4862
| Event | Handler | Syarat pemasangan |
|---|---|---|
touchstart | showEffect | isTouchAvailable |
touchcancel | TouchHandler.registerEvent | isTouchAvailable |
touchend | TouchHandler.registerEvent | isTouchAvailable |
mousedown | showEffect | selalu dipasang |
Anatomi TouchHandler
Objek ini hanya memiliki satu field dan dua method. Komentar di atas deklarasinya menyebut tujuannya secara langsung: "Disable mousedown event for 500ms during and after touch". src/js/waves.js:321-3593
| Member | Bentuk | Perilaku |
|---|---|---|
touches | integer, mulai 0 | Penghitung sentuh yang sedang berjalan. Dipilih integer, bukan boolean, agar tidak perlu clearTimeout saat sentuhan baru datang dalam 500 ms. |
allowEvent(e) | function | Mengembalikan false untuk mousedown dan mousemove bila touches bukan nol, selain itu true. |
registerEvent(e) | function | Menambah touches pada touchstart, dan menjadwalkan pengurangan pada touchend atau touchcancel. |
registerEvent menaikkan penghitung tanpa syarat waktu pada touchstart, sedangkan touchend dan touchcancel menurunkan penghitung lewat setTimeout(..., 500). Penurunan dijaga if (TouchHandler.touches) agar tidak menjadi negatif. src/js/waves.js:342-3574
Gerbang allowEvent
allowEvent memakai satu ekspresi reguler untuk membatasi cakupannya: hanya event yang cocok dengan /^(mousedown|mousemove)$/ yang bisa ditolak. Event lain, termasuk touchstart itu sendiri, selalu lolos. src/js/waves.js:332-3415
Penolakan itu dipakai paling awal di getWavesEffectElement. Bila TouchHandler.allowEvent(e) mengembalikan false, fungsi langsung mengembalikan null, sehingga showEffect berhenti sebelum mencari elemen .waves-effect dan tidak ada ripple baru. src/js/waves.js:366-3706
graph LR
TS["touchstart"] --> INC["TouchHandler.touches += 1"]
INC --> MOUSE{"mousedown atau mousemove"}
MOUSE -->|touches terisi| BLOCK["allowEvent: false"]
MOUSE -->|touches kosong| PASS["allowEvent: true"]
BLOCK --> NULL["getWavesEffectElement: null"]
PASS --> FIND["cari elemen .waves-effect"]
style INC fill:#f59e0b,color:#000
style BLOCK fill:#dc2626,color:#fff
style NULL fill:#dc2626,color:#fff
style PASS fill:#2d7d46,color:#fff
%% fig: Gerbang allowEvent pada TouchHandler
%% desc: touchstart menaikkan penghitung touches, lalu setiap mousedown dan mousemove diperiksa gerbang allowEvent sebelum elemen dicari.⚠️ Kenaikan
touchesterjadi di dalamshowEffect, bukan di listenertouchstartmilikdocument.body.registerEvent(e)hanya dipanggil setelah elemen.waves-effectditemukan dan tidak berstatusdisabled,getAttribute('disabled'), atau kelasdisabled. Sentuhan di luar elemen tersebut tidak menaikkan penghitung, jadi tidak ada yang menahanmousedownsesudahnya. src/js/waves.js:399-4067
Opsi delay
Effect.delay bernilai 200 secara default, dengan komentar "check for scroll before showing effect". Nilainya bisa diganti lewat Waves.init({ delay: ... }) karena init menyalin opsi delay ke Effect.delay. src/js/waves.js:107-1088 src/js/waves.js:476-4789
Opsi itu juga muncul di tipe init pada src/typings/waves.d.ts, lihat API Publik dan Tipings TypeScript. src/typings/waves.d.ts:310
Cabang delay hanya dipakai ketika e.type === 'touchstart' dan Effect.delay bernilai bukan nol. mousedown tidak pernah ditunda oleh opsi ini. src/js/waves.js:408-45111
| Kejadian pada elemen | Aksi di kode | Hasil |
|---|---|---|
touchstart dengan Effect.delay | setTimeout menyimpan timer, isinya Effect.show(e, element) | Efek belum tampil selama Effect.delay |
| timer habis | timer diisi null, Effect.show(e, element) berjalan | Ripple muncul |
touchmove (pengguna menggulir) | clearTimeout(timer) lalu hideEffect(moveEvent) | Efek dibatalkan, tidak ada ripple |
touchend atau touchcancel | hideEffect menampilkan efek lebih dulu bila timer masih hidup, lalu Effect.hide | Sentuhan singkat tetap memberi efek |
Di akhir tiap jalur, removeListeners melepas kembali listener touchmove, touchend, dan touchcancel yang dipasang pada elemen. Fungsi itu dideklarasikan setelah pemasangan listener, tetapi baru dipanggil dari callback sehingga deklarasi var sudah terisi saat dipakai. src/js/waves.js:408-45111
Bila Effect.delay bernilai nol atau falsy, jalur lain yang berjalan: Effect.show(e, element) dipanggil langsung, lalu touchend dan touchcancel diarahkan ke Effect.hide selama isTouchAvailable. Effect.hide sendiri melepas kedua listener sentuh itu setelah ripple terakhir dihapus. src/js/waves.js:452-46312 src/js/waves.js:192-19513
stateDiagram-v2
[*] --> Idle
Idle --> Touching: "touchstart pada elemen .waves-effect"
Touching --> Pending: "Effect.delay bukan nol, setTimeout"
Touching --> RippleVisible: "Effect.delay nol, Effect.show langsung"
Pending --> RippleVisible: "timer habis, Effect.show"
Pending --> Scrolling: "touchmove, clearTimeout"
Scrolling --> Idle: "hideEffect lalu removeListeners"
RippleVisible --> Idle: "touchend atau touchcancel, Effect.hide"
Touching --> Cooldown: "touchend atau touchcancel, registerEvent"
Pending --> Cooldown: "touchend atau touchcancel, registerEvent"
RippleVisible --> Cooldown: "touchend atau touchcancel, registerEvent"
Cooldown --> Idle: "500 ms, touches -= 1"
style Pending fill:#f59e0b,color:#000
style Scrolling fill:#dc2626,color:#fff
style RippleVisible fill:#2d7d46,color:#fff
style Cooldown fill:#8b5cf6,color:#fff
%% fig: Siklus sentuh dari touchstart sampai touches kembali nol
%% desc: Cabang delay menunda Effect.show, menggulir lewat touchmove membatalkannya, dan touchend atau touchcancel menahan mousedown selama 500 ms.Pembatalan lewat touchmove inilah yang membuat delay berguna: gulir halaman tidak memicu efek, sedangkan ketukan singkat tetap menampilkannya lewat hideEffect. src/js/waves.js:433-44114
⚠️ Nama
delaydipakai ulang sebagai variabel lokal diremoveRippledengan nilai350 - diffdan150untukmousemove. Variabel itu tidak ada hubungannya denganEffect.delay. src/js/waves.js:273-28315
Titik sentuh dan ripple
Effect.show memilih koordinat dari e.touches[0].pageY dan e.touches[0].pageX bila event membawa daftar touches, lalu memakai e.pageY dan e.pageX untuk event mouse. Perhitungan pusat ripple selengkapnya ada di Siklus Hidup Ripple. src/js/waves.js:129-13216
Pencarian elemen .waves-effect dan penyaringan status disabled berada di Alur Efek Klik dari Event ke Elemen; halaman ini hanya membahas bagaimana sentuhan menahan event mouse.