Um widget no Customizador pode ser “de uso único” (ou seja, desativado após a inclusão de 1 instância)?

8

Estou em uma missão noturna para criar um widget de uso único personalizado .

Assim que uma instância dele tiver sido adicionada a um painel da barra lateral no personalizador , seu controle no painel Widgets disponíveis deverá ser exibido como desativado (ou alternativamente , desaparecer completamente).

É assim que fica (observe o widget visualmente "desativado" à direita):

OWidgetpersonalizadoestáregistradoetudo,masestoupresoaorequisitodeusoúnico.

Especificações

  • Aescalanãoéumproblema.Nãoháproblemaemassumirapenasumabarralateralregistrada.Aabordagempodeserlimitarousodowidgeta1porbarralateraloua1portodasasbarraslateraisregistradas-ambosseriamigualmentebonsporenquanto.
  • ApáginaWidgetsnoback-endnãoéumproblema.IssonãoénecessárioparafuncionarigualmentebemnapáginaWidgetsemAparêncianoback-end.SótemquetrabalharnoCustomizador.

Perguntas

  1. Cercade250anosatrás,todososwidgetscostumavamser"de uso único". Alguém sabe de uma maneira legítima de trazer esses tempos de volta e fazer um widget personalizado ser usado apenas 1x através da API Widget?
  2. Se não (o que estou assumindo depois de ter analisado uma boa quantidade de arquivos principais), provavelmente adiaria a uma abordagem baseada em CSS (eventos de ponteiro, sobreposição de pseudo elementos, etc.). Algum tipo de alma ajudaria meu conhecimento very limitado de Customizador / JavaScript com uma abordagem básica sobre como adicionar / remover uma classe CSS dedicada ao controle de widget no painel "disponível" (aquele em à direita) uma vez que uma instância do referido widget tenha sido adicionada / removida ao painel da barra lateral?

O que eu tentei até agora

  • Pesquise uma boa parte dos arquivos principais.
  • Leia this , e this , mas nenhum parece prático.
  • Alterado com eventos jQuery widget-added , widget-updated e widget-synced , mas falta um evento para "widget excluído".

Obrigado antecipadamente!

Atualização: não coloquei minha prova de conceito em um repositório público ainda, é claro que o faria.

Solução

Eu envolvi a solução gentilmente compartilhada por kraftner abaixo em um plug-in de prova de conceito no GitHub .

    
por glueckpress 28.11.2017 / 19:00

1 resposta

5

Abordagem

Então, olhei para isso e minha abordagem é esta:

  1. Ao iniciar o personalizador, passe por todas as barras laterais e desative o widget assim que encontrar algum uso dele
  2. Sempre que uma barra lateral for alterada, faça isso novamente.

Aviso de isenção

Isso tem as seguintes limitações:

  1. Esta é a primeira vez que eu me interajo em brincar com a API JS do Customizador. Então, eu posso estar fazendo coisas ineficientes aqui, mas hey, funciona;)
  2. Só se importa com o personalizador (conforme indicado na pergunta)
  3. Não faz nenhum tipo de validação no lado do servidor. Ele simplesmente oculta a interface do usuário, portanto, se você está preocupado com alguém contornando a interface do usuário, isso está incompleto / inseguro.
  4. Desativar o widget é global - qualquer uso em qualquer barra lateral desativa o widget globalmente.

O código

Agora que temos o aviso de isenção feito, vamos ver o código:

(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: use a ação customize_controls_enqueue_scripts para adicionar o script.

Provavelmente, você poderia estender isso para limitá-lo a uma base por barra lateral em vez de globalmente. Eu diria que ouça a ativação de uma barra lateral e conte os widgets nessa barra lateral. Mas também não encontrei tempo para investigar isso.

    
por kraftner 01.12.2017 / 13:53