پدرام بهروزی

افزودن یک دکمه به ویرایشگر متن وردپرس tinyMCE

tinymce_wp

خوبی وردپرس (یکی از خوبی‌های وردپرس) این است که از tinyMCE به عنوان WYSIWYG editor استفاده می‌کند. این ویرایشگر متن به وسیله پلاگین‌های متعدد قابلیت سفارشی‌سازی خیلی زیادی دارد. درواقع خود وردپرس هم یک پلاگین برای حذف کردن امکاناتی که نیاز نداشته نوشته و آن را به tinyMCE اضافه کرده است.

قبل از اینکه ادامه پست را بخوانید، دقت کنید که باید اطلاعات مختصری راجع به زبان PHP، پلاگین‌نویسی وردپرس، hookهای وردپرس و همچنین زبان جاوااسکریپت داشته باشید.

ما برای پروژه‌ای که روی آن کار می‌کردیم نیاز داشتیم یک دکمه داشته باشیم شبیه برچسب Read More خود وردپرس. این دکمه که قرار بود گام‌های یک پست را نشان بدهد، باید یک تگ img به ویرایشگر اضافه می‌کرد تا کاربر متوجه شود که هر قسمت از متن‌اش مربوط به کدام گام است. توی تصویر پایین می‌توانید ببینید راجع به چی دارم حرف می‌زنم.

1

خب. اولین کار این است که به tinyMCE بفهمانیم می‌خواهیم یک دکمه برای خودمان داشته باشیم. برای این کار باید یک پلاگین بنویسید. اول داخل پوشه theme خودتان یک پوشه به اسم plugins بسازید. می‌توانید توی همین پوشه فایل‌هایتان را بگذارید اما من ترجیح می‌دهم پوشه دیگری به اسم tinymce-customize بسازم و کدهای مربوط را داخل این پوشه ایجاد کنم. بعد از ساختن این پوشه‌ها به دو تا فایل نیاز دارید یکی php برای نوشتن hookهای مورد نیاز وردپرس و یکی js برای تعریف عملکرد دکمه. بنابراین ساختار پوشه‌ها و فایل‌هایتان چیزی شبیه این می‌شود:

2

در اینجا می‌بینید که اسم theme ما berdook است و یک فایل عکس دیگر به اسم next-step.png هم وجود دارد که بعداً راجع به آن بهتان توضیح می‌دهم. نکته دیگر اینکه اسم فایل‌هایتان می‌تواند هرچیزی که دلتان خواست باشد.

برای اضافه کردن دکمه، فایل berdook-tinymce.php را باز کنید و این قطعه کد را بنویسید:

add_action('init', 'berdook_buttons');
function berdook_buttons() {
    add_filter( "mce_external_plugins", "berdook_add_buttons" );
    add_filter( 'mce_buttons', 'berdook_register_buttons' );
}

function berdook_add_buttons($plugin_array) {
    $plugin_array['berdook'] = get_template_directory_uri() . '/plugins/tinymce-customize/berdook-tinymce-plugin.js';
    return $plugin_array;
}

function berdook_register_buttons($buttons) {
    array_push($buttons, 'eos');
    return $buttons;
}

  1. init: بعد از اینکه وردپرس بارگذاری شد صدا زده می‌شود و فیلترهایی که می‌خواهیم را اعمال می‌کند. برای خواندن بیشتر راجع به init اینجا را بخوانید: http://codex.wordpress.org/Plugin_API/Action_Reference/init
  2. ما به دو فیلتر mce_external_plugins و mce_buttons نیاز داریم و باید آنها را فراخوانی کنیم. فیلتر اول فایل پلاگین ما را به لیست پلاگین‌های tinymce و فیلتر دوم دکمه‌ی ما را به لیست دکمه‌ها اضافه می‌کند. دقت کنید که آدرس فایل جاوااسکریپت پلاگین‌تان را باید به صورت کامل بفرستید. برای این کار از متد get_template_directory_uri استفاده کرده‌ایم که آدرس کامل تم فعال را به ما می‌دهد. و همچنین رشته berdook را به آرایه اضافه کرده‌ایم که نام پلاگین ما محسوب می‌شود. این نام را می‌توانید به هرچه که می‌خواهید تغییر دهید اما در گام‌های بعدی هم باید این کار را بکنید. در متد berdook_register_buttons هم به آرایه‌ی buttons رشته‌ی eos را اضافه کرده‌ایم که نام دکمه‌ی ما محسوب می‌شود. اگر این نام را هم تغییر می‌دهید حواستان باشد که در گام‌های بعدی هم باید از همین نام استفاده کنید.

خب کار ما با فایل php دیگر تمام است. فقط باید در فایل functions.php این فایل را include کنید:

require 'plugins/tinymce-customize/berdook-tinymce.php';

در فایل berdook-tinymce-plugin.js این کدها را وارد کنید:

