Bisakah widget di Customizer menjadi "sekali pakai" (yaitu dinonaktifkan setelah 1 instance ditambahkan)?

8

Saya sedang dalam perjalanan setiap malam untuk membangun widget sekali pakai khusus .

Segera setelah satu instance ditambahkan ke panel sidebar di Customizer , kontrolnya pada panel Widgets yang tersedia harus ditampilkan sebagai dinonaktifkan (atau sebagai alternatif, dihilangkan seluruhnya).

Begini tampilannya (perhatikan widget yang "dinonaktifkan" secara visual di sebelah kanan):

...

Widget khusus terdaftar dan semuanya, tapi saya terjebak dengan persyaratan sekali pakai.

Spesifikasi

  • Skala bukanlah masalah. Boleh saja menganggap hanya 1 bilah sisi yang terdaftar. Pendekatannya adalah membatasi penggunaan widget menjadi 1 per bilah sisi, atau 1 per semua bilah sisi yang terdaftar — keduanya akan sama-sama baik untuk saat ini.
  • Halaman Widget di back-end tidak menjadi masalah. Ini tidak diperlukan untuk bekerja dengan baik di halaman Widget di bawah Tampilan di back-end. Hanya perlu bekerja di Customizer.

Pertanyaan

  1. Sekitar 250 tahun yang lalu, semua widget digunakan untuk “sekali pakai”. Adakah yang tahu cara yang sah untuk mengembalikan waktu tersebut dan membuat widget khusus hanya digunakan 1x melalui API Widget?
  2. Jika tidak (yang saya asumsikan setelah menggali cukup banyak file inti), saya mungkin akan menunda pendekatan berbasis CSS (pointer-events, overlay elemen pseudo, apa pun). Apakah ada orang yang mau membantu pengetahuan Customizer / JavaScript saya yang sangat terbatas dengan pendekatan dasar tentang cara menambah / menghapus kelas CSS khusus ke kontrol widget di panel "tersedia" (panel di sebelah kanan) setelah instance dari widget tersebut memiliki telah ditambahkan / dihapus ke panel sidebar?

Apa yang saya coba sejauh ini

  • Menggali banyak file inti.
  • Baca ini , dan ini , tetapi tidak ada yang tampak praktis.
  • Bermain-main dengan peristiwa jQuery widget-added, widget-updateddan widget-synced, tetapi melewatkan acara untuk “dihapus widget”.

Terima kasih banyak sebelumnya!


Pembaruan: Belum menempatkan bukti konsep saya pada repo publik, tentu saja akan dilakukan.

Larutan

Saya membungkus solusi yang dibagikan dengan baik oleh kraftner di bawah ini dalam sebuah bukti konsep plugin di GitHub .

glueckpress
sumber
Anda juga bisa menggunakan API widget klasik alih-alih WP_Widget, misalnya: gist.github.com/westonruter/7141599
Weston Ruter

Jawaban:

5

Pendekatan

Jadi saya telah melihat ini dan pendekatan saya adalah ini:

  1. Saat meluncurkan penyesuai, buka semua bilah sisi dan nonaktifkan widget segera setelah Anda menemukan penggunaannya
  2. Setiap kali sidebar diubah lakukan itu lagi.

Penolakan

Ini memiliki batasan sebagai berikut:

  1. Ini adalah pertama kalinya saya mencoba-coba bermain dengan JS API Customizer. Jadi saya mungkin melakukan hal-hal yang tidak efisien di sini, tapi hei, itu berhasil;)
  2. Hanya peduli dengan Penyesuai (sebagaimana dinyatakan dalam pertanyaan)
  3. Tidak melakukan validasi sisi server apa pun. Ini hanya menyembunyikan UI, jadi jika Anda khawatir tentang seseorang yang mengelak dari UI ini tidak lengkap / tidak aman.
  4. Menonaktifkan widget bersifat global - setiap penggunaan di bilah samping apa pun menonaktifkan widget secara global.

Kode

Sekarang kita telah melakukan Penafian, mari kita lihat kode:

(function() {
    wp.customize.bind( 'ready', function() {

        var api = wp.customize,
            widgetId = 'foo_widget',
            widget = wp.customize.Widgets.availableWidgets.findWhere( { id_base: widgetId } );

        /**
         * Counts how often a widget is used based on an array of Widget IDs.
         *
         * @param widgetIds
         * @returns {number}
         */
        var countWidgetUses = function( widgetIds ){

            var widgetUsedCount = 0;

            widgetIds.forEach(function(id){

                if( id.indexOf( widgetId ) == 0 ){
                    widgetUsedCount++;
                }

            });

            return widgetUsedCount;

        };

        var isSidebar = function( setting ) {
            return (
                0 === setting.id.indexOf( 'sidebars_widgets[' )
                &&
                setting.id !== 'sidebars_widgets[wp_inactive_widgets]'
            );
        };

        var updateState = function(){

            //Enable by default...
            widget.set('is_disabled', false );

            api.each( function( setting ) {
                if ( isSidebar( setting ) ) {
                    //...and disable as soon as we encounter any usage of the widget.
                    if( countWidgetUses( setting.get() ) > 0 ) widget.set('is_disabled', true );
                }
            } );

        };

        /**
         * Listen to changes to any sidebar.
         */
        api.each( function( setting ) {
            if ( isSidebar( setting ) ) {
                setting.bind( updateState );
            }
        } );

        updateState();

    });
})( jQuery );

Sidenote: Gunakan customize_controls_enqueue_scriptstindakan untuk menambahkan skrip.


Anda mungkin dapat memperpanjang ini untuk membatasinya agar berfungsi sebagai basis per sidebar alih-alih secara global. Saya akan mengatakan mendengarkan aktivasi sidebar dan kemudian menghitung widget di sidebar itu. Tetapi saya tidak menemukan waktu untuk menyelidiki hal itu juga.

pembuat kraftner
sumber
Fantastis! Saya kehilangan kata-kata, ini berfungsi seperti pesona dan menyelesaikan kasus saya sepenuhnya. Tidak akan mengharapkan contoh kerja penuh, terima kasih banyak!
glueckpress
1
Pertanyaan bagus (penjelasan yang jelas, tangkapan layar, bukti usaha) pantas mendapatkan jawaban lengkap. Meninggalkan komentar ini sebagai petunjuk kepada orang lain bagaimana mendapatkan jawaban yang tepat untuk pertanyaan mereka. ;)
kraftner