নেভিগেশনের জন্য পরবর্তী বোতাম ব্যবহার করে অ্যাডমিন পয়েন্টারযুক্ত ব্যবহারকারীদের জন্য ডাব্লুপি টিউটোরিয়াল তৈরি করুন


9

আমি প্রশাসক অঞ্চলের জন্য আমার ব্যবহারকারীদের উপর একটি টিউটোরিয়াল তৈরি করার লক্ষ্য রাখি। এটি অর্জনের জন্য, আমি ডাব্লুপি কোর-এ উপলব্ধ অ্যাডমিন পয়েন্টারগুলি ব্যবহার করছি। আমার লক্ষ্য:

এখানে চিত্র বর্ণনা লিখুন

আমি প্রায় সেখানে. এতক্ষণ যা পেলাম ...

ডাব্লুপি-পয়েন্টার স্ক্রিপ্টগুলি সারিবদ্ধ করুন:

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

শর্তাধীন চেক এবং পাদলেখ স্ক্রিপ্ট সহ সহায়ক ফাংশন:

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
}

এখন আমরা পয়েন্টারের অ্যারে একসাথে রাখতে প্রস্তুত:

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

}

কোডটি স্ব-বর্ণনামূলক। অ্যারে বাড়িয়ে আমরা আরও বেশি পয়েন্টার যুক্ত করতে পারি। ডাব্লুপি 4 এ সবকিছু ঠিকঠাক কাজ করে।

এখন সমস্যায়: সমস্ত পপআপ পয়েন্টার একই সাথে উপস্থিত হয়, এটি একটি টিউটোরিয়ালের জন্য দুর্বল ইন্টারফেস হিসাবে তৈরি করে।

আমার লক্ষ্য হ'ল পয়েন্টারগুলিকে একে একে দেখানো, এবং টিউটোরিয়ালটি দিয়ে ব্যবহারকারীকে নেক্সট বোতামে ক্লিক করার অনুমতি দেওয়া। পরের বোতামটি পরবর্তী পয়েন্টারটি খুলতে হবে এবং শেষটি বন্ধ করতে হবে।

কিভাবে আমি এটি করতে পারব?

উত্তর:


10

আপনি .pointer( 'open' );সমস্ত পয়েন্টার অবজেক্টগুলিতে জাভাস্ক্রিপ্ট ফাংশনটি কল করছেন , তাই অবাক হওয়ার কিছু নেই যে সমস্ত পয়েন্টার একই সময়ে উপস্থিত হয় ...

