Архив метки: short

WordPress. Создаем плагин для вставки стилизованных ссылок

В далеком 2008 году, когда я только начинала вести свой блог, я как-то не подумала о том, что придется выкладывать много ссылок на архивы с примерами и демонстрационные страницы. Со временем таких статей становилось все больше и больше, а мне приходилось ставить обычные текстовые ссылки, которые никак не выделялись из основного текста. При этом, я уже давно придумала как именно сделать удобную вставку красивых ссылок-кнопок, но дальше фантазий дело не доходило. Пришла пора это исправить, в сегодняшней статье мы создадим плагин для вставки стилизованных ссылок в текстовый редактор WordPress.

Если вы еще не поняли о чем именно идет речь, вот пример того как выглядят подобные ссылки:

Идея не нова, почти все блоги о веб-разработке которые я читаю, так или иначе оформляют ссылки на демо-страницы и архивы, поскольку это красиво и удобно. Сразу хочу сказать, я не знаю как у них это реализовано, не пыталась узнать и не искала плагинов, решающих такую задачу. Поэтому, если вы вдруг начнете обвинять меня в плагиате, я буду все отрицать Smile.

1. Задача

Для начала разберемся с задачей: нам нужно иметь возможность вставлять стилизованные ссылки в любом месте статьи, парами или поодиночке. HTML-разметка будет выглядеть следующим образом:

 <div id="my-article-links">
    <a href="#">Пример кнопки</a>
 </div>

Блок #my-article-links служит для отделения блока от основного текста, чистки потока от флоатов и является контейнером для произвольного количества ссылок. Каждая ссылка будет задаваться двумя параметрами– текстом и URL.

2. Плагин

Создаем папку insert_dr_links (префикс dr для исключения совпадений имен) внутри  wp-content/plugins. Внутри папки создаем файл insert_dr_links.php, и добавляем заголовок плагина:

<?php
/*
Plugin Name: Insert custom dr-links
Plugin URI: http://dreamhelg.ru
Description: Simple plugin for inserting custom links
Version: 1.0
Author: dreamhelg
Author URI: http://dreamhelg.ru
*/

Теперь наш плагин можно увидеть и даже активировать в административной панели вордпресс, правда он пока ничего не умеет.

3. Шорткод

Теперь давайте научим плагин работать. Для этого нам понадобиться создать простой шорткод для вставки в редактор необходимого html-кода.

function add_dr_links($atts) {
    extract($atts);

    $i = 0;
    $output = '<div id="my-article-links">';

    foreach ($atts as $value) {
        if (($i %= 2) == 0) {
            $output .= '<a href="' . $value . '">';
        } else {
            $output .= $value . '</a>';
        }
        $i++;
    }

    $output .= '</div>';
    return $output;
}
add_shortcode('links', 'add_dr_links');

Разберем по порядку его работу. Первым делом, мы распаковываем полученные атрибуты, назначаем переменной $i значение 0, для определения четного элемента, а переменной $output задаем начало разметки блока ссылок.

 extract($atts);

 $i = 0;
 $output = '<div id="my-article-links">';

Поскольку ссылок может быть несколько, циклом перебираем полученные атрибуты, внутри которого четные элементы определяем как ссылку, а нечетные как текст ссылки, добавляя к переменной $output соответствующую разметку. После того как достигнут конец цикла, закрываем блок ссылок, и возвращаем переменную $output.

foreach ($atts as $value) {
        if (($i %= 2) == 0) {
            $output .= '<a href="' . $value . '">';
        } else {
            $output .= $value . '</a>';
        }
        $i++;
    }

    $output .= '</div>';
 return $output;

Последняя строчка регистрирует нашу функцию add_dr_links(), как шорткод links. Теперь, если в вы вставите в редактор следующую строчку, плагин отобразит ее в виде ссылок, завернутых в нужную нам разметку.

[links link="http://ya.ru" text="яндекс" link1="http://google.ru" text1 ="гугл" ]

Полдела сделано, теперь давайте сделаем наш плагин немного удобнее для использования.

4. Плагин для tinyMCE

