Buat tutorial WP untuk pengguna dengan pointer admin menggunakan tombol berikutnya untuk navigasi

9

Saya bertujuan untuk membuat tutorial tentang pengguna saya untuk area admin. Untuk mencapai ini, saya menggunakan pointer admin yang tersedia di WP core. Tujuanku:

masukkan deskripsi gambar di sini

Saya hampir sampai. Apa yang saya dapatkan sejauh ini ...

Script wp-pointer enqueue:

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' );
    }
}

Fungsi pembantu, termasuk pemeriksaan bersyarat dan skrip catatan kaki:

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
}

Sekarang kita siap untuk mengumpulkan array pointer:

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 ) )
        )
    );

}

Kode ini jelas. Kita dapat dengan mudah menambahkan lebih banyak pointer dengan memperluas array. Semuanya berfungsi dengan baik di WP4.

Sekarang masalahnya: Semua pointer popup muncul pada saat yang sama, menjadikannya antarmuka yang buruk untuk tutorial.

Tujuan saya adalah untuk menunjukkan pointer satu per satu, dan memungkinkan pengguna mengklik tombol Next untuk menavigasi tutorial. Tombol selanjutnya harus membuka pointer berikutnya dan menutup yang terakhir.

Bagaimana saya bisa melakukan ini?

Christine Cooper
sumber

Jawaban:

10

Anda memanggil .pointer( 'open' );fungsi javascript pada semua objek pointer, jadi tidak mengherankan bahwa semua pointer muncul pada waktu yang sama ...

Yang mengatakan, saya tidak mengerti mengapa Anda mengembalikan semua pointer (bahkan yang tidak aktif) dari custom_admin_pointers()dan kemudian menambahkan fungsi tambahan untuk memeriksa apakah ada beberapa pointer aktif dan cek di dalam pointer pointer ( if ( $array['active'] ) {) untuk memilih untuk menambahkan pointer javascript atau tidak. Bukankah lebih sederhana hanya mengembalikan pointer aktif saja?

Apalagi Anda menambahkan javascript itu di semua halaman admin, tidak terlalu banyak? Juga pertimbangkan bahwa beberapa elemen seperti "# save-post" hanya tersedia di halaman posting baru, jadi bukankah lebih baik menambahkan pointer hanya di halaman pot baru?

Akhirnya, betapa berantakannya javascript yang dicampur dengan PHP, saya pikir Anda harus mempertimbangkan untuk menggunakan wp_localize_scriptuntuk meneruskan data ke javascript.

Rencana:

  1. Pindahkan definisi pointer dalam PHP ke file terpisah, dengan cara ini mudah diedit dan juga menghapus markup dari kode PHP, semuanya menghasilkan lebih mudah dibaca dan dikelola
  2. Dalam pointer konfigurasi menambahkan properti "di mana" yang akan digunakan untuk set di mana halaman admin popup akan muncul: post-new.php, index.php...
  3. Tulis kelas yang akan menangani pemuatan, penguraian dan pemfilteran info pointer
  4. Tulis beberapa kebaikan yang akan membantu kita mengubah tombol "Hapus" menjadi "Selanjutnya"

The # 4 kaleng (mungkin) dilakukan dengan mudah mengetahui pointer Plugin baik, tapi itu bukan kasus saya. Jadi saya akan menggunakan kode jQuery umum untuk mendapatkan hasilnya, jika seseorang dapat meningkatkan kode saya, saya akan menghargai.


Edit

Saya mengedit kode (terutama js) karena ada beberapa hal yang tidak saya pertimbangkan: beberapa pointer dapat ditambahkan ke anchor yang sama, atau pointer yang sama dapat ditambahkan ke anchor yang tidak ada atau tidak terlihat. Dalam semua kasus kode sebelumnya tidak berfungsi, versi baru tampaknya mengatasi masalah itu dengan baik.

Saya juga menyiapkan Gist dengan semua kode yang saya uji.


Mari kita mulai dengan poin # 1 dan # 2 : buat file bernama pointers.phpdan tulis di sana:

<?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; 

Semua konfigurasi pointer ada di sini. Ketika Anda perlu mengubah sesuatu, cukup buka file ini dan edit.

Perhatikan properti "di mana" yang merupakan array halaman tempat penunjuk harus tersedia.

Jika Anda ingin menampilkan pointer di halaman yang dihasilkan oleh plugin, cari baris yang diuraikan di bawah ini public function filter( $page ) {dan tambahkan die($page);segera di bawahnya. Kemudian buka halaman plugin masing-masing dan gunakan string itu di whereproperti.

Ok, sekarang poin # 3 .

Sebelum menulis kelas saya hanya ingin kode antarmuka: di sana saya akan memberikan komentar sehingga Anda dapat lebih memahami apa yang akan dilakukan kelas.

<?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 );

}