(function() {
    tinymce.create('tinymce.plugins.Berdook', {
    /**
     * Initializes the plugin, this will be executed after the plugin has been created.
     * This call is done before the editor instance has finished it's initialization so use the onInit event
     * of the editor instance to intercept that event.
     *
     * @param {tinymce.Editor} ed Editor instance that the plugin is initialized in.
     * @param {string} url Absolute URL to where the plugin is located.
     */
    init : function(editor, url) {
        editor.addButton('eos', {
            title : 'Add Next Step tag',
            cmd : 'eosCommand',
            image : url + '/next-step.png'
        });
    });

    tinymce.PluginManager.add( 'berdook', tinymce.plugins.Berdook );
})();
  1.  create متدی است که در آن ما تمام کارهایی که دکمه باید انجام دهد را تعریف می‌کنیم. اول به tinymce.plugins.Berdook دقت کنید. این نام کامل پلاگین ماست. در خط یکی مانده به آخر متد tinymce.PluginManager.add را هم فراخوانی می‌کنیم که نام کوچک پلاگین و نام کامل آن را می‌گیرد. نام کوچک همان نامی است که در فایل php تعریف کرده‌اید.
  2. بقیه کار یعنی در واقع تمام تعریف عملکرد دکمه را در قسمت init انجام می‌دهیم. با این قسمت در گام‌های بعدی هم زیاد سروکار داریم پس آن را فراموش نکنید. با استفاده از متد addButton می‌توانیم دکمه خودمان را تعریف کنیم. پارامتر اول همان اسمی است که در فایل php برای دکمه تعریف کرده‌اید و پارامتر دوم هم تنظیمات دکمه است. یک title که وقتی ماوس را روی دکمه نگاه دارید نمایش داده می‌شود، یک cmd که نام متدی است که عملکرد دکمه در آن تعریف می‌شود و یک image که آدرس فایل آیکون دکمه است. next-step.png که در ساختار فایل بالا دیده بودید برای همین کار بود.

فایل را ذخیره کنید و به صفحه اضافه کردن پست جدید در وردپرس بروید. اگر همه چیز درست باشد باید بتوانید دکمه‌تان را ببینید. اما در حال حاضر این دکمه هیچ کاری نمی‌کند. باید متد eosCommand را پیاده‌سازی کنیم.

در فایل جاوااسکریپت در قسمت init و بعد از addButton این کد را اضافه کنید:

editor.addCommand('eosCommand', function() {
    var html, title,
    classname = 'wp-eos-tag',
    dom = editor.dom,
    node = editor.selection.getNode();

    classname += ' mce-wp-tag’;
    title = 'Next Step';
    html = '<img src="' + tinymce.Env.transparentSrc + '" title="' + title + '" ' +
           'data-mce-resize="false" data-mce-placeholder="1" />';

    // Most common case

    editor.execCommand('mceInsertContent', 0, html);
});

به وسیله‌ی editor.addCommand می‌توانید متد خودتان را پیاده کنید و هرکاری که صلاح می‌دانید در آن انجام دهید. ما چون می‌خواستیم هروقت دکمه کلیک شد یک تگ img به متن اضافه شود از editor.execCommand(‘mceInsertContent, 0, html) استفاده کردیم که برای اضافه کردن یک کد html به ویرایشگر استفاده می‌شود. چیزی که باید به آن دقت کنید این است که ما به وسیله css به تگ imgمان background-image می‌دهیم و در اینجا فقط یک عکس transparent به ویرایشگر اضافه می‌کنیم. در مورد اضافه کردن css به tinymce هم در ادامه توضیح خواهم داد.

خب. حالا فایل را ذخیره کنید و به صفحه پست وردپرس بروید. حالا باید دکمه‌تان آنجا باشد و کار هم بکند. وقتی روی دکمه کلیک می‌کنید یک تگ img به متن اضافه می‌شود. اما بعید می‌دانم چیزی ببینید چون باید به وسیله css تگ img را پر کنید.

برای اضافه کردن فایل css خودتان به tinymce کد زیر را در functions.php اضافه کنید:

add_editor_style( 'css/editor-style.css' );

آنوقت در پوشه تم خودتان یک پوشه به نام css و داخل آن یک فایل به نام editor-style.css ایجاد کنید. در این فایل کدهای زیر را بنویسید:

.mce-content-body img.mce-wp-eos {
    background: transparent url( images/next_step.png ) repeat-y scroll center center;
    border: 0;
    -webkit-box-shadow: none;
    box-shadow: none;
    width: 96%;
    height: 16px;
    display: block;
    margin: 15px auto 0;
    outline: 0;
    cursor: default;
}
.mce-content-body img.mce-wp-eos[data-mce-selected] {
  outline: 1px dotted #888;
}

حالا دیگر می‌توانید همه چیز را به طور کامل ببینید. دکمه به خوبی کار می‌کند و کار دیگری باقی نمانده است. اما اگر شما هم مثل ما می‌خواهید دکمه‌ای با کارکرد مشابه داشته باشید، احتمالاٌ ادامه این پست به کارتان می‌آید.

مشکلی که ما داشتیم این بود که می‌خواستیم گام‌های یک پست را از هم جدا کنیم و بنابراین باید می‌توانستیم هنگامی که محتوای یک پست را می‌خوانیم، آن را بر اساس مکان قرارگیری برچسب next step قطعه قطعه کنیم. مشکل این بود که برچسب next step یک تگ img خیلی زشت و طولانی بود. چیزی شبیه به این:

<img title="Next Step..." alt="" data-wp-eos="" data-mce-resize="false" data-mce-placeholder="1" data-mce-src="data:image/gif;base64,R0lGODlhAQABAIAAAAAAAP///yH5BAEAAAAALAAAAAABAAEAAAIBRAA7">

 با اینکه تصور می‌کنم بشود به وسیله متد explode در php متن را با رشته بالا هم قطعه قطعه کرد اما اصلا دلم نمی‌خواهد امتحانش کنم :) بنابراین باید کاری می‌کردیم که ویرایشگر در حالت Visual به کاربر یک عکس و در حالت Text (یعنی همان متنی که ذخیره می‌شود و به دست ما می‌رسد) یک رشته تر و تمیز و کوتاه نمایش بدهد. یعنی چیزی مثل شکلهای زیر:

3

4

برای انجام دادن این کار اول فایل berdook-tinymce-plugin.js را باز کنید. در قسمت init بلافاصله بعد از تمام شدن تعریف editor.addCommand(‘eosCommand’ این قطعه کد را وارد کنید:

// Replace tag with image
editor.on( 'BeforeSetContent', function( e ) {
    if ( e.content ) {
        if ( e.content.indexOf( '<!--eos-->' ) !== -1 ) {
            e.content = e.content.replace( /<!--eos-->/g, function( match, moretext ) {
                return '<img src="' + tinymce.Env.transparentSrc + '" data-wp-eos="' + moretext + '" ' + 'class="wp-eos-tag mce-wp-eos" title="Next Step..." data-mce-resize="false" data-mce-placeholder="1" />';
            });
        }
    }
});

// Replace image with tag
editor.on( 'PostProcess', function( e ) {
    if ( e.get ) {
        e.content = e.content.replace(/<img[^>]+>/g, function( image ) {
            var match, moretext = '';

            if ( image.indexOf('wp-eos-tag') !== -1 ) {
                if ( image.indexOf('mce-wp-eos') !== -1 ) {
                    image = '<!--eos-->';
                }
            }

            return image;
        });
    }
});

در اینجا از دو رویداد BeforeSetContent و PostProcess استفاده می‌کنیم تا تگ img و رشته <!–eos–> را به هم تبدیل کنیم. کار خیلی ساده‌ای است و با خواندن کد احتمال زیاد متوجه می‌شوید که چه اتفاقی دارد می‌افتد.

تنها یک چیز دیگر می‌ماند و آنهم اضافه کردن یک دکمه در حالت Text ویرایشگر است. دکمه next step را در عکس قبل می‌بینید؟ به این دکمه‌ها quick tag می‌گویند که توضیح عملکردها و قابلیت‌هایشان یک پست جداگانه می‌طلبد. برای همین اینجا فقط می‌گویم چطوری باید از آنها استفاده کنید. برای اضافه کردن یک quick tag در فایل berdook-tinymce.php این کد را اضافه کنید:

function appthemes_add_quicktags() {
    if (wp_script_is('quicktags')){
?>
    <script type="text/javascript">
    QTags.addButton( 'eos', 'next step', '<!--eos-->', '', '', 'Next Step tag', 100);
    </script>
<?php
    }
}
add_action( 'admin_print_footer_scripts', 'appthemes_add_quicktags' );

 با استفاده از admin_print_footer در فوتر قسمت ادمین وردپرس یک تکه کد جاوااسکریپت اضافه می‌کنیم. این کد جاوااسکریپت با استفاده از متد addButton یک دکمه به quick tags های tinymce اضافه می‌کند.

پدرام بهروزی

از سال ۸۵ برنامه‌نویسی را با نوشتن یک بازی ساده با ++C شروع کرد. به زبان PHP مسلط است و با سیستم‌های مدیریت محتوای زیادی مثل دروپال، وردپرس، بیتریکس و مجنتو آشنایی دارد. درحال حاضر در سارینا با Magento، Laravel و Ruby on Rails کار می‌کند. عاشق سرک کشیدن در تکنولوژی‌های جدید، خواندن کتاب و موسیقی راک است.

  1. پنج شنبه، ۱۹ تیر ۱۳۹۳ داریوش
    خیلی هم عالی .
    جالبه من از دیشب دنبال چیز مشابه این می گشتم و پیدا نکردم و الان که اتفاقی بلاگ رو که از توییتر لینک شده بود دیدم ! :)
    موفق باشین
  2. شنبه، ۳ تیر ۱۳۹۶ رضا ابراهیمی
    سلام.ممنون از پستی که گذاشتید
    اگر امکان داره بگید چطور یک لیست باکس مثل تصویر زیر اضافه کرد.
    http://uupload.ir/files/gmvm_photo_2017-06-24_15-41-37.jpg
    ممنون