Un widget nel Customizer può essere "monouso" (ovvero disabilitato dopo l'aggiunta di 1 istanza)?


8

Sono in missione notturna per creare un widget personalizzato monouso .

Non appena una sua istanza è stata aggiunta a un pannello della barra laterale nel Personalizzatore , il suo controllo nel pannello Widget disponibili dovrebbe essere visualizzato come disabilitato (o, in alternativa, scomparire del tutto).

Ecco come apparirebbe (notare il widget visivamente "disabilitato" sulla destra):

...

Il Widget personalizzato è registrato e tutto, ma sono bloccato al requisito di uso singolo.

Specifiche

  • La scala non è un problema. Va bene presumere solo 1 barra laterale registrata. L'approccio può essere quello di limitare l'uso del widget a 1 per barra laterale o a 1 per tutte le barre laterali registrate, entrambe per ora andrebbero ugualmente bene.
  • La pagina Widget sul back-end non è un problema. Questo non è necessario per funzionare altrettanto bene nella pagina Widget in Aspetto sul back-end. Deve funzionare solo nel Customizer.

Domande

  1. Circa 250 anni fa, tutti i widget erano "monouso". Qualcuno conosce un modo legittimo per riportare quei tempi e fare in modo che un widget personalizzato venga utilizzato solo 1x tramite l'API Widget?
  2. Altrimenti (cosa che presumo dopo aver scavato attraverso una buona quantità di file core), probabilmente rimanderei ad un approccio basato su CSS (eventi puntatore, sovrapposizione di pseudo-elementi, qualunque cosa). Qualsiasi anima gentile aiuterebbe la mia conoscenza molto limitata di Customizer / JavaScript con un approccio di base su come aggiungere / rimuovere una classe CSS dedicata al controllo widget nel pannello "disponibile" (quello a destra) una volta che un'istanza di detto widget ha stato aggiunto / rimosso al pannello della barra laterale?

Quello che ho provato finora

  • Scavato attraverso una buona parte di file core.
  • Leggi questo e questo , ma nessuno dei due sembra pratico.
  • Armeggiato con eventi jQuery widget-added, widget-updatede widget-synced, ma perdere un evento per “widget di cancellata”.

Grazie mille in anticipo!


Aggiornamento: non ho ancora messo la mia prova di concetto su un repository pubblico, lo farebbe ovviamente.

Soluzione

Ho racchiuso la soluzione condivisa gentilmente da Kraftner di seguito in un plugin di prova del concetto su GitHub .


Potresti anche utilizzare semplicemente l'API del widget classico anziché WP_Widget, ad esempio: gist.github.com/westonruter/7141599
Weston Ruter,

Risposte:


5

Approccio

Quindi ho esaminato questo e il mio approccio è questo:

  1. Quando avvii il personalizzatore, passa attraverso tutte le barre laterali e disabilita il widget non appena ne trovi l'utilizzo
  2. Ogni volta che una barra laterale viene cambiata, fallo di nuovo.

disconoscimento

Ciò ha le seguenti limitazioni:

  1. Questa è la prima volta che mi diletto a giocare con l'API JS del Customizer. Quindi potrei fare cose inefficienti qui, ma ehi, funziona;)
  2. Si preoccupa solo del Customizer (come indicato nella domanda)
  3. Non esegue alcun tipo di convalida sul lato server. Nasconde semplicemente l'interfaccia utente, quindi se sei preoccupato per qualcuno che elude l'interfaccia utente, questo è incompleto / insicuro.
  4. La disabilitazione del widget è globale: qualsiasi utilizzo in qualsiasi barra laterale disabilita il widget a livello globale.

Il codice

Ora che abbiamo fatto il Disclaimer, diamo un'occhiata al codice:

(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: utilizzare l' customize_controls_enqueue_scriptsazione per aggiungere lo script.


Probabilmente potresti estenderlo per limitarlo a lavorare su una base per barra laterale anziché a livello globale. Direi di ascoltare l'attivazione di una barra laterale e di contare i widget in quella barra laterale. Ma non ho trovato il tempo di esaminare anche quello.


Fantastico! Sono a corto di parole, questo funziona come un fascino e risolve completamente il mio caso. Non mi sarei aspettato un esempio funzionante, grazie mille!
glueckpress,

1
Buone domande (spiegazione chiara, schermate, prova dello sforzo) meritano risposte complete. Lasciando questo commento come suggerimento per altre persone su come ottenere risposte adeguate alle loro domande. ;)
kraftner
Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.