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

Kamu membaca versi lama. Halaman ini hanya bisa dibaca.

7

Pembungkusan Elemen input dan img

Elemen input dan img tidak bisa menampung anak elemen <div class="waves-ripple">, sehingga ripple tidak akan pernah tampil. TagWrapper adalah objek internal di src/js/waves.js yang menyelesaikan masalah itu: ia adalah kumpulan fungsi pembungkus untuk elemen HTML yang hanya punya satu tag, yaitu <input> dan <img> src/js/waves.js:202-206. Setiap fungsi mengubah struktur DOM sebelum kelas waves-effect dipasang pada elemen.

Titik masuk pembungkusan

Pembungkusan hanya dipicu dari Waves.attach. Di dalam loop, tagName diambil dari element.tagName.toLowerCase(), lalu diperiksa terhadap daftar ['input', 'img']. Jika cocok, TagWrapper[tagName](element) dipanggil dan variabel element langsung diganti dengan element.parentElement, yaitu wrapper hasil pembungkusan src/js/waves.js:507-515. Setelah itu barulah kelas waves-effect dan kelas tambahan ditempelkan ke elemen yang sekarang menunjuk ke wrapper src/js/waves.js:517-519.

graph TD
  A["Waves.attach: loop elemen"] --> B["tagName = element.tagName.toLowerCase"]
  B --> C{"tagName ada di daftar input atau img"}
  C -- tidak --> Z["className += ' waves-effect' + classes"]
  C -- input --> D{"parent i sudah punya waves-effect"}
  C -- img --> L{"parent i sudah punya waves-effect"}
  D -- ya --> S["return: pass through tanpa pembungkusan"]
  L -- ya --> S
  D -- tidak --> E["wrapper = createElement i"]
  E --> F["wrapper.className = element.className + waves-input-wrapper"]
  F --> G["element.className = waves-button-input"]
  G --> H["parent.replaceChild lalu wrapper.appendChild"]
  H --> I["getComputedStyle: color dan backgroundColor"]
  I --> J["wrapper style color + background"]
  J --> K["element style background-color:rgba 0 0 0 0"]
  L -- tidak --> M["wrapper = createElement i"]
  M --> N["parent.replaceChild lalu wrapper.appendChild"]
  K --> Z
  N --> Z
  Z --> O["element = element.parentElement"]
  style A fill:#f59e0b,color:#000
  style C fill:#f59e0b,color:#000
  style D fill:#f59e0b,color:#000
  style L fill:#f59e0b,color:#000
  style S fill:#dc2626,color:#fff
  style J fill:#8b5cf6,color:#fff
  style K fill:#8b5cf6,color:#fff
  style O fill:#2d7d46,color:#fff
%% fig: Urutan pembungkusan input dan img di Waves.attach
%% desc: attach memeriksa tagName, memilih jalur input atau img, membungkus elemen dengan i, lalu menempelkan waves-effect pada wrapper. Jalur input menyalin warna, jalur img tidak.
Fig. 1: Urutan pembungkusan input dan img di Waves.attachattach memeriksa tagName, memilih jalur input atau img, membungkus elemen dengan i, lalu menempelkan waves-effect pada wrapper. Jalur input menyalin warna, jalur img tidak.

Jalur input: kelas, gaya, dan warna

Fungsi TagWrapper.input mulai dengan penjaga pembungkusan ganda. Jika parentNode sudah berupa tag i yang memuat kelas waves-effect, fungsi langsung return tanpa menyentuh DOM src/js/waves.js:209-216. Penjaga ini membuat Waves.attach aman dipanggil berulang pada elemen yang sama.

Bila belum dibungkus, fungsi membuat elemen i baru dan memindahkan identitas elemen ke wrapper: wrapper.className = element.className + ' waves-input-wrapper', sedangkan kelas asli pada input diganti menjadi waves-button-input src/js/waves.js:218-225. Pertukaran lalu dilakukan dengan parent.replaceChild(wrapper, element) diikuti wrapper.appendChild(element), sehingga input menjadi anak wrapper pada posisi yang sama src/js/waves.js:218-225.

Langkah terakhir menyalin warna. window.getComputedStyle(element, null) dibaca untuk mengambil color dan backgroundColor, keduanya ditulis sebagai atribut style pada wrapper, lalu input sendiri diberi background-color:rgba(0,0,0,0) agar latar aslinya tidak menutupi ripple src/js/waves.js:227-233.