Шорткод работает, но заниматься вставкой квадратных скобок, прописывать параметры, следить чтобы не было ошибок – все это нудно и не очень удобно. Давайте переложим эту работу на плечи нашего визуального редактора tinyMCE, для этого нам понадобиться всего лишь написать несложный плагин.

Для начала создадим внутри папки с нашим плагином новую папку с названием mce, а внутри нее папку с названием insert_links, а внутри нее файл с именем insert_links.js. В этом файле будет инициализирован наш плагин. Также, внутри папки insert_links создайте папку img, и файл с именем dialog.htm. В папке img будет лежать иконка для кнопки редактора, в моем случае это картинка со звеньями цепи, вы можете выбрать любую на свой вкус. Файл dialog.htm это окно, которое будет открываться по клику на кнопку редактора, чуть позже мы добавим туда нужную html-разметку.

Добавляем плагин в wordpress

Теперь, нам нужно сообщить вордпресс о том, что мы планируем добавить новый плагин визуального редактора, для этого нам потребуется следующий код:

function dr_insert_links($plugin_array){
    $plugin_array['dr_insert_links'] = WP_PLUGIN_URL . '/insert_dr_links/mce/insert_links/insert_links.js';
    return $plugin_array;
}

function dr_add_button($buttons){
    array_push($buttons, "|", "dr_insert_links");
    return $buttons;
}

function dr_custom_button(){
    if ( ! current_user_can('edit_posts') && ! current_user_can('edit_pages') )
        return;

    //Add only in Rich Editor Mode
    if( get_user_option('rich_editing') == 'true'){
        add_filter('mce_external_plugins', 'dr_insert_links');
        add_filter('mce_buttons', 'dr_add_button');
    }
}

add_action('init', 'dr_custom_button');

Первая функция dr_insert_links() – добавляет в массив плагинов редактора новый плагин dr_insert_links, указывая путь к предварительно созданному нами файлу insert_links.js. Следующая функция dr_add_button() добавляет новую кнопку редактора, dr_insert_links. Функция dr_custom_button() запускает фильтры, добавляющие плагин и кнопку к редактору, при условии, что пользователь имеет права на редактирование записей и страниц, а также находится в режиме визуального редактора. Последним идет экшен для запуска функции dr_custom_button().

Инициализируем плагин

Возможно вы удивитесь, но после всех этих функций, вы все равно не увидите кнопки в редакторе. Для того чтобы она появилась, нужно отредактировать предварительно созданный нами файл insert_links.js.  Открываем и вставляем следующий код:

(function(){
    tinymce.create("tinymce.plugins.DrInsertLinks",{
        init:function(a, b){
            a.addCommand("drInsert", function(){
                a.windowManager.open({
                    file: b + "/dialog.htm",
                    width: 420,
                    height: 125,
                    inline: 1
                })
            });
          
            a.addButton("dr_insert_links",{
                title: "insert_links.desc",
                cmd: "drInsert",
                image: b + "/img/link.gif"
            });
        },

        getInfo:function(){
            return{
                longname:"Insert custom links",
                author:"dreamhelg",
                authorurl:"http://dreamhelg.ru",
                version:"1.0"
            }
        }
    });
    
    tinymce.PluginManager.add("dr_insert_links",tinymce.plugins.DrInsertLinks)
})();

Сначала создаем функцию create для создания плагина DrInsertLinks, внутри нее запускаем функцию init, инициализирующую плагин, а внутри нее еще две функции: addCommand() и addButton(). Первая функция addCommand() служит для добавления новой команды в редактор, в нашем случае она будет открывать диалоговое окно, путь к которому указывается в свойстве file (переменная b содержит url к папке с плагином).

Вторая функция addButton() добавляет долгожданную кнопку в редактор, в свойствах перечисляются название кнопки, команда, которая будет запущена при нажатии (та команда, которую мы только что создали с помощью функции addCommand) и картинка для кнопки.

Функция getInfo() возвращает информацию об авторе плагина, например для окна помощи.

И наконец последняя строчка добавляет только что описанный нами плагин dr_insert_links. Теперь, если вы все сделали правильно, то должны уже увидеть кнопку, а также диалоговое окно, появляющееся при нажатии.

Окно пустое, потому что мы пока ничего туда не добавили. Давайте это исправим.

