Gezinme için sonraki düğmeyi kullanarak yönetici işaretçisi olan kullanıcılar için WP eğitimi oluşturun


9

Yönetici alanı için kullanıcılarım hakkında bir eğitim oluşturmayı hedefliyorum. Bunu başarmak için, WP çekirdeğinde bulunan yönetici işaretçileri kullanıyorum. Amacım:

resim açıklamasını buraya girin

Neredeyse geldim. Şimdiye kadar ne aldım ...

Wp-pointer komut dosyalarını 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' );
    }
}

Koşullu kontrol ve altbilgi komut dosyası dahil yardımcı işlevler:

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
}

Şimdi işaretçiler dizisini bir araya getirmeye hazırız:

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

}

Kod açıklayıcıdır. Diziyi genişleterek kolayca daha fazla işaretçi ekleyebiliriz. WP4'te her şey iyi çalışıyor.

Şimdi sorun: Tüm pop-up işaretçiler aynı anda görünür, bu da bir eğitim için kötü bir arayüz yapar.

Amacım, işaretçileri tek tek göstermek ve kullanıcının öğretici içinde gezinmek için bir İleri düğmesine tıklamasına izin vermektir . Bir sonraki düğme bir sonraki işaretçiyi açmalı ve sonuncuyu kapatmalıdır.

Bunu nasıl yapabilirim?

Yanıtlar:


10

.pointer( 'open' );Tüm işaretçiler nesnelerinde javascript işlevini çağırıyorsunuz , bu yüzden tüm işaretçilerin aynı anda görünmesi sürpriz değil ...

