Jak dodać niestandardowy CSS (opcja motywu) do TinyMCE?

14

Próbuję dodać niestandardowy CSS (ustawiany za pomocą opcji motywu) do edytora wizualnego TinyMCE w WordPress. Z przodu motyw generuje ten CSS i generuje go na wp_headhaku. Problem, na który wpadam, to możliwość dodania tego wyjścia CSS do edytora.

Nie można tego zrobić, add_editor_style( 'editor-style.css' )ponieważ musimy użyć PHP, aby uzyskać dostęp do opcji motywu.

Jako przykład tego, jak działa na interfejsie:

add_action( 'wp_head', 'my_custom_colors' );

function my_custom_colors() {
    $color_1 = get_theme_mod( 'color_1', 'cc4a00' );

    echo "<style type='text/css'>a { color: #{$color_1}; }";
}

Potrzebuję metody wprowadzenia tego niestandardowego stylu do edytora wizualnego. Każda pomoc byłaby bardzo mile widziana.

Justin Tadlock
źródło
1
Uwaga: niestandardowy CSS post-content to terytorium wtyczek i nie należy go umieszczać w motywie. W przeciwnym razie użytkownicy utracą swój niestandardowy CSS po przejściu na inny motyw.
Chip Bennett
@ChipBennett Zgadzam się tylko częściowo. To bardzo zależy od tego , co projektujesz . Poza tym nie ma znaczenia, gdzie to jest (dla tego pytania).
kaiser
@ChipBennett Dotyczy to stylów motywów, a nie niestandardowych treści CSS. To dość standardowe rzeczy, które możesz zrobić za pomocą dostosowywania motywu. Po prostu stosuję te style, które mnie zaskoczyły. Ma się komplementować editor-style.css, czyli terytorium tematycznego.
Justin Tadlock
Czekaj: mówisz o dynamicznym stylu niestandardowego edytora ? Jak w: czy edytor wizualny (TinyMCE) jest świadomy stylów definiowanych przez opcje motywu? Jeśli tak, zignoruj ​​mój oryginalny komentarz i +1 dla pytania.
Chip Bennett
Czy możesz złożyć edycję i pokazać przykład pełnego zestawu dla stylu motywu? Łatwiej byłoby wtedy przetestować.
kaiser

Odpowiedzi:

7

Rozwiązanie 1

Działa to jako rozwiązanie javascript:

Przykład:

tinyMCE.activeEditor.dom.addStyle('p {color:red; font-size:28px;}');

wystarczy otworzyć konsolę js i wkleić ją do szybkiego testu. Aby celować w konkretnego edytora, należy użyć:

tinyMCE.getInstanceById('##editorID##').dom.addStyle('p {color:red; font-size:28px;}');

Spowoduje to wstrzyknięcie podanego ciągu do edytora iframe <head><style id="mceDefaultStyles"></style> ...

Rozwiązanie 2

Użyj wp_ajax jako modułu obsługi wywołania zwrotnego, aby dodać style dynamiczne do edytora init za pomocą filtra

add_filter('tiny_mce_before_init', 'dynamic_editor_styles', 10);

function dynamic_editor_styles($settings){
    // you could use a custom php file as well, I'm using wp_ajax as
    // callback handler for demonstration
    // content_css is a string with several files seperated by a comma
    // e.g. file1, file2, ... extend the string

    $settings['content_css'] .= ",".admin_url('admin-ajax.php') ."/?action=dynamic_styles";

    return $settings;
}

// add wp_ajax callback
add_action('wp_ajax_dynamic_styles', 'dynamic_styles_callback');
function dynamic_styles_callback(){
    echo "p {color:red} h1{font-size:48px;}";
}
ungestaltbar
źródło
2
Nie jestem do końca pewien, co z tym zrobić.
Justin Tadlock
Rozwiązanie nr 2 naprawdę ma dla mnie sens. Przeprowadzę test.
Justin Tadlock
Poszedłem z rozwiązaniem nr 2. Różnica polega na tym, że upuściłem pierwszą funkcję i użyłem jej, add_editor_style( add_query_arg( 'action', 'my_editor_styles', admin_url( 'admin-ajax.php' ) )ponieważ jest to standardowy sposób dodawania stylów edytora przez motywy.
Justin Tadlock
Chciałbym tylko dowiedzieć się, czy mce_cssdla ciebie zadziałało (jeśli spróbowałeś).
Chip Bennett
Właściwie nie próbowałem tego, ponieważ wiedziałem, że możesz przekazać plik inny niż CSS add_editor_style(), ale powinno dobrze działać, patrząc na kod. Używanie mce_cssjest w rzeczywistości lepszym rozwiązaniem w przypadku, gdy musisz zaczepić się po dodaniu stylów za pomocą add_editor_style(). Jednym z takich powodów w kompozycji jest to, że pełne adresy URL dodawane za pośrednictwem add_editor_style()są generowane jako pierwsze, pomimo kolejności dodawania.
Justin Tadlock
10

WordPress zapewnia mce_cssfiltr , którego można używać do dodawania niestandardowych arkuszy stylów do Edytora wizualnego. Zgodnie z Kodeksem:

Plik może być plikiem .php, umożliwiającym dynamiczne generowanie reguł CSS dla edytora treści.

Przykład wywołania zwrotnego filtra kodeksu, zmodyfikowanego dla motywu:

function wpse120831_mce_css( $mce_css ) {
    if ( ! empty( $mce_css ) )
        $mce_css .= ',';

    $mce_css .= get_template_directory_uri() . '/dynamic-css.php';

    return $mce_css;
}

add_filter( 'mce_css', 'wpse120831_mce_css' );
Chip Bennett
źródło
Mr.Bennett był szybszy, właśnie dodał to do mojej odpowiedzi poniżej :), ale nieco inaczej.
ungestaltbar
@ungestaltbar używamy dwóch zupełnie różnych filtrów. :)
Chip Bennett
z tym samym rezultatem :)
ungestaltbar
4