Диалоговое окно плагина

Как не трудно догадаться по расширению, диалоговое окно представляет собой обычный html-файл, добавляем в него следующую разметку:

<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
<html xmlns="http://www.w3.org/1999/xhtml">
<head>
        <meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
	<title>Вставить ссылку</title>
</head>
    
<body> 
<form id="dr-links" method="" action="">
    <div id="dr-container">
        <fieldset>
            <legend>Атрибуты ссылки</legend>
            <span>URL</span><input type="text" id="link" name="link1" /><br/>
            <span>текст</span><input type="text" id="text" name="text1" />
        </fieldset>
    </div>
    
    <div>
        <input type="button" id="add_link" name="add_link" value=" + " class="mceButton"/>
        <input type="button" id="insert" name="insert" value="вставить" />
        <input type="button" id="cancel" name="cancel" value="отменить" />
    </div>
</form>
</body>
</html>

Ничего сложного, доктайп, мета-тег с кодировкой, чтобы русские символы нормально отображались, простая форма с двумя полями ввода, и тремя кнопками. Одно поле для ввода ссылки, другое для текста, кнопка с плюсом доля добавления дополнительных полей. Добавим немного CSS-стилей для красоты:

<style type="text/css">
    fieldset{
        margin: 5px 0 10px 0;
        overflow: hidden;
    }

    fieldset span{
        width: 40px;
        display: block;
        float: left;
        clear: left;
        line-height: 15px;
    }

    fieldset input{
        margin-bottom: 5px;
}
 </style>

Получилось вполне неплохо, только кнопки пока не работают. Чтобы они заработали, нужно подключить в секцию head, jquery и файл tiny_mce_popup.js, с помощью которого мы будем передавать введенные данные в редактор.

<script type="text/javascript" src="/wp-includes/js/jquery/jquery.js"></script>
<script type="text/javascript" src="/wp-includes/js/tinymce/tiny_mce_popup.js"></script>

В принципе jquery тут не обязателен, можно обойтись и без него, просто мне не хочется. Добавим следующий код, для того чтобы кнопки формы заработали:

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

                jQuery("#insert").click(function(){
                    var shortcode = ' ';

                    jQuery("form").find("input:text").each(function(){
                        var att_name = jQuery(this).attr("id"),
                        att_value = jQuery(this).val(),
                        att_result = att_name + '="' + att_value + '" ';

                        shortcode += att_result;
                    })
                
                    shortcode += ']';
                    tinyMCEPopup.editor.execCommand('mceInsertContent', false,  shortcode);
                    tinyMCEPopup.close();
                })

                jQuery("#add_link").click(function(){
                    newid = jQuery("input:text").length / 2;
                    output = '<fieldset><legend>Атрибуты ссылки-' + newid +
                        '</legend><span>URL</span><input type="text" id="link' + newid +
                        '" name="link'  + newid + '" /><br/><span>текст</span><input type="text" id="text' + newid +
                        ' " name="text' + newid  + '" /></fieldset>';
                     
                    jQuery("#dr-container").append(output);
                })

                jQuery("#cancel").click(function(){
                    tinyMCEPopup.close();
                })
            })
        </script>

Первым идет код для кнопки “вставить”. Внутри него мы открываем шорткод (обратите внимание: в строке var shortcode = '1 '; вместо единицы должно быть [links , мой плагин подсветки синтаксиса не справился со своей ролью), затем перебираем каждый инпут с типом “текст”, получаем его значение и добавляем к переменной с открытой скобкой шорткода, затем закрываем шорткод. Теперь, когда у нас есть переменная, содержащая готовый шорткод, нужно вставить его в редактор, для этого нам понадобится команда mceInsertContent, редактора tinyMCE.

Если предполагается использование нескольких ссылок, нужно предусмотреть возможность добавления дополнительных полей. Для этого нам и нужна кнопка с плюсом. Здесь всего лишь нужно сгенерировать дополнительные поля с уникальными идентификаторами. Для получения уникального номера, вначале функции мы берем количество уже существующих полей, и делим полученное значение на два. После того как разметка готова, добавляем ее внутрь формы.

Кнопка “отмена” просто закрывает окно, с помощью метода tinyMCE close().

Диалоговое окно готово, и все кнопки работают, можно добавить сколько угодно дополнительных полей.

Добавляем CSS-стили

Пришла пора навести красоту, для этого нам понадобится создать CSS-файл dr-style.css в корневой директории плагина. Поскольку я делаю плагин в первую очередь для себя, кнопки будут выполнены в стиле моего блога:

#my-article-links{
    overflow: hidden;
    margin: 15px 0;
}