Jalur img: pembungkusan tanpa penyalinan gaya

Fungsi TagWrapper.img memakai penjaga yang sama persis: parent bertag i dengan kelas waves-effect berarti elemen sudah dibungkus dan fungsi berhenti src/js/waves.js:238-245. Jika belum, fungsi hanya membuat elemen i, memanggil parent.replaceChild(wrapper, element), lalu wrapper.appendChild(element) src/js/waves.js:247-250. Tidak ada pemindahan kelas, tidak ada getComputedStyle, dan tidak ada penulisan atribut style. Wrapper img baru memperoleh kelas waves-effect saat kendali kembali ke Waves.attach.

Aspekinputimg
Penjaga pembungkusan gandaparent i + waves-effect → return src/js/waves.js:209-216parent i + waves-effect → return src/js/waves.js:238-245
Kelas pada wrapperelement.className + ' waves-input-wrapper' src/js/waves.js:218-225tidak diisi
Kelas pada elemendiganti waves-button-input src/js/waves.js:218-225tidak diubah src/js/waves.js:247-250
Nilai color dan backgroundColordisalin ke wrapper lewat setAttribute('style', ...) src/js/waves.js:227-233tidak disalin
Latar elemendipaksa rgba(0,0,0,0) src/js/waves.js:227-233tidak diubah
Operasi DOMreplaceChild lalu appendChild src/js/waves.js:218-225replaceChild lalu appendChild src/js/waves.js:247-250

Mengapa wrapper yang menerima efek

Effect.show menempelkan ripple sebagai anak dari elemen yang dianggap memicu efek, yaitu document.createElement('div') dengan kelas waves-ripple waves-rippling yang di-appendChild ke elemen tersebut src/js/waves.js:120-122. Elemen itu dicari oleh getWavesEffectElement, yang menelusuri target.parentElement sampai menemukan node dengan kelas waves-effect src/js/waves.js:366-383. Karena kelas waves-effect ditempel pada wrapper <i>, ripple selalu lahir di dalam wrapper, bukan di dalam input atau img.

Penelusuran ke atas juga menjelaskan mengapa wrapper harus menjadi wadah ripple: .waves-effect menetapkan position: relative dan overflow: hidden src/less/waves.less:29-33, sehingga .waves-ripple yang memakai position: absolute dengan ukuran 100px terpotong rapi pada kotak wrapper src/less/waves.less:29-33. Tanpa wrapper, tidak ada kotak ber-overflow: hidden yang bisa memotong ripple pada elemen input atau img.

Gaya yang menyertai wrapper

.waves-input-wrapper menambahkan border-radius: 0.2em dan vertical-align: bottom, menetralkan padding bila wrapper juga memakai .waves-button, dan membuat .waves-button-input di dalamnya menjadi position: relative dengan top: 0, left: 0, serta z-index: 1 src/less/waves.less:119-133. Aturan terakhir ini penting karena input yang sudah dipindah ke dalam wrapper harus tetap berada di atas lapisan ripple.

.waves-button-input sendiri masuk satu grup selektor dengan .waves-button, yang menetapkan border: none, outline: none, background-color: rgba(0, 0, 0, 0), cursor: pointer, dan z-index: 1 src/less/waves.less:91-107. Inilah sebabnya input hasil pembungkusan tampak tanpa border dan latar transparan meski atribut style-nya ditimpa.

⚠️ TagWrapper.input memanggil element.setAttribute('style', 'background-color:rgba(0,0,0,0);'), yang mengganti seluruh atribut style pada input. Gaya inline lain seperti width atau padding pada input ikut hilang dan harus dipindahkan ke wrapper atau ke aturan CSS src/js/waves.js:227-233.

⚠️ Warna yang disalin hanya color dan backgroundColor hasil getComputedStyle. Latar berupa gradient atau background-image pada input tidak terbawa ke wrapper, sehingga ripple berjalan di atas latar transparan src/js/waves.js:227-233.

Untuk melihat bagaimana elemen hasil pembungkusan menerima event dan menghitung koordinat ripple, lihat Alur Efek Klik dari Event ke Elemen. Untuk urutan kelas yang dipakai ripple saat muncul dan hilang, lihat Siklus Hidup Ripple.