Akceptowałem powyższe rozwiązanie przez @ungestaltbar. Chciałem jednak nieco rozszerzyć tę odpowiedź o pełne rozwiązanie, którego używam, aby inni mogli zobaczyć, jak to działa.

add_action( 'after_setup_theme', 'my_theme_setup' );

function my_theme_setup() {

    add_editor_style(
        array(
            'editor-style.css',
            add_query_arg( 'action', 'my_editor_styles', admin_url( 'admin-ajax.php' ) ),
        )
    );
}

add_action( 'wp_ajax_my_editor_styles', 'my_editor_styles_callback' );
add_action( 'wp_ajax_nopriv_my_editor_styles', 'my_editor_styles_callback' );

function my_editor_styles_callback() {

    // @todo sanitize
    $color_1 = get_theme_mod( 'color_1', 'cc4a00' );

    echo "a { color: #{$color_1}; }";

    die();
}

Mam nadzieję, że można w tym miejscu opublikować kolejną odpowiedź. Nie widziałem sposobu, aby opublikować to w bezpośredniej odpowiedzi na moje zaakceptowane rozwiązanie. Wciąż uczę się, jak korzystać z WPSE.

Justin Tadlock
źródło
Może powinieneś dodać, add_action( 'wp_ajax_nopriv_my_editor_styles', 'my_editor_styles_callback' );jeśli edytor jest używany w interfejsie użytkownika (dla niezalogowanych użytkowników).
OriginalEXE
Tak, odpowiedź ze znaczącymi zmianami / poprawkami jest całkowicie w porządku. :) FYI, jeśli to był jakiś problem do rozwiązania w oryginalnej odpowiedzi, wtedy przesłanie edycji byłoby dobrym rozwiązaniem.
Rarst
@OriginalEXE - Tak. Zaktualizuję to.
Justin Tadlock
Tylko wskazówka dla każdego, kto znajdzie to później, nie byłem w stanie sprawić, aby działała poprawnie, tak jak to przedstawiono. W końcu doszedłem do wniosku, że muszę zawrzeć informacje zwrotne w wywołaniu zwrotnym, aby było to widziane jako css. nagłówek („Content-type: text / css; charset: UTF-8”); Nie jestem pewien, czy jest to coś innego w moim .htaccess czy co.
SkyShab
4

Prawdopodobnie spóźniłem się na tę imprezę, ale po użyciu powyższego rozwiązania szybko zdałem sobie sprawę, że szybkość wczytywania strony edytora została poważnie sparaliżowana! Przyjrzawszy się kodowi, zdałem sobie sprawę, że kod działa długo po zainicjowaniu tinyMCE.activeEditor. Kod używa metody setInterval (), która ocenia wyrażenie w określonych odstępach czasu. Sądzę, że było tak, ponieważ nie można było ustalić, w którym momencie podczas wykonywania kodu dostępne będzie „activeEditor”. To właśnie spowodowało, że szybkość strony spadła na kolana.

Jest to o wiele lepsze rozwiązanie, którego używam do zbudowania wtyczki

   /**
     * Extend TinyMCE config with a setup function.
     * See http://www.tinymce.com/wiki.php/API3:event.tinymce.Editor.onInit

     */
    function custom_tinymce_css($init) {

      $css = get_option('some_css'); 

     ?>

        <script type="text/javascript">            

            function addTempCSS( ed ) {
                ed.onInit.add( function() {
                    tinyMCE.activeEditor.dom.addStyle(<?php echo json_encode($css) ?>);
                } );
            };
        </script>

        <?php
        if (wp_default_editor() == 'tinymce')
            $init['setup'] = 'addTempCSS';

        return $init;
    }
    add_filter('tiny_mce_before_init', 'custom_tinymce_css');

Tutaj rodzimy nasłuch TinyMCE służy do wykonania kodu po zainicjowaniu aktywnego edytora. Mam nadzieję, że to pomoże komuś tam. Z poważaniem.

Ayebare M.
źródło
1
Działa to dla mnie po prostu ma przestarzałe wywołanie API w tinymce 4.0, które musisz zmienić ed.onInit.add (function () {... to ed.on ('init', function () {...
Mohammed
1

To jest zmodyfikowane rozwiązanie opublikowane na forach WordPress.org na to pytanie: http://wordpress.org/support/topic/customdynamic-css-in-tinymce?replies=14#post-4827573

To zdecydowanie działa. Nie jestem jednak guru JS, więc nie jestem do końca pewien, czy to najlepsze rozwiązanie.

add_action( 'before_wp_tiny_mce', 'my_tinymce_callback' );

function my_tinymce_callback() {

    $color_1 = get_theme_mod( 'color_1', 'cc4a00' ); ?>

    <script type="text/javascript">
    jQuery( document ).ready(

        function() {
            var my_style = 'a { color: #<?php echo $color_1; ?>; }';

            var checkInterval = setInterval(
                function() {

                    if ( 'undefined' !== typeof( tinyMCE ) ) {
                        if ( tinyMCE.activeEditor && ! tinyMCE.activeEditor.isHidden() ) {

                            jQuery( '#content_ifr' ).contents().find( 'head' ).append( '<style type="text/css">' + my_style + '</style>' );

                            clearInterval( checkInterval );
                        }
                    }
                }, 
                500 
            );
        }
    );
    </script>
<?php }

Można to również dodać do pliku JS. Dzięki temu można łatwo przekazywać zmienne wp_localize_script().

Justin Tadlock
źródło