使用下一步导航按钮为具有管理员指针的用户创建WP教程


9

我旨在为我的用户创建一个有关管理区域的教程。为此,我使用了WP核心中提供的管理指针。我的目标:

在此处输入图片说明

我快到了 我到目前为止所得到的...

排队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中一切正常。

现在要解决的问题:所有弹出指针都同时出现,这对于教程来说是一个糟糕的界面。

我的目的是一个一个地显示指针,并允许用户单击“ 下一步”按钮浏览本教程。下一个按钮应打开下一个指针,然后关闭最后一个。

我怎样才能做到这一点?

Answers:


10

您正在.pointer( 'open' );所有指针对象上调用javascript函数,因此所有指针都同时出现并不奇怪...

就是说,我不明白为什么您要从中返回所有指针(甚至是非活动指针) custom_admin_pointers(),然后添加一个附加函数来检查是否存在一些活动指针,并在检查指针循环(if ( $array['active'] ) {)中选择添加javascript指针或不。仅返回活动指针不是更简单吗?

而且,您在所有管理页面上都添加了javascript,不是太多吗?还要考虑某些元素,例如“#save-post”仅在新的帖子页面上可用,因此更好地仅在新的pot页面上添加指针吗?

最后,该javascript与PHP混杂在一起有多混乱,我认为您应该考虑wp_localize_script将数据传递给javascript。

计划:

  1. 将PHP中的指针定义移动到一个单独的文件中,这样就可以轻松地进行编辑,并且还可以从PHP代码中删除标记,所有内容均更具可读性和可维护性
  2. 在指针配置中,添加属性“ where”,该属性将用于设置应在哪个管理页面中显示弹出窗口:post-new.phpindex.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个锚点ID添加1个指针:对多个指针使用相同的锚点将导致脚本失败。第二个问题是某些指针使用锚指向可能不在页面中的ID。例如,一个指针指向index.php中的“#comment-55”,但找不到该指针。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”-我到底要添加到where数组什么?我尝试了“ 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. 如果没有,我们将继续加入必要的脚本。

您无需在这些第一个功能中进行任何更改。

设置指针项数组

下一步是定义每个指针。我们需要定义五个项目(最后一个指针除外)。我们将使用数组进行此操作。让我们看一下函数:

// 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元素ID相匹配。
  3. function命令将重新加载/重定位窗口。这就是用来显示下一个指针的内容。我们必须重新加载窗口,或将其重新定位到下一个将显示指针的管理页面。
  4. 我们get_admin_url()使用两个变量运行该函数;第一个是我们接下来要去的管理页面;第二个是我们希望显示的指针的唯一数组键。

再往下看,您将看到开始的代码if (!array_key_exists($tab, $tour)) {。这是我们确定是否已设置url查询变量的地方。如果没有,则需要定义要显示的第一个指针。

该指针使用与上述数组中使用的id, content, button2, and function项完全相同的项$tour。请记住,get_admin_url()函数的第二个参数必须与$tour变量中的数组键完全相同。这就是告诉脚本转到下一个指针的原因。

如果在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();

同样,无需更改以上任何内容。该脚本将在指针覆盖窗口中定义并输出两个按钮。一个永远是“关闭”按钮;并将更新当前的用户meta dismissed_pointers选项。

第二个按钮(动作按钮)将执行功能(我们的窗口重定位方法)。

然后我们关闭课程。

这是完整的代码。 WP指针类

您可以将其复制/粘贴到您的开发站点中,然后访问“仪表板”页面。它将指导您完成整个旅程。

请记住,第一个指针在代码中的最后定义有点令人困惑。那就是它应该起作用的方式。该数组将保存您希望使用的所有其余指针。

请记住,“ id”数组项必须与get_admin_url()上一个数组项“ function”命令中的函数的第二个参数匹配。这就是指针相互“交谈”并知道如何前进的方式。

请享用!!:)


这是可爱的乔什,非常感谢!我将尝试一下,看看其功能如何。我要强调的是,通用汽车的代码是我可能会赏识的代码,因为它具有我要求的一些基本功能,并且我认为这对于创建指南非常重要,特别是对于wp-admin中的多个页面。尽管如此,很高兴看到另一种解决方案,它将对正在寻找好的解决方案的其他用户派上用场。出于好奇,您说过在使用指针时有很多混杂的感觉,在乎详细说明吗?
克里斯汀·库珀

2
不用担心:)好吧,过多使用指针时,指针可能会“妨碍您”。没有人愿意访问页面并显示三个或四个指针...尤其是在它们不相关的情况下。假设其他两个插件都显示了指针,然后我们添加了更多指针。大多数人说要谨慎使用它们……但是每个人都是他们自己的:)很高兴您能正常使用它。
2014年

1
我也建议Josh这样做很出色,以使其更加灵活,并使其可以在其中简单地将数组传递给公共函数,而不是将其存储在类代码本身中。其次,对第一个指针(如何分开)进行修改,使其可以成为指针数组中的第一个数组键/值。仅有几个想法,因此可以从另一个脚本中调用该类,并将其简单地传递给指针数组。我还是很喜欢,谢谢分享,我会用这个!
JasonDavis 2014年

谢谢@jasondavis。实际上,我从为某人开发的另一个插件中提取了该代码。我只是想让它正常工作。但是,是的,我绝对同意您的观点……需要清洗。也许我会在今天晚些时候停下来,然后再把它弄乱:)兄弟,你摇滚!
2014年

太酷了,我实际上从未打算使用管理指针,主要是因为它们看起来像一场噩梦,而第二个则是因为我对它们没有实际用途,但是您的班级使它们看起来是如此易于使用,以至于我觉得必须使用它们,并且与该类非常容易!我喜欢这样的小项目/图书馆,好东西
JasonDavis 2014年
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.