Saya pikir harus cukup jelas. Sekarang mari kita menulis kelas, itu akan berisi 2 metode dari antarmuka plus konstruktor.

<?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;
  }
}

Kode sangat sederhana, dan melakukan apa yang diharapkan antarmuka.

Namun, kelas tidak melakukan apa-apa dengan sendirinya, kita memerlukan sebuah kait di mana untuk instantiate kelas dan meluncurkan 2 metode yang melewati argumen yang tepat.

Ini 'admin_enqueue_scripts'sempurna untuk ruang lingkup kami: di sana kami akan memiliki akses ke halaman admin saat ini dan kami juga dapat membuat skrip dan gaya yang diperlukan.

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 );
} );

Tidak ada yang istimewa: hanya menggunakan kelas untuk mendapatkan data petunjuk dan jika beberapa petunjuk lulus filter gaya enqueue dan skrip. Lalu, lewati data pointer ke skrip ke label "Next" yang dilokalkan untuk tombol.

Ok, sekarang bagian "paling sulit": js. Sekali lagi saya ingin menyoroti bahwa saya tidak tahu menggunakan plugin pointer WordPress, jadi apa yang saya lakukan dalam kode saya dapat dilakukan lebih baik jika seseorang mengetahuinya, namun kode saya melakukan pekerjaannya dan - secara umum - itu tidak terlalu buruk.