#my-article-links a{
    background: #444444; /* Fallback */
    background: -moz-linear-gradient(top, #444444 0%, #333333 100%); /* FF 3.6+ */
    background: -webkit-gradient(linear, left top, left bottom, color-stop(0%,#444444), color-stop(100%,#333333)); /* Chrome, Safari 4+ */
    background: -webkit-linear-gradient(top, #444444 0%,#333333 100%); /* Chrome 10+, Safari 5.1+ */
    background: -o-linear-gradient(top, #444444 0%,#333333 100%); /* Opera 11.10+ */
    background: -ms-linear-gradient(top, #444444 0%,#333333 100%); /* IE10+ */
    background: linear-gradient(top, #444444 0%,#333333 100%); /* W3C */

    color: #fff;
    border-color: transparent;
    border-radius: 10px 0 10px 0;
    display: inline-block;
    font-weight: bold;
    padding: 10px 20px;
    text-shadow: 0 1px 0 #444444;
    -webkit-transition: all 100ms linear;
    -moz-transition: all 100ms linear;
    transition: all 100ms linear;
}

#my-article-links a:hover{
    border-radius: 0px 10px 0px 10px;
}

Теперь нужно подключить этот CSS-файл в секцию head, текущей темы. Используем для этого функцию вордпресс wp_register_style(), регистрирующую новый CSS-стиль для последующего безопасного подключения с помощью функции wp_enqueue_style(). Запускаем выполнение функции dr_add_css() на экшен wp_enqueue_scripts:

function dr_add_css(){
    wp_register_style('dr-links', WP_PLUGIN_URL . '/insert_dr_links/dr-style.css');
    wp_enqueue_style('dr-links');
}

add_action('wp_enqueue_scripts', 'dr_add_css');

После этого CSS-файл будет добавлен к текущей активной теме, и вы увидите кнопки-ссылки во всей красе.

Создаем страницу настроек

Несмотря на то, что основная задача выполнена, конечный результат всегда можно немного доработать. В нашем случае (так как мы все-таки делаем плагин), можно добавить страницу настроек, с тем чтобы предоставить пользователю возможность задания собственного стиля для кнопки-ссылки.

Сначала добавляем новый пункт меню, и пустую страницу:

function register_plugin_menu(){
    add_menu_page('Insert Links Options', 'Insert Links', 'edit_posts', 'dr_insert_links', 'dr_css_change');
}

function dr_css_change(){
}

add_action('admin_menu', 'register_plugin_menu');

Я не буду подробно расписывать все параметры, так как это давно известные штуки, о которых я уже неоднократно писала в своем блоге. Следующим этапом добавляем разметку для страницы настроек внутри функции dr_css_change():

 <div class="wrap">
        <div id="icon-options-general" class="icon32"><br/></div>
        <h2>Внешний вид ссылки</h2>
        <form method="POST" action="">
            <?php wp_nonce_field('update-options'); ?>
            <p>
                <input type="radio" id="" name="insert-default" value="default" <?php echo $checked1; ?>/>
                Использовать встроенный стиль кнопки
                <div id="my-article-links">
                    <a href="#">Пример кнопки</a>
                </div>
            </p>
            <p>
                <input type="radio" id="" name="insert-default" value="custom" <?php echo $checked2; ?> />
                Добавить собственный стиль<br/>
                <code>
                    ID контейнера для кнопки - <strong>#my-article-links</strong>,
                    стиль для кнопки <strong>#my-article-links a</strong>
                </code>
            </p>
            <textarea cols="50" rows="10" name="custom-css" id="custom-css"><?php echo get_option('user-css'); ?></textarea>
            
            <p><input type="submit" id="update-css-option" name="update-css-options" class="button-primary"/></p>
        </form>
    </div>

Используем простую форму с двумя переключателями и одним текстовым полем для ввода пользовательского CSS. Переменные $checked1-$checked2, используются для отображения текущего состояния переключателя. Обратите внимание, что в разметке мы используем пример кнопки, чтобы пользователь мог видеть как именно смотрится кнопка с дефолтным CSS-стилем. Для того, чтобы отобразить кнопку в дефолтном стиле, нам нужно подключить уже знакомый CSS-файл в админ-панель вордпресс, делается это очень просто:

add_action('admin_head', 'dr_add_css');

Теперь наша страница настроек выглядит вот так:

Давайте научим ее работать. Для определения состояния переключателя и хранения пользовательского CSS-стиля, будем использовать механизм опций вордпресс.

function dr_css_change(){
    $checked1 = '';
    $checked2 = '';

    if($_REQUEST['update-css-options']){
        if($_REQUEST['insert-default'] == 'default'){
            update_option('default-css', 'true');
        }else{
            update_option('default-css', 'false');
            update_option('user-css', $_REQUEST['custom-css']);
        }
    }

     if(get_option('default-css') == 'true'){
        $checked1 = 'checked';
        $checked2 = '';
     }else{
        $checked2 = 'checked';
        $checked1 = '';
     }

Вначале объявляем переменные $checked1-$checked2, далее, проверяем пришел ли запрос от кнопки отправки нашей формы и чему равно значение переключателя.  В зависимости от состояния переключателя, обновляем одну или две опции. Затем обновляем значение переменных $checked, в зависимости от значения опции ‘default-css’. Полный код функции dr_css_change() выглядит следующим образом:

function dr_css_change(){
    $checked1 = '';
    $checked2 = '';

    if($_REQUEST['update-css-options']){
        if($_REQUEST['insert-default'] == 'default'){
            update_option('default-css', 'true');
        }else{
            update_option('default-css', 'false');
            update_option('user-css', $_REQUEST['custom-css']);
        }
    }

     if(get_option('default-css') == 'true'){
        $checked1 = 'checked';
        $checked2 = '';
     }else{
        $checked2 = 'checked';
        $checked1 = '';
     }
 ?>
    <div class="wrap">
        <div id="icon-options-general" class="icon32"><br/></div>
        <h2>Внешний вид ссылки</h2>
        <form method="POST" action="">
            <?php wp_nonce_field('update-options'); ?>
            <p>
                <input type="radio" id="" name="insert-default" value="default" <?php echo $checked1; ?>/>
                Использовать встроенный стиль кнопки
                <div id="my-article-links">
                    <a href="#">Пример кнопки</a>
                </div>
            </p>
            <p>
                <input type="radio" id="" name="insert-default" value="custom" <?php echo $checked2; ?> />
                Добавить собственный стиль<br/>
                <code>
                    ID контейнера для кнопки - <strong>#my-article-links</strong>,
                    стиль для кнопки <strong>#my-article-links a</strong>
                </code>
            </p>
            <textarea cols="50" rows="10" name="custom-css" id="custom-css"><?php echo get_option('user-css'); ?></textarea>
            
            <p><input type="submit" id="update-css-option" name="update-css-options" class="button-primary"/></p>
        </form>
    </div>

<?php }

В административной панели все хорошо, переключатель работает как надо, осталось сделать так, чтобы он заработал для текущей темы. Для этого нам понадобится слегка переписать код подключения CSS-файла к шаблону:

$option = get_option('default-css');

function insert_user_css(){
    echo '<style type="text/css">';
    echo get_option('user-css');
    echo '</style';
}

if($option == 'true'){
    add_action('wp_enqueue_scripts', 'dr_add_css');
}else{
    add_action('wp_head', 'insert_user_css');
}

Все просто – объявляем переменную $option со значением опции ‘default-css’ и создаем функцию insert_user_css(), которая будет содержать пользовательский css-файл. Затем, в зависимости от значения переменной $option, либо подключаем в шаблон css-файл плагина, либо выводим пользовательский CSS в секцию head.

На этом работу можно считать законченной, как видите плагин уже работает в моем блоге. Если у вас есть какие-то замечания или предложения по работе плагина, буду рада услышать.

скачать