Может ли виджет в Настройщике быть «одноразовым» (т.е. отключен после добавления 1 экземпляра)?

8

Я нахожусь в ночном поиске, чтобы создать пользовательский одноразовый виджет .

Как только один его экземпляр был добавлен на боковую панель в настройщике , его элемент управления на панели «Доступные виджеты» должен отображаться как отключенный (или, наоборот, полностью исчезнуть).

Вот как это будет выглядеть (обратите внимание на визуально «отключенный» виджет справа):

...

Пользовательский виджет зарегистрирован и все, но я застрял в требовании одноразового использования.

Спекуляции

  • Масштаб не проблема. Можно предположить только 1 зарегистрированную боковую панель. Подход может заключаться в том, чтобы ограничить использование виджета либо 1 на боковую панель, либо 1 на все зарегистрированные боковые панели - и то, и другое было бы одинаково хорошо на данный момент.
  • Страница виджетов на сервере не является проблемой. Это не обязательно должно работать одинаково хорошо на странице виджетов в разделе « Внешний вид» на серверной части. Это должно работать только в настройщике.

Вопросов

  1. Около 250 лет назад все виджеты были «одноразовыми». Кто-нибудь знает законный способ вернуть те времена и сделать так, чтобы пользовательский виджет использовался только 1 раз через Widget API?
  2. Если нет (то, что я предполагаю после того, как вырыл изрядное количество основных файлов), я бы, вероятно, предпочел подход, основанный на CSS (события указателя, наложение псевдоэлемента, что угодно). Поможет ли моя любезная душа моим очень ограниченным знаниям Customizer / JavaScript базовым подходом к тому, как добавить / удалить выделенный класс CSS к элементу управления виджета на панели «доступны» (тот, что справа), как только экземпляр указанного виджета были добавлены / удалены на боковую панель?

Что я пробовал до сих пор

  • Выкопал изрядную часть основных файлов.
  • Прочитайте это , и это , но ни один не кажется практичным.
  • Возился с JQuery событий widget-added, widget-updatedи widget-synced, но пропустить событие для «виджет удален».

Большое спасибо заранее!


Обновление: пока не разместите мои доказательства концепции в публичном репо, сделаю, конечно.

Решение

Я обернул решение, любезно предоставленное kraftner ниже, в плагин проверки концепции на GitHub .

glueckpress
источник
Вы также можете просто использовать классический API виджетов вместо WP_Widget, например: gist.github.com/westonruter/7141599
Уэстон Рутер,

Ответы:

5

Подходить

Итак, я посмотрел на это, и мой подход заключается в следующем:

  1. При запуске настройщика перейдите на все боковые панели и отключите виджет, как только вы обнаружите, что его используете
  2. Всякий раз, когда изменяется боковая панель, делайте это снова.

отказ

Это имеет следующие ограничения:

  1. Это первый раз, когда я баловался игрой с JS API Настройщика. Так что я мог бы делать неэффективные вещи здесь, но эй, это работает;)
  2. Заботится только о настройщике (как указано в вопросе)
  3. Не выполняет никакой проверки на стороне сервера. Он просто скрывает пользовательский интерфейс, поэтому, если вы беспокоитесь о том, как кто-то может его обойти, это неполно / небезопасно.
  4. Отключение виджета является глобальным - любое использование на любой боковой панели отключает виджет глобально.

Код

Теперь, когда мы сделали Отказ от ответственности, давайте посмотрим на код:

(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: используйте customize_controls_enqueue_scriptsдействие, чтобы добавить скрипт.


Вы могли бы, вероятно, расширить это, чтобы ограничить его работой для каждой боковой панели, а не глобально. Я бы послушал активацию боковой панели и затем посчитал виджеты на этой боковой панели. Но я также не нашел времени, чтобы разобраться в этом.

kraftner
источник
Фантастический! Я в недоумении для слов, это работает как очарование и решает мое дело полностью. Не ожидал полноценного рабочего примера, спасибо большое!
glueckpress
1
Хорошие вопросы (четкое объяснение, скриншоты, доказательство усилий) заслуживают полных ответов. Оставив этот комментарий как подсказку другим людям, как получить правильные ответы на свои вопросы. ;)
kraftner