WordPress 4.0 – co nowego dla programistów?

W piątek na WordPress 4.0 Release Party we Wrocławiu pokazywałem prezentację na temat zmian w WordPressie 4.0, które mogą zainteresować programistów. Poniżej znajduje się moja prezentacja z tego wydarzenia:

Bazuje ona na moim porównaniu kodu WordPressa 3.9.2 i 4.0.0RC. Od razu podkreślam – to są najciekawsze zmiany jakie wychwyciłem i uznałem, że warto je pokazać. Wszystkich zmian jest dużo więcej, ale musiałbym mieć 2 godziny aby wszystkie je pokazać w trakcie prezentacji 😉

TinyMCE – dodawanie walidacji w popupie

Gdy tworzymy popup z ustawieniami dla naszego przycisku w TinyMCE, prawdopodobnie szybko odkryjemy, że przydałaby się jakaś walidacja danych wprowadzanych w polach popupa, aby użytkownik nie mógł wprowadzić błędnych danych. Prosta walidacja danych jest możliwa w łatwy sposób. Podświetlenie błędnie wypełnionych pól także da się zrobić, choć wymaga ono już trochę pracy i paru mniej eleganckich chwytów.

Zacznijmy od kodu bazowego – przyjmijmy, że nasz popup z dwoma polami: width i height, ma zdefiniowaną akcję onsubmit w następujący sposób:

onsubmit: function(e) {
    editor.insertContent('Lorem ipsum: ' + e.data.width + ' x ' + e.data.height + '.');
}

Zaimplementowanie podstawowej walidacji jest w tym wypadku bardzo proste – sprawdzamy wartości pól i w zależności od spełnienia kryteriów wysyłamy dane z popupa lub nie korzystając z return false do blokowania wysyłania popupa:

onsubmit: function(e) {
    if(e.data.width === '' || e.data.height === '') {
        return false;
    }
    editor.insertContent('Lorem ipsum: ' + e.data.width + ' x ' + e.data.height + '.');
}

Niestety taki sposób walidacji ma poważną wadę – użytkownik nie wie tak naprawdę co się stało i dlaczego formularz nie został wysłany. Dlatego powinniśmy wyświetlić mu odpowiedni komunikat – możemy skorzystać z funkcji alert ale dużo zgrabniej będzie skorzystać z wbudowanego w TinyMCE okna komunikatu:

onsubmit: function(e) {
    if(e.data.width === '' || e.data.height === '') {
        editor.windowManager.alert('Proszę wypełnić wszystkie pola w popupie.');
        return false;
    }
    editor.insertContent('Lorem ipsum: ' + e.data.width + ' x ' + e.data.height + '.');
}

Użytkownik po takiej informacji powinien już być uświadomiony, że coś jest nie tak z wprowadzonymi przez niego danymi, ale warto na wszelki wypadek jeszcze pokazać mu, które pola są wypełnione nieprawidłowo. W tym celu będziemy musieli już stworzyć trochę bardziej wyszukany kod, który pozwoli nam dodać obramowanie wokół źle wypełnionych elementów.

Szukałem możliwie najbardziej eleganckiej metody, niestety nie obyło się bez odwoływania do właściwości obiektów, które patrząc po nazwach powinny być prywatne, ale niestety nie doszukałem się w kodzie TinyMCE innej równie wygodnej metody.

Zacznijmy od tego, że musimy zdobyć uchwyt do pól formularza wyświetlanego w popupie – w tym celu musimy się odwołać do właściwości zwracającej ID wyświetlanego popupa:

var window_id = this._id;

Dzięki temu ID możemy pobrać pola formularza:

var inputs = jQuery('#' + window_id + '-body').find('.mce-formitem input');

Mając uchwyty do pól formularza możemy nadać im kolor obramowania:

if(e.data.width === '') {
    $(inputs.get(0)).css('border-color', 'red');
}

W powyższym wypadku nadamy czerwone obramowanie pierwszemu polu tekstowemu w formularzu.

Żeby wszystko zachowywało się sensownie musimy też sprawić by to obramowanie zniknęło w momencie kliknięcia pola. Zamieniamy zatem:

{
    type: 'textbox',
    name: 'height',
    label: 'Height'
},

na:

{
    type: 'textbox',
    name: 'height',
    label: 'Height',
    onclick: function(e) {
        jQuery(e.target).css('border-color', '');
    }
},