( 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`

Dengan bantuan komentar kode harus cukup jelas, setidaknya, saya harap begitu.

Ok kita sudah selesai. PHP kami lebih sederhana dan lebih terorganisir, javascript kami lebih mudah dibaca, pointer lebih mudah diedit dan, yang lebih penting, semuanya berfungsi.

gmazzap
sumber
1
@ChristineCooper yakin. Oke, masalahnya 2: 1 untuk cara skrip bekerja sekarang, Anda dapat menambahkan 1 pointer untuk 1 anchor id: menggunakan anchor yang sama untuk lebih dari satu pointer akan menyebabkan skrip gagal. Masalah kedua adalah bahwa beberapa petunjuk menggunakan jangkar untuk id yang mungkin tidak ada di halaman. Misalnya satu pointer untuk '# comment-55' di index.php, dan itu tidak ditemukan. Beberapa petunjuk di metabox target post.php yang mungkin disembunyikan ... dan seterusnya. Setelah dalam versi saat ini, pointer skrip "dirantai" jika tidak ditemukan semua selanjutnya tidak akan berfungsi juga. Saya akan melihat apakah ada cara sederhana untuk mengatasi masalah tersebut.
gmazzap
1
@ChristineCooper Senang itu berhasil. Saya akan menyalin semua kode dari Gist kembali ke sini. Kondisi dapat dimasukkan hanya setelah add_action( 'admin_enqueue_scripts', function( $page ) {kembali jika pengguna tidak memiliki peran yang diperlukan.
gmazzap
Silakan ubah nilai 30 menjadi 120 pada baris: "scrollTop: $ pointer.offset (). Top - 30" - Alasannya adalah karena bilah alat atas menutup jendela penunjuk sesekali saat menggulir.
Christine Cooper
Saya punya satu masalah kecil. Halaman yang perlu saya tampilkan adalah: "admin.php? Page = plugin-path / file.php" - apa sebenarnya yang saya tambahkan ke array tempat ? Saya mencoba "admin.php", "plugin-path / file.php", "file.php" dan variasi apa pun yang dapat saya pikirkan. Apakah ada alasan mengapa ia tidak dapat mendeteksi halaman ini atau saya melakukan kesalahan ini?
Christine Cooper
1
@ChristineCooper buka halaman admin plugin dan salin url dari browser . Setelah itu, buka file yang berisi kode saya di atas. Temukan baris public function filter( $page ) {di PointersManagerkelas, dan segera setelah baris diletakkan die($page);. Buka browser Anda dan rekatkan kembali url, halaman tersebut akan mati dengan string: itulah yang harus Anda gunakan 'where'.
gmazzap
7

Ahhh .. ya. Pointer WordPress. Anda tahu, ada cukup banyak perasaan campur aduk ketika menggunakan pointer;)

Anda berada di jalur yang benar dengan kode Anda di atas. Tetapi ada beberapa masalah.

@ GM benar tentang pointer('open')perintah membuka semua petunjuk Anda sekaligus. Selain itu, Anda tidak menyediakan metode untuk maju melalui petunjuk.

Saya melawan masalah yang sama ini .. dan muncul dengan pendekatan saya sendiri. Saya menggunakan variabel kueri di url, memuat ulang halaman ke halaman admin tempat saya ingin menampilkan pointer berikutnya, dan biarkan jQuery menangani sisanya.

WP Pointer Kelas

Saya memutuskan untuk menulis ini sebagai kelas. Tetapi saya akan menunjukkannya secara bertahap pada awalnya untuk membantu Anda lebih memahami apa yang terjadi.

Memulai Kelas

// 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. Kami telah mendefinisikan kelas.
  2. Kami membangun kelas, dan menambahkan tindakan ke admin_enqueue_scripts.
  3. Kami memutuskan apakah petunjuk kami telah diberhentikan.
  4. Jika tidak, kami terus membuat skrip yang diperlukan.

Anda TIDAK perlu mengubah apa pun di fungsi pertama ini.

Menyiapkan array Item Pointer

Langkah selanjutnya adalah mendefinisikan masing-masing pointer. Ada lima item yang perlu kita definisikan (kecuali untuk pointer terakhir). Kami akan melakukan ini menggunakan array. Mari kita lihat fungsinya:

// 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);
    }
}

Oke .. mari kita lihat beberapa hal di sini.

Pertama, $tourarray kami . Ini adalah array yang menampung semua pointer KECUALI pointer pertama yang ditampilkan kepada pengguna (lebih lanjut tentang ini nanti). Jadi, Anda ingin memulai dengan pointer kedua yang ingin Anda tampilkan .. dan lanjutkan ke pointer terakhir.

Selanjutnya, kami memiliki beberapa item yang sangat penting.

  1. The $tourkunci array harus unik (quick_press, SITE_TITLE, quick_press_last, seperti contoh di atas).
  2. Perintah 'id' HARUS cocok dengan id elemen html dari item yang ingin Anda lampirkan pada pointer.
  3. The functionperintah akan reload / pindah jendela. Inilah yang digunakan untuk menunjukkan pointer berikutnya. Kami harus memuat ulang jendela, atau memindahkannya ke halaman admin berikutnya tempat penunjuk akan ditampilkan.
  4. Kami menjalankan get_admin_url()fungsi dengan dua variabel; yang pertama adalah halaman admin tempat kami ingin pergi berikutnya; dan yang kedua adalah kunci array unik dari pointer yang ingin kami tampilkan.

Lebih jauh ke bawah, Anda akan melihat kode yang dimulai if (!array_key_exists($tab, $tour)) {. Di sinilah kami menentukan apakah variabel kueri url telah ditetapkan. Jika TIDAK, maka kita perlu menentukan pointer pertama untuk ditampilkan.

Pointer ini menggunakan id, content, button2, and functionitem yang sama persis seperti yang digunakan dalam $tourarray kami di atas. Ingat, argumen kedua dari get_admin_url()fungsi HARUS sama persis dengan kunci array dalam $tourvariabel. Inilah yang memberitahu skrip untuk pergi ke pointer berikutnya.

Sisa fungsi digunakan jika variabel kueri sudah disetel di url. Tidak perlu lagi menyesuaikan fungsi.

Mendapatkan Url Admin Fungsi selanjutnya sebenarnya adalah fungsi pembantu ... digunakan untuk mendapatkan url admin dan memajukan pointer.

// 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;
}

Ingat, ada dua argumen; halaman admin kita akan .. dan tab. Tab akan menjadi $tourkunci larik yang ingin kita tuju selanjutnya. INI HARUS MATCH .

Jadi, ketika kita memanggil fungsi get_admin_url()dan melewatkan dua variabel; variabel pertama menentukan halaman admin berikutnya .. dan variabel kedua menentukan penunjuk mana yang akan ditampilkan.

Terakhir ... kita akhirnya dapat mencetak skrip admin ke footer.

// 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();

Sekali lagi, tidak perlu mengubah apa pun di atas. Script ini akan mendefinisikan dan mengeluarkan dua tombol di jendela overlay pointer. Satu akan selalu menjadi tombol "Tutup"; dan akan memperbarui dismissed_pointersopsi meta pengguna saat ini .

Tombol kedua (tombol aksi) akan menjalankan fungsi (metode relokasi jendela kami).

Dan kami menutup kelas.

Ini adalah kode keseluruhannya. WP Pointer Class

Anda dapat menyalin / menempelkannya ke situs pengembang Anda dan mengunjungi halaman "Dasbor". Ini akan memandu Anda melalui tur.

Ingat, agak membingungkan bahwa pointer pertama didefinisikan terakhir dalam kode. Begitulah seharusnya bekerja. Array akan menampung semua pointer yang ingin Anda gunakan.

Ingat, item array 'id' HARUS cocok dengan argumen kedua get_admin_url()fungsi dari perintah 'fungsi' item array sebelumnya. Ini adalah bagaimana pointer 'berbicara' satu sama lain dan tahu bagaimana untuk maju.

Nikmati!! :)

wah
sumber
Ini Josh yang indah, terima kasih banyak! Saya akan mencoba ini dan melihat seberapa baik fungsinya. Saya harus menyoroti bahwa kode GM adalah kode yang kemungkinan besar akan saya berikan hadiah ini karena memiliki beberapa fitur penting yang saya minta dan yang saya yakini penting untuk membuat panduan, terutama untuk banyak halaman di wp-admin. Meskipun demikian, itu bagus untuk melihat pendekatan lain dalam hal ini dan akan berguna bagi pengguna lain yang mencari solusi yang baik. Karena penasaran, Anda mengatakan ada cukup banyak perasaan campur aduk ketika menggunakan pointer , peduli untuk menguraikan?
Christine Cooper
2
Jangan khawatir :) Yah, pointer bisa 'menghalangi' saat digunakan secara berlebihan. Tidak ada yang ingin mengunjungi halaman dan memiliki tampilan tiga atau empat petunjuk ... terutama jika mereka tidak terkait. Katakanlah dua plugin lain menunjukkan pointer, lalu kita tambahkan lebih banyak pointer .. itu bisa menjadi berlebihan. Kebanyakan orang mengatakan untuk menggunakannya dengan hemat ... tetapi untuk masing-masing adalah milik mereka sendiri :) Senang Anda membuatnya berfungsi dengan baik.
Astaga
1
Josh ini juga luar biasa, saya akan membuat 1 saran, untuk membuatnya lebih fleksibel dan memilikinya di mana Anda bisa meneruskan array ke fungsi publik alih-alih menyimpannya di dalam kode kelas itu sendiri. Kedua, pointer pertama, bagaimana itu terpisah, modifikasi sehingga bisa menjadi kunci / nilai array pertama dalam array pointer. Hanya beberapa ide sehingga kelas ini bisa dipanggil dari skrip lain dan cukup diteruskan dalam array pointer. Saya masih sangat menyukainya, terima kasih sudah berbagi saya akan menggunakan ini!
JasonDavis
Terima kasih @ jasondavis. Saya benar-benar menarik kode itu dari plugin lain yang saya kembangkan untuk seseorang. Saya hanya tertarik untuk membuatnya berfungsi dengan baik. Tapi ya, saya sangat setuju dengan Anda ... itu perlu dibersihkan. Mungkin saya akan mampir hari ini dan mengacaukannya lagi :) Anda cewek, bro!
Astaga
Keren; sebenarnya saya tidak pernah punya niat menggunakan Pointer Admin, terutama karena mereka tampak seperti mimpi buruk dan ke-2 karena saya tidak punya kegunaan nyata untuk mereka, tetapi kelas Anda membuatnya terlihat sangat mudah digunakan sekarang sehingga saya merasa saya harus menggunakannya dengan begitu mudah dengan kelas itu! Saya suka proyek kecil / perpustakaan seperti itu, bagus
JasonDavis