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

时间:2014-09-27 作者:Christine Cooper

我的目标是为管理领域创建一个关于我的用户的教程。为了实现这一点,我使用了WP core中可用的管理指针。我的目标:

enter image description here

我快到了。到目前为止我得到的。。。

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

Now to the problem: 所有弹出指针同时出现,这对于教程来说是一个糟糕的界面。

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

我该怎么做?

2 个回复
最合适的回答,由SO网友:gmazzap 整理而成

您正在呼叫.pointer( \'open\' ); javascript函数在所有指针对象上运行,所以所有指针同时出现也就不足为奇了。。。

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

此外,您正在所有管理页面上添加javascript,是不是太多了?还要考虑一些元素,如#“保存帖子”;只有在新的post页面上才可用,所以只在新的pot页面中添加指针不是更好吗?

最后,javascript与PHP的混合有多混乱,我认为您应该考虑使用wp_localize_script 将数据传递给javascript。

计划是:将PHP中的指针定义移动到一个单独的文件中,这样很容易编辑,也可以从PHP代码中删除标记,所有内容都更加可读和可维护,在指针配置中添加一个属性;其中;用于设置弹出窗口应出现在哪个管理页面:post-new.php, index.php...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; 
所有指针的配置都在这里。当您需要更改某些内容时,只需打开此文件并进行编辑。

请注意;其中;属性,该属性是指针应该可用的页面数组。

如果您想在插件生成的页面中显示指针,请查找下面列出的这一行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更可读,指针更容易编辑,更重要的是,一切都正常。

SO网友:josh

啊哈。。对WordPress指针。你知道,当谈到使用指针时,有很多复杂的感觉;)

上面的代码正确无误。但有几个问题。

@G、 M.关于pointer(\'open\') 命令立即打开所有指针。此外,您没有提供通过指针前进的方法。

我和这个问题斗争过。。并想出了我自己的方法。我在url中使用一个查询变量,将页面重新加载到要显示下一个指针的管理页面,并让jQuery处理其余部分。

WP Pointers Class

我决定把它作为一门课来写。但我首先要以增量的形式展示它,以帮助您更好地理解正在发生的事情。

Beginning the Class

// 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
    }
我们已经定义了类admin_enqueue_scripts.您不需要更改这些第一个函数中的任何内容。

Setting up the array of Pointer Items

下一步是定义每个指针。我们需要定义五项(最后一个指针的expept)。我们将使用数组来实现这一点。让我们看看函数:

// 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 大堆这是一个数组,其中包含除显示给用户的第一个指针之外的所有指针(稍后将对此进行详细介绍)。因此,您需要从要显示的第二个指针开始。。并继续到最后一个指针。

接下来,我们有几个非常重要的项目。

$tour 数组键必须唯一(quick\\u press、site\\u title、quick\\u press\\u last;如上所示)

  • function 命令将重新加载/重新定位窗口。这是用于显示下一个指针的内容。我们要么重新加载窗口,要么将其重新定位到下一个显示指针的管理页面get_admin_url() 具有两个变量的函数;第一个是我们下一步要去的管理页面;第二个是要显示的指针的唯一数组键
  • 再往下,您将看到开始的代码if (!array_key_exists($tab, $tour)) {. 这是我们确定是否已设置url查询变量的地方。如果没有,那么我们需要定义要显示的第一个指针。

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

    如果url中已经设置了查询变量,则使用该函数的其余部分。无需再调整任何功能。

    Getting Admin 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 我们要转到下一个数组键。THESE MUST MATCH.

    所以,当我们调用函数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 Pointer Class

    您可以将其复制/粘贴到您的开发站点,并访问;仪表板“;页它将引导你完成整个旅行。

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

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

    享受!!:)

    结束