Własne kontrolki dla ekranu personalizacji motywu

Ekran personalizacji motywu pokazuje swoje prawdziwe możliwości wtedy, gdy potrzebujemy stworzyć całkowicie nową kontrolkę – dzięki API ekranu personalizacji możemy całkiem łatwo utworzyć dedykowaną kontrolkę z dedykowanym wyglądem i zachowaniami.

Podstawy

Aby stworzyć pierwszą własną kontrolkę musimy najpierw zapoznać się z kilkoma ważnymi elementami API.

Przede wszystkim tworząc własną kontrolkę, będziemy korzystali z klasy WP_Customize_Control. Tworząc jej klasę potomną będziemy najczęściej musieli nadpisać dwie lub trzy metody:

  • enqueue – odpowiada ona za dodawanie dodatkowych styli CSS i skryptów JS dla naszej kontrolki
  • render_content – jest to metoda używana do wygenerowania struktury HTML naszej kontrolki
  • to_json – rzadziej nadpisywana metoda, służąca do przekazywania odpowiednich parametrów do API dostępnego w JavaScript.

Oczywiście możemy też stworzyć kilka własnych metod, które wykorzystamy w kodzie wspomnianych, nadpisywanych metod.

Jedynym polem klasy WP_Customize_Control, które należy nadpisać jest pole type, które odpowiada za typ naszej kontrolki i domyślnie ma wartość text.

Plan

Nasza kontrolka będzie tworzyła pole wyboru daty, które będzie można wykorzystywać do określenia konkretnego terminu.

Taką kontrolkę można wykorzystać np. przy okazji tworzenia motywu, który oferuje zmianę stylu w określonym czasie (przykładowo na styl świąteczny).

Teoretycznie można skorzystać po prostu z faktu, że od WordPressa 4.0 możemy stworzyć dowolną kontrolkę dostępną w HTML5, ale oczywiście wsparcie dla tych kontrolek jest dość wybiórcze, co powoduje, że nie nadają się one do zastosowań, gdzie wymagane jest wsparcie różnych przeglądarek.

Zatem nasza kontrolka będzie składać się z kilku elementów:

  • odpowiedniej struktury HTML,
  • skryptu JavaScript, który będzie odpowiadał za obsługę zachowań naszej kontrolki,
  • kodu CSS, który zapewni odpowiedni wygląd naszej kontrolki.

Oczywiście nie będziemy implementować skryptu kalendarza w JavaScript od podstaw, bo to temat na cały oddzielny wpis, zamiast tego skorzystamy ze skryptu Kalendae.

Implementujemy

Zaczynamy od pobrania skryptu Kalendae i umieszczenia jego plików z katalogu build w katalogu tc-calendar.

Następnie tworzymy plik tc-calendar.php i tworzymy w nim klasę TC_Calendar_Control:

class TC_Calendar_Control extends WP_Customize_Control {
    public $type = 'tc-calendar';
    public function __construct($manager, $id, $args = array()) {
         parent::__construct($manager, $id, $args);
    }
}

Następnie dodajemy pliki JS i CSS naszej kontrolki, tworząc metodę enqueue:

public function enqueue() {
        wp_enqueue_script('tc-calendar', get_template_directory_uri() . '/inc/tc-calendar/kalendae.standalone.js' );
        wp_enqueue_style('tc-calendar', get_template_directory_uri() . '/inc/tc-calendar/kalendae.css');
}

Jak widać powyżej, korzystamy z pliku kalendae.standalone.js, gdyż biblioteka moment.js nie jest dostępna w WordPressie.

Ostatnią ważną metodą, którą musimy stworzyć jest oczywiście render_content:

public function render_content() {
    ?>
    <label>
        <?php if(!empty($this->label)) : ?>
            <span class="customize-control-title">
                <?php echo esc_html( $this->label ); ?>
            </span>
        <?php endif; ?>

		<?php if(!empty($this->description)) : ?>
        	<span class="description customize-control-description">
            <?php echo $this->description ; ?>
        	</span>
        <?php endif; ?>

        <input type="text" class="auto-kal" <?php $this->link(); ?> value="<?php echo esc_attr($this->value()); ?>" />
    </label>
    <?php
}

Poza sprawdzeniem czy istnieje etykieta oraz opis naszej kontrolki mamy też oczywiście kod tworzący właściwą część naszej kontrolki – element input z klasą auto-kal – dzięki tej klasie skrypt Kalendae automatycznie wykrywa pola do których dodaje pole wyboru daty.