Bununla birlikte, neden tüm işaretçileri (etkin olmayanlar bile) döndürdüğünüzü anlamıyorum custom_admin_pointers()ve sonra bazı aktif işaretçiler olup olmadığını kontrol etmek için ek bir işlev ve if ( $array['active'] ) {javascript işaretçisi eklemeyi seçmek için bir işaretçi döngüsü ( ) içinde kontrol edin. ya da değil. Daha basit olan sadece aktif işaretçiler döndürmek değil midir?

Ayrıca, javascript'i tüm yönetici sayfalarına ekliyorsunuz, fazla değil mi? Ayrıca, "# save-post" gibi bazı öğelerin yalnızca yeni gönderi sayfasında kullanılabildiğini, bu nedenle işaretçileri yalnızca yeni pot sayfasına eklemek daha iyi olmaz mı?

Son olarak, bu javascript PHP ile karıştırılmış ne kadar dağınık, bence wp_localize_scriptjavascript veri geçirmek için kullanmayı düşünmelisiniz .

Plan:

  1. PHP'deki işaretçi tanımlarını ayrı bir dosyaya taşıyın, bu şekilde düzenlemek ve PHP kodundan işaretlemeyi kaldırmak kolaydır, her şey daha okunabilir ve bakım yapılabilir
  2. İşaretçiler olarak bir pop-up görünmesi gereken yönetici sayfası sete kullanılacak "" bir özellik eklemek yapılandırma: post-new.php, index.php...
  3. İşaretçi bilgilerinin yüklenmesi, ayrıştırılması ve filtrelenmesini işleyecek bir sınıf yazın
  4. Varsayılan "Kaldır" düğmesini "İleri" olarak değiştirmemize yardımcı olacak bazı js iyiliklerini yazın

4. kutu (muhtemelen) eklentisini de işaretçisi bilerek kolaylıkla yapılabilir, ama benim böyle değil. Sonuç almak için genel jQuery kodunu kullanacağım, eğer birisi kodumu geliştirebilirse takdir edeceğim.


Düzenle

Kodu (özellikle js) düzenledim çünkü dikkate almadığım farklı şeyler var: bazı işaretçiler aynı bağlantıya eklenebilir veya mevcut olmayan veya görünmeyen bağlantılara aynı işaretçiler eklenebilir. Tüm bu durumda önceki kod işe yaramadı, yeni sürüm bu sorunları güzel bir şekilde ele alıyor gibi görünüyor.

Ayrıca test etmek için kullandığım tüm kod ile bir Gist kurduk.


1 ve 2 numaralı noktalarla başlayalım : adlı bir dosya oluşturun pointers.phpve buraya yazın:

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

Tüm işaretçiler yapılandırması burada. Bir şeyi değiştirmeniz gerektiğinde, bu dosyayı açın ve düzenleyin.

İşaretçinin kullanılabilir olması gereken sayfa dizisi olan "where" özelliğini not edin.

Eklentinin oluşturduğu bir sayfada işaretçileri görüntülemek istiyorsanız, aşağıda ana hatlarıyla verilen bu satırı arayın public function filter( $page ) {ve die($page);hemen altına ekleyin . Ardından, ilgili eklenti sayfasını açın ve whereözellikte bu dizeyi kullanın .

Tamam, şimdi 3. nokta .

Sınıfı yazmadan önce sadece bir arayüz kodlamak istiyorum: orada sınıfın ne yapacağını daha iyi anlayabilmeniz için yorumlar koyacağım.

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

}

Bence oldukça açık olmalı. Şimdi sınıfı yazalım, arayüz artı yapıcıdan 2 yöntem içerecektir.

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

Kod çok basittir ve arayüzün tam olarak ne beklediğini yapar.

Bununla birlikte, sınıf kendi başına hiçbir şey yapmaz, sınıfın somutlaştırılması ve uygun argümanları geçen 2 yöntemi başlatmak için bir kancaya ihtiyacımız vardır.

'admin_enqueue_scripts'Bizim kapsam için idealdir: orada biz şimdiki yönetici sayfasına erişimi olacak ve biz de enqueue komut dosyaları ve stilleri gerekli olabilir.

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

Özel bir şey yok: sadece işaretçi verilerini almak için sınıfın kullanılması ve bazı işaretçilerin geçmesi durumunda filtreler stilleri ve komut dosyalarını enqueue eder. Ardından, işaretçi verilerini komut dosyasının yerelleştirilmiş "İleri" etiketine iletin.

Tamam, şimdi "en zor" kısım: js. Yine, WordPress'in kullandığı işaretçi eklentisini bilmediğimi vurgulamak istiyorum, bu yüzden kodumda ne yaparsam biri bilirse daha iyi yapılabilir, ancak kodum işini yapar ve -genel olarak konuşur- o kadar da kötü değildir.

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

Yorumların yardımıyla kod en azından açık olmalı, umarım öyle olur.

Tamam bitti. PHP'miz daha basit ve daha iyi organize edilmiştir, javascriptimiz daha okunabilir, işaretçiler daha kolay düzenlenir ve daha da önemlisi her şey işe yarar.


1
@ChristineCooper emin. Tamam, sorunlar betiğin şimdi nasıl çalıştığı için 2: 1'dir, 1 bağlantı kimliği için 1 işaretçi ekleyebilirsiniz: birden fazla işaretçi için aynı bağlantıyı kullanmak komut dosyasının başarısız olmasına neden olur. 2. sorun, bazı işaretçilerin sayfada bulunmayan kimlikleri tutturmasıdır. Örneğin, bir işaretçi index.php içindeki '# comment-55' içindir ve bulunamadı. Post.php dosyasındaki bazı işaretçiler gizli olabilecek meta kutuları hedefler ... vb. Komut dosyasının geçerli sürümünde bir kez bulunmazsa işaretçiler "zincirlenir", sonraki tüm istemler de çalışmaz. Bu sorunların üstesinden gelmenin basit bir yolu olup olmadığını göreceğim.
gmazzap

1
@ChristineCooper Çalıştığına sevindim. Gist'teki tüm kodları buraya kopyalayacağım. Koşul, add_action( 'admin_enqueue_scripts', function( $page ) {kullanıcının gerekli bir rolü yoksa geri döndükten hemen sonra konabilir .
gmazzap

Lütfen satırdaki 30 değerini 120 olarak değiştirin: "scrollTop: $ pointer.offset (). Top - 30" - Bunun nedeni, üst araç çubuğunun kaydırma sırasında zaman zaman işaretçi penceresini kaplamasıdır.
Christine Cooper

Küçük bir sorunum var. Görünmek için bazı işaretçiler gereken sayfa: "admin.php? Page = plugin-path / file.php" - tam olarak nerede dizisine eklerim ? "Admin.php", "plugin-path / file.php", "file.php" ve aklıma gelen herhangi bir varyasyonu denedim. Bu sayfayı algılamamasının bir nedeni var mı yoksa bunu yanlış mı yapıyorum?
Christine Cooper

1
@ChristineCooper eklenti yönetici sayfasını açın ve url'yi tarayıcıdan kopyalayın . Bundan sonra, yukarıdaki kodumu içeren dosyayı açın. Satırı bulun public function filter( $page ) {yılında PointersManagersınıfının ve hemen o hat put sonra die($page);. Tarayıcınızı açın ve URL'yi yapıştırın, sayfa bir dize ile ölür: bu, kullanmanız gereken şeydir 'where'.
gmazzap

7

Ahhh .. evet. WordPress işaretçileri. Bilirsiniz, işaretçiler kullanmaya gelince oldukça karışık duygular var;)

