Guest User

Untitled

a guest
Jan 18th, 2019
102
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
text 20.20 KB | None | 0 0
  1. add_action( 'admin_enqueue_scripts', 'custom_admin_pointers_header' );
  2.  
  3. function custom_admin_pointers_header() {
  4. if ( custom_admin_pointers_check() ) {
  5. add_action( 'admin_print_footer_scripts', 'custom_admin_pointers_footer' );
  6.  
  7. wp_enqueue_script( 'wp-pointer' );
  8. wp_enqueue_style( 'wp-pointer' );
  9. }
  10. }
  11.  
  12. function custom_admin_pointers_check() {
  13. $admin_pointers = custom_admin_pointers();
  14. foreach ( $admin_pointers as $pointer => $array ) {
  15. if ( $array['active'] )
  16. return true;
  17. }
  18. }
  19.  
  20. function custom_admin_pointers_footer() {
  21. $admin_pointers = custom_admin_pointers();
  22. ?>
  23. <script type="text/javascript">
  24. /* <![CDATA[ */
  25. ( function($) {
  26. <?php
  27. foreach ( $admin_pointers as $pointer => $array ) {
  28. if ( $array['active'] ) {
  29. ?>
  30. $( '<?php echo $array['anchor_id']; ?>' ).pointer( {
  31. content: '<?php echo $array['content']; ?>',
  32. position: {
  33. edge: '<?php echo $array['edge']; ?>',
  34. align: '<?php echo $array['align']; ?>'
  35. },
  36. close: function() {
  37. $.post( ajaxurl, {
  38. pointer: '<?php echo $pointer; ?>',
  39. action: 'dismiss-wp-pointer'
  40. } );
  41. }
  42. } ).pointer( 'open' );
  43. <?php
  44. }
  45. }
  46. ?>
  47. } )(jQuery);
  48. /* ]]> */
  49. </script>
  50. <?php
  51. }
  52.  
  53. function custom_admin_pointers() {
  54. $dismissed = explode( ',', (string) get_user_meta( get_current_user_id(), 'dismissed_wp_pointers', true ) );
  55. $version = '1_0'; // replace all periods in 1.0 with an underscore
  56. $prefix = 'custom_admin_pointers' . $version . '_';
  57.  
  58. $new_pointer_content = '<h3>' . __( 'Add New Item' ) . '</h3>';
  59. $new_pointer_content .= '<p>' . __( 'Easily add a new post, media item, link, page or user by selecting from this drop down menu.' ) . '</p>';
  60.  
  61. $story_pointer_content = '<h3>' . __( 'Another info' ) . '</h3>';
  62. $story_pointer_content .= '<p>' . __( 'Lorem ipsum...' ) . '</p>';
  63.  
  64.  
  65. return array(
  66. $prefix . 'new_items' => array(
  67. 'content' => $new_pointer_content,
  68. 'anchor_id' => '#wp-admin-bar-new-content',
  69. 'edge' => 'top',
  70. 'align' => 'left',
  71. 'active' => ( ! in_array( $prefix . 'new_items', $dismissed ) )
  72. ),
  73. $prefix.'story_cover_help' => array(
  74. 'content' => $story_pointer_content,
  75. 'anchor_id' => '#save-post',
  76. 'edge' => 'top',
  77. 'align' => 'right',
  78. 'active' => ( ! in_array( $prefix . 'story_cover_help', $dismissed ) )
  79. )
  80. );
  81.  
  82. }
  83.  
  84. <?php
  85. $pointers = array();
  86.  
  87. $pointers['new-items'] = array(
  88. 'title' => sprintf( '<h3>%s</h3>', esc_html__( 'Add New Item' ) ),
  89. 'content' => sprintf( '<p>%s</p>', esc_html__( 'Easily add a new post..' ) ),
  90. 'anchor_id' => '#wp-admin-bar-new-content',
  91. 'edge' => 'top',
  92. 'align' => 'left',
  93. 'where' => array( 'index.php', 'post-new.php' ) // <-- Please note this
  94. );
  95.  
  96. $pointers['story_cover_help'] = array(
  97. 'title' => sprintf( '<h3>%s</h3>', esc_html__( 'Another info' ) ),
  98. 'content' => sprintf( '<p>%s</p>', esc_html__( 'Lore ipsum....' ) ),
  99. 'anchor_id' => '#save-post',
  100. 'edge' => 'top',
  101. 'align' => 'right',
  102. 'where' => array( 'post-new.php' ) // <-- Please note this
  103. );
  104.  
  105. // more pointers here...
  106.  
  107. return $pointers;
  108.  
  109. <?php
  110. interface PointersManagerInterface {
  111.  
  112. /**
  113. * Load pointers from file and setup id with prefix and version.
  114. * Cast pointers to objects.
  115. */
  116. public function parse();
  117.  
  118. /**
  119. * Remove from parse pointers dismissed ones and pointers
  120. * that should not be shown on given page
  121. *
  122. * @param string $page Current admin page file
  123. */
  124. public function filter( $page );
  125.  
  126. }
  127.  
  128. <?php namespace GM;
  129.  
  130. class PointersManager implements PointersManagerInterface {
  131.  
  132. private $pfile;
  133. private $version;
  134. private $prefix;
  135. private $pointers = array();
  136.  
  137. public function __construct( $file, $version, $prefix ) {
  138. $this->pfile = file_exists( $file ) ? $file : FALSE;
  139. $this->version = str_replace( '.', '_', $version );
  140. $this->prefix = $prefix;
  141. }
  142.  
  143. public function parse() {
  144. if ( empty( $this->pfile ) ) return;
  145. $pointers = (array) require_once $this->pfile;
  146. if ( empty($pointers) ) return;
  147. foreach ( $pointers as $i => $pointer ) {
  148. $pointer['id'] = "{$this->prefix}{$this->version}_{$i}";
  149. $this->pointers[$pointer['id']] = (object) $pointer;
  150. }
  151. }
  152.  
  153. public function filter( $page ) {
  154. if ( empty( $this->pointers ) ) return array();
  155. $uid = get_current_user_id();
  156. $no = explode( ',', (string) get_user_meta( $uid, 'dismissed_wp_pointers', TRUE ) );
  157. $active_ids = array_diff( array_keys( $this->pointers ), $no );
  158. $good = array();
  159. foreach( $this->pointers as $i => $pointer ) {
  160. if (
  161. in_array( $i, $active_ids, TRUE ) // is active
  162. && isset( $pointer->where ) // has where
  163. && in_array( $page, (array) $pointer->where, TRUE ) // current page is in where
  164. ) {
  165. $good[] = $pointer;
  166. }
  167. }
  168. $count = count( $good );
  169. if ( $good === 0 ) return array();
  170. foreach( array_values( $good ) as $i => $pointer ) {
  171. $good[$i]->next = $i+1 < $count ? $good[$i+1]->id : '';
  172. }
  173. return $good;
  174. }
  175. }
  176.  
  177. add_action( 'admin_enqueue_scripts', function( $page ) {
  178. $file = plugin_dir_path( __FILE__ ) . 'pointers.php';
  179. // Arguments: pointers php file, version (dots will be replaced), prefix
  180. $manager = new PointersManager( $file, '5.0', 'custom_admin_pointers' );
  181. $manager->parse();
  182. $pointers = $manager->filter( $page );
  183. if ( empty( $pointers ) ) { // nothing to do if no pointers pass the filter
  184. return;
  185. }
  186. wp_enqueue_style( 'wp-pointer' );
  187. $js_url = plugins_url( 'pointers.js', __FILE__ );
  188. wp_enqueue_script( 'custom_admin_pointers', $js_url, array('wp-pointer'), NULL, TRUE );
  189. // data to pass to javascript
  190. $data = array(
  191. 'next_label' => __( 'Next' ),
  192. 'close_label' => __('Close'),
  193. 'pointers' => $pointers
  194. );
  195. wp_localize_script( 'custom_admin_pointers', 'MyAdminPointers', $data );
  196. } );
  197.  
  198. ( function($, MAP) {
  199.  
  200. $(document).on( 'MyAdminPointers.setup_done', function( e, data ) {
  201. e.stopImmediatePropagation();
  202. MAP.setPlugin( data ); // open first popup
  203. } );
  204.  
  205. $(document).on( 'MyAdminPointers.current_ready', function( e ) {
  206. e.stopImmediatePropagation();
  207. MAP.openPointer(); // open a popup
  208. } );
  209.  
  210. MAP.js_pointers = {}; // contain js-parsed pointer objects
  211. MAP.first_pointer = false; // contain first pointer anchor jQuery object
  212. MAP.current_pointer = false; // contain current pointer jQuery object
  213. MAP.last_pointer = false; // contain last pointer jQuery object
  214. MAP.visible_pointers = []; // contain ids of pointers whose anchors are visible
  215.  
  216. MAP.hasNext = function( data ) { // check if a given pointer has valid next property
  217. return typeof data.next === 'string'
  218. && data.next !== ''
  219. && typeof MAP.js_pointers[data.next].data !== 'undefined'
  220. && typeof MAP.js_pointers[data.next].data.id === 'string';
  221. };
  222.  
  223. MAP.isVisible = function( data ) { // check if anchor for given pointer is visible
  224. return $.inArray( data.id, MAP.visible_pointers ) !== -1;
  225. };
  226.  
  227. // given a pointer object, return its the anchor jQuery object if available
  228. // otherwise return first available, lookin at next property of subsequent pointers
  229. MAP.getPointerData = function( data ) {
  230. var $target = $( data.anchor_id );
  231. if ( $.inArray(data.id, MAP.visible_pointers) !== -1 ) {
  232. return { target: $target, data: data };
  233. }
  234. $target = false;
  235. while( MAP.hasNext( data ) && ! MAP.isVisible( data ) ) {
  236. data = MAP.js_pointers[data.next].data;
  237. if ( MAP.isVisible( data ) ) {
  238. $target = $(data.anchor_id);
  239. }
  240. }
  241. return MAP.isVisible( data )
  242. ? { target: $target, data: data }
  243. : { target: false, data: false };
  244. };
  245.  
  246. // take pointer data and setup pointer plugin for anchor element
  247. MAP.setPlugin = function( data ) {
  248. if ( typeof MAP.last_pointer === 'object') {
  249. MAP.last_pointer.pointer('destroy');
  250. MAP.last_pointer = false;
  251. }
  252. MAP.current_pointer = false;
  253. var pointer_data = MAP.getPointerData( data );
  254. if ( ! pointer_data.target || ! pointer_data.data ) {
  255. return;
  256. }
  257. $target = pointer_data.target;
  258. data = pointer_data.data;
  259. $pointer = $target.pointer({
  260. content: data.title + data.content,
  261. position: { edge: data.edge, align: data.align },
  262. close: function() {
  263. // open next pointer if it exists
  264. if ( MAP.hasNext( data ) ) {
  265. MAP.setPlugin( MAP.js_pointers[data.next].data );
  266. }
  267. $.post( ajaxurl, { pointer: data.id, action: 'dismiss-wp-pointer' } );
  268. }
  269. });
  270. MAP.current_pointer = { pointer: $pointer, data: data };
  271. $(document).trigger( 'MyAdminPointers.current_ready' );
  272. };
  273.  
  274. // scroll the page to current pointer then open it
  275. MAP.openPointer = function() {
  276. var $pointer = MAP.current_pointer.pointer;
  277. if ( ! typeof $pointer === 'object' ) {
  278. return;
  279. }
  280. $('html, body').animate({ // scroll page to pointer
  281. scrollTop: $pointer.offset().top - 30
  282. }, 300, function() { // when scroll complete
  283. MAP.last_pointer = $pointer;
  284. var $widget = $pointer.pointer('widget');
  285. MAP.setNext( $widget, MAP.current_pointer.data );
  286. $pointer.pointer( 'open' ); // open
  287. });
  288. };
  289.  
  290. // if there is a next pointer set button label to "Next", to "Close" otherwise
  291. MAP.setNext = function( $widget, data ) {
  292. if ( typeof $widget === 'object' ) {
  293. var $buttons = $widget.find('.wp-pointer-buttons').eq(0);
  294. var $close = $buttons.find('a.close').eq(0);
  295. $button = $close.clone(true, true).removeClass('close');
  296. $buttons.find('a.close').remove();
  297. $button.addClass('button').addClass('button-primary');
  298. has_next = false;
  299. if ( MAP.hasNext( data ) ) {
  300. has_next_data = MAP.getPointerData(MAP.js_pointers[data.next].data);
  301. has_next = has_next_data.target && has_next_data.data;
  302. }
  303. var label = has_next ? MAP.next_label : MAP.close_label;
  304. $button.html(label).appendTo($buttons);
  305. }
  306. };
  307.  
  308. $(MAP.pointers).each(function(index, pointer) { // loop pointers data
  309. if( ! $().pointer ) return; // do nothing if pointer plugin isn't available
  310. MAP.js_pointers[pointer.id] = { data: pointer };
  311. var $target = $(pointer.anchor_id);
  312. if ( $target.length && $target.is(':visible') ) { // anchor exists and is visible?
  313. MAP.visible_pointers.push(pointer.id);
  314. if ( ! MAP.first_pointer ) {
  315. MAP.first_pointer = pointer;
  316. }
  317. }
  318. if ( index === ( MAP.pointers.length - 1 ) && MAP.first_pointer ) {
  319. $(document).trigger( 'MyAdminPointers.setup_done', MAP.first_pointer );
  320. }
  321. });
  322.  
  323. } )(jQuery, MyAdminPointers); // MyAdminPointers is passed by `wp_localize_script`
  324.  
  325. // Create as a class
  326. class testWPpointers {
  327.  
  328. // Define pointer version
  329. const DISPLAY_VERSION = 'v1.0';
  330.  
  331. // Initiate construct
  332. function __construct () {
  333. add_action('admin_enqueue_scripts', array($this, 'admin_enqueue_scripts')); // Hook to admin_enqueue_scripts
  334. }
  335.  
  336. function admin_enqueue_scripts () {
  337.  
  338. // Check to see if user has already dismissed the pointer tour
  339. $dismissed = explode (',', get_user_meta (wp_get_current_user ()->ID, 'dismissed_wp_pointers', true));
  340. $do_tour = !in_array ('test_wp_pointer', $dismissed);
  341.  
  342. // If not, we are good to continue
  343. if ($do_tour) {
  344.  
  345. // Enqueue necessary WP scripts and styles
  346. wp_enqueue_style ('wp-pointer');
  347. wp_enqueue_script ('wp-pointer');
  348.  
  349. // Finish hooking to WP admin areas
  350. add_action('admin_print_footer_scripts', array($this, 'admin_print_footer_scripts')); // Hook to admin footer scripts
  351. add_action('admin_head', array($this, 'admin_head')); // Hook to admin head
  352. }
  353. }
  354.  
  355. // Used to add spacing between the two buttons in the pointer overlay window.
  356. function admin_head () {
  357. ?>
  358. <style type="text/css" media="screen">
  359. #pointer-primary {
  360. margin: 0 5px 0 0;
  361. }
  362. </style>
  363. <?php
  364. }
  365.  
  366. // Define footer scripts
  367. function admin_print_footer_scripts () {
  368.  
  369. // Define global variables
  370. global $pagenow;
  371. global $current_user;
  372.  
  373. //*****************************************************************************************************
  374. // This is our array of individual pointers.
  375. // -- The array key should be unique. It is what will be used to 'advance' to the next pointer.
  376. // -- The 'id' should correspond to an html element id on the page.
  377. // -- The 'content' will be displayed inside the pointer overlay window.
  378. // -- The 'button2' is the text to show for the 'action' button in the pointer overlay window.
  379. // -- The 'function' is the method used to reload the window (or relocate to a new window).
  380. // This also creates a query variable to add to the end of the url.
  381. // The query variable is used to determine which pointer to display.
  382. //*****************************************************************************************************
  383. $tour = array (
  384. 'quick_press' => array (
  385. 'id' => '#dashboard_quick_press',
  386. 'content' => '<h3>' . __('Congratulations!', 'test_lang') . '</h3>'
  387. . '<p><strong>' . __('WP Pointers is working properly.', 'test_lang') . '</strong></p>'
  388. . '<p>' . __('This pointer is attached to the "Quick Draft" admin widget.', 'test_lang') . '</p>'
  389. . '<p>' . __('Our next pointer will take us to the "Settings" admin menu.', 'test_lang') . '</p>',
  390. 'button2' => __('Next', 'test_lang'),
  391. 'function' => 'window.location="' . $this->get_admin_url('options-general.php', 'site_title') . '"' // We are relocating to "Settings" page with the 'site_title' query var
  392. ),
  393. 'site_title' => array (
  394. 'id' => '#blogname',
  395. 'content' => '<h3>' . __('Moving along to Site Title.', 'test_lang') . '</h3>'
  396. . '<p><strong>' . __('Another WP Pointer.', 'test_lang') . '</strong></p>'
  397. . '<p>' . __('This pointer is attached to the "Blog Title" input field.', 'test_lang') . '</p>',
  398. 'button2' => __('Next', 'test_lang'),
  399. 'function' => 'window.location="' . $this->get_admin_url('index.php', 'quick_press_last') . '"' // We are relocating back to "Dashboard" with 'quick_press_last' query var
  400. ),
  401. 'quick_press_last' => array (
  402. 'id' => '#dashboard_quick_press',
  403. 'content' => '<h3>' . __('This concludes our WP Pointers tour.', 'test_lang') . '</h3>'
  404. . '<p><strong>' . __('Last WP Pointer.', 'test_lang') . '</strong></p>'
  405. . '<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>'
  406. )
  407. );
  408.  
  409. // Determine which tab is set in the query variable
  410. $tab = isset($_GET['tab']) ? $_GET['tab'] : '';
  411. // Define other variables
  412. $function = '';
  413. $button2 = '';
  414. $options = array ();
  415. $show_pointer = false;
  416.  
  417. // *******************************************************************************************************
  418. // This will be the first pointer shown to the user.
  419. // If no query variable is set in the url.. then the 'tab' cannot be determined... and we start with this pointer.
  420. // *******************************************************************************************************
  421. if (!array_key_exists($tab, $tour)) {
  422.  
  423. $show_pointer = true;
  424. $file_error = true;
  425.  
  426. $id = '#dashboard_right_now'; // Define ID used on page html element where we want to display pointer
  427. $content = '<h3>' . sprintf (__('Test WP Pointers %s', 'test_lang'), self::DISPLAY_VERSION) . '</h3>';
  428. $content .= __('<p>Welcome to Test WP Pointers admin tour!</p>', 'test_lang');
  429. $content .= __('<p>This pointer is attached to the "At a Glance" dashboard widget.</p>', 'test_lang');
  430. $content .= '<p>' . __('Click the <em>Begin Tour</em> button to get started.', 'test_lang' ) . '</p>';
  431.  
  432. $options = array (
  433. 'content' => $content,
  434. 'position' => array ('edge' => 'top', 'align' => 'left')
  435. );
  436. $button2 = __('Begin Tour', 'test_lang' );
  437. $function = 'document.location="' . $this->get_admin_url('index.php', 'quick_press') . '";';
  438. }
  439. // Else if the 'tab' is set in the query variable.. then we can determine which pointer to display
  440. else {
  441.  
  442. if ($tab != '' && in_array ($tab, array_keys ($tour))) {
  443.  
  444. $show_pointer = true;
  445.  
  446. if (isset ($tour[$tab]['id'])) {
  447. $id = $tour[$tab]['id'];
  448. }
  449.  
  450. $options = array (
  451. 'content' => $tour[$tab]['content'],
  452. 'position' => array ('edge' => 'top', 'align' => 'left')
  453. );
  454.  
  455. $button2 = false;
  456. $function = '';
  457.  
  458. if (isset ($tour[$tab]['button2'])) {
  459. $button2 = $tour[$tab]['button2'];
  460. }
  461. if (isset ($tour[$tab]['function'])) {
  462. $function = $tour[$tab]['function'];
  463. }
  464. }
  465. }
  466.  
  467. // If we are showing a pointer... let's load the jQuery.
  468. if ($show_pointer) {
  469. $this->make_pointer_script ($id, $options, __('Close', 'test_lang'), $button2, $function);
  470. }
  471. }
  472.  
  473. // This function is used to reload the admin page.
  474. // -- $page = the admin page we are passing (index.php or options-general.php)
  475. // -- $tab = the NEXT pointer array key we want to display
  476. function get_admin_url($page, $tab) {
  477.  
  478. $url = admin_url();
  479. $url .= $page.'?tab='.$tab;
  480.  
  481. return $url;
  482. }
  483.  
  484. // Print footer scripts
  485. function make_pointer_script ($id, $options, $button1, $button2=false, $function='') {
  486.  
  487. ?>
  488. <script type="text/javascript">
  489.  
  490. (function ($) {
  491.  
  492. // Define pointer options
  493. var wp_pointers_tour_opts = <?php echo json_encode ($options); ?>, setup;
  494.  
  495. wp_pointers_tour_opts = $.extend (wp_pointers_tour_opts, {
  496.  
  497. // Add 'Close' button
  498. buttons: function (event, t) {
  499.  
  500. button = jQuery ('<a id="pointer-close" class="button-secondary">' + '<?php echo $button1; ?>' + '</a>');
  501. button.bind ('click.pointer', function () {
  502. t.element.pointer ('close');
  503. });
  504. return button;
  505. },
  506. close: function () {
  507.  
  508. // Post to admin ajax to disable pointers when user clicks "Close"
  509. $.post (ajaxurl, {
  510. pointer: 'test_wp_pointer',
  511. action: 'dismiss-wp-pointer'
  512. });
  513. }
  514. });
  515.  
  516. // This is used for our "button2" value above (advances the pointers)
  517. setup = function () {
  518.  
  519. $('<?php echo $id; ?>').pointer(wp_pointers_tour_opts).pointer('open');
  520.  
  521. <?php if ($button2) { ?>
  522.  
  523. jQuery ('#pointer-close').after ('<a id="pointer-primary" class="button-primary">' + '<?php echo $button2; ?>' + '</a>');
  524. jQuery ('#pointer-primary').click (function () {
  525. <?php echo $function; ?> // Execute button2 function
  526. });
  527. jQuery ('#pointer-close').click (function () {
  528.  
  529. // Post to admin ajax to disable pointers when user clicks "Close"
  530. $.post (ajaxurl, {
  531. pointer: 'test_wp_pointer',
  532. action: 'dismiss-wp-pointer'
  533. });
  534. })
  535. <?php } ?>
  536. };
  537.  
  538. if (wp_pointers_tour_opts.position && wp_pointers_tour_opts.position.defer_loading) {
  539.  
  540. $(window).bind('load.wp-pointers', setup);
  541. }
  542. else {
  543. setup ();
  544. }
  545. }) (jQuery);
  546. </script>
  547. <?php
  548. }
  549. }
  550. $testWPpointers = new testWPpointers();
Add Comment
Please, Sign In to add comment