Niestety z moich obserwacji wynika, że onclick to chyba jedyne sensowne zdarzenie, które działa – zatem nie możemy się posłużyć tutaj bezpośrednio zdarzeniami onblur czy onfocus.

Finalnie nasz kod w onsubmit wyglądać może następująco:

onsubmit: function(e) {
    if(e.data.width === '' || e.data.height === '') {
        var window_id = this._id;
        var inputs = jQuery('#' + window_id + '-body').find('.mce-formitem input');

        editor.windowManager.alert('Proszę wypełnić wszystkie pola w popupie.');

        if(e.data.width === '') {
            $(inputs.get(0)).css('border-color', 'red');
        }

        if(e.data.height === '') {
            $(inputs.get(1)).css('border-color', 'red');
        }

        return false;
    }
    editor.insertContent('Lorem ipsum: ' + e.data.width + ' x ' + e.data.height + '.');
}

A co jeśli potrzebujemy więcej zdarzeń dla elementów formularza?

Nie ma co ukrywać, że domyślnie dostępne zdarzenia w TinyMCE nie pozwalają nam tworzyć zbyt rozbudowanych popupów z bardziej złożoną logiką. Na szczęście da się ten problem rozwiązać – jeżeli potrzebujemy dodać obsługę np. zdarzeń onblur czy onfocus do naszych pól możemy skorzystać z małego tricku.

Popup tworzony w TinyMCE wywołuje co najmniej dwa razy zdarzenie repaint – umiejętnie podpinając się pod to zdarzenie możemy uzupełnić braki funkcjonalne naszego popupu.

Przykładowa implementacja, dodająca obsługę zdarzeń onfocus i onblur do pierwszego pola w formularzu:

onrepaint: function(e) {
    var window_id = this._id;

    if(!jQuery('#' + window_id).hasClass('form-initialized')) {
        jQuery('#' + window_id).addClass('form-initialized');

        var inputs = jQuery('#' + window_id + '-body').find('.mce-formitem input');

        jQuery(inputs.get(0)).blur(function() {
            console.log('blur');
        });

        jQuery(inputs.get(0)).focus(function() {
            console.log('focus');
        });
    }
},

Chciałbym w tym miejscu uczulić na fakt wywoływania się zdarzenia repaint kilkukrotnie – dlatego stworzyłem w powyższym kodzie prosty mechanizm sprawdzania czy wywołał się on tylko raz – po pierwszym wywołaniu tej funkcji dodawana jest do popupu klasa form-initialized, która powoduje, że już więcej nasz kod nie zostanie wywołany. Dzięki temu unikniemy między innymi problemów z podwójnie dodanymi zdarzeniami.

Korzystając z powyższej metody możemy w zasadzie stworzyć dowolną logikę dla naszego formularza w popupie. Główną uciążliwością jest tutaj dostęp do pól formularza – różne typy pól mają różne klasy i musimy wszystko odpowiednio wyselekcjonować a potem poprawnie się w tym wszystkim poruszać.

Nie zmienia to faktu, że stworzenie walidacji zawartości popupu w TinyMCE jest możliwe, choć w wypadku bardziej skomplikowanych formularzy wymaga dość skomplikowanego kodu, ze wzgledu na pewne braki w API TinyMCE, które trzeba samodzielnie obejść.

Wykorzystanie menadżera mediów we własnych wtyczkach

Dzięki wykorzystaniu menadżera mediów we własnych wtyczkach możemy znacząco ułatwić życie użytkownikowi – nie musi on z pamięci wprowadzać adresów do wybranych grafik. W tym wpisie chciałbym pokazać jak łatwo dodać obsługę menadżera mediów do własnej wtyczki/motywu.

Uproszczony schemat działania jakie chcemy osiągnąć prezentuje się następująco:

  1. Dodajemy do określonych przycisków akcję otwierania menadżera mediów po ich kliknięciu
  2. Definiujemy właściwości okna menadżera mediów wykorzystywanego przez nasz skrypt
  3. Dodajemy obsługę operacji wyboru obrazka
  4. Dodajemy obsługę operacji zamknięcia menadżera

Jak widać sama idea nie wygląda zbyt skomplikowanie – na szczęście większość operacji wykonywania jest po stronie skryptów menadżera mediów – musimy obsłużyć tylko kluczowe operacje takie jak wybór zdjęcia i zakończenie korzystania z menadżera. Czytaj dalej Wykorzystanie menadżera mediów we własnych wtyczkach

Front-endowe Inspiracje #1

