Support » Developing with WordPress » How to create custom item in menu

  • (file: nav-menus.php)
    I want to attach images to items, and then get items using filter, like this:

    
    function wpse19375_nav_class( $classes, $item ){
      if( in_array( 'current-menu-item', $classes ) )
      {
          get_post_meta($item->ID, 'custom_image_data_' . $item_id, true);
      }
      return $classes;
    }
    
    add_filter( 'nav_menu_css_class', 'wpse19375_nav_class', 10, 2 );

    I have problem with upload images
    1)If I come to the page then page (nav-menus.php) have error because $_REQUEST[‘menu’] is empty and I cannot get current nav menu ID
    2)I cannot make js script for every item, I try to use loop but get a lot of error

    functions.php
    Problem:
    – $menuItems = wp_get_nav_menu_items($_REQUEST[‘menu’]);
    – wp_localize_script(
    ‘wp_img_upload’,
    ‘customUploads_’ . $items_id[$i],
    array(
    ‘imageData’ => get_post_meta($items_id[$i++],
    ‘custom_image_data_’ . $items_id[$i],
    true ) ) );

    function register_admin_script() 
    {
        $menuItems = wp_get_nav_menu_items($_REQUEST['menu']);
        $items_id;
        $i = 0;
        wp_enqueue_script( 'wp_img_upload', CURRENT_DIR_URL . '/include/uploader.js', array('jquery', 'media-upload'), '0.0.1', true );
        foreach ($menuItems as $currentItem) {
            $items_id[$i] = $currentItem->ID;
            wp_localize_script( 
                'wp_img_upload', 
                'customUploads_' . $items_id[$i], 
                    array( 
                        'imageData' => get_post_meta($items_id[$i++], 
                        'custom_image_data_' . $items_id[$i], 
                        true ) ) );
        }
    	wp_localize_script( 'wp_img_upload', 'currentItemsID', array('itemsID' => $items_id));
    	wp_enqueue_media();
    }
    add_action( 'admin_enqueue_scripts', 'register_admin_script' );

    uploader.js
    Problem: I cannot make js script for every item

    var addButton = document.getElementById( 'image-upload-button_' + currentItemsID.itemsID[0] );
    var deleteButton = document.getElementById( 'image-delete-button_' + currentItemsID.itemsID[0] );
    var img = document.getElementById( 'image-tag_' + currentItemsID.itemsID[0] );
    var hidden = document.getElementById( 'img-hidden-field_' + currentItemsID.itemsID[0] );
    var customUploader = wp.media({
        title: 'Select an Image',
        button: {
            text: 'Use this Image'
        },
        multiple: false
    });
    
    addButton.addEventListener( 'click', function() {
        if ( customUploader ) {
            customUploader.open();
        }
    } );
    
    customUploader.on( 'select', function() {
        var attachment = customUploader.state().get('selection').first().toJSON();
        img.setAttribute( 'src', attachment.url );
        hidden.setAttribute( 'value', JSON.stringify( [{ id: attachment.id, url: attachment.url }]) );
        toggleVisibility( 'ADD' );
    } );
    
    deleteButton.addEventListener( 'click', function() {
        img.removeAttribute( 'src' );
        hidden.removeAttribute( 'value' );
        toggleVisibility( 'DELETE' );
    } );
    
    var toggleVisibility = function( action ) {
        if ( 'ADD' === action ) {
            addButton.style.display = 'none';
            deleteButton.style.display = '';
            img.setAttribute( 'style', 'width: 100%;' );
        }
    
        if ( 'DELETE' === action ) {
            addButton.style.display = '';
            deleteButton.style.display = 'none';
            img.removeAttribute('style');
        }
    };
    
    window.addEventListener( 'DOMContentLoaded', function() {
        if ( "" === customUploads.imageData || 0 === customUploads.imageData.length ) {
            toggleVisibility( 'DELETE' );
        } else {
            img.setAttribute( 'src', customUploads.imageData.src );
            hidden.setAttribute( 'value', JSON.stringify([ customUploads.imageData ]) );
            toggleVisibility( 'ADD' );
        }
    } );

    The files below have no problem
    Important part of edit_custom_walker.php file (151-156)

    <div id="metabox_wrapper">
    					<img id="image-tag_<?=$item_id?>">
    					<input type="hidden" id="img-hidden-field_<?=$item_id?>" name="custom_image_data_<?=$item_id?>">
    					<input type="button" id="image-upload-button_<?=$item_id?>" class="button" value="Add Image">
    					<input type="button" id="image-delete-button_<?=$item_id?>" class="button" value="Delete Image">
    				</div>

    edit_custom_walker.php

    <?php
    class Walker_Nav_Menu_Edit_Custom extends Walker_Nav_Menu {
    
    	public function start_el( &$output, $item, $depth = 0, $args = array(), $id = 0 ) {
    		global $_wp_nav_menu_max_depth;
    		$_wp_nav_menu_max_depth = $depth > $_wp_nav_menu_max_depth ? $depth : $_wp_nav_menu_max_depth;
    
    		ob_start();
    		$item_id = esc_attr( $item->ID );
    		$removed_args = array(
    			'action',
    			'customlink-tab',
    			'edit-menu-item',
    			'menu-item',
    			'page-tab',
    			'_wpnonce',
    		);
    
    		$original_title = '';
    		if ( 'taxonomy' == $item->type ) {
    			$original_title = get_term_field( 'name', $item->object_id, $item->object, 'raw' );
    			if ( is_wp_error( $original_title ) )
    				$original_title = false;
    		} elseif ( 'post_type' == $item->type ) {
    			$original_object = get_post( $item->object_id );
    			$original_title = get_the_title( $original_object->ID );
    		}
    
    		$classes = array(
    			'menu-item menu-item-depth-' . $depth,
    			'menu-item-' . esc_attr( $item->object ),
    			'menu-item-edit-' . ( ( isset( $_GET['edit-menu-item'] ) && $item_id == $_GET['edit-menu-item'] ) ? 'active' : 'inactive'),
    		);
    
    		$title = $item->title;
    
    		if ( ! empty( $item->_invalid ) ) {
    			$classes[] = 'menu-item-invalid';
    			/* translators: %s: title of menu item which is invalid */
    			$title = sprintf( __( '%s (Invalid)' ), $item->title );
    		} elseif ( isset( $item->post_status ) && 'draft' == $item->post_status ) {
    			$classes[] = 'pending';
    			/* translators: %s: title of menu item in draft status */
    			$title = sprintf( __('%s (Pending)'), $item->title );
    		}
    
    		$title = ( ! isset( $item->label ) || '' == $item->label ) ? $title : $item->label;
    
    		$submenu_text = '';
    		if ( 0 == $depth )
    			$submenu_text = 'style="display: none;"';
    
    		?>
    		<li id="menu-item-<?php echo $item_id; ?>" class="<?php echo implode(' ', $classes ); ?>">
    			<dl class="menu-item-bar">
    				<dt class="menu-item-handle">
    					<span class="item-title"><span class="menu-item-title"><?php echo esc_html( $title ); ?></span> <span class="is-submenu" <?php echo $submenu_text; ?>><?php _e( 'sub item' ); ?></span></span>
    					<span class="item-controls">
    						<span class="item-type"><?php echo esc_html( $item->type_label ); ?></span>
    						<span class="item-order hide-if-js">
    							<a href="<?php
    								echo wp_nonce_url(
    									add_query_arg(
    										array(
    											'action' => 'move-up-menu-item',
    											'menu-item' => $item_id,
    										),
    										remove_query_arg($removed_args, admin_url( 'nav-menus.php' ) )
    									),
    									'move-menu_item'
    								);
    							?>" class="item-move-up"><abbr title="<?php esc_attr_e('Move up'); ?>">↑</abbr></a>
    							|
    							<a href="<?php
    								echo wp_nonce_url(
    									add_query_arg(
    										array(
    											'action' => 'move-down-menu-item',
    											'menu-item' => $item_id,
    										),
    										remove_query_arg($removed_args, admin_url( 'nav-menus.php' ) )
    									),
    									'move-menu_item'
    								);
    							?>" class="item-move-down"><abbr title="<?php esc_attr_e('Move down'); ?>">↓</abbr></a>
    						</span>
    						<a class="item-edit" id="edit-<?php echo $item_id; ?>" title="<?php esc_attr_e('Edit Menu Item'); ?>" href="<?php
    							echo ( isset( $_GET['edit-menu-item'] ) && $item_id == $_GET['edit-menu-item'] ) ? admin_url( 'nav-menus.php' ) : add_query_arg( 'edit-menu-item', $item_id, remove_query_arg( $removed_args, admin_url( 'nav-menus.php#menu-item-settings-' . $item_id ) ) );
    						?>"><?php _e( 'Edit Menu Item' ); ?></a>
    					</span>
    				</dt>
    			</dl>
    
    			<div class="menu-item-settings wp-clearfix" id="menu-item-settings-<?php echo $item_id; ?>">
    				<?php if( 'custom' == $item->type ) : ?>
    					<p class="field-url description description-wide">
    						<label for="edit-menu-item-url-<?php echo $item_id; ?>">
    							<?php _e( 'URL' ); ?><br />
    							<input type="text" id="edit-menu-item-url-<?php echo $item_id; ?>" class="widefat code edit-menu-item-url" name="menu-item-url[<?php echo $item_id; ?>]" value="<?php echo esc_attr( $item->url ); ?>" />
    						</label>
    					</p>
    				<?php endif; ?>
    				<p class="description description-thin">
    					<label for="edit-menu-item-title-<?php echo $item_id; ?>">
    						<?php _e( 'Navigation Label' ); ?><br />
    						<input type="text" id="edit-menu-item-title-<?php echo $item_id; ?>" class="widefat edit-menu-item-title" name="menu-item-title[<?php echo $item_id; ?>]" value="<?php echo esc_attr( $item->title ); ?>" />
    					</label>
    				</p>
    				<p class="description description-thin">
    					<label for="edit-menu-item-attr-title-<?php echo $item_id; ?>">
    						<?php _e( 'Title Attribute' ); ?><br />
    						<input type="text" id="edit-menu-item-attr-title-<?php echo $item_id; ?>" class="widefat edit-menu-item-attr-title" name="menu-item-attr-title[<?php echo $item_id; ?>]" value="<?php echo esc_attr( $item->post_excerpt ); ?>" />
    					</label>
    				</p>
    				<p class="field-link-target description">
    					<label for="edit-menu-item-target-<?php echo $item_id; ?>">
    						<input type="checkbox" id="edit-menu-item-target-<?php echo $item_id; ?>" value="_blank" name="menu-item-target[<?php echo $item_id; ?>]"<?php checked( $item->target, '_blank' ); ?> />
    						<?php _e( 'Open link in a new window/tab' ); ?>
    					</label>
    				</p>
    				<p class="field-css-classes description description-thin">
    					<label for="edit-menu-item-classes-<?php echo $item_id; ?>">
    						<?php _e( 'CSS Classes (optional)' ); ?><br />
    						<input type="text" id="edit-menu-item-classes-<?php echo $item_id; ?>" class="widefat code edit-menu-item-classes" name="menu-item-classes[<?php echo $item_id; ?>]" value="<?php echo esc_attr( implode(' ', $item->classes ) ); ?>" />
    					</label>
    				</p>
    				<p class="field-xfn description description-thin">
    					<label for="edit-menu-item-xfn-<?php echo $item_id; ?>">
    						<?php _e( 'Link Relationship (XFN)' ); ?><br />
    						<input type="text" id="edit-menu-item-xfn-<?php echo $item_id; ?>" class="widefat code edit-menu-item-xfn" name="menu-item-xfn[<?php echo $item_id; ?>]" value="<?php echo esc_attr( $item->xfn ); ?>" />
    					</label>
    				</p>
    
    				<?php
    				// This is the added section
    				do_action( 'wp_nav_menu_item_custom_fields', $item_id, $item, $depth, $args );
    				// end added section
    				?>
    
    				<p class="field-description description description-wide">
    					<label for="edit-menu-item-description-<?php echo $item_id; ?>">
    						<?php _e( 'Description' ); ?><br />
    						<textarea id="edit-menu-item-description-<?php echo $item_id; ?>" class="widefat edit-menu-item-description" rows="3" cols="20" name="menu-item-description[<?php echo $item_id; ?>]"><?php echo esc_html( $item->description ); // textarea_escaped ?></textarea>
    						<span class="description"><?php _e('The description will be displayed in the menu if the current theme supports it.'); ?></span>
    					</label>
    				</p>
    				<?php
    	            /* New fields insertion ends here */
    	            //$locations = get_nav_menu_locations();
    	            ?>
    	            <div id="metabox_wrapper">
    					<img id="image-tag_<?=$item_id?>">
    					<input type="hidden" id="img-hidden-field_<?=$item_id?>" name="custom_image_data_<?=$item_id?>">
    					<input type="button" id="image-upload-button_<?=$item_id?>" class="button" value="Add Image">
    					<input type="button" id="image-delete-button_<?=$item_id?>" class="button" value="Delete Image">
    				</div>
    	            <?php
    	            /* End New fields insertion ends here */
    	            /*Save field*/
    	            update_post_meta($item_id, 'custom_image_data_' . $item_id, $_POST['custom_image_data']);
    	            ?>
    				<div class="menu-item-actions description-wide submitbox">
    					<?php if( 'custom' != $item->type && $original_title !== false ) : ?>
    						<p class="link-to-original">
    							<?php printf( __('Original: %s'), '<a href="' . esc_attr( $item->url ) . '">' . esc_html( $original_title ) . '</a>' ); ?>
    						</p>
    					<?php endif; ?>
    					<a class="item-delete submitdelete deletion" id="delete-<?php echo $item_id; ?>" href="<?php
    					echo wp_nonce_url(
    						add_query_arg(
    							array(
    								'action' => 'delete-menu-item',
    								'menu-item' => $item_id,
    							),
    							admin_url( 'nav-menus.php' )
    						),
    						'delete-menu_item_' . $item_id
    					); ?>"><?php _e( 'Remove' ); ?></a> <span class="meta-sep hide-if-no-js"> | </span> <a class="item-cancel submitcancel hide-if-no-js" id="cancel-<?php echo $item_id; ?>" href="<?php echo esc_url( add_query_arg( array( 'edit-menu-item' => $item_id, 'cancel' => time() ), admin_url( 'nav-menus.php' ) ) );
    						?>#menu-item-settings-<?php echo $item_id; ?>"><?php _e('Cancel'); ?></a>
    				</div>
    
    				<input class="menu-item-data-db-id" type="hidden" name="menu-item-db-id[<?php echo $item_id; ?>]" value="<?php echo $item_id; ?>" />
    				<input class="menu-item-data-object-id" type="hidden" name="menu-item-object-id[<?php echo $item_id; ?>]" value="<?php echo esc_attr( $item->object_id ); ?>" />
    				<input class="menu-item-data-object" type="hidden" name="menu-item-object[<?php echo $item_id; ?>]" value="<?php echo esc_attr( $item->object ); ?>" />
    				<input class="menu-item-data-parent-id" type="hidden" name="menu-item-parent-id[<?php echo $item_id; ?>]" value="<?php echo esc_attr( $item->menu_item_parent ); ?>" />
    				<input class="menu-item-data-position" type="hidden" name="menu-item-position[<?php echo $item_id; ?>]" value="<?php echo esc_attr( $item->menu_order ); ?>" />
    				<input class="menu-item-data-type" type="hidden" name="menu-item-type[<?php echo $item_id; ?>]" value="<?php echo esc_attr( $item->type ); ?>" />
    			</div><!-- .menu-item-settings-->
    			<ul class="menu-item-transport"></ul>
    		<?php
    		$output .= ob_get_clean();
    	}
    }
