it-swarm.com.de

Kann ein Widget im Customizer verwendet werden (dh deaktiviert, nachdem eine Instanz hinzugefügt wurde)?

Ich bin auf der nächtlichen Suche nach einem benutzerdefinierten Einweg-Widget .

Sobald eine Instanz davon zu einem Seitenleistenfenster im Customizer hinzugefügt wurde, sollte sein Steuerelement im Fenster "Verfügbare Widgets" als deaktiviert angezeigt werden (oder alternativ ganz verschwinden).

So würde es aussehen (beachten Sie das optisch „deaktivierte“ Widget auf der rechten Seite):

 … 

Das benutzerdefinierte Widget ist registriert und alles, aber ich bin bei der Einweganforderung festgefahren.

Technische Daten

  • Maßstab ist kein Problem. Es ist in Ordnung, nur eine registrierte Seitenleiste anzunehmen. Der Ansatz kann darin bestehen, die Verwendung des Widgets entweder auf 1 pro Seitenleiste oder auf 1 pro alle registrierter Seitenleisten zu beschränken - beides wäre vorerst gleichermaßen in Ordnung.
  • Die Widgets-Seite im Backend ist kein Problem. Dies ist nicht erforderlich, um auf der Seite Widgets unter Darstellung im Back-End gleich gut zu funktionieren. Es muss nur im Customizer funktionieren.

Fragen

  1. Vor etwa 250 Jahren waren alle Widgets "Einweg". Kennt jemand eine legitime Möglichkeit, diese Zeiten zurückzubringen und ein benutzerdefiniertes Widget nur 1x über die Widget-API zu verwenden?
  2. Wenn nicht (was ich annehme, nachdem ich eine ganze Reihe von Kerndateien durchgegraben habe), würde ich wahrscheinlich auf einen CSS-basierten Ansatz (Zeigerereignisse, Pseudoelement-Overlay, was auch immer) zurückgreifen. Würde irgendeine Art von Seele meinen sehr eingeschränkten Kenntnissen in Customizer/JavaScript mit einem grundlegenden Ansatz zum Hinzufügen/Entfernen einer dedizierten CSS-Klasse zum Widget-Steuerelement im Bereich "Verfügbar" (der im richtig) Sobald eine Instanz des Widgets zum Seitenleistenfenster hinzugefügt/daraus entfernt wurde?

Was ich bisher versucht habe

  • Durchsuchte einen ganzen Haufen Kerndateien.
  • Lesen Sie das , und das , aber keiner scheint praktisch zu sein.
  • Mit jQuery-Ereignissen widget-added, widget-updated und widget-synced gebastelt, aber ein Ereignis für "Widget gelöscht" verpasst.

Vielen Dank im Voraus!


Update: Ich habe meinen Proof of Concept noch nicht in ein öffentliches Repo eingestellt, würde es natürlich tun.

Lösung

Ich habe die von kraftner unten freundlicherweise mitgeteilte Lösung in ein Proof-of-Concept-Plugin auf GitHub eingepackt.

8
glueckpress

Ansatz

Also habe ich mir das angeschaut und mein Ansatz ist folgender:

  1. Wenn Sie den Customizer starten, gehen Sie alle Seitenleisten durch und deaktivieren Sie das Widget, sobald Sie eine Verwendung finden
  2. Immer wenn eine Seitenleiste geändert wird, wiederholen Sie dies.

Haftungsausschluss

Dies hat folgende Einschränkungen:

  1. Dies ist das erste Mal, dass ich mit der JS-API des Customizers experimentiert habe. Also mache ich hier vielleicht ineffiziente Sachen, aber hey, es funktioniert;)
  2. Kümmert sich nur um den Customizer (wie in der Frage angegeben)
  3. Führt keine serverseitige Validierung durch. Die Benutzeroberfläche wird lediglich ausgeblendet. Wenn Sie also befürchten, dass jemand die Benutzeroberfläche umgeht, ist dies unvollständig/unsicher.
  4. Das Deaktivieren des Widgets ist global - jede Verwendung in einer Seitenleiste deaktiviert das Widget global.

Der Code

Nachdem wir den Haftungsausschluss fertiggestellt haben, schauen wir uns den Code an:

(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 );

Nebenbemerkung: Verwenden Sie die Aktion customize_controls_enqueue_scripts, um das Skript hinzuzufügen.


Sie könnten dies wahrscheinlich erweitern, um die Verwendung einer Basis pro Seitenleiste anstatt global zu beschränken. Ich würde sagen, hören Sie sich die Aktivierung einer Seitenleiste an und zählen Sie dann die Widgets in dieser Seitenleiste. Aber ich hatte auch keine Zeit, das zu untersuchen.

5
kraftner