Ostatnio odszedłem od gromadzenia dużych ilości linków do zasobów programistycznych, ale wciąż kolekcjonuję najciekawsze z nich – stąd narodził się pomysł na serię „Front-endowe Inspiracje”.

Front-end nieodłącznie jest związany z WordPressem, zatem liczę na to, że uda mi się dostarczyć Wam inspirujących materiałów, które zachęcą Was do ulepszania swoich witryn i motywów.

Wykorzystanie input[type=”radio”] do zarządzania stanami w webaplikacji

Artykuł opisujący kilka ciekawych przykładów wykorzystania elementów typu radio button do zarządzania stanami w sposób, który pozwala zaoszczędzić sporo kodu JavaScript.

Blast.js

Blast.js to biblioteka do manipulowania tekstem, pozwalająca na tworzenie złożonych animacji tekstu, stylowanie oraz wyszukiwanie zadanych ciągów znaków.

Tworzenie efektu wypełniania ikon

Opis sposobu na utworzenie efektu wypełniających się kolorem ikon.  Demo efektu finalnego.

Animowana ikona Hamburger Menu w SVG

Skoro już jesteśmy przy ikonkach to powyższy artykuł zawiera opis tego jak z użyciem SVG stworzyć efektowną animację ikony hamburger menu.

Walidacja formularzy bez użycia JavaScript

Dwa przykłady jak stworzyć formularze, które się walidują i pokazują odpowiednie komunikaty bez użycia JavaScript.

Zestaw programistycznych ikonek

Kolekcja ikonek związanych z różnymi technologiami i narzędziami webowymi. Na licencji MIT.

18 niespodzianek z kodu jQuery

Autor powyższego wpisu przejrzał kod jQuery i wynotował znalezione ciekawostki.

Jak w prosty sposób stworzyć cache dla shortcode’ów?

Czasami zdarza się, że shortcode przed zwróceniem efektów swojego działania musi wykonać dużo czasochłonnych operacji – np. jeżeli robimy shortcode, który zwraca statusy z Twittera dla określonego zapytania. W takim wypadku powinniśmy stworzyć cache z dwóch powodów:

  • pobranie informacji o statusach z Twittera wymaga pobrania tych danych z zewnętrznego serwera co może zająć sporo czasu
  • Twitter nakłada limity zapytań do swojego API

Na szczęście stworzenie prostego mechanizmu cache dla shortcode’ów jest w WordPressie bardzo proste.

Przyjmijmy, że nasz shortcode pobiera 3 różne parametry z wartościami domyślnymi i zamieniane na zmienne o odpowiednich nazwach w poniższy sposób:

$atts = shortcode_atts(array(
'param1' => 'lorem',
'param2' => 'ipsum',
'param3' => 'dolor'
), $atts);

extract($atts);

Zatem nasz shortcode ma poniższą składnię:

[txt][shortcode param1=”x” param2=”y” param3=”z”][/txt]

Pierwsza istotna obserwacja – nasz shortcode zwróci te same rezultaty dla takich samych wartości parametrów, zatem ciąg złożony z wartości tych parametów może śmiało posłużyć za identyfikator rezultatów danego shortcode’a. Do przechowania zawartości cache wykorzystamy Transients API.

Zatem nasz mechanizm cache będzie potrzebował dwóch kluczowych fragmentów kodu – zapisu i odczytu zawartości cache.

Zacznijmy od odczytu zawartości cache, gdyż ta operacja jest wykonywana przez rozpoczęciem operacji przez nasz shortcode:

$cache = get_transient(md5('PREFIX'.serialize($atts)));

if($cache) {
    return $cache;
}

Jak wspominałem – wykorzystujemy ciąg wartości parametrów jako identyfikator, do tego sugeruję dodać też jakiś własny prefix – dzięki temu zabezpieczymy się przed sytuacją gdy wszystkie parametry będą puste. Jeżeli cache dla danej konfiguracji istnieje to po prostu funkcja zwróci od razu zawartość cache, bez wykonywania dodatkowych operacji.

Następnie cały kod wyjściowy generowany przez shortcode umieszczamy w zmiennej np. $cache_output – jeżeli dobrze tworzycie swoje shortcode’y to zapewne taką zmienną z zawartością rezultatów już posiadacie (nie używacie w shortcode’ach echo, prawda?). Na koniec działania naszego shortcode’u możemy umieścić zawartość tej zmiennej w bazie danych:

set_transient(md5('PREFIX'.serialize($atts)) , $cache_output, 10 * 60);

