Last active
January 13, 2017 19:06
-
-
Save gmazzap/5e3ddad68e5e3a02f45f to your computer and use it in GitHub Desktop.
Pointers Tour (WPSE 162794)
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
<?php namespace GM; | |
/** | |
* Plugin Name: Pointers Tour (WPSE 162794) | |
* Description: A plugin to create an help tour using WP pointer jQuery plugin | |
* Plugin URI: http://wordpress.stackexchange.com/questions/162794/ | |
* Author: Giuseppe Mazzapica | |
* Author URI: https://gm.zoomlab.it | |
* License: GPLv3 | |
* Version: 1.0.0 | |
* | |
*/ | |
/* | |
Copyright (C) 2014 Giuseppe Mazzapica | |
This program is free software: you can redistribute it and/or modify | |
it under the terms of the GNU General Public License as published by | |
the Free Software Foundation, either version 3 of the License, or | |
(at your option) any later version. | |
This program is distributed in the hope that it will be useful, | |
but WITHOUT ANY WARRANTY; without even the implied warranty of | |
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | |
GNU General Public License for more details. | |
You should have received a copy of the GNU General Public License | |
along with this program. If not, see <http://www.gnu.org/licenses/>. | |
*/ | |
require_once plugin_dir_path( __FILE__ ) . 'PointersManagerInterface.php'; | |
require_once plugin_dir_path( __FILE__ ) . 'PointersManager.php'; | |
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 ); | |
} ); |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
( 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 object 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 a anchor of a given pointer object 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` |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
<?php | |
$pointers = array(); | |
// index.php pointers | |
$pointers['pointer1'] = array( | |
'title' => sprintf( '<h3>%s</h3>', esc_html__( '1Add 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' ) // <-- Please note this | |
); | |
$pointers['pointer2'] = array( | |
'title' => sprintf( '<h3>%s</h3>', esc_html__( '2Another info' ) ), | |
'content' => sprintf( '<p>%s</p>', esc_html__( 'Lore ipsum....' ) ), | |
'anchor_id' => '#dashboard_primary', | |
'edge' => 'top', | |
'align' => 'right', | |
'where' => array( 'index.php' ) // <-- Please note this | |
); | |
$pointers['pointer3'] = array( | |
'title' => sprintf( '<h3>%s</h3>', esc_html__( '3Another info' ) ), | |
'content' => sprintf( '<p>%s</p>', esc_html__( 'Lore ipsum....' ) ), | |
'anchor_id' => '#wp-admin-bar-new-content', | |
'edge' => 'top', | |
'align' => 'right', | |
'where' => array( 'index.php' ) // <-- Please note this | |
); | |
$pointers['pointer4'] = array( | |
'title' => sprintf( '<h3>%s</h3>', esc_html__( '4Another info' ) ), | |
'content' => sprintf( '<p>%s</p>', esc_html__( 'Lore ipsum....' ) ), | |
'anchor_id' => '#dashboard_primary', | |
'edge' => 'top', | |
'align' => 'right', | |
'where' => array( 'index.php' ) // <-- Please note this | |
); | |
$pointers['pointer5'] = array( | |
'title' => sprintf( '<h3>%s</h3>', esc_html__( '5Another info' ) ), | |
'content' => sprintf( '<p>%s</p>', esc_html__( 'Lore ipsum....' ) ), | |
'anchor_id' => '#comment-55', | |
'edge' => 'top', | |
'align' => 'right', | |
'where' => array( 'index.php' ) // <-- Please note this | |
); | |
// post-new.php pointers | |
$pointers['art_pointer1'] = array( | |
'title' => sprintf( '<h3>%s</h3>', esc_html__( '1Add New Item' ) ), | |
'content' => sprintf( '<p>%s</p>', esc_html__( 'Easily add a new post..' ) ), | |
'anchor_id' => '#title', | |
'edge' => 'top', | |
'align' => 'left', | |
'where' => array( 'post-new.php', 'post.php' ) // <-- Please note this | |
); | |
$pointers['art_pointer2'] = array( | |
'title' => sprintf( '<h3>%s</h3>', esc_html__( '2Another info' ) ), | |
'content' => sprintf( '<p>%s</p>', esc_html__( 'Lore ipsum....' ) ), | |
'anchor_id' => '#set-post-thumbnail', | |
'edge' => 'top', | |
'align' => 'right', | |
'where' => array( 'post-new.php', 'post.php' ) // <-- Please note this | |
); | |
$pointers['art_pointer3'] = array( | |
'title' => sprintf( '<h3>%s</h3>', esc_html__( '3Another info' ) ), | |
'content' => sprintf( '<p>%s</p>', esc_html__( 'Lore ipsum....' ) ), | |
'anchor_id' => '#assistant_editor_box', | |
'edge' => 'top', | |
'align' => 'right', | |
'where' => array( 'post-new.php', 'post.php' ) // <-- Please note this | |
); | |
$pointers['art_pointer4'] = array( | |
'title' => sprintf( '<h3>%s</h3>', esc_html__( '4Another info' ) ), | |
'content' => sprintf( '<p>%s</p>', esc_html__( 'Lore ipsum....' ) ), | |
'anchor_id' => '#postcustom', | |
'edge' => 'top', | |
'align' => 'right', | |
'where' => array( 'post-new.php', 'post.php' ) // <-- Please note this | |
); | |
$pointers['art_pointer5'] = array( | |
'title' => sprintf( '<h3>%s</h3>', esc_html__( '5Another info' ) ), | |
'content' => sprintf( '<p>%s</p>', esc_html__( 'Lore ipsum....' ) ), | |
'anchor_id' => '#post-preview', | |
'edge' => 'top', | |
'align' => 'right', | |
'where' => array( 'post-new.php', 'post.php' ) // <-- Please note this | |
); | |
return $pointers; |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
<?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; | |
} | |
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
<?php namespace GM; | |
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 ); | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment