Wysiwyg editor

Pro pohodlnější psaní textů v administraci se hodí mít nějaký wysiwyg editor. Je z čeho vybírat. Spousta jich jse zdarma, některé se platí. Já se rozhodl pro Tiny MCE. Editor už máme stažený ve složce vendor/bower_component.

Napadlo by mě načíst potřebné js a css soubory přes komponenty Css a Js, které jsme si vyráběli v BaseModule. Ovšem nejde jen o nějaký jeden či dva soubory. Je to celý systém, kdy se jednotlivé js odkazují na další a počítají s tím, že leží v nějaké adresářové struktuře. Takže budeme postupovat klasickým způsobem.

V první řadě zkopíruj celou složku tiny mce z bower_component do složky www/js.Plánujeme použití nějakého nástroje pro upload obrázků a souborů. Jako nejlepší se i jeví ResponsiveFilemanager: https://www.responsivefilemanager.com. Stáhni si ho a rozbal složku filemanager do složky www/js. Uvnitř archivu najdeš i složku tinymce. Obsahuje plugin responsivefilemanager, který bys měl zkopírovat do www/js/tinymce/plugins.

Pak upravíme šablonu prezenteru pro zobrazení detailu stránky. Doplň řádky:

{block myJs}
    <script src="/js/tinymce/tinymce.min.js"></script>
    <script src="/js/tinymce/langs/cs.js"></script>
    <script>
        tinymce.init({
            selector: '.tinymcetext',
            valid_elements: "span[class]",
            verify_html: false,
            language: 'cs',
            plugins: 'print preview searchreplace autolink directionality visualblocks ' +
            'visualchars fullscreen image link media template codesample table charmap hr pagebreak ' +
            'nonbreaking anchor toc insertdatetime advlist lists wordcount imagetools' +
            ' textpattern help code responsivefilemanager',
            toolbar: 'formatselect | bold italic strikethrough forecolor backcolor permanentpen formatpainter | link ' +
            'image media pageembed | alignleft aligncenter alignright alignjustify | numlist bullist outdent indent ' +
            '| removeformat | code codesample responsivefilemanager',
            codesample_languages: [
                { text: 'HTML/XML', value: 'markup'},
                { text: 'JavaScript', value: 'javascript'},
                { text: 'CSS', value: 'css'},
                { text: 'PHP', value: 'php'},
                { text: 'Bash', value: 'bash'},
                { text: 'Ini', value: 'ini'},
                { text: 'JSON', value: 'json'},
                { text: 'PowerShell', value: 'powershell'},
                { text: 'Smarty', value: 'smarty'},
                { text: 'SQL', value: 'sql'}
            ],
            image_advtab: true,
            image_title: true,
            external_filemanager_path: "/js/filemanager/",
            filemanager_title: "Responsive Filemanager",
            external_plugins: {
                "responsivefilemanager": "/js/tinymce/plugins/responsivefilemanager/plugin.min.js",
                "filemanager": "/js/filemanager/plugin.min.js"
            },
            forced_root_block : 'p',
            menubar: false,
            height: 400,
            image_caption: true,
            automatic_uploads: true,
            contenteditable: false,
            mode : "specific_textareas",
        });
    </script>
{/block}

Tu konfiguraci si klidně uprav jak tě napadne. Dokumentace je celkem dobře zpracovaná. Například já používám zvýrazňovač kódu, ale pokud ho nepotřebuješ, smaž codesample_languages.

Nejdůležitější je parametr selector: '.tinymcetext'. Tím říkáme, jaký prvek se pokusíme nahradit editorem. V tomto případě to budou všechny, které mají class tinymcetext.

Upravíme layout @layout.latte tak, aby končil řádky:

{control js}
<script>
    $.nette.init();

    $(document).ready(function () {
        $("li.active").parents('li').toggleClass('active');
    });

    $(".alert-dismissible").fadeTo(5000, 500).slideUp(500, function () {
        $(".alert-dismissible").alert('close');
    });

    $('a').click(function () {
        if ($(this).attr('data-toggle') === "push-menu") {
            if ($('body').hasClass('sidebar-collapse')) {
                localStorage.setItem('collapseItem', "false");
            } else {
                localStorage.setItem('collapseItem', "true");
            }
        };
    });

    var collapseItem = localStorage.getItem('collapseItem');
    if (collapseItem === "true") {
        $('body').addClass('sidebar-collapse');
    }

    $.widget.bridge('uibutton', $.ui.button);
</script>

{block myJs}{/block}
</body>
</html>

Fyzicky sice potřebujeme jen ten {blog myJs}, jelikož do něj jsme vložili v šabloně editace stránky ten editor, ale dodali jsme si i několik příkazů pro lepší použitelnost administrace. Například samovolné mizení boxů s alerty. Nebo ať si systém zapamatuje stav levého menu - rozbalené, zabalené.

Již teď by to fungovalo, ale ještě si trochu upravíme šablonu komponenty Page.detail.latte:

<div class="row" id="snippet--grid">
    <div class="col-sm-12" id="snippet-grid-grid">
        <div class="panel panel-default datagrid datagrid-grid">
            <div class="panel-body">
                <div class="box box-success">
                    <div class="box-header with-border">
                        <h3 class="box-title">Editace stránky</h3>
                    </div>
                    <!-- /.box-header -->
                    <!-- form start -->
                    <form n:name=editForm class='form-horizontal card card-1'>
                        <div n:if="$form->hasErrors()"  n:foreach="$form->errors as $error" class="alert alert-danger
                        alert-dismissible fade in">
                            <a href="#" class="close" data-dismiss="alert" aria-label="close">&times;</a>
                            {$error}
                        </div>
                        <ul class="nav nav-tabs">
                            <li class="nav-item">
                                <a class="nav-link active" data-toggle="tab" href="#podrobnosti">Podrobnosti</a>
                            </li>
                            <li class="nav-item">
                                <a class="nav-link" data-toggle="tab" href="#seo">SEO</a>
                            </li>
                        </ul>
                        {input id}
                        <div class="tab-content">
                            <div>&nbsp;</div>
                            <div id="podrobnosti" class="tab-pane small active">
                                <div class="form-group">
                                    <div class="input-group mb-3">
                                        <div class="col-md-6 form-group form-inline">
                                            <div class="col-sm-2">
                                                <label class="col-form-label justify-content-end" n:name=name>Název
                                                    stránky:</label>
                                            </div>
                                            <input type="text"
                                                   class="col-sm-10 form-control form-control-sm" n:name="name">
                                        </div>
                                        <div class="col-md-6 form-group form-inline">
                                            <div class="col-sm-2">
                                                <label class="col-form-label justify-content-end" n:name=menu_title>Název
                                                    v menu:</label>
                                            </div>
                                            <input type="text" class="col-sm-10 form-control form-control-sm"
                                                    n:name="menu_title">
                                        </div>
                                        <div class="col-md-6 form-group form-inline">
                                            <div class="col-sm-2">
                                                <label class="col-form-label justify-content-end" n:name=parent>Rodič:</label>
                                            </div>
                                            {input parent}
                                        </div>

                                        <div class="col-md-6 form-group form-inline">
                                            <div class="col-sm-2 text-right">
                                                Je v menu:
                                            </div>
                                            <div class="custom-control custom-checkbox col-sm-10">
                                                <div class="custom-control-inline col-sm-12">
                                                    {foreach $form[in_menu]->items as $key => $label}
                                                        <div class="col-sm-3">
                                                            <input n:name="in_menu:$key" class="custom-control-input">
                                                            <label class="custom-control-label justify-content-start"
                                                                    n:name="in_menu:$key"> {$label}</label>
                                                        </div>
                                                    {/foreach}
                                                </div>
                                            </div>
                                        </div>

                                        <div class="col-md-6 form-group form-inline">
                                            <div class="col-sm-2 text-right">
                                                Vlastnosti:
                                            </div>
                                            <div class="custom-control custom-checkbox col-sm-10">
                                                <div class="custom-control-inline col-sm-12">
                                                    <div class="col-sm-3">
                                                        <input n:name="status" class="custom-control-input">
                                                        <label class="custom-control-label justify-content-start" n:name="status">
                                                            Aktivní
                                                        </label>
                                                    </div>
                                                    <div class="col-sm-3">
                                                        <input n:name="on_homepage" class="custom-control-input">
                                                        <label class="custom-control-label justify-content-start" n:name="on_homepage">
                                                            Úvodní strana
                                                        </label>
                                                    </div>
                                                </div>
                                            </div>
                                        </div>

                                        <div class="col-sm-12 form-group">
                                            <div class="col-sm-12 form-group">
                                                <label class="col-form-label justify-content-start"
                                                        n:name=text>Text:</label>
                                                {input text}
                                            </div>
                                        </div>
                                        <div class="col-sm-12 form-group">
                                            <div class="col-sm-12 form-group">
                                                <label class="col-form-label justify-content-start"
                                                        n:name=perex>Perex:</label>
                                                {input perex}
                                            </div>
                                        </div>
                                    </div>
                                </div>
                            </div>

                            <div id="seo" class="tab-pane small">
                                <div class="form-group">
                                    <div class="input-group mb-3">
                                        <div class="col-md-12 form-group form-inline">
                                            <div class="col-sm-2">
                                                <label class="col-form-label justify-content-end" n:name=url>URL adresa
                                                    stránky:</label>
                                            </div>
                                            <input type="text"
                                                   class="col-sm-10 form-control form-control-sm" n:name="url">
                                        </div>
                                        <div class="col-md-12 form-group form-inline">
                                            <div class="col-sm-2">
                                                <label class="col-form-label justify-content-end" n:name=title>Titulek
                                                    prohlížeče:</label>
                                            </div>
                                            <input type="text"
                                                   class="col-sm-10 form-control form-control-sm" n:name="title">
                                        </div>
                                        <div class="col-md-12 form-group form-inline">
                                            <div class="col-sm-2">
                                                <label class="col-form-label justify-content-end" n:name=description>Popisek
                                                    stránky:</label>
                                            </div>
                                            <input type="text"
                                                   class="col-sm-10 form-control form-control-sm" n:name="description">
                                        </div>
                                    </div>
                                </div>
                            </div>

                            <div class="form-group">
                                <div class="col-lg-12">
                                    {input save} {input saveandstay}
                                </div>
                            </div>
                        </div>
                    </form>
                </div>
            </div>
        </div>
    </div>
</div>

Podobně budeme postupovat i při úpravě komponenty a šablony presenteru pro novou stránku. To už ale nechám na tobě. Kdybys ses ale někde zadrhnul, vždycky si můžeš stáhnout dnešní práci.

Celý seriál o vývoji redakčního systému

Komentáře

O mně

Jmenuji se Rudolf Svátek - lektor výpočetní techniky, trochu PHP programátor a SEO konzultant na volné noze.

Adresa

Příčná 326/3
736 01 Havířov

Kontakty

Email: office@rudolfsvatek.cz
Telefon: +420 777 828 353
Skype: svatekr