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ść.

Odpowiedzi na pytania z WordUpa w Krakowie

Na ostatnim WordUpie w Krakowie po mojej prelekcji pojawiło się kilka pytań wartych opisania z odpowiedziami w formie wpisu.

Jak dodać do popupa własną logikę?

W zasadzie dobór metody zależy od poziomu skomplikowania zawartości popupa i logiki go obsługującej. Jeżeli potrzebujemy zawartości popupa mającej niewiele wspólnego z listą kontrolek to mamy do dyspozycji dwa rozwiązania – skorzystać z kontrolki typu container, która oferuje nam możliwość wstawienia własnego kodu HTML przez właściwość html oraz obsługę zdarzeń poprzez onclick, onmouseover etc. Przykładem wykorzystania tej kontrolki jest wtyczka charmap – polecam lekturę jej kodu.

Drugie wyjście to sposób w jaki rozwiązano to w wypadku wstawiania linków – istnieje wtyczka wplink, która korzysta z obiektu window.wpLink zdefiniowanego w pliku wp-includes/js/wp-link.js – w tym wypadku działa to tak, że kliknięcie przycisku powoduje wywołanie metody open obiektu window.wpLink z ID aktywnego edytora. Dzięki temu możemy wykonać w popupie w zasadzie dowolny kod a na koniec rezultaty umieścić w edytorze znając jego ID. Póki co polecam analizę kodu wspomnianej wtyczki i skryptu z nią związanego – możecie się spodziewać, że rozwinę ten temat w sierpniu na łamach bloga 😉

Jak usunąć buttony po nazwie (czy jest oddzielna metoda)?

Jest to bardzo dobre pytanie, gdyż związane jest ono z większą elastyką naszych skryptów. Wyobraźmy sobie sytuację w której korzystamy z następującego kodu:

function dziudek_remove_btn($btns) {
    unset($btns[0]);
    return $btns;
}

add_action('mce_buttons', 'dziudek_remove_btn');

Ten kod będzie działał dokładnie tak jak sobie to zaplanowaliśmy do momentu gdy użytkownik nie wpadnie na pomysł wstawienia na początku pierwszego rzędu przycisków własnego przycisku – wtedy nasz skrypt usunie ten nowo dodany przycisk a nie przycisk pogrubienia tekstu. Na szczęście możemy temu łatwo zaradzić modyfikując trochę kod usuwania przycisku:

function dziudek_remove_btn($btns) {
    $index = array_search('bold', $buttons);

    if($index !== FALSE) {
        array_splice($buttons, $index, 1);
    }

    return $btns;
}

add_action('mce_buttons', 'dziudek_remove_btn');

Powyższy kod korzysta z faktu, że przyciski są przechowywane w tablicach według nazw. Istnieje też druga metoda – można przyciski usunąć już na etapie działania filtra tinymce_before_init.

Niestety nie natrafiłem na dedykowaną funkcję służącą do usuwania przycisków po samej nazwie.

Jak wykorzystać w TinyMCE kontrolki wyboru kolorów w popupie?

Pytanie o kontrolki kolorów pojawia się bardzo często, niestety są one też najbardziej problematyczne w wykorzystaniu. Teoretycznie można umieścić kontrolkę wyboru kolorów w popupie z użyciem pola typu colorbutton. Problem polega na tym, że aby ta kontrolka zadziałała trzeba stworzyć spory kawałek kodu generujący listę kolorów – w najprostszym wypadku wymaga to skopiowania 3/4 kodu wtyczki textcolor, gdyż ta wtyczka posiada kod, który generuje całą strukturę bloku pozwalającego wybrać kolor tekstu/tła.

Mam pewien pomysł na podejście do tego problemu i myślę, że w sierpniu można spodziewać się wpisu na ten temat (podobnie jak w wypadku logiki w popupach).

Jaką korzyść dają nam przyciski wstawiające kod, który można uzyskać poprzez dostępne już w TinyMCE przyciski?

To pytanie zasugerowało mi, że sekcja prezentacji odpowiadająca na pytanie – “Dlaczego warto tworzyć wtyczki dla TinyMCE?” wymaga rozwinięcia 🙂 Przede wszystkim trzeba wziąć poprawkę na to, że moja prelekcja opisuje podstawowe funkcjonalności i rzeczywiście efekty mogą się wydawać powieleniem dostępnych już funkcji. Co nie zmienia faktu, że przy edycji dużej ilości tekstu nawet przycisk, który jednym kliknięciem zastępuje trzy kliknięcia w edytorze jest naprawdę dużym udogodnieniem (nieraz się o tym przekonałem na własnej skórze). No i pozostaje kwestia bardziej zaawansowanych rozwiązań przygotowywanych pod klientów – jeżeli musimy wstawiać np. mapy we wpisach to miło byłoby gdyby klient od razu widział podgląd tego co wstawił i nie musiał znać całego API skryptu generującego mapki – tu właśnie leży siła autorskich rozwiązań – możemy sobie i klientowi dość łatwo ułatwić życie i uniknąć zbędnych pytań.

 