এটি বলেছিল, আমি বুঝতে পারি না যে আপনি কেন সমস্ত পয়েন্টার (এমনকি অ-অ্যাক্টিভ वाले) থেকে ফিরিয়ে দেন custom_admin_pointers()এবং তারপরে if ( $array['active'] ) {জাভাস্ক্রিপ্ট পয়েন্টার যুক্ত করার জন্য কিছু সক্রিয় পয়েন্টার এবং পয়েন্টার লুপের ভিতরে একটি চেক রয়েছে কিনা তা পরীক্ষা করার জন্য একটি অতিরিক্ত ফাংশন যুক্ত করেন? অথবা না. সহজ কি কেবলমাত্র সক্রিয় পয়েন্টারগুলি ফিরছে না?

তাছাড়া, আপনি সমস্ত অ্যাডমিন পৃষ্ঠায় জাভাস্ক্রিপ্ট যুক্ত করছেন, খুব বেশি না? এছাড়াও বিবেচনা করুন যে "# সেভ-পোস্ট" এর মতো কিছু উপাদানগুলি কেবল নতুন পোস্ট পৃষ্ঠায় পাওয়া যায়, তবে কেবলমাত্র নতুন পট পৃষ্ঠায় পয়েন্টার যুক্ত করা ভাল নয়?

পরিশেষে, এই জাভাস্ক্রিপ্টটি পিএইচপি এর সাথে মিশে গেছে এমন কতটা অগোছালো, আমি মনে করি আপনার wp_localize_scriptজাভাস্ক্রিপ্টে ডেটা পাস করার জন্য ব্যবহার করা উচিত ।

পরিকল্পনা:

  1. পিএইচপি-র পয়েন্টার সংজ্ঞাগুলি একটি পৃথক ফাইলে সরান, এইভাবে সম্পাদনা করা সহজ এবং পিএইচপি কোড থেকে মার্কআপ অপসারণ করা সহজ, সবকিছুই আরও পঠনযোগ্য এবং মূল লক্ষ্যযোগ্য
  2. পয়েন্টার একটি সম্পত্তি "কোথায়" সেট যা অ্যাডমিন পৃষ্ঠা থেকে একটি পপআপ প্রদর্শিত হওয়া উচিত করতে ব্যবহার করা হবে যোগ কনফিগারেশন: post-new.php, index.php...
  3. এমন একটি শ্রেণি লিখুন যা লোডিং, পার্সিং এবং পয়েন্টারগুলির তথ্যের ফিল্টারিং পরিচালনা করবে
  4. কিছু জেএস নেকি লিখুন যা আমাদের ডিফল্ট "সরান" বোতামটি "পরবর্তী" তে পরিবর্তন করতে সহায়তা করবে

# 4 করতে পারেন (সম্ভবত) সহজে সম্পন্ন পয়েন্টার ভাল প্লাগ ইন বুদ্ধিমান, কিন্তু এটা আমার ক্ষেত্রে নয়। সুতরাং আমি ফলাফলটি পেতে সাধারণ jQuery কোড ব্যবহার করব, যদি কেউ আমার কোডটি উন্নত করতে পারে তবে আমি প্রশংসা করব।


সম্পাদন করা

আমি কোডটি সম্পাদনা করেছি (প্রধানত জেএস) কারণ বিভিন্ন জিনিস যা আমি বিবেচনা করি নি: কিছু পয়েন্টার একই অ্যাঙ্কারে যুক্ত হতে পারে, বা একই পয়েন্টারগুলি অ-বিদ্যমান বা অ-দৃশ্যমান অ্যাঙ্করগুলিতে যুক্ত করা যেতে পারে। আগের ক্ষেত্রে কোডটি কাজ করত না, নতুন সংস্করণটি দুর্দান্তভাবে সমাধান করেছে বলে মনে হচ্ছে।

আমি পরীক্ষার জন্য ব্যবহৃত সমস্ত কোড সহ একটি গিস্ট সেটআপ করেছি ।


আসুন পয়েন্ট # 1 এবং # 2 দিয়ে শুরু করুন : একটি ফাইল তৈরি করুন pointers.phpএবং সেখানে লিখুন:

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

সমস্ত পয়েন্টার কনফিগারেশন এখানে। আপনার যখন কিছু পরিবর্তন করার দরকার পড়ে তখন কেবল এই ফাইলটি খুলুন এবং সম্পাদনা করুন।

"যেখানে" সম্পত্তি নোট করুন যে পৃষ্ঠাগুলির একটি অ্যারে যেখানে পয়েন্টারটি পাওয়া উচিত।

আপনি যদি কোনও প্লাগইন দ্বারা উত্পাদিত কোনও পৃষ্ঠায় পয়েন্টার প্রদর্শন করতে চান public function filter( $page ) {তবে die($page);নীচে বর্ণিত এই লাইনটি দেখুন এবং এর নীচে অবিলম্বে যুক্ত করুন । তারপরে সম্পর্কিত প্লাগইন পৃষ্ঠাটি খুলুন এবং whereসম্পত্তিটিতে স্ট্রিংটি ব্যবহার করুন ।

ঠিক আছে, এখন পয়েন্ট # 3

ক্লাসটি লেখার আগে আমি কেবল একটি ইন্টারফেস কোড করতে চাই: সেখানে আমি মন্তব্য করব যাতে ক্লাস কী করবে তা আপনি আরও ভাল করে বুঝতে পারবেন।

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

}

আমি মনে করি বেশ পরিষ্কার হওয়া উচিত। এখন ক্লাসটি লিখি, এতে ইন্টারফেস প্লাস কনস্ট্রাক্টর থেকে 2 টি পদ্ধতি থাকবে।

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

কোড খুব সহজ, এবং ইন্টারফেসটি যা প্রত্যাশা করে ঠিক তা করে।

যাইহোক, ক্লাসটি নিজে থেকে কিছুই করে না, আমাদের এমন একটি হুক দরকার যেখানে ক্লাসের ন্যাডটি ইনস্ট্যান্ট করতে উপযুক্ত যুক্তিগুলি পাস করার 2 টি পদ্ধতি।

'admin_enqueue_scripts'আমাদের সুযোগ জন্য নির্ভুল: সেখানে আমরা বর্তমান অ্যাডমিন পৃষ্ঠা থেকে অ্যাক্সেস থাকবে এবং আমরা সারিবদ্ধ স্ক্রিপ্ট এবং শৈলী প্রয়োজন পারবেন না।

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

বিশেষ কিছু নয়: কেবলমাত্র পয়েন্টার ডেটা পেতে ক্লাস ব্যবহার করে এবং যদি কিছু পয়েন্টারগুলি ফিল্টারগুলি শৈলী এবং স্ক্রিপ্টগুলি সঞ্চার করে। তারপরে বোতামের জন্য স্থানীয়করণ করা "নেক্সট" লেবেলের সাথে স্ক্রিপ্টে পয়েন্টার ডেটাগুলি পাস করুন।

ঠিক আছে, এখন "সবচেয়ে শক্ত" অংশ: জেএস। আবার আমি হাইলাইট করতে চাই যে আমি পয়েন্টার প্লাগইন ওয়ার্ডপ্রেস ব্যবহারগুলি জানি না, তাই আমার কোডে আমি যা করি তা যদি কেউ জেনে থাকে তবে আরও ভাল কাজ করা যায়, তবে আমার কোডটি এটির কাজ করে এবং জেনারিকভাবে বলতে হয়- এটি এতটা খারাপ নয়।

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

মন্তব্যের সাহায্যে কোডটি বেশ পরিষ্কার হওয়া উচিত, কমপক্ষে, আমিও আশা করি।

ঠিক আছে আমরা হয়ে গেলাম। আমাদের পিএইচপি সহজ এবং আরও সুগঠিত, আমাদের জাভাস্ক্রিপ্ট আরও পাঠযোগ্য, পয়েন্টারগুলি সম্পাদনা করা সহজ এবং আরও গুরুত্বপূর্ণ, সব কিছু কাজ করে।


1
@ ক্রিসটাইনকুপার নিশ্চিত ঠিক আছে, স্ক্রিপ্টটি এখন কীভাবে কাজ করে তার জন্য সমস্যাগুলি 2: প্রথম, আপনি 1 অ্যাঙ্কর আইডির জন্য 1 পয়েন্টার যুক্ত করতে পারেন: একাধিক পয়েন্টারের জন্য একই অ্যাঙ্কর ব্যবহার করলে স্ক্রিপ্টটি ব্যর্থ হবে। ২ য় সমস্যাটি হ'ল কিছু পয়েন্টার আইডিতে অ্যাঙ্কর ব্যবহার করে যা পৃষ্ঠায় নাও থাকতে পারে। উদাহরণস্বরূপ, একটি পয়েন্টার ইনডেক্স.এফপি-তে '# মন্তব্য -৫৫' এর জন্য এবং এটি খুঁজে পাওয়া যায় না। Post.php টার্গেট মেটাবক্সে কিছু পয়েন্টার লুকানো থাকতে পারে ... ইত্যাদি। স্ক্রিপ্টের বর্তমান সংস্করণে পয়েন্টারগুলিকে একবার "শৃঙ্খলিত" করা হয় যদি এটি না পাওয়া যায় তবে সমস্ত অনুগামী খুব বেশি কাজ করবে না। আমি দেখতে যাচ্ছি যে এই সমস্যাগুলি কাটিয়ে উঠার কোনও সহজ উপায় আছে কিনা।
গাজাজ্যাপ

1
@ ক্রিসটাইনকুপার এতে খুশী হয়েছে। আমি জিস্ট থেকে সমস্ত কোড এখানে ফিরে কপি করব। add_action( 'admin_enqueue_scripts', function( $page ) {ব্যবহারকারীর কোনও প্রয়োজনীয় ভূমিকা না থাকলে কেবল ফিরে আসার পরে শর্ত রাখা যেতে পারে ।
গাজাজ্যাপ

দয়া করে 30 মানটি লাইনে 120 তে পরিবর্তন করুন: "স্ক্রোলটপ: $ পয়েন্টার.অফসেট () শীর্ষ - 30" - কারণটি কারণ শীর্ষস্থানীয় সরঞ্জামদণ্ডটি মাঝে মাঝে স্ক্রল করার সময় পয়েন্টার উইন্ডোটি coversেকে দেয়।
ক্রিস্টিন কুপার

আমার একটা ছোটখাটো সমস্যা আছে পৃষ্ঠা আমি কিছু পয়েন্টার প্রয়োজন প্রদর্শিত is: "admin.php পৃষ্ঠা = প্লাগ ইন-পাথ / file.php?" - ঠিক আমি যুক্ত করব যেখানে অ্যারের? আমি "অ্যাডমিন.এফপি", "প্লাগইন-পাথ / ফাইল.পিএফ", "ফাইল.পিএফপি" এবং আমার মনে হতে পারে এমন কোনও প্রকারের চেষ্টা করেছি। এটির এই পৃষ্ঠাটি সনাক্ত করতে না পারার কোনও কারণ আছে বা আমি এইটি ভুল করছি?
ক্রিস্টিন কুপার

1
@ ক্রিসটাইনকুপার প্লাগইন অ্যাডমিন পৃষ্ঠা খুলুন এবং ব্রাউজার থেকে url অনুলিপি করুন । এর পরে, উপরে আমার কোড রয়েছে এমন ফাইলটি খুলুন। ক্লাসে লাইনটি public function filter( $page ) {সন্ধান করুন PointersManagerএবং তারপরে লাইনটি লাগানোর পরে die($page);। আপনার ব্রাউজারটি খুলুন এবং ইউআরএলটি পেস্ট করুন, পৃষ্ঠাটি একটি স্ট্রিংয়ের সাথে মারা যাবে: এটিই আপনাকে ব্যবহার করতে হবে 'where'
গাজাজ্যাপ

7

আহ .. হ্যাঁ। ওয়ার্ডপ্রেস পয়েন্টার। আপনি জানেন, পয়েন্টার ব্যবহার করার ক্ষেত্রে মিশ্র অনুভূতিগুলি প্রচুর পরিমাণে থাকে;)

আপনি উপরের কোড সহ সঠিক পথে ছিলেন। তবে দু'একটি বিষয় রয়েছে।

@GM pointer('open')আপনার পয়েন্টার একবারে খোলার আদেশ সম্পর্কে সঠিক @ তদতিরিক্ত, আপনি পয়েন্টারগুলির মাধ্যমে অগ্রিম হওয়ার কোনও পদ্ধতি সরবরাহ করছেন না।

আমি এই একই ইস্যুতে লড়াই করেছি .. এবং আমার নিজস্ব পদ্ধতি নিয়ে এসেছি। আমি ইউআরএল-তে একটি ক্যোয়ারী ভেরিয়েবল ব্যবহার করি, পৃষ্ঠাটি অ্যাডমিন পৃষ্ঠায় পুনরায় লোড করুন যেখানে আমি পরবর্তী পয়েন্টারটি প্রদর্শন করতে চাই এবং jQuery কে বাকি অংশটি পরিচালনা করতে দিন।

ডব্লিউপি পয়েন্টার ক্লাস

আমি ক্লাস হিসাবে এটি লিখতে সিদ্ধান্ত নিয়েছে। তবে আমি আপনাকে প্রথমে বর্ধিত পরিমাণে দেখাবো যা ঘটছে তা আরও ভালভাবে বুঝতে help

ক্লাস শুরু

// 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. আমরা ক্লাস সংজ্ঞায়িত করেছি।
  2. আমরা ক্লাসটি তৈরি করেছি এবং এতে একটি ক্রিয়া যুক্ত করেছি admin_enqueue_scripts
  3. আমাদের পয়েন্টারগুলি ইতিমধ্যে খারিজ করা হয়েছে কিনা তা আমরা নির্ধারণ করেছি।
  4. যদি তা না হয় তবে আমরা প্রয়োজনীয় স্ক্রিপ্টগুলি সরিয়ে ফেলতে থাকি।

এই প্রথম কার্যগুলিতে আপনাকে কোনও পরিবর্তন করার দরকার নেই।

পয়েন্টার আইটেমগুলির অ্যারে সেট আপ করা হচ্ছে

পরবর্তী পদক্ষেপটি প্রতিটি পয়েন্টারকে সংজ্ঞায়িত করছে। আমাদের পাঁচটি আইটেম সংজ্ঞায়িত করতে হবে (শেষ পয়েন্টারের জন্য ব্যয়)। অ্যারে ব্যবহার করে আমরা এটি করব। আসুন ফাংশনটি একবার দেখুন:

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

ঠিক আছে .. আসুন এখানে কয়েকটি জিনিস দেখুন।

প্রথম, আমাদের $tourঅ্যারে। এটি অ্যারে যা সমস্ত পয়েন্টারকে ধরে রাখে প্রথম পয়েন্টারটি ছাড়াই ব্যবহারকারীর কাছে প্রদর্শিত হয় (আরও পরে এটি)। সুতরাং, আপনি যে দ্বিতীয় পয়েন্টারটি দেখানোর ইচ্ছা করছেন তার সাথে শুরু করতে চান .. এবং শেষ পয়েন্টারটি অবিরত রাখতে পারেন।

এর পরে, আমাদের কয়েকটি আইটেম রয়েছে যা খুব গুরুত্বপূর্ণ।

  1. $tourঅ্যারে কী অনন্য (; উপরের উদাহরণগুলোতে যেমন quick_press, SITE_TITLE, quick_press_last) হবে।
  2. 'আইডি' কমান্ডটি আপনাকে পয়েন্টারের সাথে সংযুক্ত করতে ইচ্ছুক আইটেমটির এইচটিএমএল উপাদান আইডিটির সাথে মেলে match
  3. functionকমান্ড পুনরায় লোড / উইন্ডো নূতন স্থান নির্দেশ করা হবে। এটিই পরবর্তী পয়েন্টারটি দেখানোর জন্য ব্যবহৃত হয়। আমাদের হয় উইন্ডোটি পুনরায় লোড করতে হবে, বা এটি পরবর্তী অ্যাডমিন পৃষ্ঠাতে স্থানান্তর করতে হবে যেখানে একটি পয়েন্টার প্রদর্শিত হবে।
  4. আমরা get_admin_url()দুটি ভেরিয়েবল দিয়ে ফাংশনটি পরিচালনা করি ; প্রথমটি অ্যাডমিন পৃষ্ঠা যেখানে আমরা পরবর্তী যেতে চাই; এবং দ্বিতীয়টি হ'ল আমরা যে পয়েন্টারটি প্রদর্শন করতে চাই তার অনন্য অ্যারে কী।

আরও নীচে, আপনি যে কোডটি শুরু করেছিলেন তা দেখতে পাবেন if (!array_key_exists($tab, $tour)) {। এখানেই আমরা নির্ধারণ করি যে কোনও ইউআরএল ক্যোয়ারী ভেরিয়েবল সেট করা হয়েছে কিনা। যদি এটি না থাকে, তবে আমাদের প্রদর্শনের জন্য প্রথম পয়েন্টারটি সংজ্ঞায়িত করতে হবে।

এই পয়েন্টারটি উপরে id, content, button2, and functionআমাদের $tourঅ্যারেতে ব্যবহৃত একই আইটেমগুলি ব্যবহার করে । মনে রাখবেন, get_admin_url()ফাংশনের দ্বিতীয় যুক্তিটি $tourভেরিয়েবলের অ্যারে কী হিসাবে ঠিক একই হওয়া উচিত । এটিই স্ক্রিপ্টটিকে পরবর্তী পয়েন্টারে যাওয়ার জন্য বলে।

যদি কোনও ক্যোয়ারী ভেরিয়েবলটি ইতিমধ্যে ইউআরএলটিতে সেট করা থাকে তবে বাকী ফাংশনটি ব্যবহৃত হয়। ফাংশনটির আর কোনও সামঞ্জস্য করার দরকার নেই।

অ্যাডমিন url পাওয়া পরবর্তী ফাংশনটি আসলে একটি সহায়ক ফাংশন ... অ্যাডমিন url পেতে এবং পয়েন্টারটি অগ্রসর করার জন্য ব্যবহৃত হয় used

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

মনে রাখবেন, দুটি যুক্তি রয়েছে; অ্যাডমিন পৃষ্ঠাতে আমরা যাচ্ছি .. এবং ট্যাব। ট্যাবটি $tourঅ্যারে কী হবে যা আমরা পরেরটিতে যেতে চাই। এই ম্যাচ করা আবশ্যক

সুতরাং, যখন আমরা ফাংশনটি কল করি get_admin_url()এবং দুটি ভেরিয়েবল পাস করি; প্রথম ভেরিয়েবল পরবর্তী অ্যাডমিন পৃষ্ঠা নির্ধারণ করে .. এবং দ্বিতীয় ভেরিয়েবলটি কোন পয়েন্টারটি প্রদর্শিত হবে তা নির্ধারণ করে।

শেষ পর্যন্ত ... আমরা অবশেষে পাদচরণে অ্যাডমিন স্ক্রিপ্ট মুদ্রণ করতে পারি।

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

আবার উপরের কিছু পরিবর্তন করার দরকার নেই। এই স্ক্রিপ্টটি পয়েন্টার ওভারলে উইন্ডোতে দুটি বোতাম সংজ্ঞায়িত এবং আউটপুট করবে। এক সর্বদা "বন্ধ" বোতামটি থাকবে; এবং বর্তমান ব্যবহারকারী মেটা dismissed_pointersবিকল্প আপডেট করবে will

দ্বিতীয় বোতামটি (অ্যাকশন বোতাম) ফাংশনটি কার্যকর করবে (আমাদের উইন্ডো স্থানান্তর পদ্ধতি)।

এবং আমরা ক্লাস বন্ধ।

এটি সম্পূর্ণরূপে কোড এখানে। ডাব্লুপি পয়েন্টার ক্লাস

আপনি এটি আপনার ডেভ সাইটে কপি / পেস্ট করতে পারেন এবং "ড্যাশবোর্ড" পৃষ্ঠাটি দেখতে পারেন। এটি আপনাকে সফরের মাধ্যমে গাইড করবে।

মনে রাখবেন, এটি কিছুটা বিভ্রান্তিকর যে প্রথম পয়েন্টারটি কোডে শেষ নির্ধারিত হয়েছিল। এভাবেই কাজ করার কথা রয়েছে। অ্যারে আপনি ব্যবহার করতে ইচ্ছুক বাকী সমস্ত পয়েন্টার ধরে রাখবে।

মনে রাখবেন, 'আইডি' অ্যারে আইটেমটি get_admin_url()আগের অ্যারে আইটেম 'ফাংশন' কমান্ড থেকে ফাংশনের দ্বিতীয় যুক্তির সাথে মিলে যায় । পয়েন্টাররা একে অপরের সাথে এভাবেই 'আলাপ' করে এবং কীভাবে এগিয়ে যায় তা জানে।

উপভোগ করুন !! :)


এই সুন্দর জোশ, আপনাকে অনেক ধন্যবাদ! আমি এটি চেষ্টা করে দেখব এবং এটি কতটা কার্যকরভাবে কাজ করে। আমার হাইলাইট করা উচিত যে জিএম এর কোডটি আমি সম্ভবত এই অনুগ্রহটি প্রদান করব কারণ এতে কয়েকটি প্রয়োজনীয় বৈশিষ্ট্য রয়েছে যা আমি অনুরোধ করেছি এবং যা আমি বিশ্বাস করি একটি গাইড তৈরি করা গুরুত্বপূর্ণ, বিশেষত ডাব্লুপি-প্রশাসনের একাধিক পৃষ্ঠাগুলির জন্য। তা সত্ত্বেও, এটির জন্য আরেকটি পদ্ধতির বিষয়টি দেখতে পারা দুর্দান্ত এবং এটি যে অন্য ব্যবহারকারীদের পক্ষে ভাল সমাধানের সন্ধান করছেন তাদের কাজে আসবে। কৌতূহলের বাইরে, আপনি বলেছিলেন যে পয়েন্টার ব্যবহার করার ক্ষেত্রে, বিস্তৃত যত্ন নেওয়ার ক্ষেত্রে মিশ্র অনুভূতিগুলি প্রচুর পরিমাণে আছে?
খ্রীস্টিন কুপার

2
কোনও উদ্বেগ নয় :) ভাল, পয়েন্টার অতিরিক্ত ব্যবহারের সময় 'পথে যেতে' পারে। কেউ কোনও পৃষ্ঠাতে যেতে এবং তিন বা চারটি পয়েন্টার প্রদর্শন করতে চায় না ... বিশেষত যদি তারা সম্পর্কিত না হয়। বলুন অন্য দুটি প্লাগইন পয়েন্টার দেখাচ্ছে, তারপরে আমরা আরও পয়েন্টার যুক্ত করব .. এটি ওভারকিল হয়ে যেতে পারে। বেশিরভাগ লোক এগুলিকে অল্প পরিমাণে ব্যবহার করতে বলে ... তবে প্রত্যেকের কাছে তাদের নিজস্ব :) খুশী যে আপনি এটি সঠিকভাবে কাজ করতে পেরেছেন।
জোশ

1
এটি আরও বিস্ময়কর জোশ, আমি আরও 1 টি পরামর্শ দেব, এটি আরও নমনীয় করে তুলতে এবং যেখানে ক্লাস কোডের ভিতরেই সংরক্ষণের পরিবর্তে আপনি অ্যারেতে পাবলিক ফাংশনে সারণি করতে পারেন সেখানে এটি রাখতে পারেন। দ্বিতীয়ত, প্রথম পয়েন্টার, এটি কীভাবে পৃথক, এটিকে সংশোধন করুন যাতে এটি পয়েন্টার অ্যারেতে প্রথম অ্যারে কী / মান হতে পারে। এই ক্লাসটি অন্য স্ক্রিপ্ট থেকে কল করা যায় এবং কেবল পয়েন্টারের অ্যারে পাস করা যেতে পারে মাত্র কয়েক দম্পতি ধারণা। আমি এখনও সত্যিই এটি পছন্দ করি, ভাগ করে নেওয়ার জন্য ধন্যবাদ আমি এটি ব্যবহার করব!
জেসনডাভিস

ধন্যবাদ @ জাসনদাভিস আমি কারওর জন্য বিকাশ করা অন্য প্লাগইন থেকে আসলে কোডটি টানলাম। আমি কেবল এটি সঠিকভাবে কাজ করতে আগ্রহী ছিল। তবে হ্যাঁ, আমি আপনার সাথে একমত ... এটি পরিষ্কার করা দরকার। সম্ভবত আমি আজকের পরের দিকে থামব এবং এটির সাথে আবার গণ্ডগোল করব :) আপনি দোস্ত, ভাই!
জোশ

এটি দুর্দান্ত, অ্যাডমিন পয়েন্টারগুলি ব্যবহার করার আমার আসলে কোনও উদ্দেশ্য ছিল না, মূলত তারা এগুলিকে একটি দুঃস্বপ্ন এবং 2 য়ের মতো দেখায় কারণ তাদের জন্য আমার কোন ব্যবহার নেই, তবে আপনার ক্লাসটি তাদের এখন ব্যবহার করা এত সহজ দেখায় যে আমার মনে হয় এই শ্রেণীর সাথে এটি এত সহজ হচ্ছে তাদের ব্যবহার করতে হবে! আমি তার মতো ছোট প্রকল্পগুলি / লাইব্রেরিগুলি পছন্দ করি, ভাল স্টাফ
জেসনডাভিস
আমাদের সাইট ব্যবহার করে, আপনি স্বীকার করেছেন যে আপনি আমাদের কুকি নীতি এবং গোপনীয়তা নীতিটি পড়েছেন এবং বুঝতে পেরেছেন ।
Licensed under cc by-sa 3.0 with attribution required.