Уважаемые пользователи Голос!
Сайт доступен в режиме «чтение» до сентября 2020 года. Операции с токенами Golos, Cyber можно проводить, используя альтернативные клиенты или через эксплорер Cyberway. Подробности здесь: https://golos.io/@goloscore/operacii-s-tokenami-golos-cyber-1594822432061
С уважением, команда “Голос”
GOLOS
RU
EN
UA
vp-webdev
7 лет назад

Wordpress модифицируем виджет бегущей строки и добавляем AJAX


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

Изначально мы использовали API метод https://api.coinmarketcap.com/v1/ticker/, который возвращает список всех криптовалют, отсортированных по популярности. Искать в нем нужную валюту не целесообразно и, к сожалению, в API отсутствуют какие-либо методы, которые давали бы данные по списку из интересующих нас криптовалют. Поэтому мы будем использовать метод https://api.coinmarketcap.com/v1/ticker/{currency}/. Он выдаст нам всю необходимую информацию о каждой валюте отдельно.

Итак, мы разобрались каким образом будем получать необходимые данные, теперь модифицируем наш виджет. Начнем с функции form, нам необходимо добавить радио-группу, с помощью которой можно было бы переключаться на список из валют или на популярные валюты, а также добавим ещё одно поле ввода для этого самого списка. Теперь метод будет выглядеть следующим образом:

   function form( $instance ) {
    $defaults = array (
     'currenciesLimit' => 10,
     'type' => 'popular', // <-- новая опция
     'list' => 'bitcoin,Ethereum' // <-- новая опция
    );
    $instance = wp_parse_args((array)$instance, $defaults);
    ?>
    
    
     <p>
      Вывод: <br/>
      <label><input id="<?php echo $this->get_field_id( 'type' ); ?>" name="<?php echo $this->get_field_name( 'type' ); ?>" value="popular"  type="radio" <?php checked( $instance['type'], 'popular', true ); ?> /> Популярные криптовалюты </label> <br/>
      <label><input id="<?php echo $this->get_field_id( 'type' ); ?>" name="<?php echo $this->get_field_name( 'type' ); ?>" value="list"  type="radio" <?php checked( $instance['type'], 'list', true ); ?>/> Список из криптовалют </label>
     </p>
      
     <p>
      <label for="<?php echo $this->get_field_id( 'currenciesLimit' ); ?>"> Выводить <input id="<?php echo $this->get_field_id( 'currenciesLimit' ); ?>" name="<?php echo $this->get_field_name( 'currenciesLimit' ); ?>" value="<?php echo $instance['currenciesLimit']; ?>" style="width:50px;" type="number"/> популярных криптовалют</label>
     </p>
     
     <p>
      <label for="<?php echo $this->get_field_id( 'list' ); ?>"> Список криптовалют</label>
      <input id="<?php echo $this->get_field_id( 'list' ); ?>" name="<?php echo $this->get_field_name( 'list' ); ?>" value="<?php echo $instance['list']; ?>" type="text"/>
     </p>
      

    <?
  }

Как вы могли заметить, появились две новые опции type и list, думаю и так понятно за что они отвечают. Теперь изменим метод сохранения настроек, за это у нас отвечает update :

function update( $new_instance, $old_instance ) {
    $instance = $old_instance;

    $instance['currenciesLimit'] = strip_tags( $new_instance['currenciesLimit'] );
    $instance['type'] = strip_tags( $new_instance['type'] );
    $instance['list'] = strip_tags( $new_instance['list'] );
    
    return $instance;
   }

Здесь ничего сложного нет, мы просто добавили сохранение ещё двух опций. Следующим у нас идет метод widget, где и происходит основная работа.

   function widget( $args, $instance ){

    $currencies = array();

    switch ($instance['type']) {
        case 'popular':
            {
                $res = file_get_contents('https://api.coinmarketcap.com/v1/ticker/?convert=RUB&limit='.$instance['currenciesLimit']);
                $currencies = json_decode($res,true);
            }
            break;

        case 'list':
            {
                            $list = explode(',',$instance['list']);

                            $currencies = array();

                            for ($i=0;$i<count($list);$i++) {
                            $res = file_get_contents('https://api.coinmarketcap.com/v1/ticker/'.str_replace(' ','-',$list[$i]).'/?convert=RUB');
                            $res = json_decode($res,true);
                            $currencies[] = $res[0];
                            }
            }
            break;

    }

    ?>
     <marquee scrollamount="3" behavior="scroll" loop="infinite" direction="left">
    <?
    foreach ($currencies as $key => $currency) {
    ?>
     <span><strong><? echo $currency['name'].' ('.$currency['symbol'].')'; ?></strong> : <? echo number_format($currency['price_rub'], 2, '.', ' ').' руб.';?> &nbsp;&nbsp;</span>
    <?
    }
    ?>
     </marquee>
    <?
         
   }

