Створіть навчальний посібник для користувачів з покажчиком адміністратора, використовуючи наступну кнопку для навігації


9

Я маю на меті створити підручник для своїх користувачів для області адміністратора. Для цього я використовую вказівники адміністратора, доступні в ядрі WP. Моя мета:

введіть тут опис зображення

Я майже там. Що я отримав поки що ...

Ставити сор-покажчик сценаріїв:

add_action( 'admin_enqueue_scripts', 'custom_admin_pointers_header' );

function custom_admin_pointers_header() {
    if ( custom_admin_pointers_check() ) {
        add_action( 'admin_print_footer_scripts', 'custom_admin_pointers_footer' );

        wp_enqueue_script( 'wp-pointer' );
        wp_enqueue_style( 'wp-pointer' );
    }
}

Допоміжні функції, в тому числі умовної перевірки і колонтитул сценарію:

function custom_admin_pointers_check() {
    $admin_pointers = custom_admin_pointers();
    foreach ( $admin_pointers as $pointer => $array ) {
        if ( $array['active'] )
            return true;
    }
}

function custom_admin_pointers_footer() {
    $admin_pointers = custom_admin_pointers();
    ?>
    <script type="text/javascript">
        /* <![CDATA[ */
        ( function($) {
            <?php
            foreach ( $admin_pointers as $pointer => $array ) {
               if ( $array['active'] ) {
                  ?>
            $( '<?php echo $array['anchor_id']; ?>' ).pointer( {
                content: '<?php echo $array['content']; ?>',
                position: {
                    edge: '<?php echo $array['edge']; ?>',
                    align: '<?php echo $array['align']; ?>'
                },
                close: function() {
                    $.post( ajaxurl, {
                        pointer: '<?php echo $pointer; ?>',
                        action: 'dismiss-wp-pointer'
                    } );
                }
            } ).pointer( 'open' );
            <?php
         }
      }
      ?>
        } )(jQuery);
        /* ]]> */
    </script>
<?php
}

Тепер ми готові зібрати масив покажчиків:

function custom_admin_pointers() {
    $dismissed = explode( ',', (string) get_user_meta( get_current_user_id(), 'dismissed_wp_pointers', true ) );
    $version = '1_0'; // replace all periods in 1.0 with an underscore
    $prefix = 'custom_admin_pointers' . $version . '_';

    $new_pointer_content = '<h3>' . __( 'Add New Item' ) . '</h3>';
    $new_pointer_content .= '<p>' . __( 'Easily add a new post, media item, link, page or user by selecting from this drop down menu.' ) . '</p>';

    $story_pointer_content = '<h3>' . __( 'Another info' ) . '</h3>';
    $story_pointer_content .= '<p>' . __( 'Lorem ipsum...' ) . '</p>';


    return array(
        $prefix . 'new_items' => array(
            'content' => $new_pointer_content,
            'anchor_id' => '#wp-admin-bar-new-content',
            'edge' => 'top',
            'align' => 'left',
            'active' => ( ! in_array( $prefix . 'new_items', $dismissed ) )
        ),
        $prefix.'story_cover_help' => array(
            'content' => $story_pointer_content,
            'anchor_id' => '#save-post',
            'edge' => 'top',
            'align' => 'right',
            'active' => ( ! in_array( $prefix . 'story_cover_help', $dismissed ) )
        )
    );

}

Код не вимагає пояснень. Ми можемо легко додати більше покажчиків, розширюючи масив. Все працює відмінно в WP4.

Тепер до проблеми: Усі всплывающие вказівники з’являються одночасно, що робить це поганим інтерфейсом для навчального посібника.

Моя мета полягає в тому, щоб показати покажчики один на один, і дозволяє користувачеві натиснути на Next кнопку , щоб перейти через підручник. Наступна кнопка повинна відкрити наступний вказівник і закрити останню.

Як я можу це зробити?

Відповіді:


10

Ви викликаєте .pointer( 'open' );функцію javascript на всіх об'єктах покажчиків, тому не дивно, що всі вказівники з’являються одночасно ...