Mamy też wywoływane dwie ważne metody pochodzące z klasy WP_Customize_Control:

  • $this->link() – jest to zapis odpowiadający za zarejestrowanie naszej kontrolki po stronie JavaScriptowego API ekranu personalizacji. Bez niej ekran personalizacji nie zareaguje na zmiany wartości naszej kontrolki a ona sama nie będzie dostępna z poziomu skryptów JavaScript.
  • $this->value() – wywołanie tej metody zapewni nam zachowanie wartości naszej opcji w interfejsie po zapisaniu, inaczej wartość opcji zapisałaby się, ale po kolejnym zapisaniu ustawień znów byłaby pusta (chyba, że użytkownik odkryłby, że trzeba wartość opcji uzupełnić ponownie.

Mała poprawka w CSS

W pliku kalendae.css musimy zwiększyć wartość z-index do 1000000 dla selektora: .kalendae.k-floating, inaczej blok kalendarza się nam nie pojawi – znajdzie się pod strukturą kontrolek.

Nasza kontrolka jest gotowa!

Jak widać nie musieliśmy się zbyt wiele napracować by stworzyć naszą pierwszą całkiem złożoną kontrolkę. Teraz wystarczy stworzyć kod, który będzie jej używał.

Poza dołączeniem kodu naszej kontrolki do pliku obsługującego ekran personalizacji w naszym motywie:

require_once('tc-calendar/tc-calendar.php');

Musimy też oczywiście zdefiniować ustawienie i nową kontrolkę:

$wp_customize->add_setting('theme_date', array(
        'default' => '',
        'sanitize_callback' => 'custom_sanitize_callback'
));
$wp_customize->add_control(
    new TC_Calendar_Control(
        $wp_customize,
        'theme_date',
        array(
            'label'   => __('Show posts since', 'theme_slug'),
            'section' => 'features'
        )
    )
);

Powinna się nam pojawić następująca kontrolka:

calendar-customize

Dodajemy własne opcje kontrolki

Na deser jeszcze mały dodatek – skrypt Kalendae oferuje naprawdę dużo opcji konfiguracyjnych – warto byłoby zawrzeć w naszej kontrolce możliwość określania co najmniej niektórych ustawień z poziomu kodu PHP.

Dla przykładu dodamy ustawienie pozwalające określić format daty wykorzystywany w kontrolce.

Od strony tworzenia kontrolki w zapisie dojdzie nam po prostu dodatkowy parametr format:

$wp_customize->add_control(
    new TC_Calendar_Control(
        $wp_customize,
        'theme_date',
        array(
            'label'   => __('Show posts since', 'theme_slug'),
            'section' => 'features',
            'format' => 'DD-MM-YYYY';
        )
    )
);

Do naszej klasy dodajemy pole $format zawierające domyślną wartość nowego parametru:

public $format = 'DD-MM-YYYY';

Natomiast w metodzie render_content dodamy atrybut data-kal, który pozwala określić konfigurację skryptu:

<input type="text" class="auto-kal" data-kal="format: '<?php echo $this->format; ?>'" <?php $this->link(); ?> value="<?php echo esc_attr($this->value()); ?>" />

Uwaga! Jeżeli stworzymy parametr o nazwie wykorzystywanej przez klasę WP_Customize_Control (np. id, manager itd.) to po prostu nie otrzymamy właściwej nazwy parametru, bo przypisywanie wartości tych pól odbywa się po przypisaniu pól na bazie tablicy argumentów kontrolki.

I w zasadzie to by było na tyle w kwestii dodawania dodatkowych parametrów, gdyby nie fakt, że nasze parametry nie będą dostępne z poziomu JavaScript – dlatego musimy jeszcze stworzyć własną implementację metody to_json:

public function to_json() {
    parent::to_json();
    $this->json['format'] = $this->format;
}

Dzięki powyższej metodzie nasza opcja będzie dostępna w JavaScriptowym obiekcie naszej kontrolki.

Podsumowanie

W dość prosty sposób udało się nam stworzyć całkiem złożoną kontrolkę z własnym kodem CSS i JS. Zachęcam do własnych eksperymentów i poznawania klasy WP_Customize_Control. W jednym z kolejnych wpisów postaram się pokazać jeszcze kilka ciekawych elementów o które można wzbogacić własną kontrolkę.