Была добавлена конструкция switch, которая позволяет выполнять различный код в зависимости от значения опции type. В "list" сначала мы должны превратить список в массив, для этого используется функция php explode(), первый параметр это разделитель, а второй непосредственно сама строка. Важно! между словами должны быть лишь запятые, никаких пробелов и лишних знаков, иначе функция добавит это все к нашим словам и API будет возвращать ошибку. Вы могли заметить, что в запрос мы подставляем не просто элемент массива, а конструкцию str_replace(' ','-',$list[$i]) - функция, которая меняет в строке пробелы на знак тире. Это нужно, потому как API принимает названия валют таких как Bitcoin cash или Ethereum Classic только со знаком "-" между словами. Дальнейший код аналогичен коду из секции "popular", за исключением того, что он обрамлен в цикл.

И вот наш модифицированный виджет готов, но где же AJAX спросите вы? Дело в том, что если сделать список из 5+ криптовалют, то продолжительность загрузки веб-страницы значительно увеличиться. Чтобы этого избежать нам и пригодится AJAX. Сначала ajax-запрос необходимо зарегистрировать в Wordpress, делается это одной из следующих функций:

add_action('wp_ajax_(action)', 'my_action_callback'); - эту функция регистрирует ajax-действие для админ-панели. Первый аргумент - название действия, где вместо (action) - имя вашего запроса. Второй параметр - функция, которая будет обрабатывать запрос.

add_action('wp_ajax_(action)', 'my_action_callback'); - для авторизованных пользователей.
add_action('wp_ajax_nopriv_(action)', 'my_action_callback'); - для неавторизованных пользователей.

Функции выше предназначены для создания действий на самом сайте, параметры обеих аналогичны параметрам функции для админ-панели.

Добавим в конструктор виджета следующие строки:

add_action('wp_ajax_getCurrencies', array($this,'my_action_callback'));
add_action('wp_ajax_nopriv_getCurrencies', array($this,'my_action_callback'));

Имя функции указано следующим образом array($this,'my_action_callback'), поскольку она будет являться методом класса виджета.

Теперь создадим сам метод и скопируем в него весь код из widget

   function my_action_callback(){

    $currencies = array();

    switch ($_POST['type']) {
        case 'popular':
            {
                $res = file_get_contents('https://api.coinmarketcap.com/v1/ticker/?convert=RUB&limit='.$_POST['currenciesLimit']);
                $currencies = json_decode($res,true);
            }
            break;

        case 'list':
            {
                            $list = explode(',',$_POST['list']);

                            $currencies = array();

                            for ($i=0;$i<count($list);$i++) {
                            $res = file_get_contents('https://api.coinmarketcap.com/v1/ticker/'.str_replace(' ','-',$list[$i]).'/?convert=RUB');
                            $res = json_decode($res,true);
                            $currencies[] = $res[0];
                            }
            }
            break;

    }

    ?>
     <marquee scrollamount="3" behavior="scroll" loop="infinite" direction="left">
    <?
    foreach ($currencies as $key => $currency) {
    ?>
     <span><strong><? echo $currency['name'].' ('.$currency['symbol'].')'; ?></strong> : <? echo number_format($currency['price_rub'], 2, '.', ' ').' руб.';?> &nbsp;&nbsp;</span>
    <?
    }
    ?>
     </marquee>
    <?
    wp_die();    
   }

К сожалению, в данном методе нам не доступна переменная $instance, поэтому мы заменим её везде на $_POST, в которой будут хранится все значения, передаваемые POST параметрами в запросе. Также в конце функции необходимо написать wp_die();, чтобы Wordpress не возвращал ничего лишнего.

Теперь возвращаемся к методу widget и пишем в нем скрипт, который будет запрашивать данные:

   function widget( $args, $instance ){
   ?>
       <div id="marqueeCurrency" style="text-align:center;"> загрузка...</div>
    <script type="text/javascript" >
    jQuery(document).ready(function($) {
        var data = {
            action: 'getCurrencies',
            currenciesLimit: <? echo $instance['currenciesLimit']?>,
            type: '<? echo $instance['type']?>',
            list: '<? echo $instance['list']?>',
        };


        jQuery.post( '<?echo admin_url('admin-ajax.php');?>', data, function(response) {
            document.getElementById('marqueeCurrency').innerHTML = response;
        });
    });
    </script>
   <?        
   }

Самым важным параметром запроса является action - действие, которое необходимо выполнить. Также в POST параметрах мы передали все необходимые данные. Выполнением запроса будет являться html конструкция, которую мы вставим в блок div.

Таким образом теперь страница будет гораздо быстрее загружаться, поскольку не ждет пока отработает скрипт виджета.

Скачать исходный код виджета
Заглавное фото с сайта pvsm.ru


Данный материал подготовлен автором @mo3golom в рамках цикла статей о WordPress.

18
124.736 GOLOS
На Golos с August 2017
Комментарии (4)
Сортировать по:
Сначала старые