Ticket #11817: menus.2.diff
File menus.2.diff, 93.2 KB (added by , 15 years ago) |
---|
-
wp-includes/default-menu-items.php
1 <?php 2 3 /** 4 * Home Menu Item class 5 * 6 * @since 3.0 7 */ 8 class WP_Menu_Item_Home extends WP_Menu_Item { 9 10 function WP_Menu_Item_Home() { 11 $menu_item_ops = array('classname' => 'menu_item_home', 'description' => __('The site homepage') ); 12 $this->WP_Menu_Item('home', __('Home'), $menu_item_ops); 13 } 14 15 function display( $args, $instance ) { 16 // TODO 17 } 18 } 19 20 /** 21 * Page Menu Item class 22 * 23 * @since 3.0 24 */ 25 class WP_Menu_Item_Page extends WP_Menu_Item { 26 27 function WP_Menu_Item_Page() { 28 $menu_item_ops = array('classname' => 'menu_item_page', 'description' => __('A WordPress page') ); 29 $this->WP_Menu_Item('page', __('Page'), $menu_item_ops); 30 } 31 32 function display( $args, $instance ) { 33 extract( $args ); 34 35 $title = apply_filters('menu_title', empty( $instance['title'] ) ? __( 'Page' ) : $instance['title']); 36 $sortby = empty( $instance['sortby'] ) ? 'menu_order' : $instance['sortby']; 37 $exclude = empty( $instance['exclude'] ) ? '' : $instance['exclude']; 38 39 if ( $sortby == 'menu_order' ) 40 $sortby = 'menu_order, post_title'; 41 42 wp_list_page( apply_filters('menu_page_args', array('title_li' => '', 'sort_column' => $sortby, 'exclude' => $exclude) ) ); 43 } 44 45 function update( $new_instance, $old_instance ) { 46 $instance = $old_instance; 47 $instance['title'] = strip_tags($new_instance['title']); 48 if ( in_array( $new_instance['sortby'], array( 'post_title', 'menu_order', 'ID' ) ) ) { 49 $instance['sortby'] = $new_instance['sortby']; 50 } else { 51 $instance['sortby'] = 'menu_order'; 52 } 53 54 $instance['exclude'] = strip_tags( $new_instance['exclude'] ); 55 56 return $instance; 57 } 58 59 function form( $instance ) { 60 //Defaults 61 $instance = wp_parse_args( (array) $instance, array( 'sortby' => 'post_title', 'title' => '', 'exclude' => '') ); 62 $title = esc_attr( $instance['title'] ); 63 $exclude = esc_attr( $instance['exclude'] ); 64 ?> 65 <p><label for="<?php echo $this->get_field_id('title'); ?>"><?php _e('Title:'); ?></label> <input class="widefat" id="<?php echo $this->get_field_id('title'); ?>" name="<?php echo $this->get_field_name('title'); ?>" type="text" value="<?php echo $title; ?>" /></p> 66 <p> 67 <label for="<?php echo $this->get_field_id('sortby'); ?>"><?php _e( 'Sort by:' ); ?></label> 68 <select name="<?php echo $this->get_field_name('sortby'); ?>" id="<?php echo $this->get_field_id('sortby'); ?>" class="widefat"> 69 <option value="post_title"<?php selected( $instance['sortby'], 'post_title' ); ?>><?php _e('Page title'); ?></option> 70 <option value="menu_order"<?php selected( $instance['sortby'], 'menu_order' ); ?>><?php _e('Page order'); ?></option> 71 <option value="ID"<?php selected( $instance['sortby'], 'ID' ); ?>><?php _e( 'Page ID' ); ?></option> 72 </select> 73 </p> 74 <p> 75 <label for="<?php echo $this->get_field_id('exclude'); ?>"><?php _e( 'Exclude:' ); ?></label> <input type="text" value="<?php echo $exclude; ?>" name="<?php echo $this->get_field_name('exclude'); ?>" id="<?php echo $this->get_field_id('exclude'); ?>" class="widefat" /> 76 <br /> 77 <small><?php _e( 'Page IDs, separated by commas.' ); ?></small> 78 </p> 79 <?php 80 } 81 } 82 83 84 /** 85 * Link menu item class 86 * 87 * @since 3.0 88 */ 89 class WP_Menu_Item_Link extends WP_Menu_Item { 90 91 function WP_Menu_Item_Link() { 92 $menu_item_ops = array('description' => __('An external link') ); 93 $this->WP_Menu_Item('link', __('Link'), $menu_item_ops); 94 } 95 96 function display( $args, $instance ) { 97 extract($args, EXTR_SKIP); 98 99 $show_description = isset($instance['description']) ? $instance['description'] : false; 100 $show_name = isset($instance['name']) ? $instance['name'] : false; 101 $show_rating = isset($instance['rating']) ? $instance['rating'] : false; 102 $show_images = isset($instance['images']) ? $instance['images'] : true; 103 $category = isset($instance['category']) ? $instance['category'] : false; 104 105 wp_list_bookmarks(apply_filters('menu_item_links_args', array( 106 'title_before' => $before_title, 'title_after' => $after_title, 107 'show_images' => $show_images, 'show_description' => $show_description, 108 'show_name' => $show_name, 'show_rating' => $show_rating, 109 'category' => $category, 'class' => 'linkcat menu_item' 110 ))); 111 } 112 113 function update( $new_instance, $old_instance ) { 114 $new_instance = (array) $new_instance; 115 $instance = array( 'images' => 0, 'name' => 0, 'description' => 0, 'rating' => 0); 116 foreach ( $instance as $field => $val ) { 117 if ( isset($new_instance[$field]) ) 118 $instance[$field] = 1; 119 } 120 $instance['category'] = intval($new_instance['category']); 121 122 return $instance; 123 } 124 125 function form( $instance ) { 126 127 //Defaults 128 $instance = wp_parse_args( (array) $instance, array( 'images' => true, 'name' => true, 'description' => false, 'rating' => false, 'category' => false ) ); 129 $link_cats = get_terms( 'link_category'); 130 ?> 131 <p> 132 <label for="<?php echo $this->get_field_id('category'); ?>" class="screen-reader-text"><?php _e('Select Link Category'); ?></label> 133 <select class="widefat" id="<?php echo $this->get_field_id('category'); ?>" name="<?php echo $this->get_field_name('category'); ?>"> 134 <option value=""><?php _e('All Links'); ?></option> 135 <?php 136 foreach ( $link_cats as $link_cat ) { 137 echo '<option value="' . intval($link_cat->term_id) . '"' 138 . ( $link_cat->term_id == $instance['category'] ? ' selected="selected"' : '' ) 139 . '>' . $link_cat->name . "</option>\n"; 140 } 141 ?> 142 </select></p> 143 <p> 144 <input class="checkbox" type="checkbox" <?php checked($instance['images'], true) ?> id="<?php echo $this->get_field_id('images'); ?>" name="<?php echo $this->get_field_name('images'); ?>" /> 145 <label for="<?php echo $this->get_field_id('images'); ?>"><?php _e('Show Link Image'); ?></label><br /> 146 <input class="checkbox" type="checkbox" <?php checked($instance['name'], true) ?> id="<?php echo $this->get_field_id('name'); ?>" name="<?php echo $this->get_field_name('name'); ?>" /> 147 <label for="<?php echo $this->get_field_id('name'); ?>"><?php _e('Show Link Name'); ?></label><br /> 148 <input class="checkbox" type="checkbox" <?php checked($instance['description'], true) ?> id="<?php echo $this->get_field_id('description'); ?>" name="<?php echo $this->get_field_name('description'); ?>" /> 149 <label for="<?php echo $this->get_field_id('description'); ?>"><?php _e('Show Link Description'); ?></label><br /> 150 <input class="checkbox" type="checkbox" <?php checked($instance['rating'], true) ?> id="<?php echo $this->get_field_id('rating'); ?>" name="<?php echo $this->get_field_name('rating'); ?>" /> 151 <label for="<?php echo $this->get_field_id('rating'); ?>"><?php _e('Show Link Rating'); ?></label> 152 </p> 153 <?php 154 } 155 } 156 157 /** 158 * Category menu item class 159 * 160 * @since 3.0 161 */ 162 class WP_Menu_Item_Category extends WP_Menu_Item { 163 164 function WP_Menu_Item_Category() { 165 $menu_item_ops = array( 'classname' => 'menu_item_category', 'description' => __('A WordPress category') ); 166 $this->WP_Menu_Item('category', __('Category'), $menu_item_ops); 167 } 168 169 function display( $args, $instance ) { 170 extract( $args ); 171 172 $title = apply_filters('menu_item_title', empty( $instance['title'] ) ? __( 'Categories' ) : $instance['title']); 173 $c = $instance['count'] ? '1' : '0'; 174 $h = $instance['hierarchical'] ? '1' : '0'; 175 $d = $instance['dropdown'] ? '1' : '0'; 176 177 $cat_args = array('orderby' => 'name', 'show_count' => $c, 'hierarchical' => $h); 178 179 if ( $d ) { 180 $cat_args['show_option_none'] = __('Select Category'); 181 wp_dropdown_categories(apply_filters('menu_item_category_dropdown_args', $cat_args)); 182 ?> 183 184 <script type='text/javascript'> 185 /* <![CDATA[ */ 186 var dropdown = document.getElementById("cat"); 187 function onCatChange() { 188 if ( dropdown.options[dropdown.selectedIndex].value > 0 ) { 189 location.href = "<?php echo home_url(); ?>/?cat="+dropdown.options[dropdown.selectedIndex].value; 190 } 191 } 192 dropdown.onchange = onCatChange; 193 /* ]]> */ 194 </script> 195 196 <?php 197 } else { 198 ?> 199 <ul> 200 <?php 201 $cat_args['title_li'] = ''; 202 wp_list_categories(apply_filters('menu_item_category_args', $cat_args)); 203 ?> 204 </ul> 205 <?php 206 } 207 } 208 209 function update( $new_instance, $old_instance ) { 210 $instance = $old_instance; 211 $instance['title'] = strip_tags($new_instance['title']); 212 $instance['count'] = $new_instance['count'] ? 1 : 0; 213 $instance['hierarchical'] = $new_instance['hierarchical'] ? 1 : 0; 214 $instance['dropdown'] = $new_instance['dropdown'] ? 1 : 0; 215 216 return $instance; 217 } 218 219 function form( $instance ) { 220 //Defaults 221 $instance = wp_parse_args( (array) $instance, array( 'title' => '') ); 222 $title = esc_attr( $instance['title'] ); 223 $count = isset($instance['count']) ? (bool) $instance['count'] :false; 224 $hierarchical = isset( $instance['hierarchical'] ) ? (bool) $instance['hierarchical'] : false; 225 $dropdown = isset( $instance['dropdown'] ) ? (bool) $instance['dropdown'] : false; 226 ?> 227 <p><label for="<?php echo $this->get_field_id('title'); ?>"><?php _e( 'Title:' ); ?></label> 228 <input class="widefat" id="<?php echo $this->get_field_id('title'); ?>" name="<?php echo $this->get_field_name('title'); ?>" type="text" value="<?php echo $title; ?>" /></p> 229 230 <p><input type="checkbox" class="checkbox" id="<?php echo $this->get_field_id('dropdown'); ?>" name="<?php echo $this->get_field_name('dropdown'); ?>"<?php checked( $dropdown ); ?> /> 231 <label for="<?php echo $this->get_field_id('dropdown'); ?>"><?php _e( 'Show as dropdown' ); ?></label><br /> 232 233 <input type="checkbox" class="checkbox" id="<?php echo $this->get_field_id('count'); ?>" name="<?php echo $this->get_field_name('count'); ?>"<?php checked( $count ); ?> /> 234 <label for="<?php echo $this->get_field_id('count'); ?>"><?php _e( 'Show post counts' ); ?></label><br /> 235 236 <input type="checkbox" class="checkbox" id="<?php echo $this->get_field_id('hierarchical'); ?>" name="<?php echo $this->get_field_name('hierarchical'); ?>"<?php checked( $hierarchical ); ?> /> 237 <label for="<?php echo $this->get_field_id('hierarchical'); ?>"><?php _e( 'Show hierarchy' ); ?></label></p> 238 <?php 239 } 240 } 241 242 /** 243 * Register all of the default WordPress menu items on startup. 244 * 245 * Calls 'menu_items_init' action after all of the WordPress menu items have been 246 * registered. 247 * 248 * @since 3.0 249 */ 250 function wp_menu_items_init() { 251 if ( !is_blog_installed() ) 252 return; 253 254 register_menu_item('WP_Menu_Item_Home'); 255 register_menu_item('WP_Menu_Item_Page'); 256 register_menu_item('WP_Menu_Item_Link'); 257 register_menu_item('WP_Menu_Item_Category'); 258 259 do_action('menu_items_init'); 260 } 261 262 add_action('init', 'wp_menu_items_init', 1); 263 -
wp-includes/menus.php
1 <?php 2 /** 3 * API for creating dynamic menus without hardcoding functionality into 4 * themes. Includes both internal WordPress routines and theme use routines. 5 * 6 * @link http://codex.wordpress.org/Plugins/WordPress_Menu_Items WordPress Menu_Items 7 * @link http://codex.wordpress.org/Plugins/WordPress_Menu_Items_Api Menu_Items API 8 * 9 * @package WordPress 10 * @subpackage Menus 11 */ 12 13 /** 14 * This class must be extended for each menu item and WP_Menu_Item::menu_item(), WP_Menu_Item::update() 15 * and WP_Menu_Item::form() need to be over-ridden. 16 * 17 * @package WordPress 18 * @subpackage Menu_Items 19 * @since 3.0 20 */ 21 class WP_Menu_Item { 22 23 var $id_base; // Root id for all menu_items of this type. 24 var $name; // Name for this menu_item type. 25 var $menu_item_options; // Option array passed to wp_register_menu_item() 26 var $control_options; // Option array passed to wp_register_menu_item_control() 27 28 var $number = false; // Unique ID number of the current instance. 29 var $id = false; // Unique ID string of the current instance (id_base-number) 30 var $updated = false; // Set true when we update the data after a POST submit - makes sure we don't do it twice. 31 32 // Member functions that you must over-ride. 33 34 /** Echo the menu_item content. 35 * 36 * Subclasses should over-ride this function to generate their menu_item code. 37 * 38 * @param array $args Display arguments including before_title, after_title, before_menu_item, and after_menu_item. 39 * @param array $instance The settings for the particular instance of the menu_item 40 */ 41 function output($args, $instance) { 42 die('function WP_Menu_Item::menu_item() must be over-ridden in a sub-class.'); 43 } 44 45 /** Update a particular instance. 46 * 47 * This function should check that $new_instance is set correctly. 48 * The newly calculated value of $instance should be returned. 49 * If "false" is returned, the instance won't be saved/updated. 50 * 51 * @param array $new_instance New settings for this instance as input by the user via form() 52 * @param array $old_instance Old settings for this instance 53 * @return array Settings to save or bool false to cancel saving 54 */ 55 function update($new_instance, $old_instance) { 56 return $new_instance; 57 } 58 59 /** Echo the settings update form 60 * 61 * @param array $instance Current settings 62 */ 63 function form($instance) { 64 echo '<p class="no-options-menu_item">' . __('There are no options for this menu item.') . '</p>'; 65 return 'noform'; 66 } 67 68 // Functions you'll need to call. 69 70 /** 71 * PHP4 constructor 72 */ 73 function WP_Menu_Item( $id_base = false, $name, $menu_item_options = array(), $control_options = array() ) { 74 $this->__construct( $id_base, $name, $menu_item_options, $control_options ); 75 } 76 77 /** 78 * PHP5 constructor 79 * 80 * @param string $id_base Optional Base ID for the menu_item, lower case, 81 * if left empty a portion of the menu_item's class name will be used. Has to be unique. 82 * @param string $name Name for the menu_item displayed on the configuration page. 83 * @param array $menu_item_options Optional Passed to wp_register_menu_item() 84 * - description: shown on the configuration page 85 * - classname 86 * @param array $control_options Optional Passed to wp_register_menu_item_control() 87 * - width: required if more than 250px 88 * - height: currently not used but may be needed in the future 89 */ 90 function __construct( $id_base = false, $name, $menu_item_options = array(), $control_options = array() ) { 91 $this->id_base = empty($id_base) ? preg_replace( '/(wp_)?menu_item_/', '', strtolower(get_class($this)) ) : strtolower($id_base); 92 $this->name = $name; 93 $this->option_name = 'menu_item_' . $this->id_base; 94 $this->menu_item_options = wp_parse_args( $menu_item_options, array('classname' => $this->option_name) ); 95 $this->control_options = wp_parse_args( $control_options, array('id_base' => $this->id_base) ); 96 } 97 98 /** 99 * Constructs name attributes for use in form() fields 100 * 101 * This function should be used in form() methods to create name attributes for fields to be saved by update() 102 * 103 * @param string $field_name Field name 104 * @return string Name attribute for $field_name 105 */ 106 function get_field_name($field_name) { 107 return 'menu-item-' . $this->id_base . '[' . $this->number . '][' . $field_name . ']'; 108 } 109 110 /** 111 * Constructs id attributes for use in form() fields 112 * 113 * This function should be used in form() methods to create id attributes for fields to be saved by update() 114 * 115 * @param string $field_name Field name 116 * @return string ID attribute for $field_name 117 */ 118 function get_field_id($field_name) { 119 return 'menu-item-' . $this->id_base . '-' . $this->number . '-' . $field_name; 120 } 121 122 // Private Functions. Don't worry about these. 123 124 function _register() { 125 $settings = $this->get_settings(); 126 $empty = true; 127 128 if ( is_array($settings) ) { 129 foreach ( array_keys($settings) as $number ) { 130 if ( is_numeric($number) ) { 131 $this->_set($number); 132 $this->_register_one($number); 133 $empty = false; 134 } 135 } 136 } 137 138 if ( $empty ) { 139 // If there are none, we register the menu_item's existance with a 140 // generic template 141 $this->_set(1); 142 $this->_register_one(); 143 } 144 } 145 146 function _set($number) { 147 $this->number = $number; 148 $this->id = $this->id_base . '-' . $number; 149 } 150 151 function _get_display_callback() { 152 return array(&$this, 'display_callback'); 153 } 154 155 function _get_update_callback() { 156 return array(&$this, 'update_callback'); 157 } 158 159 function _get_form_callback() { 160 return array(&$this, 'form_callback'); 161 } 162 163 /** Generate the actual menu_item content. 164 * Just finds the instance and calls output(). 165 * Do NOT over-ride this function. */ 166 function display_callback( $args, $menu_item_args = 1 ) { 167 if ( is_numeric($menu_item_args) ) 168 $menu_item_args = array( 'number' => $menu_item_args ); 169 170 $menu_item_args = wp_parse_args( $menu_item_args, array( 'number' => -1 ) ); 171 $this->_set( $menu_item_args['number'] ); 172 $instance = $this->get_settings(); 173 174 if ( array_key_exists( $this->number, $instance ) ) { 175 $instance = $instance[$this->number]; 176 // filters the menu_item's settings, return false to stop displaying the menu_item 177 $instance = apply_filters('menu_item_display_callback', $instance, $this, $args); 178 if ( false !== $instance ) 179 $this->output($args, $instance); 180 } 181 } 182 183 /** Deal with changed settings. 184 * Do NOT over-ride this function. */ 185 function update_callback( $menu_item_args = 1 ) { 186 global $wp_registered_menu_items; 187 188 if ( is_numeric($menu_item_args) ) 189 $menu_item_args = array( 'number' => $menu_item_args ); 190 191 $menu_item_args = wp_parse_args( $menu_item_args, array( 'number' => -1 ) ); 192 $all_instances = $this->get_settings(); 193 194 // We need to update the data 195 if ( $this->updated ) 196 return; 197 198 $wp_menu_items = wp_get_menu_items(); 199 200 if ( isset($_POST['delete_menu_item']) && $_POST['delete_menu_item'] ) { 201 // Delete the settings for this instance of the menu_item 202 if ( isset($_POST['the-menu-item-id']) ) 203 $del_id = $_POST['the-menu-item-id']; 204 else 205 return; 206 207 if ( isset($wp_registered_menu_items[$del_id]['params'][0]['number']) ) { 208 $number = $wp_registered_menu_items[$del_id]['params'][0]['number']; 209 210 if ( $this->id_base . '-' . $number == $del_id ) 211 unset($all_instances[$number]); 212 } 213 } else { 214 if ( isset($_POST['menu-item-' . $this->id_base]) && is_array($_POST['menu-item-' . $this->id_base]) ) { 215 $settings = $_POST['menu-item-' . $this->id_base]; 216 } elseif ( isset($_POST['id_base']) && $_POST['id_base'] == $this->id_base ) { 217 $num = $_POST['multi_number'] ? (int) $_POST['multi_number'] : (int) $_POST['menu_item_number']; 218 $settings = array( $num => array() ); 219 } else { 220 return; 221 } 222 223 foreach ( $settings as $number => $new_instance ) { 224 $new_instance = stripslashes_deep($new_instance); 225 $this->_set($number); 226 227 $old_instance = isset($all_instances[$number]) ? $all_instances[$number] : array(); 228 229 $instance = $this->update($new_instance, $old_instance); 230 231 // filters the menu_item's settings before saving, return false to cancel saving (keep the old settings if updating) 232 $instance = apply_filters('menu_item_update_callback', $instance, $new_instance, $old_instance, $this); 233 if ( false !== $instance ) 234 $all_instances[$number] = $instance; 235 236 break; // run only once 237 } 238 } 239 240 $this->save_settings($all_instances); 241 $this->updated = true; 242 } 243 244 /** Generate the control form. 245 * Do NOT over-ride this function. */ 246 function form_callback( $menu_item_args = 1 ) { 247 if ( is_numeric($menu_item_args) ) 248 $menu_item_args = array( 'number' => $menu_item_args ); 249 250 $menu_item_args = wp_parse_args( $menu_item_args, array( 'number' => -1 ) ); 251 $all_instances = $this->get_settings(); 252 253 if ( -1 == $menu_item_args['number'] ) { 254 // We echo out a form where 'number' can be set later 255 $this->_set('__i__'); 256 $instance = array(); 257 } else { 258 $this->_set($menu_item_args['number']); 259 $instance = $all_instances[ $menu_item_args['number'] ]; 260 } 261 262 // filters the menu_item admin form before displaying, return false to stop displaying it 263 $instance = apply_filters('menu_item_form_callback', $instance, $this); 264 265 $return = null; 266 if ( false !== $instance ) { 267 $return = $this->form($instance); 268 // add extra fields in the menu_item form - be sure to set $return to null if you add any 269 // if the menu_item has no form the text echoed from the default form method can be hidden using css 270 do_action_ref_array( 'in_menu_item_form', array(&$this, &$return, $instance) ); 271 } 272 return $return; 273 } 274 275 /** Helper function: Registers a single instance. */ 276 function _register_one($number = -1) { 277 wp_register_menu_item( $this->id, $this->name, $this->_get_display_callback(), $this->menu_item_options, array( 'number' => $number ) ); 278 _register_menu_item_update_callback( $this->id_base, $this->_get_update_callback(), $this->control_options, array( 'number' => -1 ) ); 279 _register_menu_item_form_callback( $this->id, $this->name, $this->_get_form_callback(), $this->control_options, array( 'number' => $number ) ); 280 } 281 282 function save_settings($settings) { 283 update_option( $this->option_name, $settings ); 284 } 285 286 function get_settings() { 287 $settings = get_option($this->option_name); 288 289 if ( false === $settings && isset($this->alt_option_name) ) 290 $settings = get_option($this->alt_option_name); 291 292 if ( !is_array($settings) ) 293 $settings = array(); 294 295 unset($settings['__i__']); 296 return $settings; 297 } 298 } 299 300 /** 301 * Singleton that registers and instantiates WP_Menu_Item classes. 302 * 303 * @package WordPress 304 * @subpackage Menu_Items 305 * @since 3.0 306 */ 307 class WP_Menu_Item_Factory { 308 var $menu_items = array(); 309 310 function WP_Menu_Item_Factory() { 311 add_action( 'menu_items_init', array( &$this, '_register_menu_items' ), 100 ); 312 } 313 314 function register($menu_item_class) { 315 $this->menu_items[$menu_item_class] = & new $menu_item_class(); 316 } 317 318 function unregister($menu_item_class) { 319 if ( isset($this->menu_items[$menu_item_class]) ) 320 unset($this->menu_items[$menu_item_class]); 321 } 322 323 function _register_menu_items() { 324 global $wp_registered_menu_items; 325 $keys = array_keys($this->menu_items); 326 $registered = array_keys($wp_registered_menu_items); 327 $registered = array_map('_get_menu_item_id_base', $registered); 328 329 foreach ( $keys as $key ) { 330 // don't register new menu_item if old menu_item with the same id is already registered 331 if ( in_array($this->menu_items[$key]->id_base, $registered, true) ) { 332 unset($this->menu_items[$key]); 333 continue; 334 } 335 336 $this->menu_items[$key]->_register(); 337 } 338 } 339 } 340 341 /* Global Variables */ 342 343 /** @ignore */ 344 global $wp_registered_menus, $wp_registered_menu_items, $wp_registered_menu_item_controls, $wp_registered_menu_item_updates; 345 346 /** 347 * Stores the menus, since many themes can have more than one. 348 * 349 * @global array $wp_registered_menus 350 * @since 3.0.0 351 */ 352 $wp_registered_menus = array(); 353 354 /** 355 * Stores the registered menu_items. 356 * 357 * @global array $wp_registered_menu_items 358 * @since 3.0.0 359 */ 360 $wp_registered_menu_items = array(); 361 362 /** 363 * Stores the registered menu_item control (options). 364 * 365 * @global array $wp_registered_menu_item_controls 366 * @since 3.0.0 367 */ 368 $wp_registered_menu_item_controls = array(); 369 $wp_registered_menu_item_updates = array(); 370 371 /** 372 * Private 373 */ 374 $_wp_menu_items = array(); 375 376 /* Template tags & API functions */ 377 378 /** 379 * Register a menu_item 380 * 381 * Registers a WP_Menu_Item menu_item 382 * 383 * @since 3.0.0 384 * 385 * @see WP_Menu_Item 386 * @see WP_Menu_Item_Factory 387 * @uses WP_Menu_Item_Factory 388 * 389 * @param string $menu_item_class The name of a class that extends WP_Menu_Item 390 */ 391 function register_menu_item($menu_item_class) { 392 global $wp_menu_item_factory; 393 394 $wp_menu_item_factory->register($menu_item_class); 395 } 396 397 /** 398 * Unregister a menu_item 399 * 400 * Unregisters a WP_Menu_Item menu_item. Useful for unregistering default menu_items. 401 * Run within a function hooked to the menu_items_init action. 402 * 403 * @since 3.0.0 404 * 405 * @see WP_Menu_Item 406 * @see WP_Menu_Item_Factory 407 * @uses WP_Menu_Item_Factory 408 * 409 * @param string $menu_item_class The name of a class that extends WP_Menu_Item 410 */ 411 function unregister_menu_item($menu_item_class) { 412 global $wp_menu_item_factory; 413 414 $wp_menu_item_factory->unregister($menu_item_class); 415 } 416 417 /** 418 * Creates multiple menus. 419 * 420 * If you wanted to quickly create multiple menus for a theme or internally. 421 * This function will allow you to do so. If you don't pass the 'name' and/or 422 * 'id' in $args, then they will be built for you. 423 * 424 * The default for the name is "Menu #", with '#' being replaced with the 425 * number the menu is currently when greater than one. If first menu, the 426 * name will be just "Menu". The default for id is "menu-" followed by the 427 * number the menu creation is currently at. 428 * 429 * @since 3.0.0 430 * 431 * @see register_menu() The second parameter is documented by register_menu() and is the same here. 432 * @uses parse_str() Converts a string to an array to be used in the rest of the function. 433 * @uses register_menu() Sends single menu information [name, id] to this 434 * function to handle building the menu. 435 * 436 * @param int $number Number of menus to create. 437 * @param string|array $args Builds Menu based off of 'name' and 'id' values. 438 */ 439 function register_menus($number = 1, $args = array()) { 440 global $wp_registered_menus; 441 $number = (int) $number; 442 443 if ( is_string($args) ) 444 parse_str($args, $args); 445 446 for ( $i=1; $i <= $number; $i++ ) { 447 $_args = $args; 448 449 if ( $number > 1 ) { 450 $_args['name'] = isset($args['name']) ? sprintf($args['name'], $i) : sprintf(__('Menu %d'), $i); 451 } else { 452 $_args['name'] = isset($args['name']) ? $args['name'] : __('Menu'); 453 } 454 455 if ( !isset($args['id']) ) { 456 $n = count($wp_registered_menus); 457 do { 458 $n++; 459 $_args['id'] = "menu-$n"; 460 } while (isset($wp_registered_menus[$_args['id']])); 461 } 462 463 register_menu($_args); 464 } 465 } 466 467 /** 468 * Builds the definition for a single menu and returns the ID. 469 * 470 * The $args parameter takes either a string or an array with 'name' and 'id' 471 * contained in either usage. It will be noted that the values will be applied 472 * to all menus, so if creating more than one, it will be advised to allow 473 * for WordPress to create the defaults for you. 474 * 475 * Example for string would be <code>'name=whatever;id=whatever1'</code> and for 476 * the array it would be <code>array( 477 * 'name' => 'whatever', 478 * 'id' => 'whatever1')</code>. 479 * 480 * name - The name of the menu, which presumably the title which will be 481 * displayed. 482 * id - The unique identifier by which the menu will be called by. 483 * before_menu_item - The content that will prepended to the menu_items when they are 484 * displayed. 485 * after_menu_item - The content that will be appended to the menu_items when they are 486 * displayed. 487 * before_title - The content that will be prepended to the title when displayed. 488 * after_title - the content that will be appended to the title when displayed. 489 * 490 * <em>Content</em> is assumed to be HTML and should be formatted as such, but 491 * doesn't have to be. 492 * 493 * @since 3.0.0 494 * @uses $wp_registered_menus Stores the new menu in this array by menu ID. 495 * @uses parse_str() Converts a string to an array to be used in the rest of the function. 496 * @usedby register_menus() 497 * 498 * @param string|array $args Builds Menu based off of 'name' and 'id' values 499 * @return string The menu id that was added. 500 */ 501 function register_menu($args = array()) { 502 global $wp_registered_menus; 503 504 $i = count($wp_registered_menus) + 1; 505 506 $defaults = array( 507 'name' => sprintf(__('Menu %d'), $i ), 508 'id' => "menu-$i", 509 'description' => '', 510 'before_menu' => '<ul id="%1$s" class="menu %2$s">', 511 'after_menu' => "</ul>\n", 512 ); 513 514 $menu = wp_parse_args($args, $defaults); 515 516 $wp_registered_menus[$menu['id']] = $menu; 517 518 return $menu['id']; 519 } 520 521 /** 522 * Removes a menu from the list. 523 * 524 * @since 3.0.0 525 * 526 * @uses $wp_registered_menus Stores the new menu in this array by menu ID. 527 * 528 * @param string $name The ID of the menu when it was added. 529 */ 530 function unregister_menu( $name ) { 531 global $wp_registered_menus; 532 533 if ( isset( $wp_registered_menus[$name] ) ) 534 unset( $wp_registered_menus[$name] ); 535 } 536 537 /** 538 * Register menu_item for use in menus. 539 * 540 * The default menu_item option is 'classname' that can be override. 541 * 542 * The function can also be used to unregister menu_items when $output_callback 543 * parameter is an empty string. 544 * 545 * @since 3.0.0 546 * 547 * @uses $wp_registered_menu_items Uses stored registered menu_items. 548 * @uses $wp_register_menu_item_defaults Retrieves menu_item defaults. 549 * 550 * @param int|string $id Menu_Item ID. 551 * @param string $name Menu_Item display title. 552 * @param callback $output_callback Run when menu_item is called. 553 * @param array|string Optional. $options Menu_Item Options. 554 * @param mixed $params,... Menu_Item parameters to add to menu_item. 555 * @return null Will return if $output_callback is empty after removing menu_item. 556 */ 557 function wp_register_menu_item($id, $name, $output_callback, $options = array()) { 558 global $wp_registered_menu_items, $wp_registered_menu_item_controls, $wp_registered_menu_item_updates; 559 560 $id = strtolower($id); 561 562 if ( empty($output_callback) ) { 563 unset($wp_registered_menu_items[$id]); 564 return; 565 } 566 567 $id_base = _get_menu_item_id_base($id); 568 if ( !is_callable($output_callback) ) { 569 if ( isset($wp_registered_menu_item_controls[$id]) ) 570 unset($wp_registered_menu_item_controls[$id]); 571 572 if ( isset($wp_registered_menu_item_updates[$id_base]) ) 573 unset($wp_registered_menu_item_updates[$id_base]); 574 575 return; 576 } 577 578 $defaults = array('classname' => $output_callback); 579 $options = wp_parse_args($options, $defaults); 580 $menu_item = array( 581 'name' => $name, 582 'id' => $id, 583 'callback' => $output_callback, 584 'params' => array_slice(func_get_args(), 4) 585 ); 586 $menu_item = array_merge($menu_item, $options); 587 588 if ( is_callable($output_callback) && ( !isset($wp_registered_menu_items[$id]) || did_action( 'menu_items_init' ) ) ) 589 $wp_registered_menu_items[$id] = $menu_item; 590 } 591 592 /** 593 * Retrieve description for menu_item. 594 * 595 * When registering menu_items, the options can also include 'description' that 596 * describes the menu_item for display on the menu_item administration panel or 597 * in the theme. 598 * 599 * @since 3.0.0 600 * 601 * @param int|string $id Menu_Item ID. 602 * @return string Menu_Item description, if available. Null on failure to retrieve description. 603 */ 604 function wp_menu_item_description( $id ) { 605 if ( !is_scalar($id) ) 606 return; 607 608 global $wp_registered_menu_items; 609 610 if ( isset($wp_registered_menu_items[$id]['description']) ) 611 return esc_html( $wp_registered_menu_items[$id]['description'] ); 612 } 613 614 /** 615 * Retrieve description for a menu. 616 * 617 * When registering menus a 'description' parameter can be included that 618 * describes the menu for display on the menu_item administration panel. 619 * 620 * @since 3.0.0 621 * 622 * @param int|string $id menu ID. 623 * @return string Menu description, if available. Null on failure to retrieve description. 624 */ 625 function wp_menu_description( $id ) { 626 if ( !is_scalar($id) ) 627 return; 628 629 global $wp_registered_menus; 630 631 if ( isset($wp_registered_menus[$id]['description']) ) 632 return esc_html( $wp_registered_menus[$id]['description'] ); 633 } 634 635 636 /** 637 * Remove menu_item from menu. 638 * 639 * @since 3.0.0 640 * 641 * @param int|string $id Menu_Item ID. 642 */ 643 function wp_unregister_menu_item($id) { 644 wp_register_menu_item($id, '', ''); 645 wp_unregister_menu_item_control($id); 646 } 647 648 /** 649 * Registers menu_item control callback for customizing options. 650 * 651 * The options contains the 'height', 'width', and 'id_base' keys. The 'height' 652 * option is never used. The 'width' option is the width of the fully expanded 653 * control form, but try hard to use the default width. The 'id_base' is for 654 * multi-menu_items (menu_items which allow multiple instances such as the text 655 * menu_item), an id_base must be provided. The menu_item id will end up looking like 656 * {$id_base}-{$unique_number}. 657 * 658 * @since 3.0.0 659 * 660 * @param int|string $id Menu ID. 661 * @param string $name Menu display name. 662 * @param callback $control_callback Run when menu is displayed. 663 * @param array|string $options Optional. Menu_Item options. See above long description. 664 * @param mixed $params,... Optional. Additional parameters to add to menu_item. 665 */ 666 function wp_register_menu_item_control($id, $name, $control_callback, $options = array()) { 667 global $wp_registered_menu_item_controls, $wp_registered_menu_item_updates, $wp_registered_menu_items; 668 669 $id = strtolower($id); 670 $id_base = _get_menu_item_id_base($id); 671 672 if ( empty($control_callback) ) { 673 unset($wp_registered_menu_item_controls[$id]); 674 unset($wp_registered_menu_item_updates[$id_base]); 675 return; 676 } 677 678 if ( !is_callable($control_callback) ) { 679 if ( isset($wp_registered_menu_items[$id]) ) 680 unset($wp_registered_menu_items[$id]); 681 682 return; 683 } 684 685 if ( isset($wp_registered_menu_item_controls[$id]) && !did_action( 'menu_items_init' ) ) 686 return; 687 688 $defaults = array('width' => 250, 'height' => 200 ); // height is never used 689 $options = wp_parse_args($options, $defaults); 690 $options['width'] = (int) $options['width']; 691 $options['height'] = (int) $options['height']; 692 693 $menu_item = array( 694 'name' => $name, 695 'id' => $id, 696 'callback' => $control_callback, 697 'params' => array_slice(func_get_args(), 4) 698 ); 699 $menu_item = array_merge($menu_item, $options); 700 701 $wp_registered_menu_item_controls[$id] = $menu_item; 702 703 if ( isset($wp_registered_menu_item_updates[$id_base]) ) 704 return; 705 706 if ( isset($menu_item['params'][0]['number']) ) 707 $menu_item['params'][0]['number'] = -1; 708 709 unset($menu_item['width'], $menu_item['height'], $menu_item['name'], $menu_item['id']); 710 $wp_registered_menu_item_updates[$id_base] = $menu_item; 711 } 712 713 function _register_menu_item_update_callback($id_base, $update_callback, $options = array()) { 714 global $wp_registered_menu_item_updates; 715 716 if ( isset($wp_registered_menu_item_updates[$id_base]) ) { 717 if ( empty($update_callback) ) 718 unset($wp_registered_menu_item_updates[$id_base]); 719 return; 720 } 721 722 $menu_item = array( 723 'callback' => $update_callback, 724 'params' => array_slice(func_get_args(), 3) 725 ); 726 727 $menu_item = array_merge($menu_item, $options); 728 $wp_registered_menu_item_updates[$id_base] = $menu_item; 729 } 730 731 function _register_menu_item_form_callback($id, $name, $form_callback, $options = array()) { 732 global $wp_registered_menu_item_controls; 733 734 $id = strtolower($id); 735 736 if ( empty($form_callback) ) { 737 unset($wp_registered_menu_item_controls[$id]); 738 return; 739 } 740 741 if ( isset($wp_registered_menu_item_controls[$id]) && !did_action( 'menu_items_init' ) ) 742 return; 743 744 $defaults = array('width' => 250, 'height' => 200 ); 745 $options = wp_parse_args($options, $defaults); 746 $options['width'] = (int) $options['width']; 747 $options['height'] = (int) $options['height']; 748 749 $menu_item = array( 750 'name' => $name, 751 'id' => $id, 752 'callback' => $form_callback, 753 'params' => array_slice(func_get_args(), 4) 754 ); 755 $menu_item = array_merge($menu_item, $options); 756 757 $wp_registered_menu_item_controls[$id] = $menu_item; 758 } 759 760 /** 761 * Remove control callback for menu_item. 762 * 763 * @since 3.0.0 764 * @uses wp_register_menu_item_control() Unregisters by using empty callback. 765 * 766 * @param int|string $id Menu_Item ID. 767 */ 768 function wp_unregister_menu_item_control($id) { 769 return wp_register_menu_item_control($id, '', ''); 770 } 771 772 /** 773 * Display dynamic menu. 774 * 775 * By default it displays the default menu or 'menu-1'. The 'menu-1' is 776 * not named by the theme, the actual name is '1', but 'menu-' is added to 777 * the registered menus for the name. If you named your menu 'after-post', 778 * then the parameter $index will still be 'after-post', but the lookup will be 779 * for 'menu-after-post'. 780 * 781 * It is confusing for the $index parameter, but just know that it should just 782 * work. When you register the menu in the theme, you will use the same name 783 * for this function or "Pay no heed to the man behind the curtain." Just accept 784 * it as an oddity of WordPress menu register and display. 785 * 786 * @since 3.0.0 787 * 788 * @param int|string $index Optional, default is 1. Name or ID of dynamic menu. 789 * @return bool True, if menu_item menu was found and called. False if not found or not called. 790 */ 791 function dynamic_menu($index = 1) { 792 global $wp_registered_menus, $wp_registered_menu_items; 793 794 if ( is_int($index) ) { 795 $index = "menu-$index"; 796 } else { 797 $index = sanitize_title($index); 798 foreach ( (array) $wp_registered_menus as $key => $value ) { 799 if ( sanitize_title($value['name']) == $index ) { 800 $index = $key; 801 break; 802 } 803 } 804 } 805 806 $wp_menu_items = wp_get_menu_items(); 807 808 if ( empty($wp_registered_menus[$index]) || !array_key_exists($index, $wp_menu_items) || !is_array($wp_menu_items[$index]) || empty($wp_menu_items[$index]) ) 809 return false; 810 811 $menu = $wp_registered_menus[$index]; 812 813 $did_one = false; 814 foreach ( (array) $wp_menu_items[$index] as $id ) { 815 816 if ( !isset($wp_registered_menu_items[$id]) ) continue; 817 818 $params = array_merge( 819 array( array_merge( $menu, array('menu_item_id' => $id, 'menu_item_name' => $wp_registered_menu_items[$id]['name']) ) ), 820 (array) $wp_registered_menu_items[$id]['params'] 821 ); 822 823 // Substitute HTML id and class attributes into before_menu_item 824 $classname_ = ''; 825 foreach ( (array) $wp_registered_menu_items[$id]['classname'] as $cn ) { 826 if ( is_string($cn) ) 827 $classname_ .= '_' . $cn; 828 elseif ( is_object($cn) ) 829 $classname_ .= '_' . get_class($cn); 830 } 831 $classname_ = ltrim($classname_, '_'); 832 $params[0]['before_menu_item'] = sprintf($params[0]['before_menu'], $id, $classname_); 833 834 $params = apply_filters( 'dynamic_menu_params', $params ); 835 836 $callback = $wp_registered_menu_items[$id]['callback']; 837 838 if ( is_callable($callback) ) { 839 call_user_func_array($callback, $params); 840 $did_one = true; 841 } 842 } 843 844 return $did_one; 845 } 846 847 /** 848 * Whether menu_item is displayied on the front-end. 849 * 850 * Either $callback or $id_base can be used 851 * $id_base is the first argument when extending WP_Menu_Item class 852 * Without the optional $menu_item_id parameter, returns the ID of the first menu 853 * in which the first instance of the menu_item with the given callback or $id_base is found. 854 * With the $menu_item_id parameter, returns the ID of the menu where 855 * the menu_item with that callback/$id_base AND that ID is found. 856 * 857 * NOTE: $menu_item_id and $id_base are the same for single menu_items. To be effective 858 * this function has to run after menu_items have initialized, at action 'init' or later. 859 * 860 * @since 3.0.0 861 * 862 * @param callback Optional, Menu_Item callback to check. 863 * @param int $menu_item_id Optional, but needed for checking. Menu_Item ID. 864 * @param string $id_base Optional, the base ID of a menu_item created by extending WP_Menu_Item. 865 * @param bool $skip_inactive Optional, whether to check in 'wp_inactive_menu_items'. 866 * @return mixed false if menu_item is not active or id of menu in which the menu_item is active. 867 */ 868 function is_active_menu_item($callback = false, $menu_item_id = false, $id_base = false, $skip_inactive = true) { 869 global $wp_registered_menu_items; 870 871 $wp_menu_items = wp_get_menu_items(); 872 873 if ( is_array($wp_menu_items) ) { 874 foreach ( $wp_menu_items as $menu => $menu_items ) { 875 if ( $skip_inactive && 'wp_inactive_menu_items' == $menu ) 876 continue; 877 878 if ( is_array($menu_items) ) { 879 foreach ( $menu_items as $menu_item ) { 880 if ( ( $callback && isset($wp_registered_menu_items[$menu_item]['callback']) && $wp_registered_menu_items[$menu_item]['callback'] == $callback ) || ( $id_base && _get_menu_item_id_base($menu_item) == $id_base ) ) { 881 if ( !$menu_item_id || $menu_item_id == $wp_registered_menu_items[$menu_item]['id'] ) 882 return $menu; 883 } 884 } 885 } 886 } 887 } 888 return false; 889 } 890 891 /** 892 * Whether the dynamic menu is enabled and used by theme. 893 * 894 * @since 3.0.0 895 * 896 * @return bool True, if using menu_items. False, if not using menu_items. 897 */ 898 function is_dynamic_menu() { 899 global $wp_registered_menu_items, $wp_registered_menus; 900 $wp_menu_items = get_option('wp_menu_items'); 901 foreach ( (array) $wp_registered_menus as $index => $menu ) { 902 if ( count($wp_menu_items[$index]) ) { 903 foreach ( (array) $wp_menu_items[$index] as $menu_item ) 904 if ( array_key_exists($menu_item, $wp_registered_menu_items) ) 905 return true; 906 } 907 } 908 return false; 909 } 910 911 /** 912 * Whether a menu is in use. 913 * 914 * @since 3.0 915 * 916 * @param mixed $index, menu name, id or number to check. 917 * @return bool true if the menu is in use, false otherwise. 918 */ 919 function is_active_menu( $index ) { 920 $index = ( is_int($index) ) ? "menu-$index" : sanitize_title($index); 921 $wp_menu_items = wp_get_menu_items(); 922 if ( isset($wp_menu_items[$index]) && !empty($wp_menu_items[$index]) ) 923 return true; 924 925 return false; 926 } 927 928 /* Internal Functions */ 929 930 /** 931 * Retrieve full list of menus and their menu_items. 932 * 933 * Will upgrade menu menu_item list, if needed. Will also save updated list, if 934 * needed. 935 * 936 * @since 3.0.0 937 * @access private 938 * 939 * @return array Upgraded list of menu_items to version 3 array format when called from the admin. 940 */ 941 function wp_get_menu_items() { 942 global $wp_registered_menu_items, $wp_registered_menus, $_wp_menu_items; 943 944 // If loading from front page, consult $_wp_menu_items rather than options 945 // to see if wp_convert_menu_item_settings() has made manipulations in memory. 946 if ( !is_admin() ) { 947 if ( empty($_wp_menu_items) ) 948 $_wp_menu_items = get_option('wp_menu_items', array()); 949 950 $wp_menu_items = $_wp_menu_items; 951 } else { 952 $wp_menu_items = get_option('wp_menu_items', array()); 953 $_wp_menu_items = array(); 954 955 if ( isset($wp_menu_items['wp_inactive_menu_items']) || empty($wp_menu_items) ) 956 $wp_menu_items['array_version'] = 3; 957 elseif ( !isset($wp_menu_items['array_version']) ) 958 $wp_menu_items['array_version'] = 1; 959 960 switch ( $wp_menu_items['array_version'] ) { 961 case 1 : 962 foreach ( (array) $wp_menu_items as $index => $menu ) 963 if ( is_array($menu) ) 964 foreach ( (array) $menu as $i => $name ) { 965 $id = strtolower($name); 966 if ( isset($wp_registered_menu_items[$id]) ) { 967 $_wp_menu_items[$index][$i] = $id; 968 continue; 969 } 970 $id = sanitize_title($name); 971 if ( isset($wp_registered_menu_items[$id]) ) { 972 $_wp_menu_items[$index][$i] = $id; 973 continue; 974 } 975 976 $found = false; 977 978 foreach ( $wp_registered_menu_items as $menu_item_id => $menu_item ) { 979 if ( strtolower($menu_item['name']) == strtolower($name) ) { 980 $_wp_menu_items[$index][$i] = $menu_item['id']; 981 $found = true; 982 break; 983 } elseif ( sanitize_title($menu_item['name']) == sanitize_title($name) ) { 984 $_wp_menu_items[$index][$i] = $menu_item['id']; 985 $found = true; 986 break; 987 } 988 } 989 990 if ( $found ) 991 continue; 992 993 unset($_wp_menu_items[$index][$i]); 994 } 995 $_wp_menu_items['array_version'] = 2; 996 $wp_menu_items = $_wp_menu_items; 997 unset($_wp_menu_items); 998 999 case 2 : 1000 $menus = array_keys( $wp_registered_menus ); 1001 if ( !empty( $menus ) ) { 1002 // Move the known-good ones first 1003 foreach ( (array) $menus as $id ) { 1004 if ( array_key_exists( $id, $wp_menu_items ) ) { 1005 $_wp_menu_items[$id] = $wp_menu_items[$id]; 1006 unset($wp_menu_items[$id], $menus[$id]); 1007 } 1008 } 1009 1010 // move the rest to wp_inactive_menu_items 1011 if ( !isset($_wp_menu_items['wp_inactive_menu_items']) ) 1012 $_wp_menu_items['wp_inactive_menu_items'] = array(); 1013 1014 if ( !empty($wp_menu_items) ) { 1015 foreach ( $wp_menu_items as $lost => $val ) { 1016 if ( is_array($val) ) 1017 $_wp_menu_items['wp_inactive_menu_items'] = array_merge( (array) $_wp_menu_items['wp_inactive_menu_items'], $val ); 1018 } 1019 } 1020 1021 $wp_menu_items = $_wp_menu_items; 1022 unset($_wp_menu_items); 1023 } 1024 } 1025 } 1026 1027 if ( isset($wp_menu_items['array_version']) ) 1028 unset($wp_menu_items['array_version']); 1029 1030 $wp_menu_items = apply_filters('wp_menu_items', $wp_menu_items); 1031 return $wp_menu_items; 1032 } 1033 1034 /** 1035 * Set the menu menu_item option to update menus. 1036 * 1037 * @since 3.0.0 1038 * @access private 1039 * 1040 * @param array $wp_menu_items Menu menu_items and their settings. 1041 */ 1042 function wp_set_menu_items( $wp_menu_items ) { 1043 if ( !isset( $wp_menu_items['array_version'] ) ) 1044 $wp_menu_items['array_version'] = 3; 1045 update_option( 'wp_menu_items', $wp_menu_items ); 1046 } 1047 1048 /** 1049 * Retrieve default registered menus list. 1050 * 1051 * @since 3.0.0 1052 * @access private 1053 * 1054 * @return array 1055 */ 1056 function wp_get_menu_item_defaults() { 1057 global $wp_registered_menus; 1058 1059 $defaults = array(); 1060 1061 foreach ( (array) $wp_registered_menus as $index => $menu ) 1062 $defaults[$index] = array(); 1063 1064 return $defaults; 1065 } 1066 1067 /** 1068 * Private 1069 */ 1070 function _get_menu_item_id_base($id) { 1071 return preg_replace( '/-[0-9]+$/', '', $id ); 1072 } 1073 1074 // Initialization code 1075 1076 /*ignore*/ 1077 global $wp_menu_item_factory; 1078 1079 /** 1080 * WordPress Menu Item Factory Object 1081 * @global object $wp_menu_item_factory 1082 * @since 3.0 1083 */ 1084 $wp_menu_item_factory =& new WP_Menu_Item_Factory(); 1085 -
wp-includes/script-loader.php
326 326 $scripts->add( 'admin-widgets', "/wp-admin/js/widgets$suffix.js", array( 'jquery-ui-sortable', 'jquery-ui-draggable', 'jquery-ui-droppable' ), '20090824' ); 327 327 $scripts->add_data( 'admin-widgets', 'group', 1 ); 328 328 329 $scripts->add( 'admin-menus', "/wp-admin/js/menus$suffix.js", array( 'jquery-ui-sortable', 'jquery-ui-draggable', 'jquery-ui-droppable' ), '20090824' ); 330 $scripts->add_data( 'admin-menus', 'group', 1 ); 331 329 332 $scripts->add( 'word-count', "/wp-admin/js/word-count$suffix.js", array( 'jquery' ), '20090422' ); 330 333 $scripts->add_data( 'word-count', 'group', 1 ); 331 334 $scripts->localize( 'word-count', 'wordCountL10n', array( … … 426 429 427 430 $suffix = defined('STYLE_DEBUG') && STYLE_DEBUG ? '.dev' : ''; 428 431 429 $rtl_styles = array( 'wp-admin', 'global', 'colors', 'dashboard', 'ie', 'install', 'login', 'media', 'theme-editor', 'upload', 'widgets', ' press-this', 'plugin-install', 'farbtastic' );432 $rtl_styles = array( 'wp-admin', 'global', 'colors', 'dashboard', 'ie', 'install', 'login', 'media', 'theme-editor', 'upload', 'widgets', 'menus', 'press-this', 'plugin-install', 'farbtastic' ); 430 433 431 434 // all colors stylesheets need to have the same query strings (cache manifest compat) 432 435 $colors_version = '20091227'; … … 448 451 $styles->add( 'global', "/wp-admin/css/global$suffix.css", array(), '20100108' ); 449 452 $styles->add( 'media', "/wp-admin/css/media$suffix.css", array(), '20091029' ); 450 453 $styles->add( 'widgets', "/wp-admin/css/widgets$suffix.css", array(), '20091118' ); 454 $styles->add( 'menus', "/wp-admin/css/menus$suffix.css", array(), '20100109' ); 451 455 $styles->add( 'dashboard', "/wp-admin/css/dashboard$suffix.css", array(), '20091211' ); 452 456 $styles->add( 'install', "/wp-admin/css/install$suffix.css", array(), '20090514' ); 453 457 $styles->add( 'theme-editor', "/wp-admin/css/theme-editor$suffix.css", array(), '20090625' ); -
wp-content/themes/default/functions.php
17 17 )); 18 18 } 19 19 20 // Dynamic menu support 21 add_theme_support('menus'); 22 register_menu(array( 23 'before_menu' => '<ul id="%1$s" class="menu %2$s">', 24 'after_menu' => '</ul>', 25 )); 26 20 27 /** @ignore */ 21 28 function kubrick_head() { 22 29 $head = "<style type='text/css'>\n<!--"; -
wp-settings.php
425 425 require (ABSPATH . WPINC . '/media.php'); 426 426 require (ABSPATH . WPINC . '/http.php'); 427 427 require (ABSPATH . WPINC . '/widgets.php'); 428 require (ABSPATH . WPINC . '/menus.php'); 428 429 429 430 if ( is_multisite() ) { 430 431 require_once( ABSPATH . WPINC . '/ms-functions.php' ); … … 785 786 // Load in support for template functions which the theme supports 786 787 require_if_theme_supports( 'post-thumbnails', ABSPATH . WPINC . '/post-thumbnail-template.php' ); 787 788 789 // Menus init 790 if ( current_theme_supports( 'menus' ) ) { 791 if ( apply_filters('load_default_menu_items', true) ) 792 require( ABSPATH . WPINC . '/default-menu-items.php' ); 793 794 function _wp_add_menus_menu() { 795 global $submenu; 796 $submenu['themes.php'][8] = array( __( 'Menus' ), 'switch_themes', 'menus.php' ); 797 ksort( $submenu['themes.php'], SORT_NUMERIC ); 798 } 799 add_action( '_admin_menu', '_wp_add_menus_menu' ); 800 } 801 802 788 803 /** 789 804 * Runs just before PHP shuts down execution. 790 805 * -
wp-admin/admin-ajax.php
1379 1379 1380 1380 die(); 1381 1381 break; 1382 case 'menu-items-order' : 1383 check_ajax_referer( 'save-menu-items', 'savemenu_items' ); 1384 1385 if ( !current_user_can('switch_themes') ) 1386 die('-1'); 1387 1388 unset( $_POST['savemenu_items'], $_POST['action'] ); 1389 1390 // save menu_items order for all menus 1391 if ( is_array($_POST['menus']) ) { 1392 $menus = array(); 1393 foreach ( $_POST['menus'] as $key => $val ) { 1394 $sb = array(); 1395 if ( !empty($val) ) { 1396 $val = explode(',', $val); 1397 foreach ( $val as $k => $v ) { 1398 if ( strpos($v, 'menu-item-') === false ) 1399 continue; 1400 1401 $tmp = explode('_', $v, 2); 1402 $sb[$k] = $tmp[1]; 1403 } 1404 } 1405 $menus[$key] = $sb; 1406 } 1407 wp_set_menu_items($menus); 1408 die('1'); 1409 } 1410 1411 die('-1'); 1412 break; 1413 case 'save-menu-item' : 1414 check_ajax_referer( 'save-menu-items', 'savemenu_items' ); 1415 1416 if ( !current_user_can('switch_themes') || !isset($_POST['id_base']) ) 1417 die('-1'); 1418 1419 unset( $_POST['savemenu_items'], $_POST['action'] ); 1420 1421 do_action('load-menus.php'); 1422 do_action('menus.php'); 1423 do_action('menu_admin_setup'); 1424 1425 $id_base = $_POST['id_base']; 1426 $menu_item_id = $_POST['menu-item-id']; 1427 $menu_id = $_POST['menu']; 1428 $multi_number = !empty($_POST['multi_number']) ? (int) $_POST['multi_number'] : 0; 1429 $settings = isset($_POST['menu-item-' . $id_base]) && is_array($_POST['menu-item-' . $id_base]) ? $_POST['menu-item-' . $id_base] : false; 1430 $error = '<p>' . __('An error has occured. Please reload the page and try again.') . '</p>'; 1431 1432 $menus = wp_get_menu_items(); 1433 $menu = isset($menus[$menu_id]) ? $menus[$menu_id] : array(); 1434 1435 // delete 1436 if ( isset($_POST['delete_menu_item']) && $_POST['delete_menu_item'] ) { 1437 1438 if ( !isset($wp_registered_menu_items[$menu_item_id]) ) 1439 die($error); 1440 1441 $menu = array_diff( $menu, array($menu_item_id) ); 1442 $_POST = array('menu' => $menu_id, 'menu-item-' . $id_base => array(), 'the-menu-item-id' => $menu_item_id, 'delete_menu_item' => '1'); 1443 } elseif ( $settings && preg_match( '/__i__|%i%/', key($settings) ) ) { 1444 if ( !$multi_number ) 1445 die($error); 1446 1447 $_POST['menu-item-' . $id_base] = array( $multi_number => array_shift($settings) ); 1448 $menu_item_id = $id_base . '-' . $multi_number; 1449 $menu[] = $menu_item_id; 1450 } 1451 $_POST['menu-item-id'] = $menu; 1452 1453 foreach ( (array) $wp_registered_menu_item_updates as $name => $control ) { 1454 1455 if ( $name == $id_base ) { 1456 if ( !is_callable( $control['callback'] ) ) 1457 continue; 1458 1459 ob_start(); 1460 call_user_func_array( $control['callback'], $control['params'] ); 1461 ob_end_clean(); 1462 break; 1463 } 1464 } 1465 1466 if ( isset($_POST['delete_menu_item']) && $_POST['delete_menu_item'] ) { 1467 $menus[$menu_id] = $menu; 1468 wp_set_menu_items($menus); 1469 echo "deleted:$menu_item_id"; 1470 die(); 1471 } 1472 1473 if ( !empty($_POST['add_new']) ) 1474 die(); 1475 1476 if ( $form = $wp_registered_menu_item_controls[$menu_item_id] ) 1477 call_user_func_array( $form['callback'], $form['params'] ); 1478 1479 die(); 1480 break; 1382 1481 case 'image-editor': 1383 1482 $attachment_id = intval($_POST['postid']); 1384 1483 if ( empty($attachment_id) || !current_user_can('edit_post', $attachment_id) ) -
wp-admin/includes/menus.php
1 <?php 2 /** 3 * WordPress Menus Administration API 4 * 5 * @package WordPress 6 * @subpackage Administration 7 */ 8 9 /** 10 * Display list of the available menu items, either all or matching search. 11 * 12 * The search parameter are search terms separated by spaces. 13 * 14 * @since 3.0 15 * 16 * @param string $show Optional, default is all. What to display, can be 'all', 'unused', or 'used'. 17 * @param string $_search Optional. Search for menu_items. Should be unsanitized. 18 */ 19 function wp_list_menu_items() { 20 global $wp_registered_menu_items, $menu_items_map, $wp_registered_menu_item_controls; 21 22 $sort = $wp_registered_menu_items; 23 usort( $sort, create_function( '$a, $b', 'return strnatcasecmp( $a["name"], $b["name"] );' ) ); 24 $done = array(); 25 26 foreach ( $sort as $menu_item ) { 27 if ( in_array( $menu_item['callback'], $done, true ) ) // We already showed this multi-menu_item 28 continue; 29 30 $menu = is_active_menu_item( $menu_item['callback'], $menu_item['id'], false, false ); 31 $done[] = $menu_item['callback']; 32 33 if ( ! isset( $menu_item['params'][0] ) ) 34 $menu_item['params'][0] = array(); 35 36 $args = array( 'menu_item_id' => $menu_item['id'], 'menu_item_name' => $menu_item['name'], '_display' => 'template' ); 37 38 if ( isset($wp_registered_menu_item_controls[$menu_item['id']]['id_base']) && isset($menu_item['params'][0]['number']) ) { 39 $id_base = $wp_registered_menu_item_controls[$menu_item['id']]['id_base']; 40 $args['_temp_id'] = "$id_base-__i__"; 41 $args['_multi_num'] = next_menu_item_id_number($id_base); 42 $args['_add'] = 'multi'; 43 } else { 44 $args['_add'] = 'single'; 45 if ( $menu ) 46 $args['_hide'] = '1'; 47 } 48 49 $args = wp_list_menu_item_controls_dynamic_menu( array( 0 => $args, 1 => $menu_item['params'][0] ) ); 50 call_user_func_array( 'wp_menu_item_control', $args ); 51 } 52 } 53 54 /** 55 * Show the menu_items and their settings for a menu. 56 * Used in the the admin menu_item config screen. 57 * 58 * @since 3.0 59 * 60 * @param string $menu id slug of the menu 61 */ 62 function wp_list_menu_item_controls( $menu ) { 63 add_filter( 'dynamic_menu_params', 'wp_list_menu_item_controls_dynamic_menu' ); 64 65 echo "<div id='$menu' class='menu-items-sortables'>\n"; 66 67 $description = wp_menu_description( $menu ); 68 69 if ( !empty( $description ) ) { 70 echo "<div class='menu-description'>\n"; 71 echo "\t<p class='description'>$description</p>"; 72 echo "</div>\n"; 73 } 74 75 dynamic_menu( $menu ); 76 echo "</div>\n"; 77 } 78 79 /** 80 * {@internal Missing Short Description}} 81 * 82 * @since 3.0 83 * 84 * @param array $params 85 * @return array 86 */ 87 function wp_list_menu_item_controls_dynamic_menu( $params ) { 88 global $wp_registered_menu_items; 89 static $i = 0; 90 $i++; 91 92 $menu_item_id = $params[0]['menu_item_id']; 93 $id = isset($params[0]['_temp_id']) ? $params[0]['_temp_id'] : $menu_item_id; 94 $hidden = isset($params[0]['_hide']) ? ' style="display:none;"' : ''; 95 96 $params[0]['before_menu_item'] = "<div id='menu-item-${i}_$id' class='menu-item'$hidden>"; 97 $params[0]['after_menu_item'] = "</div>"; 98 if ( is_callable( $wp_registered_menu_items[$menu_item_id]['callback'] ) ) { 99 $wp_registered_menu_items[$menu_item_id]['_callback'] = $wp_registered_menu_items[$menu_item_id]['callback']; 100 $wp_registered_menu_items[$menu_item_id]['callback'] = 'wp_menu_item_control'; 101 } 102 103 return $params; 104 } 105 106 function next_menu_item_id_number($id_base) { 107 global $wp_registered_menu_items; 108 $number = 1; 109 110 foreach ( $wp_registered_menu_items as $menu_item_id => $menu_item ) { 111 if ( preg_match( '/' . $id_base . '-([0-9]+)$/', $menu_item_id, $matches ) ) 112 $number = max($number, $matches[1]); 113 } 114 $number++; 115 116 return $number; 117 } 118 119 /** 120 * Meta menu_item used to display the control form for a menu_item. 121 * 122 * Called from dynamic_menu(). 123 * 124 * @since 3.0 125 * 126 * @param array $menu_args 127 * @return array 128 */ 129 function wp_menu_item_control( $menu_args ) { 130 global $wp_registered_menu_items, $wp_registered_menu_item_controls, $menu_items_map; 131 132 $menu_item_id = $menu_args['menu_item_id']; 133 $menu_id = isset($menu_args['id']) ? $menu_args['id'] : false; 134 $key = $menu_id ? array_search( $menu_item_id, $menu_items_map[$menu_id] ) : '-1'; // position of menu_item in menu 135 $control = isset($wp_registered_menu_item_controls[$menu_item_id]) ? $wp_registered_menu_item_controls[$menu_item_id] : array(); 136 $menu_item = $wp_registered_menu_items[$menu_item_id]; 137 138 $id_format = $menu_item['id']; 139 $menu_item_number = isset($control['params'][0]['number']) ? $control['params'][0]['number'] : ''; 140 $id_base = isset($control['id_base']) ? $control['id_base'] : $menu_item_id; 141 $multi_number = isset($menu_args['_multi_num']) ? $menu_args['_multi_num'] : ''; 142 $add_new = isset($menu_args['_add']) ? $menu_args['_add'] : ''; 143 144 $query_arg = array( 'editmenu_item' => $menu_item['id'] ); 145 if ( $add_new ) { 146 $query_arg['addnew'] = 1; 147 if ( $multi_number ) { 148 $query_arg['num'] = $multi_number; 149 $query_arg['base'] = $id_base; 150 } 151 } else { 152 $query_arg['menu'] = $menu_id; 153 $query_arg['key'] = $key; 154 } 155 156 // We aren't showing a menu_item control, we're outputing a template for a mult-menu_item control 157 if ( isset($menu_args['_display']) && 'template' == $menu_args['_display'] && $menu_item_number ) { 158 // number == -1 implies a template where id numbers are replaced by a generic '__i__' 159 $control['params'][0]['number'] = -1; 160 // with id_base menu_item id's are constructed like {$id_base}-{$id_number} 161 if ( isset($control['id_base']) ) 162 $id_format = $control['id_base'] . '-__i__'; 163 } 164 165 $wp_registered_menu_items[$menu_item_id]['callback'] = $wp_registered_menu_items[$menu_item_id]['_callback']; 166 unset($wp_registered_menu_items[$menu_item_id]['_callback']); 167 168 $menu_item_title = esc_html( strip_tags( $menu_args['menu_item_name'] ) ); 169 $has_form = 'noform'; 170 171 echo $menu_args['before_menu_item']; ?> 172 <div class="menu-item-top"> 173 <div class="menu-item-title-action"> 174 <a class="menu-item-action hide-if-no-js" href="#available-menu-items"></a> 175 <a class="menu-item-control-edit hide-if-js" href="<?php echo esc_url( add_query_arg( $query_arg ) ); ?>"><span class="edit"><?php _e('Edit'); ?></span><span class="add"><?php _e('Add'); ?></span></a> 176 </div> 177 <div class="menu-item-title"><h4><?php echo $menu_item_title ?><span class="in-menu-item-title"></span></h4></div> 178 </div> 179 180 <div class="menu-item-inside"> 181 <form action="" method="post"> 182 <div class="menu-item-content"> 183 <?php 184 if ( isset($control['callback']) ) 185 $has_form = call_user_func_array( $control['callback'], $control['params'] ); 186 else 187 echo "\t\t<p>" . __('There are no options for this menu item.') . "</p>\n"; ?> 188 </div> 189 <input type="hidden" name="menu-item-id" class="menu-item-id" value="<?php echo esc_attr($id_format); ?>" /> 190 <input type="hidden" name="id_base" class="id_base" value="<?php echo esc_attr($id_base); ?>" /> 191 <input type="hidden" name="menu-item-width" class="menu-item-width" value="<?php if (isset( $control['width'] )) echo esc_attr($control['width']); ?>" /> 192 <input type="hidden" name="menu-item-height" class="menu-item-height" value="<?php if (isset( $control['height'] )) echo esc_attr($control['height']); ?>" /> 193 <input type="hidden" name="menu_item_number" class="menu_item_number" value="<?php echo esc_attr($menu_item_number); ?>" /> 194 <input type="hidden" name="multi_number" class="multi_number" value="<?php echo esc_attr($multi_number); ?>" /> 195 <input type="hidden" name="add_new" class="add_new" value="<?php echo esc_attr($add_new); ?>" /> 196 197 <div class="menu-item-control-actions"> 198 <div class="alignleft"> 199 <a class="menu-item-control-remove" href="#remove"><?php _e('Delete'); ?></a> | 200 <a class="menu-item-control-close" href="#close"><?php _e('Close'); ?></a> 201 </div> 202 <div class="alignright<?php if ( 'noform' === $has_form ) echo ' menu-item-control-noform'; ?>"> 203 <img src="images/wpspin_light.gif" class="ajax-feedback " title="" alt="" /> 204 <input type="submit" name="savemenu_item" class="button-primary menu-item-control-save" value="<?php esc_attr_e('Save'); ?>" /> 205 </div> 206 <br class="clear" /> 207 </div> 208 </form> 209 </div> 210 211 <div class="menu-item-description"> 212 <?php echo ( $menu_item_description = wp_menu_item_description($menu_item_id) ) ? "$menu_item_description\n" : "$menu_item_title\n"; ?> 213 </div> 214 <?php 215 echo $menu_args['after_menu_item']; 216 return $menu_args; 217 } 218 -
wp-admin/js/menus.dev.js
1 (function($) { 2 window.wpMenus = { 3 4 init : function() { 5 var rem, menus = $('div.menu-items-sortables'); 6 7 $('#menu-items-right').children('.menu-items-holder-wrap').children('.menu-name').click(function(){ 8 var c = $(this).siblings('.menu-items-sortables'), p = $(this).parent(); 9 if ( !p.hasClass('closed') ) { 10 c.sortable('disable'); 11 p.addClass('closed'); 12 } else { 13 p.removeClass('closed'); 14 c.sortable('enable').sortable('refresh'); 15 } 16 }); 17 18 $('#menu-items-left').children('.menu-items-holder-wrap').children('.menu-name').click(function() { 19 $(this).siblings('.menu-item-holder').parent().toggleClass('closed'); 20 }); 21 22 menus.not('#wp_inactive_menu_items').each(function(){ 23 var h = 50, H = $(this).children('.menu-item').length; 24 h = h + parseInt(H * 48, 10); 25 $(this).css( 'minHeight', h + 'px' ); 26 }); 27 28 $('a.menu-item-action').live('click', function(){ 29 var css = {}, menu_item = $(this).closest('div.menu-item'), inside = menu_item.children('.menu-item-inside'), w = parseInt( menu_item.find('input.menu-item-width').val(), 10 ); 30 31 if ( inside.is(':hidden') ) { 32 if ( w > 250 && inside.closest('div.menu-items-sortables').length ) { 33 css['width'] = w + 30 + 'px'; 34 if ( inside.closest('div.menu-item-liquid-right').length ) 35 css['marginLeft'] = 235 - w + 'px'; 36 menu_item.css(css); 37 } 38 wpMenus.fixLabels(menu_item); 39 inside.slideDown('fast'); 40 } else { 41 inside.slideUp('fast', function() { 42 menu_item.css({'width':'','marginLeft':''}); 43 }); 44 } 45 return false; 46 }); 47 48 $('input.menu-item-control-save').live('click', function(){ 49 wpMenus.save( $(this).closest('div.menu-item'), 0, 1, 0 ); 50 return false; 51 }); 52 53 $('a.menu-item-control-remove').live('click', function(){ 54 wpMenus.save( $(this).closest('div.menu-item'), 1, 1, 0 ); 55 return false; 56 }); 57 58 $('a.menu-item-control-close').live('click', function(){ 59 wpMenus.close( $(this).closest('div.menu-item') ); 60 return false; 61 }); 62 63 menus.children('.menu-item').each(function() { 64 wpMenus.appendTitle(this); 65 if ( $('p.menu-item-error', this).length ) 66 $('a.menu-item-action', this).click(); 67 }); 68 69 $('#menu-item-list').children('.menu-item').draggable({ 70 connectToSortable: 'div.menu-items-sortables', 71 handle: '> .menu-item-top > .menu-item-title', 72 distance: 2, 73 helper: 'clone', 74 zIndex: 5, 75 containment: 'document', 76 start: function(e,ui) { 77 wpMenus.fixWebkit(1); 78 ui.helper.find('div.menu-item-description').hide(); 79 }, 80 stop: function(e,ui) { 81 if ( rem ) 82 $(rem).hide(); 83 rem = ''; 84 wpMenus.fixWebkit(); 85 } 86 }); 87 88 menus.sortable({ 89 placeholder: 'menu-item-placeholder', 90 items: '> .menu-item', 91 handle: '> .menu-item-top > .menu-item-title', 92 cursor: 'move', 93 distance: 2, 94 containment: 'document', 95 start: function(e,ui) { 96 wpMenus.fixWebkit(1); 97 ui.item.children('.menu-item-inside').hide(); 98 ui.item.css({'marginLeft':'','width':''}); 99 }, 100 stop: function(e,ui) { 101 if ( ui.item.hasClass('ui-draggable') ) 102 ui.item.draggable('destroy'); 103 104 if ( ui.item.hasClass('deleting') ) { 105 wpMenus.save( ui.item, 1, 0, 1 ); // delete menu item 106 ui.item.remove(); 107 return; 108 } 109 110 var add = ui.item.find('input.add_new').val(), 111 n = ui.item.find('input.multi_number').val(), 112 id = ui.item.attr('id'), 113 sb = $(this).attr('id'); 114 115 ui.item.css({'marginLeft':'','width':''}); 116 wpMenus.fixWebkit(); 117 if ( add ) { 118 if ( 'multi' == add ) { 119 ui.item.html( ui.item.html().replace(/<[^<>]+>/g, function(m){ return m.replace(/__i__|%i%/g, n); }) ); 120 ui.item.attr( 'id', id.replace(/__i__|%i%/g, n) ); 121 n++; 122 $('div#' + id).find('input.multi_number').val(n); 123 } else if ( 'single' == add ) { 124 ui.item.attr( 'id', 'new-' + id ); 125 rem = 'div#' + id; 126 } 127 wpMenus.save( ui.item, 0, 0, 1 ); 128 ui.item.find('input.add_new').val(''); 129 ui.item.find('a.menu-item-action').click(); 130 return; 131 } 132 wpMenus.saveOrder(sb); 133 }, 134 receive: function(e,ui) { 135 if ( !$(this).is(':visible') ) 136 $(this).sortable('cancel'); 137 } 138 }).sortable('option', 'connectWith', 'div.menu-items-sortables').parent().filter('.closed').children('.menu-items-sortables').sortable('disable'); 139 140 $('#available-menu-items').droppable({ 141 tolerance: 'pointer', 142 accept: function(o){ 143 return $(o).parent().attr('id') != 'menu-item-list'; 144 }, 145 drop: function(e,ui) { 146 ui.draggable.addClass('deleting'); 147 $('#removing-menu-item').hide().children('span').html(''); 148 }, 149 over: function(e,ui) { 150 ui.draggable.addClass('deleting'); 151 $('div.menu-item-placeholder').hide(); 152 153 if ( ui.draggable.hasClass('ui-sortable-helper') ) 154 $('#removing-menu-item').show().children('span') 155 .html( ui.draggable.find('div.menu-item-title').children('h4').html() ); 156 }, 157 out: function(e,ui) { 158 ui.draggable.removeClass('deleting'); 159 $('div.menu-item-placeholder').show(); 160 $('#removing-menu-item').hide().children('span').html(''); 161 } 162 }); 163 }, 164 165 saveOrder : function(sb) { 166 if ( sb ) 167 $('#' + sb).closest('div.menu-items-holder-wrap').find('img.ajax-feedback').css('visibility', 'visible'); 168 169 var a = { 170 action: 'menu-items-order', 171 savemenu_items: $('#_wpnonce_menu_items').val(), 172 menus: [] 173 }; 174 175 $('div.menu-items-sortables').each( function() { 176 a['menus[' + $(this).attr('id') + ']'] = $(this).sortable('toArray').join(','); 177 }); 178 179 $.post( ajaxurl, a, function() { 180 $('img.ajax-feedback').css('visibility', 'hidden'); 181 }); 182 183 this.resize(); 184 }, 185 186 save : function(menu_item, del, animate, order) { 187 var sb = menu_item.closest('div.menu-items-sortables').attr('id'), data = menu_item.find('form').serialize(), a; 188 menu_item = $(menu_item); 189 $('.ajax-feedback', menu_item).css('visibility', 'visible'); 190 191 a = { 192 action: 'save-menu-item', 193 savemenu_items: $('#_wpnonce_menu_items').val(), 194 menu: sb 195 }; 196 197 if ( del ) 198 a['delete_menu_item'] = 1; 199 200 data += '&' + $.param(a); 201 202 $.post( ajaxurl, data, function(r){ 203 var id; 204 205 if ( del ) { 206 if ( !$('input.menu_item_number', menu_item).val() ) { 207 id = $('input.menu-item-id', menu_item).val(); 208 $('#available-menu-items').find('input.menu-item-id').each(function(){ 209 if ( $(this).val() == id ) 210 $(this).closest('div.menu-item').show(); 211 }); 212 } 213 214 if ( animate ) { 215 order = 0; 216 menu_item.slideUp('fast', function(){ 217 $(this).remove(); 218 wpMenus.saveOrder(); 219 }); 220 } else { 221 menu_item.remove(); 222 wpMenus.resize(); 223 } 224 } else { 225 $('.ajax-feedback').css('visibility', 'hidden'); 226 if ( r && r.length > 2 ) { 227 $('div.menu-item-content', menu_item).html(r); 228 wpMenus.appendTitle(menu_item); 229 wpMenus.fixLabels(menu_item); 230 } 231 } 232 if ( order ) 233 wpMenus.saveOrder(); 234 }); 235 }, 236 237 appendTitle : function(menu_item) { 238 var title = $('input[id*="-title"]', menu_item); 239 if ( title = title.val() ) { 240 title = title.replace(/<[^<>]+>/g, '').replace(/</g, '<').replace(/>/g, '>'); 241 $(menu_item).children('.menu-item-top').children('.menu-item-title').children() 242 .children('.in-menu-item-title').html(': ' + title); 243 } 244 }, 245 246 resize : function() { 247 $('div.menu-items-sortables').not('#wp_inactive_menu_items').each(function(){ 248 var h = 50, H = $(this).children('.menu-item').length; 249 h = h + parseInt(H * 48, 10); 250 $(this).css( 'minHeight', h + 'px' ); 251 }); 252 }, 253 254 fixWebkit : function(n) { 255 n = n ? 'none' : ''; 256 $('body').css({ 257 WebkitUserSelect: n, 258 KhtmlUserSelect: n 259 }); 260 }, 261 262 fixLabels : function(menu_item) { 263 menu_item.children('.menu-item-inside').find('label').each(function(){ 264 var f = $(this).attr('for'); 265 if ( f && f == $('input', this).attr('id') ) 266 $(this).removeAttr('for'); 267 }); 268 }, 269 270 close : function(menu_item) { 271 menu_item.children('.menu-item-inside').slideUp('fast', function(){ 272 menu_item.css({'width':'','marginLeft':''}); 273 }); 274 } 275 }; 276 277 $(document).ready(function($){ wpMenus.init(); }); 278 279 })(jQuery); -
wp-admin/menus.php
1 <?php 2 /** 3 * Menus administration panel. 4 * 5 * @package WordPress 6 * @subpackage Administration 7 */ 8 9 /** WordPress Administration Bootstrap */ 10 require_once( 'admin.php' ); 11 12 /** WordPress Administration Menus API */ 13 require_once(ABSPATH . 'wp-admin/includes/menus.php'); 14 15 if ( ! current_user_can('switch_themes') ) 16 wp_die( __( 'Cheatin’ uh?' )); 17 18 wp_admin_css( 'menus' ); 19 20 $menus_access = get_user_setting( 'menus_access' ); 21 if ( isset($_GET['menus-access']) ) { 22 $menus_access = 'on' == $_GET['menus-access'] ? 'on' : 'off'; 23 set_user_setting( 'menus_access', $menus_access ); 24 } 25 26 if ( 'on' == $menus_access ) 27 add_filter( 'admin_body_class', create_function('', '{return " menus_access ";}') ); 28 else 29 wp_enqueue_script('admin-menus'); 30 31 do_action( 'menu_admin_setup' ); 32 33 $title = __( 'Menus' ); 34 $parent_file = 'themes.php'; 35 36 // register the inactive_menu_items area as menu 37 register_menu(array( 38 'name' => __('Inactive Menu Items'), 39 'id' => 'wp_inactive_menu_items', 40 'description' => '', 41 'before_menu' => '', 42 'after_menu' => '', 43 )); 44 45 // These are the menu_items grouped by menu 46 $menu_items_map = wp_get_menu_items(); 47 if ( empty( $menu_items_map ) ) 48 $menu_items_map = wp_get_menu_item_defaults(); 49 50 // look for "lost" menu_items, this has to run at least on each theme change 51 function retrieve_menu_items() { 52 global $wp_registered_menu_item_updates, $wp_registered_menus, $menu_items_map, $wp_registered_menu_items; 53 54 $_menus_menu_items = array(); 55 $menus = array_keys($wp_registered_menus); 56 57 unset( $menu_items_map['array_version'] ); 58 59 $old = array_keys($menu_items_map); 60 sort($old); 61 sort($menus); 62 63 if ( $old == $menus ) 64 return; 65 66 // Move the known-good ones first 67 foreach ( $menus as $id ) { 68 if ( array_key_exists( $id, $menu_items_map ) ) { 69 $_menus_menu_items[$id] = $menu_items_map[$id]; 70 unset($menu_items_map[$id], $menus[$id]); 71 } 72 } 73 74 // if new theme has less menus than the old theme 75 if ( !empty($menu_items_map) ) { 76 foreach ( $menu_items_map as $lost => $val ) { 77 if ( is_array($val) ) 78 $_menus_menu_items['wp_inactive_menu_items'] = array_merge( (array) $_menus_menu_items['wp_inactive_menu_items'], $val ); 79 } 80 } 81 82 // discard invalid, theme-specific menu_items from menus 83 $shown_menu_items = array(); 84 foreach ( $_menus_menu_items as $menu => $menu_items ) { 85 if ( !is_array($menu_items) ) 86 continue; 87 88 $_menu_items = array(); 89 foreach ( $menu_items as $menu_item ) { 90 if ( isset($wp_registered_menu_items[$menu_item]) ) 91 $_menu_items[] = $menu_item; 92 } 93 $_menus_menu_items[$menu] = $_menu_items; 94 $shown_menu_items = array_merge($shown_menu_items, $_menu_items); 95 } 96 97 $menu_items_map = $_menus_menu_items; 98 unset($_menus_menu_items, $_menu_items); 99 100 // find hidden/lost multi-menu_item instances 101 $lost_menu_items = array(); 102 foreach ( $wp_registered_menu_items as $key => $val ) { 103 if ( in_array($key, $shown_menu_items, true) ) 104 continue; 105 106 $number = preg_replace('/.+?-([0-9]+)$/', '$1', $key); 107 108 if ( 2 > (int) $number ) 109 continue; 110 111 $lost_menu_items[] = $key; 112 } 113 114 $menu_items_map['wp_inactive_menu_items'] = array_merge($lost_menu_items, (array) $menu_items_map['wp_inactive_menu_items']); 115 wp_set_menu_items($menu_items_map); 116 } 117 retrieve_menu_items(); 118 119 if ( !count($wp_registered_menus) == 1 ) { 120 // If only "wp_inactive_menu_items" is defined the theme has no menus, die. 121 require_once( 'admin-header.php' ); 122 ?> 123 124 <div class="wrap"> 125 <?php screen_icon(); ?> 126 <h2><?php echo esc_html( $title ); ?></h2> 127 <div class="error"> 128 <p><?php _e( 'No Menus Defined' ); ?></p> 129 </div> 130 <p><?php _e( 'The theme you are currently using isn’t menu-aware, meaning that it has no menus that you are able to change. For information on making your theme menu-aware, please <a href="http://codex.wordpress.org/Custom_Menus_In_Themes">follow these instructions</a>.' ); ?></p> 131 </div> 132 133 <?php 134 require_once( 'admin-footer.php' ); 135 exit; 136 } 137 138 // We're saving a menu_item without js 139 if ( isset($_POST['savemenu_item']) || isset($_POST['removemenu_item']) ) { 140 $menu_item_id = $_POST['menu-item-id']; 141 check_admin_referer("save-delete-menu-item-$menu_item_id"); 142 143 $number = isset($_POST['multi_number']) ? (int) $_POST['multi_number'] : ''; 144 if ( $number ) { 145 foreach ( $_POST as $key => $val ) { 146 if ( is_array($val) && preg_match('/__i__|%i%/', key($val)) ) { 147 $_POST[$key] = array( $number => array_shift($val) ); 148 break; 149 } 150 } 151 } 152 153 $menu_id = $_POST['menu']; 154 $position = isset($_POST[$menu_id . '_position']) ? (int) $_POST[$menu_id . '_position'] - 1 : 0; 155 156 $id_base = $_POST['id_base']; 157 $menu = isset($menu_items_map[$menu_id]) ? $menu_items_map[$menu_id] : array(); 158 159 // delete 160 if ( isset($_POST['removemenu_item']) && $_POST['removemenu_item'] ) { 161 162 if ( !in_array($menu_item_id, $menu, true) ) { 163 wp_redirect('menu_items.php?error=0'); 164 exit; 165 } 166 167 $menu = array_diff( $menu, array($menu_item_id) ); 168 $_POST = array('menu' => $menu_id, 'menu-item-' . $id_base => array(), 'the-menu-item-id' => $menu_item_id, 'delete_menu_item' => '1'); 169 } 170 171 $_POST['menu-item-id'] = $menu; 172 173 foreach ( (array) $wp_registered_menu_item_updates as $name => $control ) { 174 if ( $name != $id_base || !is_callable($control['callback']) ) 175 continue; 176 177 ob_start(); 178 call_user_func_array( $control['callback'], $control['params'] ); 179 ob_end_clean(); 180 181 break; 182 } 183 184 $menu_items_map[$menu_id] = $menu; 185 186 // remove old position 187 if ( !isset($_POST['delete_menu_item']) ) { 188 foreach ( $menu_items_map as $key => $sb ) { 189 if ( is_array($sb) ) 190 $menu_items_map[$key] = array_diff( $sb, array($menu_item_id) ); 191 } 192 array_splice( $menu_items_map[$menu_id], $position, 0, $menu_item_id ); 193 } 194 195 wp_set_menu_items($menu_items_map); 196 wp_redirect('menu_items.php?message=0'); 197 exit; 198 } 199 200 // Output the menu_item form without js 201 if ( isset($_GET['editmenu_item']) && $_GET['editmenu_item'] ) { 202 $menu_item_id = $_GET['editmenu_item']; 203 204 if ( isset($_GET['addnew']) ) { 205 // Default to the first menu 206 $menu = array_shift( $keys = array_keys($wp_registered_menus) ); 207 208 if ( isset($_GET['base']) && isset($_GET['num']) ) { // multi-menu_item 209 // Copy minimal info from an existing instance of this menu_item to a new instance 210 foreach ( $wp_registered_menu_item_controls as $control ) { 211 if ( $_GET['base'] === $control['id_base'] ) { 212 $control_callback = $control['callback']; 213 $multi_number = (int) $_GET['num']; 214 $control['params'][0]['number'] = -1; 215 $menu_item_id = $control['id'] = $control['id_base'] . '-' . $multi_number; 216 $wp_registered_menu_item_controls[$control['id']] = $control; 217 break; 218 } 219 } 220 } 221 } 222 223 if ( isset($wp_registered_menu_item_controls[$menu_item_id]) && !isset($control) ) { 224 $control = $wp_registered_menu_item_controls[$menu_item_id]; 225 $control_callback = $control['callback']; 226 } elseif ( !isset($wp_registered_menu_item_controls[$menu_item_id]) && isset($wp_registered_menu_items[$menu_item_id]) ) { 227 $name = esc_html( strip_tags($wp_registered_menu_items[$menu_item_id]['name']) ); 228 } 229 230 if ( !isset($name) ) 231 $name = esc_html( strip_tags($control['name']) ); 232 233 if ( !isset($menu) ) 234 $menu = isset($_GET['menu']) ? $_GET['menu'] : 'wp_inactive_menu_items'; 235 236 if ( !isset($multi_number) ) 237 $multi_number = isset($control['params'][0]['number']) ? $control['params'][0]['number'] : ''; 238 239 $id_base = isset($control['id_base']) ? $control['id_base'] : $control['id']; 240 241 // show the menu item form 242 $width = ' style="width:' . max($control['width'], 350) . 'px"'; 243 $key = isset($_GET['key']) ? (int) $_GET['key'] : 0; 244 245 require_once( 'admin-header.php' ); ?> 246 <div class="wrap"> 247 <?php screen_icon(); ?> 248 <h2><?php echo esc_html( $title ); ?></h2> 249 <div class="editmenu_item"<?php echo $width; ?>> 250 <h3><?php printf( __( 'Widget %s' ), $name ); ?></h3> 251 252 <form action="menus.php" method="post"> 253 <div class="menu-item-inside"> 254 <?php 255 if ( is_callable( $control_callback ) ) 256 call_user_func_array( $control_callback, $control['params'] ); 257 else 258 echo '<p>' . __('There are no options for this menu item.') . "</p>\n"; ?> 259 </div> 260 261 <p class="describe"><?php _e('Select both the menu for this menu item and the position of the menu item in that menu.'); ?></p> 262 <div class="menu-item-position"> 263 <table class="widefat"><thead><tr><th><?php _e('menu'); ?></th><th><?php _e('Position'); ?></th></tr></thead><tbody> 264 <?php 265 foreach ( $wp_registered_menus as $sbname => $sbvalue ) { 266 echo "\t\t<tr><td><label><input type='radio' name='menu' value='" . esc_attr($sbname) . "'" . checked( $sbname, $menu, false ) . " /> $sbvalue[name]</label></td><td>"; 267 if ( 'wp_inactive_menu_items' == $sbname ) { 268 echo ' '; 269 } else { 270 if ( !isset($menu_items_map[$sbname]) || !is_array($menu_items_map[$sbname]) ) { 271 $j = 1; 272 $menu_items_map[$sbname] = array(); 273 } else { 274 $j = count($menu_items_map[$sbname]); 275 if ( isset($_GET['addnew']) || !in_array($menu_item_id, $menu_items_map[$sbname], true) ) 276 $j++; 277 } 278 $selected = ''; 279 echo "\t\t<select name='{$sbname}_position'>\n"; 280 echo "\t\t<option value=''>" . __('-- select --') . "</option>\n"; 281 for ( $i = 1; $i <= $j; $i++ ) { 282 if ( in_array($menu_item_id, $menu_items_map[$sbname], true) ) 283 $selected = selected( $i, $key + 1, false ); 284 echo "\t\t<option value='$i'$selected> $i </option>\n"; 285 } 286 echo "\t\t</select>\n"; 287 } 288 echo "</td></tr>\n"; 289 } ?> 290 </tbody></table> 291 </div> 292 293 <div class="menu-item-control-actions"> 294 <?php if ( isset($_GET['addnew']) ) { ?> 295 <a href="menus.php" class="button alignleft"><?php _e('Cancel'); ?></a> 296 <?php } else { ?> 297 <input type="submit" name="removemenu_item" class="button alignleft" value="<?php esc_attr_e('Delete'); ?>" /> 298 <?php } ?> 299 <input type="submit" name="savemenu_item" class="button-primary alignright" value="<?php esc_attr_e('Save Widget'); ?>" /> 300 <input type="hidden" name="menu-item-id" class="menu-item-id" value="<?php echo esc_attr($menu_item_id); ?>" /> 301 <input type="hidden" name="id_base" class="id_base" value="<?php echo esc_attr($id_base); ?>" /> 302 <input type="hidden" name="multi_number" class="multi_number" value="<?php echo esc_attr($multi_number); ?>" /> 303 <?php wp_nonce_field("save-delete-menu-item-$menu_item_id"); ?> 304 <br class="clear" /> 305 </div> 306 </form> 307 </div> 308 </div> 309 <?php 310 require_once( 'admin-footer.php' ); 311 exit; 312 } 313 314 $messages = array( 315 __('Changes saved.') 316 ); 317 318 $errors = array( 319 __('Error while saving.'), 320 __('Error in displaying the menu item settings form.') 321 ); 322 323 require_once( 'admin-header.php' ); ?> 324 325 <div class="wrap"> 326 <?php screen_icon(); ?> 327 <h2><?php echo esc_html( $title ); ?></h2> 328 329 <?php if ( isset($_GET['message']) && isset($messages[$_GET['message']]) ) { ?> 330 <div id="message" class="updated"><p><?php echo $messages[$_GET['message']]; ?></p></div> 331 <?php } ?> 332 <?php if ( isset($_GET['error']) && isset($errors[$_GET['error']]) ) { ?> 333 <div id="message" class="error"><p><?php echo $errors[$_GET['error']]; ?></p></div> 334 <?php } ?> 335 336 <div class="menu-item-liquid-left"> 337 <div id="menu-items-left"> 338 <div id="available-menu-items" class="menu-items-holder-wrap"> 339 <div class="menu-name"> 340 <div class="menu-name-arrow"><br /></div> 341 <h3><?php _e('Available Menu Items'); ?> <span id="removing-menu-item"><?php _e('Deactivate'); ?> <span></span></span></h3></div> 342 <div class="menu-item-holder"> 343 <p class="description"><?php _e('Drag menu items from here to a menu on the right to activate them. Drag menu items back here to deactivate them and delete their settings.'); ?></p> 344 <div id="menu-item-list"> 345 <?php wp_list_menu_items(); ?> 346 </div> 347 <br class='clear' /> 348 </div> 349 <br class="clear" /> 350 </div> 351 352 <div class="menu-items-holder-wrap"> 353 <div class="menu-name"> 354 <div class="menu-name-arrow"><br /></div> 355 <h3><?php _e('Inactive Menu Items'); ?> 356 <span><img src="images/wpspin_light.gif" class="ajax-feedback" title="" alt="" /></span></h3></div> 357 <div class="menu-item-holder inactive"> 358 <p class="description"><?php _e('Drag menu items here to remove them from the menu but keep their settings.'); ?></p> 359 <?php wp_list_menu_item_controls('wp_inactive_menu_items'); ?> 360 <br class="clear" /> 361 </div> 362 </div> 363 </div> 364 </div> 365 366 <div class="menu-item-liquid-right"> 367 <div id="menu-items-right"> 368 <?php 369 $i = 0; 370 foreach ( $wp_registered_menus as $menu => $registered_menu ) { 371 if ( 'wp_inactive_menu_items' == $menu ) 372 continue; 373 $closed = $i ? ' closed' : ''; ?> 374 <div class="menu-items-holder-wrap<?php echo $closed; ?>"> 375 <div class="menu-name"> 376 <div class="menu-name-arrow"><br /></div> 377 <h3><?php echo esc_html( $registered_menu['name'] ); ?> 378 <span><img src="images/wpspin_dark.gif" class="ajax-feedback" title="" alt="" /></span></h3></div> 379 <?php wp_list_menu_item_controls( $menu ); // Show the control forms for each of the menu_items in this menu ?> 380 </div> 381 <?php 382 $i++; 383 } ?> 384 </div> 385 </div> 386 <form action="" method="post"> 387 <?php wp_nonce_field( 'save-menu-items', '_wpnonce_menu_items', false ); ?> 388 </form> 389 <br class="clear" /> 390 </div> 391 392 <?php 393 do_action( 'menu_admin_page' ); 394 require_once( 'admin-footer.php' ); -
wp-admin/css/menus.dev.css
1 html, 2 body { 3 min-width: 950px; 4 } 5 6 /* 2 column liquid layout */ 7 div.menu-item-liquid-left { 8 float: left; 9 clear: left; 10 width: 100%; 11 margin-right: -325px; 12 } 13 14 div#menu-items-left { 15 margin-left: 5px; 16 margin-right: 325px; 17 } 18 19 div#menu-items-right { 20 width: 285px; 21 margin: 0 auto; 22 } 23 24 div.menu-item-liquid-right { 25 float: right; 26 clear: right; 27 width: 300px; 28 } 29 30 .menu-item-liquid-right .menu-item, 31 #wp_inactive_menu_items .menu-item, 32 .menu-item-liquid-right .menu-description { 33 width: 250px; 34 margin: 0 auto 20px; 35 overflow: hidden; 36 } 37 38 .menu-item-liquid-right .menu-description { 39 margin-bottom: 10px; 40 } 41 42 #wp_inactive_menu_items .menu-item { 43 margin: 0 10px 20px; 44 float: left; 45 } 46 47 div.menu-name h3 { 48 margin: 0; 49 padding: 5px 12px; 50 font-size: 13px; 51 height: 19px; 52 overflow: hidden; 53 white-space: nowrap; 54 } 55 56 div.menu-name { 57 background-repeat: repeat-x; 58 background-position: 0 0; 59 cursor: pointer; 60 font-size: 13px; 61 border-width: 1px; 62 border-style: solid; 63 -moz-border-radius-topleft: 8px; 64 -moz-border-radius-topright: 8px; 65 -webkit-border-top-right-radius: 8px; 66 -webkit-border-top-left-radius: 8px; 67 -khtml-border-top-right-radius: 8px; 68 -khtml-border-top-left-radius: 8px; 69 border-top-right-radius: 8px; 70 border-top-left-radius: 8px; 71 } 72 73 .js .closed .menu-name { 74 -moz-border-radius-bottomleft: 8px; 75 -moz-border-radius-bottomright: 8px; 76 -webkit-border-bottom-right-radius: 8px; 77 -webkit-border-bottom-left-radius: 8px; 78 -khtml-border-bottom-right-radius: 8px; 79 -khtml-border-bottom-left-radius: 8px; 80 border-bottom-right-radius: 8px; 81 border-bottom-left-radius: 8px; 82 } 83 84 .menu-item-liquid-right .menu-items-sortables, 85 #menu-items-left .menu-item-holder { 86 border-width: 0 1px 1px; 87 border-style: none solid solid; 88 -moz-border-radius-bottomleft: 8px; 89 -moz-border-radius-bottomright: 8px; 90 -webkit-border-bottom-right-radius: 8px; 91 -webkit-border-bottom-left-radius: 8px; 92 -khtml-border-bottom-right-radius: 8px; 93 -khtml-border-bottom-left-radius: 8px; 94 border-bottom-right-radius: 8px; 95 border-bottom-left-radius: 8px; 96 } 97 98 .js .closed .menu-items-sortables, 99 .js .closed .menu-item-holder { 100 display: none; 101 } 102 103 .menu-item-liquid-right .menu-items-sortables { 104 padding: 15px 0 0; 105 } 106 107 #available-menu-items .menu-item-holder { 108 padding: 7px 5px 0; 109 } 110 111 #wp_inactive_menu_items { 112 padding: 5px 5px 0; 113 } 114 115 #menu-item-list .menu-item { 116 width: 250px; 117 margin: 0 10px 15px; 118 border: 0 none; 119 float: left; 120 } 121 122 #menu-item-list .menu-item-description { 123 padding: 5px 8px; 124 } 125 126 #menu-item-list .menu-item-top { 127 border-width: 1px; 128 border-style: solid; 129 -moz-border-radius: 6px; 130 -khtml-border-radius: 6px; 131 -webkit-border-radius: 6px; 132 border-radius: 6px; 133 } 134 135 .menu-item-placeholder { 136 border-width: 1px; 137 border-style: dashed; 138 margin: 0 auto 20px; 139 height: 26px; 140 width: 250px; 141 } 142 143 #wp_inactive_menu_items .menu-item-placeholder { 144 margin: 0 10px 20px; 145 float: left; 146 } 147 148 div.menu-items-holder-wrap { 149 padding: 0; 150 margin: 10px 0 20px; 151 } 152 153 #menu-items-left #available-menu-items { 154 background-color: transparent; 155 border: 0 none; 156 } 157 158 ul#menu-item-list { 159 list-style: none; 160 margin: 0; 161 padding: 0; 162 min-height: 100px; 163 } 164 165 .menu-item .menu-item-top { 166 font-size: 12px; 167 font-weight: bold; 168 height: 26px; 169 overflow: hidden; 170 } 171 172 .menu-item-top .menu-item-title { 173 padding: 5px 9px; 174 } 175 176 .menu-item-top .menu-item-title-action { 177 float: right; 178 } 179 180 a.menu-item-action { 181 display: block; 182 width: 24px; 183 height: 26px; 184 } 185 186 #available-menu-items a.menu-item-action { 187 display: none; 188 } 189 190 .menu-item-top a.menu-item-action { 191 background: url("../images/menu-bits.gif") no-repeat scroll 0 -110px; 192 } 193 194 .menu-item .menu-item-inside, 195 .menu-item .menu-item-description { 196 padding: 12px 12px 10px; 197 font-size: 11px; 198 line-height: 16px; 199 } 200 201 .menu-item-inside, 202 .menu-item-description { 203 display: none; 204 } 205 206 #available-menu-items .menu-item-description { 207 display: block; 208 } 209 210 .menu-item .menu-item-inside p { 211 margin: 0 0 1em; 212 padding: 0; 213 } 214 215 .menu-item-title h4 { 216 margin: 0; 217 line-height: 1.3; 218 overflow: hidden; 219 white-space: nowrap; 220 } 221 222 .menu-items-sortables { 223 min-height: 90px; 224 } 225 226 .menu-item-control-actions { 227 margin-top: 8px; 228 } 229 230 .menu-item-control-actions a { 231 text-decoration: none; 232 } 233 234 .menu-item-control-actions a:hover { 235 text-decoration: underline; 236 } 237 238 .menu-item-control-actions .ajax-feedback { 239 padding-bottom: 3px; 240 } 241 242 .menu-item-control-actions div.alignleft { 243 margin-top: 6px; 244 } 245 246 div#menu-info { 247 padding: 0 1em; 248 margin-bottom: 1em; 249 font-size: 11px; 250 } 251 252 .menu-item-title a, 253 .menu-item-title a:hover { 254 text-decoration: none; 255 border-bottom: none; 256 } 257 258 .menu-item-control-edit { 259 display: block; 260 font-size: 11px; 261 font-weight: normal; 262 line-height: 26px; 263 padding: 0 8px 0 0; 264 } 265 266 a.menu-item-control-edit { 267 text-decoration: none; 268 } 269 270 .menu-item-control-edit .add, 271 .menu-item-control-edit .edit { 272 display: none; 273 } 274 275 #available-menu-items .menu-item-control-edit .add, 276 #menu-items-right .menu-item-control-edit .edit, 277 #wp_inactive_menu_items .menu-item-control-edit .edit { 278 display: inline; 279 } 280 281 .editmenu-item { 282 margin: 0 auto 15px; 283 } 284 285 .editmenu-item .menu-item-inside { 286 display: block; 287 border-width: 1px; 288 border-style: solid; 289 padding: 10px; 290 -moz-border-radius: 6px; 291 -khtml-border-radius: 6px; 292 -webkit-border-radius: 6px; 293 border-radius: 6px; 294 } 295 296 .inactive p.description { 297 margin: 5px 15px 8px; 298 } 299 300 #available-menu-items p.description { 301 margin: 0 12px 12px; 302 } 303 304 .menu-item-position { 305 margin-top: 8px; 306 } 307 308 .inactive { 309 padding-top: 2px; 310 } 311 312 .menu-name-arrow { 313 float: right; 314 height: 29px; 315 width: 26px; 316 } 317 318 .menu-item-title .in-menu-item-title { 319 font-size: 11px; 320 white-space: nowrap; 321 } 322 323 #removing-menu-item { 324 display: none; 325 font-weight: normal; 326 padding-left: 15px; 327 font-size: 12px; 328 } 329 330 .menu-item-control-noform, 331 #access-off, 332 .menu-items_access .menu-item-action, 333 .menu-items_access .menu-name-arrow, 334 .menu-items_access #access-on, 335 .menu-items_access .menu-item-holder .description { 336 display: none; 337 } 338 339 .menu-items_access .menu-item-holder, 340 .menu-items_access #menu-item-list { 341 padding-top: 10px; 342 } 343 344 .menu-items_access #access-off { 345 display: inline; 346 } 347 348 .menu-items_access #wpbody-content .menu-item-title-action, 349 .menu-items_access #wpbody-content .menu-item-control-edit, 350 .menu-items_access .closed .menu-items-sortables, 351 .menu-items_access .closed .menu-item-holder { 352 display: block; 353 } 354 355 .menu-items_access .closed .menu-name { 356 -moz-border-radius-bottomleft: 0; 357 -moz-border-radius-bottomright: 0; 358 -webkit-border-bottom-right-radius: 0; 359 -webkit-border-bottom-left-radius: 0; 360 -khtml-border-bottom-right-radius: 0; 361 -khtml-border-bottom-left-radius: 0; 362 border-bottom-right-radius: 0; 363 border-bottom-left-radius: 0; 364 } 365 366 .menu-items_access .menu-name, 367 .menu-items_access .menu-item .menu-item-top { 368 cursor: default; 369 } 370 -
wp-admin/css/colors-fresh.dev.css
3 3 } 4 4 5 5 * html input, 6 * html .widget { 6 * html .widget, 7 * html .menu-item { 7 8 border-color: #dfdfdf; 8 9 } 9 10 … … 131 132 } 132 133 133 134 .widget .widget-top, 135 .menu-item .menu-item-top, 134 136 .postbox h3, 135 137 .stuffbox h3 { 136 138 background: #dfdfdf url("../images/gray-grad.png") repeat-x left top; … … 644 646 } 645 647 646 648 .widget, 647 #widget-list .widget-top, 649 .menu-item, 650 #widget-list .widget-top, 651 #menu-item-list .menu-item-top, 648 652 .postbox, 649 653 #titlediv, 650 654 #poststuff .postarea, … … 652 656 border-color: #dfdfdf; 653 657 } 654 658 655 .widget, 659 .widget, 660 .menu-item, 656 661 .postbox { 657 662 background-color: #fff; 658 663 } … … 661 666 color: #464646; 662 667 } 663 668 664 .widget .widget-top, 669 #widget-list .widget-top, 670 #menu-item-list .menu-item-top, 665 671 .ui-sortable .postbox h3:hover { 666 672 color: #000; 667 673 } … … 741 747 .file-error, 742 748 abbr.required, 743 749 .widget-control-remove:hover, 750 .menu-item-control-remove:hover, 744 751 table.widefat .delete a:hover, 745 752 table.widefat .trash a:hover, 746 753 table.widefat .spam a:hover, … … 1014 1021 #editorcontainer, 1015 1022 #post-status-info, 1016 1023 #titlediv #title, 1017 .editwidget .widget-inside { 1024 .editwidget .widget-inside, 1025 .editmenu-item .menu-item-inside { 1018 1026 border-color: #dfdfdf; 1019 1027 } 1020 1028 … … 1616 1624 } 1617 1625 1618 1626 div.widgets-sortables, 1619 #widgets-left .inactive { 1627 div.menu-items-sortables, 1628 #widgets-left .inactive, 1629 #menu-items-left .inactive { 1620 1630 background-color: #f1f1f1; 1621 1631 border-color: #ddd; 1622 1632 } 1623 1633 1624 #available-widgets .widget-holder { 1634 #available-widgets .widget-holder, 1635 #available-menu-items .menu-item-holder { 1625 1636 background-color: #fff; 1626 1637 border-color: #ddd; 1627 1638 } 1628 1639 1629 #widgets-left .sidebar-name { 1640 #widgets-left .sidebar-name, 1641 #menu-items-left .menu-name { 1630 1642 background-color: #aaa; 1631 1643 background-image: url(../images/ed-bg.gif); 1632 1644 text-shadow: #fff 0 1px 0; 1633 1645 border-color: #dfdfdf; 1634 1646 } 1635 1647 1636 #widgets-right .sidebar-name { 1648 #widgets-right .sidebar-name, 1649 #menu-items-right .menu-name { 1637 1650 background-image: url(../images/fav.png); 1638 1651 text-shadow: #3f3f3f 0 -1px 0; 1639 1652 background-color: #636363; … … 1642 1655 } 1643 1656 1644 1657 .sidebar-name:hover, 1645 #removing-widget { 1658 .menu-name:hover, 1659 #removing-widget, 1660 #removing-menu-item { 1646 1661 color: #d54e21; 1647 1662 } 1648 1663 1649 #removing-widget span { 1664 #removing-widget span, 1665 #removing-menu-item span { 1650 1666 color: black; 1651 1667 } 1652 1668 1653 #widgets-left .sidebar-name-arrow { 1669 #widgets-left .sidebar-name-arrow, 1670 #menu-items-left .menu-name-arrow { 1654 1671 background: transparent url(../images/menu-bits.gif) no-repeat scroll left -109px; 1655 1672 } 1656 1673 1657 #widgets-right .sidebar-name-arrow { 1674 #widgets-right .sidebar-name-arrow, 1675 #menu-items-right .menu-name-arrow { 1658 1676 background: transparent url(../images/fav-arrow.gif) no-repeat scroll 0 -1px; 1659 1677 } 1660 1678 1661 .in-widget-title { 1679 .in-widget-title, 1680 .in-menu-item-title { 1662 1681 color: #606060; 1663 1682 } 1664 1683 1665 .deleting .widget-title * { 1684 .deleting .widget-title *, 1685 .deleting .menu-item-title * { 1666 1686 color: #aaa; 1667 1687 } 1668 1688 -
wp-admin/css/menus-rtl.css
1 2 ul#menu-item-list li.menu-item-list-item div.menu-item-description { 3 margin: 0 200px 0 0; 4 padding: 0 4em 0 0; 5 } 6 .menu-item-control-save, 7 .menu-item-control-remove { 8 margin-right: 0; 9 margin-left: 8px; 10 float: right; 11 } -
wp-admin/css/wp-admin.dev.css
1653 1653 } 1654 1654 1655 1655 .widget .widget-top, 1656 .menu-item .menu-item-top, 1656 1657 .postbox h3 { 1657 1658 cursor: move; 1658 1659 -webkit-user-select: none; … … 1700 1701 } 1701 1702 1702 1703 .widget, 1704 .menu-item, 1703 1705 .postbox, 1704 1706 .stuffbox { 1705 1707 margin-bottom: 20px; … … 1713 1715 } 1714 1716 1715 1717 .widget .widget-top, 1718 .menu-item .menu-item-top, 1716 1719 .postbox h3, 1717 1720 .postbox h3, 1718 1721 .stuffbox h3 {