Yukarıdaki kod ile doğru yoldaydınız. Ancak birkaç sorun var.

@GM, pointer('open')tüm işaretçilerinizi bir kerede açan komut konusunda doğrudur . Ayrıca, işaretçiler arasında ilerlemek için bir yöntem sağlamaz.

Aynı meseleyle savaştım .. ve kendi yaklaşımımı buldum. URL'de bir sorgu değişkeni kullanıyorum, sayfayı sonraki işaretçiyi görüntülemek istediğim yönetici sayfasına yeniden yüklüyorum ve jQuery geri kalanını işleyebiliyorum.

WP Pointer Sınıfı

Bunu bir sınıf olarak yazmaya karar verdim. Ama ne olduğunu daha iyi anlamanıza yardımcı olmak için öncelikle artışlarla göstereceğim.

Derse Başlamak

// 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. Sınıfı tanımladık.
  2. Sınıfı inşa ettik ve bir eylem ekledik admin_enqueue_scripts.
  3. İşaretçilerimizin zaten reddedilmiş olup olmadığını belirledik.
  4. Değilse, gerekli komut dosyalarını sıralamaya devam ediyoruz.

Bu ilk işlevlerde hiçbir şeyi değiştirmeniz gerekmez.

İşaretçi Öğeleri dizisini ayarlama

Bir sonraki adım, işaretçilerin her birini tanımlamaktır. Tanımlamamız gereken beş öğe vardır (son işaretçi için öngörülmüştür). Bunu dizileri kullanarak yapacağız. Fonksiyona bir göz atalım:

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

Tamam .. hadi burada birkaç şeye bakalım.

İlk olarak $tourdizimiz. Bu, kullanıcıya görüntülenen ilk işaretçi DIŞINDA tüm işaretçileri tutan dizidir (bu konu hakkında daha fazla bilgi). Yani, göstermek istediğiniz ikinci işaretçiyle başlamak ve son işaretçiye devam etmek istersiniz.

Sonra, çok önemli birkaç öğemiz var.

  1. $tourDizi anahtarları benzersiz (yukarıda örnek olarak quick_press_last quick_press, SITE_TITLE) olması gerekir.
  2. 'İd' komutu, işaretçiye eklemek istediğiniz öğenin html öğesi kimliğiyle eşleşmelidir ZORUNLU.
  3. functionKomut / yeniden penceresini taşımak olacaktır. Bir sonraki işaretçiyi göstermek için kullanılan budur. Pencereyi yeniden yüklememiz veya bir işaretçinin görüntüleneceği bir sonraki yönetici sayfasına taşımamız gerekir.
  4. get_admin_url()İşlevi iki değişkenle çalıştırıyoruz ; birincisi, bir sonraki gitmek istediğimiz yönetici sayfası; ikincisi, görüntülemek istediğimiz işaretçinin benzersiz dizi anahtarıdır.