Jak widać dzięki stworzeniu 6 dodatkowych linijek kodu mały gotowy mechanizm cache.

Osobiscie polecam do listy parametrów takiego shortcode’a dodać też parametr cache_time – dzięki temu będzie można określić czas przechowywania cache, a ostatnia linijka związana z cache zmieni się na:

set_transient(md5('PREFIX'.serialize($atts)) , $cache_output, $cache_time * 60);

Powyższe rozwiązanie ma tą zaletę, że w wypadku shortcode’ów w których istnieje niewielkie zróżnicowanie wartości parametrów do przechowywania rezultatów nawet z kilku tysięcy wpisów, będzie potrzeba kilku-kilkunastu rekordów w bazie danych. Natomiast sugeruję ostrożność w wypadku gdy przy podobnej liczbie wpisów mamy unikalne konfiguracje shortcode’ów – wtedy istnieje ryzyko, że ilość rekordów w bazie danych będzie zbliżona do liczby wpisów.

Podgląd zmian kolorów motywu na ekranie personalizacji

Ekran personalizacji motywu to świetne narzędzie, które umożliwia łatwy podgląd zmian, które chcemy nanieść w naszym motywie z użyciem jego opcji. Jedną z ciekawszych opcji jakie możemy zaoferować użytkownikom naszego motywu jest możliwość zmiany kolorów w motywie z podglądem „na żywo” w ekranie personalizacji.

Czytaj dalej Podgląd zmian kolorów motywu na ekranie personalizacji

Tworzenie wtyczek dla TinyMCE 4.* – moja prelekcja z WordUp Wrocław #4

Po raz drugi pojawiłem się we Wrocławiu na WordUpie jako prelegent i tym razem opowiadałem o tworzeniu wtyczek dla TinyMCE 4.*.  Prelekcję można znaleźć na SlideShare.

Aby prelekcja nie była zbyt długa i nużąca zdecydowałem się wydzielić trzy tematy i stworzyć na ich podstawie wpisy, które stanowią uzupełnienie samej prelekcji:

  1. TinyMCE – dodawanie przycisków w trybie fullscreen
  2. Edytor TinyMCE w sekcji komentarzy
  3. Kontrolka styleselect w TinyMCE

Mam już sporo wartościowego feedbacku oraz kilka pomysłów na ulepszenie tej prelekcji, zatem można się spodziewać, że na jednym z kolejnych WordUpów zaprezentuję ją w ulepszonej postaci.

Dziękuję też osobom, które stale zadają mi ciekawe pytania, dzięki którym mogę tworzyć kolejne wpisy o TinyMCE – kolejna porcja wpisów odnośnie zastosowań tego edytora pojawi się niebawem.

TinyMCE – dodawanie przycisków w trybie fullscreen

WordPress od dłuższego czasu posiada pełnoekranowy tryb tworzenia wpisów, pozwalający skupić się na pisaniu (w niektórych edytorach taki tryb nazywa się „Zen mode” lub po prostu „Distraction Free”). Warto zatem nauczyć się dodawać własne przyciski do edytora w tym trybie – warto od razu podkreślić, że dodawanie przycisków do edytora w wersji pełnoekranowej rządzi się trochę innymi prawami niż w wypadku zwykłego edytora TinyMCE.

Czytaj dalej TinyMCE – dodawanie przycisków w trybie fullscreen

Kontrolka styleselect w TinyMCE

Kontrolka styleselect to domyślnie ukryty element edytora TinyMCE, który pozwala na wygodne formatowanie zaznaczonego tekstu. Domyślnie jest ona ukryta ze względu na fakt iż duplikuje funkcjonalność pozostałych przycisków, jednak po pewnych modyfikacjach można ją wykorzystać do własnych celów.

Czytaj dalej Kontrolka styleselect w TinyMCE

Dodawanie własnych przycisków w edytorze TinyMCE 4.* – Część 2

Wpis ten stanowi rozwinięcie poprzedniego wpisu na temat dodawania własnych przycisków w edytorze TinyMCE po aktualizacji tego edytora jaka nastąpiła w WordPressie 3.9. Większość wpisu powstała na bazie zadawanych mi pytań – jeżeli pojawią się kolejne pytania to zapewne powstanie też trzecia część serii 😉

Spis treści

Kod źródłowy przykładów znajduje się na Githubie.

Czytaj dalej Dodawanie własnych przycisków w edytorze TinyMCE 4.* – Część 2