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_script
untuk meneruskan data ke javascript.
Rencana:
- 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
- Dalam pointer konfigurasi menambahkan properti "di mana" yang akan digunakan untuk set di mana halaman admin popup akan muncul:
post-new.php
, index.php
...
- Tulis kelas yang akan menangani pemuatan, penguraian dan pemfilteran info pointer
- 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.php
dan 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 where
properti.
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.
add_action( 'admin_enqueue_scripts', function( $page ) {
kembali jika pengguna tidak memiliki peran yang diperlukan.public function filter( $page ) {
diPointersManager
kelas, dan segera setelah baris diletakkandie($page);
. Buka browser Anda dan rekatkan kembali url, halaman tersebut akan mati dengan string: itulah yang harus Anda gunakan'where'
.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
admin_enqueue_scripts
.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:
Oke .. mari kita lihat beberapa hal di sini.
Pertama,
$tour
array 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.
$tour
kunci array harus unik (quick_press, SITE_TITLE, quick_press_last, seperti contoh di atas).function
perintah 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.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 function
item yang sama persis seperti yang digunakan dalam$tour
array kami di atas. Ingat, argumen kedua dariget_admin_url()
fungsi HARUS sama persis dengan kunci array dalam$tour
variabel. 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.
Ingat, ada dua argumen; halaman admin kita akan .. dan tab. Tab akan menjadi
$tour
kunci 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.
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_pointers
opsi 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!! :)
sumber