Daha aşağıda, başlayan kodu göreceksiniz if (!array_key_exists($tab, $tour)) {. Bu, bir url sorgu değişkeninin ayarlanıp ayarlanmadığını belirlediğimiz yerdir. NOT değilse, görüntülenecek ilk işaretçiyi tanımlamamız gerekir.

Bu işaretçi yukarıdaki dizimizde id, content, button2, and functionkullanılanlarla aynı öğeleri kullanır $tour. Unutmayın, get_admin_url()işlevin ikinci argümanı değişkenteki dizi anahtarıyla tamamen aynı olmalıdır ZORUNLU $tour. Komut dosyasına bir sonraki işaretçiye gitmesini söyleyen budur.

Url'de zaten bir sorgu değişkeni ayarlanmışsa işlevin geri kalanı kullanılır. Fonksiyonun daha fazla ayarlanmasına gerek yoktur.

Yönetici URL'sini Alma Sonraki işlev aslında bir yönetici işlevidir ... yönetici URL'sini almak ve işaretçiyi ilerletmek için kullanılır.

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

Unutmayın, iki argüman var; Yönetici sayfasına gidiyoruz .. ve sekmesini. Sekme, bir $toursonrakine geçmek istediğimiz dizi anahtarı olacaktır . Bunlar eşleşmelidir .

Yani, fonksiyonu çağırıp get_admin_url()iki değişkeni ilettiğimizde; ilk değişken bir sonraki yönetici sayfasını belirler ve ikinci değişken hangi göstergenin gösterileceğini belirler.

Son olarak ... sonunda yönetici komut dosyasını altbilgiye yazdırabiliriz.

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

Yine, yukarıdaki hiçbir şeyi değiştirmeye gerek yoktur. Bu komut dosyası, işaretçi yer paylaşımı penceresindeki iki düğmeyi tanımlar ve çıktılar. Biri her zaman "Kapat" düğmesi olacaktır; mevcut kullanıcı meta dismissed_pointersseçeneğini güncelleyecektir .

İkinci düğme (eylem düğmesi) işlevi yürütür (pencere yer değiştirme yöntemimiz).

Ve sınıfı kapatıyoruz.

İşte kodun tamamı. WP Pointer Sınıfı

Bunu geliştirici sitenize kopyalayıp yapıştırabilir ve "Gösterge Tablosu" sayfasını ziyaret edebilirsiniz. Size tur boyunca rehberlik edecektir.

Unutmayın, ilk işaretçinin kodda son olarak tanımlanması biraz kafa karıştırıcıdır. Bu şekilde çalışması gerekiyordu. Dizi, kullanmak istediğiniz tüm işaretçileri içerecektir.

Unutmayın, 'id' dizi öğesi get_admin_url()önceki dizi öğesi 'function' komutundan işlevin ikinci argümanıyla eşleşmelidir ZORUNLU . İşaretçiler birbirleriyle böyle konuşur ve nasıl ilerleyeceklerini bilirler.

Zevk almak!! :)


Bu çok güzel Josh, çok teşekkür ederim! Bunu deneyeceğim ve ne kadar iyi çalıştığını göreceğim. Ben GM kodunu büyük olasılıkla bu lütuf ödeyecek kod olduğunu vurgulamak gerekir çünkü ben istediğim ve özellikle wp-admin birden fazla sayfa için bir rehber oluşturmak için önemli olduğuna inanıyorum birkaç temel özellikleri vardır. Bununla birlikte, bu konuda başka bir yaklaşım görmek harika ve iyi bir çözüm arayan diğer kullanıcılar için kullanışlı olacaktır. Meraktan, işaretçiler kullanmaya gelince çok fazla karışık duygu olduğunu söylediniz , özen göstermeye özen gösterdiniz mi?
Christine Cooper

2
Endişeye gerek yok :) Eh, işaretçiler aşırı kullanıldığında 'yol alabilir'. Hiç kimse bir sayfayı ziyaret etmek istemez ve üç veya dört işaretçi görüntülenir ... özellikle ilgisizse. Diyelim ki diğer iki eklenti işaretçiler gösteriyor, o zaman daha fazla işaretçi ekliyoruz .. aşırıya kaçabilir. Çoğu insan onları azıcık kullanmayı söylüyor ... ama her biri kendi :) :) Düzgün çalıştığına sevindim.
josh

1
Bu da harika Josh, ben bu daha esnek hale getirmek için 1 öneri yapmak ve sadece sınıf kodu kendisi içinde depolamak yerine, bir dizi genel işlev içine dizi geçebilir var. İkincisi, ilk işaretçi, nasıl ayrı olduğu, işaretçi dizisindeki ilk dizi anahtarı / değeri olabilecek şekilde değiştirin. Sadece birkaç fikir böylece bu sınıf başka bir komut dosyasından çağrılabilir ve sadece işaretçi dizisinde geçti. Hala çok beğendim, paylaştığınız için teşekkürler bunu kullanacağım!
14:13, JasonDavis

Teşekkürler @jasondavis. Aslında bu kodu birisi için geliştirdiğim başka bir eklentiden aldım. Sadece düzgün çalışmasını sağlamakla ilgileniyordum. Ama evet, sana kesinlikle katılıyorum ... temizlenmesi gerekiyor. Belki bugün daha sonra uğrayıp tekrar karışıklığa uğratacağım :) Sen sallan kardeşim!
Josh

Çok iyi, aslında Yönetici İşaretçileri kullanmak gibi bir niyetim olmadı, çünkü kabus ve 2'ye benziyorlardı çünkü onlar için gerçek bir kullanımım yok, ancak sınıfınız onları artık çok kolay görüyor onları bu sınıfla çok kolay olacak şekilde kullanmak zorundasınız! Böyle küçük projeleri / kütüphaneleri seviyorum, iyi şeyler
JasonDavis
Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.