З custom_admin_pointers()цього приводу я не розумію, чому ви повертаєте всі вказівники (навіть неактивні) з цього пункту, а потім додаєте додаткову функцію, щоб перевірити, чи є якісь активні вказівники та перевірку всередині циклу покажчиків ( if ( $array['active'] ) {), щоб вибрати, щоб додати покажчик javascript чи ні. Чи не простіше просто повернути лише активні покажчики?

Більше того, ви додаєте, що JavaScript на всіх сторінках адміністратора - це не надто багато? Також врахуйте, що деякі елементи на зразок "# save-post" доступні лише на новій сторінці публікацій, тож чи не краще додати покажчики лише на новій сторінці горщика?

Нарешті, наскільки брудним є те, що javascript змішується з PHP, я думаю, ви повинні розглянути можливість використання wp_localize_scriptдля передачі даних у JavaScript.

План:

  1. Перемістіть визначення покажчиків у PHP в окремий файл, таким чином легко редагувати, а також видаляти розмітку з PHP-коду, все призводить до більш читабельності та обслуговування
  2. В покажчиках конфігурації додати властивість «де» , який буде використовуватися для набору , в якому адміністратор сторінки має з'явитися спливаюче вікно: post-new.php, index.php...
  3. Напишіть клас, який буде обробляти завантаження, синтаксичний аналіз та фільтрацію інформації покажчиків
  4. Напишіть трохи js доброти, яка допоможе нам змінити типову кнопку «Видалити» на «Далі»

# 4 може (ймовірно) легко зробити , знаючи покажчик плагін добре, але це не мій випадок. Тож я буду використовувати загальний код jQuery для отримання результату, якщо хтось може покращити мій код, я буду вдячний.


Редагувати

Я редагував код (головним чином js), тому що я не розглядав різні речі: деякі покажчики можуть бути додані до того ж якоря, або ті ж покажчики можуть бути додані до неіснуючих або невидимих ​​якорів. У всьому випадку, колишній код не працював, нова версія, схоже, вирішує цю проблему чудово.

Я також налаштував Gist із усім кодом, який я використовував для тестування.


Почнемо з пунктів №1 та №2 : створимо файл з ім’ям pointers.phpі напишіть туди:

<?php
$pointers = array();

$pointers['new-items'] = array(
  'title'     => sprintf( '<h3>%s</h3>', esc_html__( 'Add New Item' ) ),
  'content'   => sprintf( '<p>%s</p>', esc_html__( 'Easily add a new post..' ) ),
  'anchor_id' => '#wp-admin-bar-new-content',
  'edge'      => 'top',
  'align'     => 'left',
  'where'     => array( 'index.php', 'post-new.php' ) // <-- Please note this
);

$pointers['story_cover_help'] = array(
  'title'     => sprintf( '<h3>%s</h3>', esc_html__( 'Another info' ) ),
  'content'   => sprintf( '<p>%s</p>', esc_html__( 'Lore ipsum....' ) ),
  'anchor_id' => '#save-post',
  'edge'      => 'top',
  'align'     => 'right',
  'where'     => array( 'post-new.php' ) // <-- Please note this
);

// more pointers here...

return $pointers; 

Усі налаштування покажчиків тут. Коли вам потрібно щось змінити, просто відкрийте цей файл і відредагуйте його.

Зверніть увагу на властивість "where", яка є масивом сторінок, де має бути доступний покажчик.

Якщо ви хочете відобразити покажчики на сторінки , що генерується плагін, погляд для цього рядка описані нижче public function filter( $page ) {і додати die($page);безпосередньо під ним. Потім відкрийте відповідну сторінку плагіна і використовувати цей рядок в whereвласності.

Добре, тепер точка # 3 .

Перш ніж писати клас, я просто хочу кодувати інтерфейс: там я розміщую коментарі, щоб ви могли краще зрозуміти, що робитиме клас.

<?php
interface PointersManagerInterface {

  /**
  * Load pointers from file and setup id with prefix and version.
  * Cast pointers to objects.
  */
  public function parse();

  /**
  * Remove from parse pointers dismissed ones and pointers
  * that should not be shown on given page
  *
  * @param string $page Current admin page file
  */
  public function filter( $page );

}

Думаю, має бути досить зрозуміло. Тепер запишемо клас, він буде містити 2 методи з інтерфейсу плюс конструктор.

<?php namespace GM;

class PointersManager implements PointersManagerInterface {

  private $pfile;
  private $version;
  private $prefix;
  private $pointers = array();

  public function __construct( $file, $version, $prefix ) {
    $this->pfile = file_exists( $file ) ? $file : FALSE;
    $this->version = str_replace( '.', '_', $version );
    $this->prefix = $prefix;
  }

  public function parse() {
    if ( empty( $this->pfile ) ) return;
    $pointers = (array) require_once $this->pfile;
    if ( empty($pointers) ) return;
    foreach ( $pointers as $i => $pointer ) {
      $pointer['id'] = "{$this->prefix}{$this->version}_{$i}";
      $this->pointers[$pointer['id']] = (object) $pointer;
    }
  }

  public function filter( $page ) {
    if ( empty( $this->pointers ) ) return array();
    $uid = get_current_user_id();
    $no = explode( ',', (string) get_user_meta( $uid, 'dismissed_wp_pointers', TRUE ) );
    $active_ids = array_diff( array_keys( $this->pointers ), $no );
    $good = array();
    foreach( $this->pointers as $i => $pointer ) {
      if (
        in_array( $i, $active_ids, TRUE ) // is active
        && isset( $pointer->where ) // has where
        && in_array( $page, (array) $pointer->where, TRUE ) // current page is in where
      ) {
       $good[] = $pointer;
      }
    }
    $count = count( $good );
    if ( $good === 0 ) return array();
    foreach( array_values( $good ) as $i => $pointer ) {
      $good[$i]->next = $i+1 < $count ? $good[$i+1]->id : '';
    }
    return $good;
  }
}

Код дуже простий і робить саме те, що очікує інтерфейс.

Однак клас нічого не робить сам, нам потрібен гачок, де інстанціювати клас над запуском 2-х методів, передаючи належні аргументи.

Це 'admin_enqueue_scripts'ідеально підходить для нашої сфери: там ми матимемо доступ до поточної сторінки адміністрування, і ми також можемо передати необхідні сценарії та стилі.

add_action( 'admin_enqueue_scripts', function( $page ) {
  $file = plugin_dir_path( __FILE__ ) . 'pointers.php';
  // Arguments: pointers php file, version (dots will be replaced), prefix
  $manager = new PointersManager( $file, '5.0', 'custom_admin_pointers' );
  $manager->parse();
  $pointers = $manager->filter( $page );
  if ( empty( $pointers ) ) { // nothing to do if no pointers pass the filter
    return;
  }
  wp_enqueue_style( 'wp-pointer' );
  $js_url = plugins_url( 'pointers.js', __FILE__ );
  wp_enqueue_script( 'custom_admin_pointers', $js_url, array('wp-pointer'), NULL, TRUE );
  // data to pass to javascript
  $data = array(
    'next_label' => __( 'Next' ),
    'close_label' => __('Close'),
    'pointers' => $pointers
  );
  wp_localize_script( 'custom_admin_pointers', 'MyAdminPointers', $data );
} );

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

Гаразд, зараз "найважча" частина: js. Ще раз хочу підкреслити, що я не знаю, що плагін покажчика використовує WordPress, тому те, що я роблю в своєму коді, можна зробити краще, якщо хтось це знає, проте мій код виконує свою роботу і, загалом кажучи, - це не так вже й погано.

( function($, MAP) {

  $(document).on( 'MyAdminPointers.setup_done', function( e, data ) {
    e.stopImmediatePropagation();
    MAP.setPlugin( data ); // open first popup
  } );

  $(document).on( 'MyAdminPointers.current_ready', function( e ) {
    e.stopImmediatePropagation();
    MAP.openPointer(); // open a popup
  } );

  MAP.js_pointers = {};        // contain js-parsed pointer objects
  MAP.first_pointer = false;   // contain first pointer anchor jQuery object
  MAP.current_pointer = false; // contain current pointer jQuery object
  MAP.last_pointer = false;    // contain last pointer jQuery object
  MAP.visible_pointers = [];   // contain ids of pointers whose anchors are visible

  MAP.hasNext = function( data ) { // check if a given pointer has valid next property
    return typeof data.next === 'string'
      && data.next !== ''
      && typeof MAP.js_pointers[data.next].data !== 'undefined'
      && typeof MAP.js_pointers[data.next].data.id === 'string';
  };

  MAP.isVisible = function( data ) { // check if anchor for given pointer is visible
    return $.inArray( data.id, MAP.visible_pointers ) !== -1;
  };

  // given a pointer object, return its the anchor jQuery object if available
  // otherwise return first available, lookin at next property of subsequent pointers
  MAP.getPointerData = function( data ) { 
    var $target = $( data.anchor_id );
    if ( $.inArray(data.id, MAP.visible_pointers) !== -1 ) {
      return { target: $target, data: data };
    }
    $target = false;
    while( MAP.hasNext( data ) && ! MAP.isVisible( data ) ) {
      data = MAP.js_pointers[data.next].data;
      if ( MAP.isVisible( data ) ) {
        $target = $(data.anchor_id);
      }
    }
    return MAP.isVisible( data )
      ? { target: $target, data: data }
      : { target: false, data: false };
  };

  // take pointer data and setup pointer plugin for anchor element
  MAP.setPlugin = function( data ) {
    if ( typeof MAP.last_pointer === 'object') {
      MAP.last_pointer.pointer('destroy');
      MAP.last_pointer = false;
    }
    MAP.current_pointer = false;
    var pointer_data = MAP.getPointerData( data );
      if ( ! pointer_data.target || ! pointer_data.data ) {
      return;
    }
    $target = pointer_data.target;
    data = pointer_data.data;
    $pointer = $target.pointer({
      content: data.title + data.content,
      position: { edge: data.edge, align: data.align },
      close: function() {
        // open next pointer if it exists
        if ( MAP.hasNext( data ) ) {
          MAP.setPlugin( MAP.js_pointers[data.next].data );
        }
        $.post( ajaxurl, { pointer: data.id, action: 'dismiss-wp-pointer' } );
      }
    });
    MAP.current_pointer = { pointer: $pointer, data: data };
    $(document).trigger( 'MyAdminPointers.current_ready' );
  };

  // scroll the page to current pointer then open it
  MAP.openPointer = function() {          
    var $pointer = MAP.current_pointer.pointer;
    if ( ! typeof $pointer === 'object' ) {
      return;
    }
    $('html, body').animate({ // scroll page to pointer
      scrollTop: $pointer.offset().top - 30
    }, 300, function() { // when scroll complete
      MAP.last_pointer = $pointer;
        var $widget = $pointer.pointer('widget');
        MAP.setNext( $widget, MAP.current_pointer.data );
        $pointer.pointer( 'open' ); // open
    });
  };

  // if there is a next pointer set button label to "Next", to "Close" otherwise
  MAP.setNext = function( $widget, data ) {
    if ( typeof $widget === 'object' ) {
      var $buttons = $widget.find('.wp-pointer-buttons').eq(0);        
      var $close = $buttons.find('a.close').eq(0);
      $button = $close.clone(true, true).removeClass('close');
      $buttons.find('a.close').remove();
      $button.addClass('button').addClass('button-primary');
      has_next = false;
      if ( MAP.hasNext( data ) ) {
        has_next_data = MAP.getPointerData(MAP.js_pointers[data.next].data);
        has_next = has_next_data.target && has_next_data.data;
      }
      var label = has_next ? MAP.next_label : MAP.close_label;
      $button.html(label).appendTo($buttons);
    }
  };

  $(MAP.pointers).each(function(index, pointer) { // loop pointers data
    if( ! $().pointer ) return;      // do nothing if pointer plugin isn't available
    MAP.js_pointers[pointer.id] = { data: pointer };
    var $target = $(pointer.anchor_id);
    if ( $target.length && $target.is(':visible') ) { // anchor exists and is visible?
      MAP.visible_pointers.push(pointer.id);
      if ( ! MAP.first_pointer ) {
        MAP.first_pointer = pointer;
      }
    }
    if ( index === ( MAP.pointers.length - 1 ) && MAP.first_pointer ) {
      $(document).trigger( 'MyAdminPointers.setup_done', MAP.first_pointer );
    }
  });

} )(jQuery, MyAdminPointers); // MyAdminPointers is passed by `wp_localize_script`

За допомогою коментарів код повинен бути досить зрозумілим, принаймні, я сподіваюся, що так.

Гаразд, ми зробили. Наш PHP простіший і краще організований, наш JavaScript читає, покажчики легше редагувати, і, що важливіше, все працює.


1
@ChristineCooper впевнений. Гаразд, проблеми 2: перше, як тепер працює сценарій, ви можете додати 1 вказівник на 1 ідентифікатор якоря: використання одного якоря для більш ніж одного вказівника призведе до збою сценарію. Друга проблема полягає в тому, що деякі вказівники використовують прив’язку до ідентифікаторів, які можуть не бути на сторінці. Наприклад, один покажчик призначений для "# comment-55" в index.php, і він не знайдений. Деякі вказівники в метабоксах post.php цілі, які можуть бути приховані ... тощо. Після того, як у поточній версії покажчики сценарію "прикуті", якщо їх не знайдено, усі підзаступники теж не працюватимуть. Я побачу, чи існує простий спосіб подолати ці проблеми.
gmazzap

1
@ChristineCooper Радий це спрацювало. Я скопію тут весь код з Gist. Стан може бути поставлений тільки після того, як add_action( 'admin_enqueue_scripts', function( $page ) {просто не повертаються , якщо користувач не потрібно роль.
gmazzap

Будь-ласка, змініть значення 30 на 120 на рядок: "scrollTop: $ pointer.offset (). Top - 30" - Причина в тому, що верхня панель інструментів періодично охоплює вікно вказівника під час прокрутки.
Крістін Купер

У мене є одна незначна проблема. Сторінка, на яку мені потрібні деякі покажчики: "admin.php? Page = plugin-path / file.php" - що саме я додати до масиву де ? Я спробував "admin.php", "plugin-path / file.php", "file.php" і будь-які варіанти, про які я міг придумати. Чи є причина, чому вона не може виявити цю сторінку чи я роблю це неправильно?
Крістін Купер

1
@ChristineCooper відкрийте сторінку адміністратора плагіна та скопіюйте URL-адресу з браузера . Після цього відкрийте файл, який містить мій код вище. Знайдіть рядок public function filter( $page ) {у PointersManagerкласі та одразу після цього поставте рядок die($page);. Відкрийте веб-переглядач і вставте назад URL-адресу, сторінка загине рядком: це те, що ви повинні використовувати як 'where'.
gmazzap

7

Ааа .. да. Вказівники WordPress. Ви знаєте, є досить багато змішаних почуттів, коли мова заходить про використання покажчиків;)

Ви були на правильному шляху зі своїм кодом вище. Але є пара питань.

@GM вірно стосується pointer('open')команди відкриття всіх ваших покажчиків одразу. Крім того, ви не надаєте методу просування через покажчики.

Я боровся з цим самим питанням .. і придумав власний підхід. Я використовую змінний запит в URL, перезавантажте сторінку на сторінку адміністратора, де я хочу, щоб відобразити наступний покажчик, і нехай JQuery впоратися з рештою.

Клас покажчиків WP

Я вирішив написати це як клас. Але я спершу покажу це з кроком, щоб краще зрозуміти, що відбувається.

Початок заняття

// Create as a class
class testWPpointers {

    // Define pointer version
    const DISPLAY_VERSION = 'v1.0';

    // Initiate construct
    function __construct () {
        add_action('admin_enqueue_scripts', array($this, 'admin_enqueue_scripts'));  // Hook to admin_enqueue_scripts
    }

    function admin_enqueue_scripts () {

        // Check to see if user has already dismissed the pointer tour
        $dismissed = explode (',', get_user_meta (wp_get_current_user ()->ID, 'dismissed_wp_pointers', true));
        $do_tour = !in_array ('test_wp_pointer', $dismissed);

        // If not, we are good to continue
        if ($do_tour) {

            // Enqueue necessary WP scripts and styles
            wp_enqueue_style ('wp-pointer');
            wp_enqueue_script ('wp-pointer');

            // Finish hooking to WP admin areas
            add_action('admin_print_footer_scripts', array($this, 'admin_print_footer_scripts'));  // Hook to admin footer scripts
            add_action('admin_head', array($this, 'admin_head'));  // Hook to admin head
        }
    }

    // Used to add spacing between the two buttons in the pointer overlay window.
    function admin_head () {
        ?>
        <style type="text/css" media="screen">
            #pointer-primary {
                margin: 0 5px 0 0;
            }
        </style>
        <?php
    }
  1. Ми визначили клас.
  2. Ми побудували клас, і додав дію на admin_enqueue_scripts.
  3. Ми визначили, чи наші покажчики вже звільнені.
  4. Якщо ні, ми продовжуємо додавати необхідні сценарії.

У цих перших функціях НЕ потрібно нічого змінювати.

Налаштування масиву Pointer Items

Наступний крок - визначення кожного з покажчиків. Нам потрібно визначити п’ять елементів (крім останнього вказівника). Ми зробимо це за допомогою масивів. Давайте розглянемо функцію:

// Define footer scripts
function admin_print_footer_scripts () {

    // Define global variables
    global $pagenow;
    global $current_user;

    //*****************************************************************************************************
    // This is our array of individual pointers.
    // -- The array key should be unique.  It is what will be used to 'advance' to the next pointer.
    // -- The 'id' should correspond to an html element id on the page.
    // -- The 'content' will be displayed inside the pointer overlay window.
    // -- The 'button2' is the text to show for the 'action' button in the pointer overlay window.
    // -- The 'function' is the method used to reload the window (or relocate to a new window).
    //    This also creates a query variable to add to the end of the url.
    //    The query variable is used to determine which pointer to display.
    //*****************************************************************************************************
    $tour = array (
        'quick_press' => array (
            'id' => '#dashboard_quick_press',
            'content' => '<h3>' . __('Congratulations!', 'test_lang') . '</h3>'
                . '<p><strong>' . __('WP Pointers is working properly.', 'test_lang') . '</strong></p>'
                . '<p>' . __('This pointer is attached to the "Quick Draft" admin widget.', 'test_lang') . '</p>'
                . '<p>' . __('Our next pointer will take us to the "Settings" admin menu.', 'test_lang') . '</p>',
            'button2' => __('Next', 'test_lang'),
            'function' => 'window.location="' . $this->get_admin_url('options-general.php', 'site_title') . '"'  // We are relocating to "Settings" page with the 'site_title' query var
            ),
        'site_title' => array (
            'id' => '#blogname',
            'content' => '<h3>' . __('Moving along to Site Title.', 'test_lang') . '</h3>'
            . '<p><strong>' . __('Another WP Pointer.', 'test_lang') . '</strong></p>'
            . '<p>' . __('This pointer is attached to the "Blog Title" input field.', 'test_lang') . '</p>',
            'button2' => __('Next', 'test_lang'),
            'function' => 'window.location="' . $this->get_admin_url('index.php', 'quick_press_last') . '"'  // We are relocating back to "Dashboard" with 'quick_press_last' query var
            ),
        'quick_press_last' => array (
            'id' => '#dashboard_quick_press',
            'content' => '<h3>' . __('This concludes our WP Pointers tour.', 'test_lang') . '</h3>'
            . '<p><strong>' . __('Last WP Pointer.', 'test_lang') . '</strong></p>'
            . '<p>' . __('When closing the pointer tour; it will be saved in the users custom meta.  The tour will NOT be shown to that user again.', 'test_lang') . '</p>'
            )
        );

    // Determine which tab is set in the query variable
    $tab = isset($_GET['tab']) ? $_GET['tab'] : '';
    // Define other variables
    $function = '';
    $button2 = '';
    $options = array ();
    $show_pointer = false;

    // *******************************************************************************************************
    // This will be the first pointer shown to the user.
    // If no query variable is set in the url.. then the 'tab' cannot be determined... and we start with this pointer.
    // *******************************************************************************************************
    if (!array_key_exists($tab, $tour)) {

        $show_pointer = true;
        $file_error = true;

        $id = '#dashboard_right_now';  // Define ID used on page html element where we want to display pointer
        $content = '<h3>' . sprintf (__('Test WP Pointers %s', 'test_lang'), self::DISPLAY_VERSION) . '</h3>';
        $content .= __('<p>Welcome to Test WP Pointers admin tour!</p>', 'test_lang');
        $content .= __('<p>This pointer is attached to the "At a Glance" dashboard widget.</p>', 'test_lang');
        $content .= '<p>' . __('Click the <em>Begin Tour</em> button to get started.', 'test_lang' ) . '</p>';

        $options = array (
            'content' => $content,
            'position' => array ('edge' => 'top', 'align' => 'left')
            );
        $button2 = __('Begin Tour', 'test_lang' );
        $function = 'document.location="' . $this->get_admin_url('index.php', 'quick_press') . '";';
    }
    // Else if the 'tab' is set in the query variable.. then we can determine which pointer to display
    else {

        if ($tab != '' && in_array ($tab, array_keys ($tour))) {

            $show_pointer = true;

            if (isset ($tour[$tab]['id'])) {
                $id = $tour[$tab]['id'];
            }

            $options = array (
                'content' => $tour[$tab]['content'],
                'position' => array ('edge' => 'top', 'align' => 'left')
            );

            $button2 = false;
            $function = '';

            if (isset ($tour[$tab]['button2'])) {
                $button2 = $tour[$tab]['button2'];
            }
            if (isset ($tour[$tab]['function'])) {
                $function = $tour[$tab]['function'];
            }
        }
    }

    // If we are showing a pointer... let's load the jQuery.
    if ($show_pointer) {
        $this->make_pointer_script ($id, $options, __('Close', 'test_lang'), $button2, $function);
    }
}

Гаразд .. давайте розглянемо кілька речей тут.

По-перше, наш $tourмасив. Це масив, який містить усі вказівники ВСЕ, крім першого вказівника, який відображається користувачеві (докладніше про це пізніше). Отже, ви хочете почати з другого вказівника, який ви маєте намір показати .., і продовжувати до останнього вказівника.

Далі ми маємо кілька пунктів, які є дуже важливими.

  1. Ці $tourключі масиву повинні бути унікальними (quick_press, SITE_TITLE, quick_press_last; в якості прикладів вище).
  2. Команда 'id' ОБОВ'ЯЗКОВА відповідати ідентифікатору елемента html елемента, який потрібно приєднати до вказівника.
  3. functionКоманда буде перезавантажити / перемістити вікно. Це те, що використовується для показу наступного вказівника. Ми повинні або перезавантажити вікно, або перенести його на наступну сторінку адміністратора, де буде відображатися покажчик.
  4. Запускаємо get_admin_url()функцію з двома змінними; перша - сторінка адміністратора, куди ми хочемо піти далі; друге - це унікальна клавіша масиву вказівника, який ми бажаємо відобразити.

Далі вниз ви побачите код, який починається if (!array_key_exists($tab, $tour)) {. Тут ми визначаємо, чи встановлена ​​змінна запиту URL-адреси. Якщо він НЕ, то нам потрібно визначити перший покажчик для відображення.

Цей вказівник використовує точно такі ж id, content, button2, and functionелементи, як і в нашому $tourмасиві вище. Пам'ятайте, другий аргумент get_admin_url()функції ОБОВ'ЯЗКОВО повинен бути точно таким же, як ключ масиву в $tourзмінній. Це те, що говорить сценарію перейти до наступного вказівника.

Решта функції використовується, якщо в URL-адресі вже встановлена ​​змінна запиту. Не потрібно більше коригувати функцію.

Отримання URL- адреси адміністратора Наступна функція насправді є допоміжною функцією ... використовується для отримання URL-адреси адміністратора та просування вказівника.

// This function is used to reload the admin page.
// -- $page = the admin page we are passing (index.php or options-general.php)
// -- $tab = the NEXT pointer array key we want to display
function get_admin_url($page, $tab) {

    $url = admin_url();
    $url .= $page.'?tab='.$tab;

    return $url;
}

Пам’ятайте, є два аргументи; сторінку адміністратора, на яку ми збираємось .. та вкладку. На вкладці буде $tourключ масиву, до якого ми хочемо перейти далі. ЦЕ ПОВИНЕН ЗБІГАТИ .

Отже, коли ми викликаємо функцію get_admin_url()і передаємо дві змінні; перша змінна визначає наступну сторінку адміністратора .., а друга змінна визначає, який покажчик відображати.

Нарешті ... ми можемо нарешті надрукувати сценарій адміністратора у колонтитулі.

// Print footer scripts
function make_pointer_script ($id, $options, $button1, $button2=false, $function='') {

    ?>
    <script type="text/javascript">

        (function ($) {

            // Define pointer options
            var wp_pointers_tour_opts = <?php echo json_encode ($options); ?>, setup;

            wp_pointers_tour_opts = $.extend (wp_pointers_tour_opts, {

                // Add 'Close' button
                buttons: function (event, t) {

                    button = jQuery ('<a id="pointer-close" class="button-secondary">' + '<?php echo $button1; ?>' + '</a>');
                    button.bind ('click.pointer', function () {
                        t.element.pointer ('close');
                    });
                    return button;
                },
                close: function () {

                    // Post to admin ajax to disable pointers when user clicks "Close"
                    $.post (ajaxurl, {
                        pointer: 'test_wp_pointer',
                        action: 'dismiss-wp-pointer'
                    });
                }
            });

            // This is used for our "button2" value above (advances the pointers)
            setup = function () {

                $('<?php echo $id; ?>').pointer(wp_pointers_tour_opts).pointer('open');

                <?php if ($button2) { ?>

                    jQuery ('#pointer-close').after ('<a id="pointer-primary" class="button-primary">' + '<?php echo $button2; ?>' + '</a>');
                    jQuery ('#pointer-primary').click (function () {
                        <?php echo $function; ?>  // Execute button2 function
                    });
                    jQuery ('#pointer-close').click (function () {

                        // Post to admin ajax to disable pointers when user clicks "Close"
                        $.post (ajaxurl, {
                            pointer: 'test_wp_pointer',
                            action: 'dismiss-wp-pointer'
                        });
                    })
                <?php } ?>
            };

            if (wp_pointers_tour_opts.position && wp_pointers_tour_opts.position.defer_loading) {

                $(window).bind('load.wp-pointers', setup);
            }
            else {
                setup ();
            }
        }) (jQuery);
    </script>
    <?php
}
} 
$testWPpointers = new testWPpointers();

Знову ж таки, немає потреби нічого змінювати вище. Цей скрипт визначатиме та виводить дві кнопки у вікні накладання вказівника. Завжди буде кнопка «Закрити»; і оновить поточну мета- dismissed_pointersопцію користувача.

Друга кнопка (кнопка дії) виконає функцію (наш метод переселення вікон).

І закриваємо клас.

Ось код в цілому. Клас покажчика WP

Ви можете скопіювати та вставити його на свій веб-сайт розробника та відвідати сторінку "Інформаційна панель". Він проведе вас через тур.

Пам'ятайте, трохи заплутано, що перший вказівник визначений останнім у коді. Ось так воно і має працювати. Масив буде містити всі решта покажчиків, які ви хочете використовувати.

Пам'ятайте, що елемент масиву "id" ОБОВ'ЯЗКОВО відповідає другому аргументу get_admin_url()функції з попередньої команди "function" попереднього елемента масиву. Ось як покажчики «розмовляють» один з одним і знають, як просунутися.

Насолоджуйтесь !! :)


Це прекрасний Джош, дуже дякую! Я спробую це і побачу, наскільки добре він працює. Я мушу підкреслити, що кодом GM є те, за що я, ймовірно, нагороджую цю суму, тому що у неї є декілька суттєвих особливостей, які я просив, і які, на мою думку, важливі для створення керівництва, особливо для декількох сторінок у wp-admin. Тим не менш, чудово бачити інший підхід у цьому і стане в нагоді іншим користувачам, які шукають хорошого рішення. З цікавості, ви сказали, що існує досить багато змішаних почуттів, коли справа стосується використання покажчиків , будьте обережні?
Крістін Купер

2
Не хвилюйтесь :) Ну, вказівники можуть «перешкоджати», коли вони використовуються в надлишку. Ніхто не хоче відвідувати сторінку і мати три-чотири покажчики ... особливо якщо вони не пов'язані. Скажімо, два інші плагіни показують покажчики, тоді ми додаємо ще вказівники .. він може стати надмірним. Більшість людей кажуть використовувати їх економно ... але у кожного своє :) Рада, що ви працюєте належним чином.
Джош

1
Це також дивовижний Джош, я б запропонував 1 пропозицію, щоб зробити це більш гнучким і мати його там, де ви можете просто передати масив у загальнодоступну функцію, а не зберігати його всередині самого коду класу. По-друге, перший вказівник, як він відокремлений, змініть його так, щоб він міг бути першим ключем / значенням масиву в масиві вказівників. Всього пара ідей, щоб цей клас можна було викликати з іншого сценарію і просто передати в масив вказівника. Мені все ще дуже подобається, дякую за те, що я буду використовувати це!
JasonDavis

Завдяки @jasondavis. Я фактично витягнув цей код з іншого плагіна, який я розробив для когось. Мене цікавило лише те, щоб воно працювало належним чином. Але так, я абсолютно з вами згоден ... це потрібно очистити. Можливо, я зупинюсь пізніше сьогодні і знову зіпсуюся з нею :) Ти рок, брате!
Josh

Це здорово, я насправді ніколи не мав наміру використовувати вказівники адміністратора, головним чином тому, що вони виглядали як кошмар, а другий, тому що я не маю для них реального використання, але ваш клас робить їх виглядом настільки простими у використанні зараз, коли я відчуваю, що я доводиться використовувати їх, оскільки це дуже просто з цим класом! Я люблю маленькі проекти / бібліотеки подібні, хороші речі
JasonDavis
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.