Viewing 3 replies - 1 through 3 (of 3 total)
  • Moderator Andrew Nevins

    (@anevins)

    Forum moderator

    2)I cannot make js script for every item, I try to use loop but get a lot of error

    Can you provide more detail of your intention? From a very top level perspective, it doesn’t make sense to add a js script for each menu item.

    Yes, I can
    I wrote all the code below
    functions.php

    /**************************************************************************/
    
    function wpse19375_nav_class( $classes, $item ){
      if( in_array( 'current-menu-item', $classes ) )
      {
        ?>
        <img src="<?=get_post_meta($item->ID, 'custom_image_data_' . $item->ID, true);?>">
        <?php
      }
      return $classes;
    }
    
    add_filter( 'nav_menu_css_class', 'wpse19375_nav_class', 10, 2 );
    
    /******************************************************************************/
    function register_admin_script() 
    {
        $menuItems = wp_get_nav_menu_items($_REQUEST['menu']);
        $i = 0;
        foreach ($menuItems as $currentItem) 
            {$items_id[$i++] = $currentItem->ID;}
        wp_enqueue_script( 'wp_img_upload', CURRENT_DIR_URL . '/include/uploader.js', array('jquery', 'media-upload'), '0.0.1', true );
        wp_localize_script( 'wp_img_upload', 'customUploads', 
                            array( 
                                'imageData' => get_post_meta($items_id[0], 
                                'custom_image_data', 
                                true ) ) );
    	wp_enqueue_media();
    }
    add_action( 'admin_enqueue_scripts', 'register_admin_script' );
    /******************************************************************************/
    require_once( CURRENT_DIR . '/include/edit_custom_walker.php' );
    class rc_sweet_custom_menu {
    
    	/*--------------------------------------------*
    	 * Constructor
    	 *--------------------------------------------*/
    
    	/**
    	 * Initializes the plugin by setting localization, filters, and administration functions.
    	 */
    	function __construct() {
             // add custom menu fields to menu
            add_filter( 'wp_setup_nav_menu_item', array( $this, 'rc_scm_add_custom_nav_fields' ) );
            // save menu custom fields
            add_action( 'wp_update_nav_menu_item', array( $this, 'rc_scm_update_custom_nav_fields'), 10, 3 );
            // edit menu walker
            add_filter( 'wp_edit_nav_menu_walker', array( $this, 'rc_scm_edit_walker'), 10, 2 );
    	} // end constructor
    
    	/* All functions will be placed here */
    	function rc_scm_add_custom_nav_fields( $menu_item ) 
    	{
            $menu_item->subtitle = get_post_meta( $menu_item->ID, '_menu_item_subtitle', true );
            return $menu_item;
        }
        /**
         * Save menu custom fields
         *
         * @access      public
         * @since       1.0 
         * @return      void
        */
        function rc_scm_update_custom_nav_fields( $menu_id, $menu_item_db_id, $args ) {
        
            // Check if element is properly sent
            if ( is_array( $_REQUEST['menu-item-subtitle']) ) {
                $subtitle_value = $_REQUEST['menu-item-subtitle'][$menu_item_db_id];
                update_post_meta( $menu_item_db_id, '_menu_item_subtitle', $subtitle_value );
            }
        
        }
        /**
         * Define new Walker edit
         *
         * @access      public
         * @since       1.0 
         * @return      void
        */
        function rc_scm_edit_walker($walker,$menu_id) {
        
            return 'Walker_Nav_Menu_Edit_Custom';
        
        }
        
    
    }
    // instantiate plugin's class
    $GLOBALS['sweet_custom_menu'] = new rc_sweet_custom_menu();
    

    edit_custom_walker.php

    <?php
    class Walker_Nav_Menu_Edit_Custom extends Walker_Nav_Menu {
    
    	public function start_el( &$output, $item, $depth = 0, $args = array(), $id = 0 ) {
    		global $_wp_nav_menu_max_depth;
    		$_wp_nav_menu_max_depth = $depth > $_wp_nav_menu_max_depth ? $depth : $_wp_nav_menu_max_depth;
    
    		ob_start();
    		$item_id = esc_attr( $item->ID );
    		$removed_args = array(
    			'action',
    			'customlink-tab',
    			'edit-menu-item',
    			'menu-item',
    			'page-tab',
    			'_wpnonce',
    		);
    
    		$original_title = '';
    		if ( 'taxonomy' == $item->type ) {
    			$original_title = get_term_field( 'name', $item->object_id, $item->object, 'raw' );
    			if ( is_wp_error( $original_title ) )
    				$original_title = false;
    		} elseif ( 'post_type' == $item->type ) {
    			$original_object = get_post( $item->object_id );
    			$original_title = get_the_title( $original_object->ID );
    		}
    
    		$classes = array(
    			'menu-item menu-item-depth-' . $depth,
    			'menu-item-' . esc_attr( $item->object ),
    			'menu-item-edit-' . ( ( isset( $_GET['edit-menu-item'] ) && $item_id == $_GET['edit-menu-item'] ) ? 'active' : 'inactive'),
    		);
    
    		$title = $item->title;
    
    		if ( ! empty( $item->_invalid ) ) {
    			$classes[] = 'menu-item-invalid';
    			/* translators: %s: title of menu item which is invalid */
    			$title = sprintf( __( '%s (Invalid)' ), $item->title );
    		} elseif ( isset( $item->post_status ) && 'draft' == $item->post_status ) {
    			$classes[] = 'pending';
    			/* translators: %s: title of menu item in draft status */
    			$title = sprintf( __('%s (Pending)'), $item->title );
    		}
    
    		$title = ( ! isset( $item->label ) || '' == $item->label ) ? $title : $item->label;
    
    		$submenu_text = '';
    		if ( 0 == $depth )
    			$submenu_text = 'style="display: none;"';
    
    		?>
    		<li id="menu-item-<?php echo $item_id; ?>" class="<?php echo implode(' ', $classes ); ?>">
    			<dl class="menu-item-bar">
    				<dt class="menu-item-handle">
    					<span class="item-title"><span class="menu-item-title"><?php echo esc_html( $title ); ?></span> <span class="is-submenu" <?php echo $submenu_text; ?>><?php _e( 'sub item' ); ?></span></span>
    					<span class="item-controls">
    						<span class="item-type"><?php echo esc_html( $item->type_label ); ?></span>
    						<span class="item-order hide-if-js">
    							<a href="<?php
    								echo wp_nonce_url(
    									add_query_arg(
    										array(
    											'action' => 'move-up-menu-item',
    											'menu-item' => $item_id,
    										),
    										remove_query_arg($removed_args, admin_url( 'nav-menus.php' ) )
    									),
    									'move-menu_item'
    								);
    							?>" class="item-move-up"><abbr title="<?php esc_attr_e('Move up'); ?>">↑</abbr></a>
    							|
    							<a href="<?php
    								echo wp_nonce_url(
    									add_query_arg(
    										array(
    											'action' => 'move-down-menu-item',
    											'menu-item' => $item_id,
    										),
    										remove_query_arg($removed_args, admin_url( 'nav-menus.php' ) )
    									),
    									'move-menu_item'
    								);
    							?>" class="item-move-down"><abbr title="<?php esc_attr_e('Move down'); ?>">↓</abbr></a>
    						</span>
    						<a class="item-edit" id="edit-<?php echo $item_id; ?>" title="<?php esc_attr_e('Edit Menu Item'); ?>" href="<?php
    							echo ( isset( $_GET['edit-menu-item'] ) && $item_id == $_GET['edit-menu-item'] ) ? admin_url( 'nav-menus.php' ) : add_query_arg( 'edit-menu-item', $item_id, remove_query_arg( $removed_args, admin_url( 'nav-menus.php#menu-item-settings-' . $item_id ) ) );
    						?>"><?php _e( 'Edit Menu Item' ); ?></a>
    					</span>
    				</dt>
    			</dl>
    
    			<div class="menu-item-settings wp-clearfix" id="menu-item-settings-<?php echo $item_id; ?>">
    				<?php if( 'custom' == $item->type ) : ?>
    					<p class="field-url description description-wide">
    						<label for="edit-menu-item-url-<?php echo $item_id; ?>">
    							<?php _e( 'URL' ); ?><br />
    							<input type="text" id="edit-menu-item-url-<?php echo $item_id; ?>" class="widefat code edit-menu-item-url" name="menu-item-url[<?php echo $item_id; ?>]" value="<?php echo esc_attr( $item->url ); ?>" />
    						</label>
    					</p>
    				<?php endif; ?>
    				<p class="description description-thin">
    					<label for="edit-menu-item-title-<?php echo $item_id; ?>">
    						<?php _e( 'Navigation Label' ); ?><br />
    						<input type="text" id="edit-menu-item-title-<?php echo $item_id; ?>" class="widefat edit-menu-item-title" name="menu-item-title[<?php echo $item_id; ?>]" value="<?php echo esc_attr( $item->title ); ?>" />
    					</label>
    				</p>
    				<p class="description description-thin">
    					<label for="edit-menu-item-attr-title-<?php echo $item_id; ?>">
    						<?php _e( 'Title Attribute' ); ?><br />
    						<input type="text" id="edit-menu-item-attr-title-<?php echo $item_id; ?>" class="widefat edit-menu-item-attr-title" name="menu-item-attr-title[<?php echo $item_id; ?>]" value="<?php echo esc_attr( $item->post_excerpt ); ?>" />
    					</label>
    				</p>
    				<p class="field-link-target description">
    					<label for="edit-menu-item-target-<?php echo $item_id; ?>">
    						<input type="checkbox" id="edit-menu-item-target-<?php echo $item_id; ?>" value="_blank" name="menu-item-target[<?php echo $item_id; ?>]"<?php checked( $item->target, '_blank' ); ?> />
    						<?php _e( 'Open link in a new window/tab' ); ?>
    					</label>
    				</p>
    				<p class="field-css-classes description description-thin">
    					<label for="edit-menu-item-classes-<?php echo $item_id; ?>">
    						<?php _e( 'CSS Classes (optional)' ); ?><br />
    						<input type="text" id="edit-menu-item-classes-<?php echo $item_id; ?>" class="widefat code edit-menu-item-classes" name="menu-item-classes[<?php echo $item_id; ?>]" value="<?php echo esc_attr( implode(' ', $item->classes ) ); ?>" />
    					</label>
    				</p>
    				<p class="field-xfn description description-thin">
    					<label for="edit-menu-item-xfn-<?php echo $item_id; ?>">
    						<?php _e( 'Link Relationship (XFN)' ); ?><br />
    						<input type="text" id="edit-menu-item-xfn-<?php echo $item_id; ?>" class="widefat code edit-menu-item-xfn" name="menu-item-xfn[<?php echo $item_id; ?>]" value="<?php echo esc_attr( $item->xfn ); ?>" />
    					</label>
    				</p>
    
    				<?php
    				// This is the added section
    				do_action( 'wp_nav_menu_item_custom_fields', $item_id, $item, $depth, $args );
    				// end added section
    				?>
    
    				<p class="field-description description description-wide">
    					<label for="edit-menu-item-description-<?php echo $item_id; ?>">
    						<?php _e( 'Description' ); ?><br />
    						<textarea id="edit-menu-item-description-<?php echo $item_id; ?>" class="widefat edit-menu-item-description" rows="3" cols="20" name="menu-item-description[<?php echo $item_id; ?>]"><?php echo esc_html( $item->description ); // textarea_escaped ?></textarea>
    						<span class="description"><?php _e('The description will be displayed in the menu if the current theme supports it.'); ?></span>
    					</label>
    				</p>
    				<?php
    	            /* New fields insertion ends here */
    	            //$locations = get_nav_menu_locations();
    	            ?>
    	            <div id="metabox_wrapper">
    					<img id="image-tag">
    					<input type="hidden" id="img-hidden-field" name="custom_image_data_<?=$item_id?>">
    					<input type="button" id="image-upload-button" class="button" value="Add Image">
    					<input type="button" id="image-delete-button" class="button" value="Delete Image">
    				</div>
    	            <?php
    	            /* End New fields insertion ends here */
    	            /*Save field*/
    	            update_post_meta($item_id, 'custom_image_data_' . $item_id, $_POST['custom_image_data_'.$item_id]);
    	            ?>
    				<div class="menu-item-actions description-wide submitbox">
    					<?php if( 'custom' != $item->type && $original_title !== false ) : ?>
    						<p class="link-to-original">
    							<?php printf( __('Original: %s'), '<a href="' . esc_attr( $item->url ) . '">' . esc_html( $original_title ) . '</a>' ); ?>
    						</p>
    					<?php endif; ?>
    					<a class="item-delete submitdelete deletion" id="delete-<?php echo $item_id; ?>" href="<?php
    					echo wp_nonce_url(
    						add_query_arg(
    							array(
    								'action' => 'delete-menu-item',
    								'menu-item' => $item_id,
    							),
    							admin_url( 'nav-menus.php' )
    						),
    						'delete-menu_item_' . $item_id
    					); ?>"><?php _e( 'Remove' ); ?></a> <span class="meta-sep hide-if-no-js"> | </span> <a class="item-cancel submitcancel hide-if-no-js" id="cancel-<?php echo $item_id; ?>" href="<?php echo esc_url( add_query_arg( array( 'edit-menu-item' => $item_id, 'cancel' => time() ), admin_url( 'nav-menus.php' ) ) );
    						?>#menu-item-settings-<?php echo $item_id; ?>"><?php _e('Cancel'); ?></a>
    				</div>
    
    				<input class="menu-item-data-db-id" type="hidden" name="menu-item-db-id[<?php echo $item_id; ?>]" value="<?php echo $item_id; ?>" />
    				<input class="menu-item-data-object-id" type="hidden" name="menu-item-object-id[<?php echo $item_id; ?>]" value="<?php echo esc_attr( $item->object_id ); ?>" />
    				<input class="menu-item-data-object" type="hidden" name="menu-item-object[<?php echo $item_id; ?>]" value="<?php echo esc_attr( $item->object ); ?>" />
    				<input class="menu-item-data-parent-id" type="hidden" name="menu-item-parent-id[<?php echo $item_id; ?>]" value="<?php echo esc_attr( $item->menu_item_parent ); ?>" />
    				<input class="menu-item-data-position" type="hidden" name="menu-item-position[<?php echo $item_id; ?>]" value="<?php echo esc_attr( $item->menu_order ); ?>" />
    				<input class="menu-item-data-type" type="hidden" name="menu-item-type[<?php echo $item_id; ?>]" value="<?php echo esc_attr( $item->type ); ?>" />
    			</div><!-- .menu-item-settings-->
    			<ul class="menu-item-transport"></ul>
    		<?php
    		$output .= ob_get_clean();
    	}
    }

    uploader.js

    var addButton = document.getElementById( 'image-upload-button' );
    var deleteButton = document.getElementById( 'image-delete-button' );
    var img = document.getElementById( 'image-tag' );
    var hidden = document.getElementById( 'img-hidden-field' );
    var customUploader = wp.media({
        title: 'Select an Image',
        button: {
            text: 'Use this Image'
        },
        multiple: false
    });
    
    addButton.addEventListener( 'click', function() {
        if ( customUploader ) {
            customUploader.open();
        }
    } );
    
    customUploader.on( 'select', function() {
        var attachment = customUploader.state().get('selection').first().toJSON();
        img.setAttribute( 'src', attachment.url );
        hidden.setAttribute( 'value', attachment.url );
        toggleVisibility( 'ADD' );
    } );
    
    deleteButton.addEventListener( 'click', function() {
        img.removeAttribute( 'src' );
        hidden.removeAttribute( 'value' );
        toggleVisibility( 'DELETE' );
    } );
    
    var toggleVisibility = function( action ) {
        if ( 'ADD' === action ) {
            addButton.style.display = 'none';
            deleteButton.style.display = '';
            img.setAttribute( 'style', 'width: 100%;' );
        }
    
        if ( 'DELETE' === action ) {
            addButton.style.display = '';
            deleteButton.style.display = 'none';
            img.removeAttribute('style');
        }
    };
    
    window.addEventListener( 'DOMContentLoaded', function() {
        if ( "" === customUploads.imageData || 0 === customUploads.imageData.length ) {
            toggleVisibility( 'DELETE' );
        } else {
            img.setAttribute( 'src', customUploads.imageData.src );
            hidden.setAttribute( 'value', JSON.stringify([ customUploads.imageData ]) );
            toggleVisibility( 'ADD' );
        }
    } );

    When I come to “Menus” (nav-menus.php), I see one error
    http://i.piccy.info/i9/47dd7ba8f6c69155d4dc3f9684ca69ce/1505318921/45990/1131628/Untitled.png
    When I select menu and click it, then the error disappears.
    When I open the first menu item, my code works correctly and I see the “Add Image” button.
    http://i.piccy.info/i9/b5891bc79f1da79f5d4baf3576aae4bc/1505319343/38394/1131628/Untitled1.png
    I click to “Add Image” button and then I see “Select an Image” panel
    http://i.piccy.info/i9/be21604be27bad69fd40f6b5cfc35506/1505319483/31987/1131628/Untitled3.png
    I can select image from my PC
    When I uploaded image, the “Add Image” button disappears and the “Delete Image” button appears. (That okay. The script works as I have conceived)
    http://i.piccy.info/i9/a5e4482bac24439680445f0e143279c8/1505319979/192472/1131628/Untitled4.png
    If I click on the “Save” button, the image will be saved.
    http://i.piccy.info/i9/95a876afa9ab4917f6019568f6e8a574/1505320170/57637/1131628/Untitled5.jpg

    I want to attach the images to the menu items, but I have two problems:
    1)The error – http://i.piccy.info/i9/47dd7ba8f6c69155d4dc3f9684ca69ce/1505318921/45990/1131628/Untitled.png
    2)I cannot attach images to second item or any other item (I do not know how I can do it. I tried but it ended in failure)
    http://i.piccy.info/i9/ffe492ec1ef10329fd8820e52201ec69/1505321382/25821/1131628/Untitled6.png

    I would like to apologize if my idea is not understood. I tried to tell as much as possible.
    May you help me ?

    Moderator bcworkz

    (@bcworkz)

    The PHP error is apparently because you are not getting the currently displayed menu property from the correct place. You are getting it from code that executes when a menu is selected, which is good for when the user changes menus, but you first need to get the currently displayed menu. I’m not sure where that is stored, but sifting through the menu screen code should give you a good clue.

    Like Andrew had mentioned, you shouldn’t need to add JS code for every menu item. If you can resolve this, maybe the above PHP issue will not matter. This is a good example of where jQuery can be very useful. As it’s loaded for this screen anyway, there’s no reason to not take advantage of it. You can then write code that executes on the click event for any menu item, based on its CSS selector. jQuery will pass that particular node that was clicked to your callback, so it’s quite simple to apply your code the this object without involving any other nodes that are using the same selector.

    If you can properly implement a jQuery solution, it should also resolve the problem of code only functioning on the first item. In short, it appears all of your issues could be resolved by implementing a jQuery based approach.

Viewing 3 replies - 1 through 3 (of 3 total)
  • You must be logged in to reply to this topic.