Zdjęcie dzięki uprzejmości Kasi Karus – współorganizatorki WordUpa w Krakowie.

TinyMCE – zarządzanie stanami przycisków

W poprzednich wpisach pokazałem jak dodawać własne przyciski do edytora TinyMCE oraz wstawić własny kod do edytora. Pora na zagadnienie bardziej złożone – dodawanie własnego formatowania i sprawienie by zachowywało się ono tak jak podstawowe przyciski formatowania dostępne w TinyMCE.
Czytaj dalej TinyMCE – zarządzanie stanami przycisków

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

WordPressowe Linki #25

Tydzień aktualizacji

To był zdecydowanie tydzień pełen różnej maści wydań – otrzymaliśmy WordPressa 3.8.3, zaraz po nim pojawił się WordPress 3.9. Poniżej zebrałem użyteczne informacje na temat zmian w nowej wersji WordPressa:

Zmiany w multisite

Nowe ikonki w Dashicons

Pojawiła się możliwość wykorzystania dowiązań symbolicznych dla wtyczek

Informacje o edycji widżetów na ekranie personalizacji motywu

Warto też pamiętać, że trzeba zamienić wykorzystanie funkcji MySQL na MySQLi

Mój wpis na temat dodawania przycisków w nowym edytorze TinyMCE – drugi wpis z rozwinięciem tematu ukaże się najprawdopodobniej w przyszłym tygodniu.

Dodatkowo ukazał się też BuddyPress w wersji 2.0 ze znaczącymi zmianami w zakresie wydajności oraz z usprawnieniami administracyjnymi.

Testowanie wtyczek z użyciem trybu piaskownicy PayPala

PayPal jako niezwykle popularna usługa, jest często wykorzystywany w różnej maści wtyczkach. Warto wiedzieć o tym, że do testów można wykorzystać tzw. sandbox mode – jak to zrobić pokazuje powyższy artykuł.

Dodawanie własnych przycisków w edytorze TinyMCE 4.*

WordPress 3.9 zawiera aktualizację edytora wpisów TinyMCE do wersji 4.*. Oznacza to spore zmiany w API edytora – dlatego postanowiłem opisać dodawanie własnych przycisków do edytora z użyciem nowego API.

Spis treści

Kod z poniższych przykładów można znaleźć też na Githubie.

  1. Deklarowanie nowego przycisku TinyMCE
  2. Przycisk z etykietą tekstową
  3. Przycisk ze standardową ikonką
  4. Przycisk z niestandardową ikonką pochodzącą z Dashicons
  5. Własna grafika jako ikonka przycisku
  6. Dodajemy przyciskowi submenu
  7. Dodajemy też sub-submenu 😉
  8. Dodajemy popup po kliknięciu
  9. Rozbudowywujemy popup

Czytaj dalej Dodawanie własnych przycisków w edytorze TinyMCE 4.*

WordPressowe Linki #13

TinyMCE 4.0 w WordPressie 3.9

Planowane na kwiecień wydanie WordPressa będzie zawierać nową wersję edytora. Zmianie uległo API edytora, zatem warto sprawdzić kompatybilność swoich wtyczek z nowym edytorem – teoretycznie będzie istniało wsparcie wsteczne dla funkcjonalności znanych z API 3.x, ale i tak warto sprawdzić czy nie ma problemów po aktualizacji edytora.

Porównanie WordPress.org i Github jako platform to hostowania wtyczek

Cóż, w tym wypadku wybór wydaje się prosty – wersja developerska wtyczki na Githubie – stabilne wydania na WordPress.org 😉 Choć nie ukrywam, że Github rozwija się bardzo dynamicznie i oferuje coraz ciekawsze narzędzia, choćby takie jak wspomniane w artykule dane o ruchu na stronie repozytorium.

Ciekawy sposób na tworzenie ikonek serwisów społecznościowych

Wygodny i ciekawy sposób tworzenia menu z ikonkami społecznościowymi. Przy okazji znika problem rozważań czy jest to funkcjonalność, która powinna być w motywie czy też jednak we wtyczce.

Lista potencjalnych zmian w WordPressie 3.9

Jak widać potencjalne zmiany dotyczyć będą obszarów udoskonalonych w WordPressie 3.8 – widżetów, ekranu z motywami oraz dodatkowo ekranu personalizacji motywu i edytora wpisów (TinyMCE 4.0)

WordPress 3.8.1 wydany

Wczoraj późnym wieczorem została wydana wersja WordPressa naprawiająca znalezione po wydaniu WordPressa 3.8 błędy – największym problemem był błąd w osadzaniu tweetów z użyciem oEmbed, który pojawił się po 14 stycznia z powodu zmian w API Twittera.