Custom Menu Wizard Widget - Version 1.0.0

Version Description

Initial release

=

Download this release

Release Info

Developer wizzud
Plugin Icon 128x128 Custom Menu Wizard Widget
Version 1.0.0
Comparing to
See all releases

Version 1.0.0

Files changed (3) hide show
  1. custom-menu-wizard.js +28 -0
  2. custom-menu-wizard.php +740 -0
  3. readme.txt +194 -0
custom-menu-wizard.js ADDED
@@ -0,0 +1,28 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ /* Plugin Name: Custom Menu Wizard
2
+ * Version: 1.0.0
3
+ * Author: Roger Barrett
4
+ *
5
+ * Script for controlling this widget's options (in Admin -> Widgets)
6
+ */
7
+ jQuery(function($){
8
+ var dotPrefix = '.widget-custom-menu-wizard'
9
+ $(document).on('click', dotPrefix + '-collapsible-fieldset', function(){
10
+ var chkbox = $('input', this).eq(0),
11
+ collapse = !chkbox.prop('checked');
12
+ if(chkbox.length){
13
+ chkbox.prop('checked', collapse);
14
+ $('div', this).css({backgroundPosition:collapse?'0 0':'0 -36px'});
15
+ $(this).next('div')[collapse?'slideUp':'slideDown']();
16
+ }
17
+ this.blur();
18
+ return false;
19
+ });
20
+ $(document).on('change', dotPrefix + '-filter-radio', function(){
21
+ $(dotPrefix + '-filter-radio-dep', this.form).prop('disabled', $(dotPrefix + '-filter-radio', this.form).eq(0).prop('checked'));
22
+ });
23
+ $(document).on('change', dotPrefix + '-select-menu', function(){
24
+ var optgroups = $('select' + dotPrefix + '-filter-radio-dep', this.form).val(0).find('optgroup');
25
+ optgroups.filter(':visible').hide();
26
+ optgroups.eq( this.selectedIndex ).show();
27
+ });
28
+ });
custom-menu-wizard.php ADDED
@@ -0,0 +1,740 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+ /*
3
+ * Plugin Name: Custom Menu Wizard
4
+ * Plugin URI: http://www.wizzud.com/
5
+ * Description: Full control over the wp_nav_menu parameters for a custom menu, plus the ability to filter for specific level(s), or for children of a selected menu item or the current item
6
+ * Version: 1.0.0
7
+ * Author: Roger Barrett
8
+ * Author URI: http://www.wizzud.com/
9
+ * License: GPL2+
10
+ */
11
+
12
+ /**
13
+ * registers the widget
14
+ */
15
+ function custom_menu_wizard_register_widget() {
16
+ register_widget('Custom_Menu_Wizard_Widget');
17
+ }
18
+ add_action('widgets_init', 'custom_menu_wizard_register_widget');
19
+
20
+ /**
21
+ * enqueues script file for the widget admin
22
+ */
23
+ function custom_menu_wizard_widget_admin_script(){
24
+ wp_enqueue_script('custom-menu-wizard-plugin-script', plugins_url('/custom-menu-wizard.js', __FILE__), array('jquery'));
25
+ }
26
+ add_action('admin_print_scripts-widgets.php', 'custom_menu_wizard_widget_admin_script');
27
+
28
+ /*
29
+ * Custom Menu Wizard Walker class
30
+ */
31
+ class Custom_Menu_Wizard_Walker extends Walker_Nav_menu{
32
+
33
+ /**
34
+ * opens a sub-level with a UL or OL start-tag
35
+ *
36
+ * @param string $output Passed by reference. Used to append additional content.
37
+ * @param int $depth Depth of page. Used for padding.
38
+ */
39
+ function start_lvl( &$output, $depth = 0, $args = array() ) {
40
+ $indent = str_repeat("\t", $depth);
41
+ $listtag = empty( $args->_custom_menu_wizard['ol_sub'] ) ? 'ul' : 'ol';
42
+ $output .= "\n$indent<$listtag class=\"sub-menu\">\n";
43
+ }
44
+
45
+ /**
46
+ * closes a sub-level with a UL or OL end-tag
47
+ *
48
+ * @param string $output Passed by reference. Used to append additional content.
49
+ * @param int $depth Depth of page. Used for padding.
50
+ */
51
+ function end_lvl( &$output, $depth = 0, $args = array() ) {
52
+ $indent = str_repeat("\t", $depth);
53
+ $listtag = empty( $args->_custom_menu_wizard['ol_sub'] ) ? 'ul' : 'ol';
54
+ $output .= "$indent</$listtag>\n";
55
+ }
56
+
57
+ /**
58
+ * pre-filters elements then calls parent::walk()
59
+ *
60
+ * @param array $elements Menu items
61
+ * @param integer $max_depth
62
+ * @return string
63
+ */
64
+ function walk($elements, $max_depth){
65
+
66
+ $args = array_slice(func_get_args(), 2);
67
+ $args = $args[0];
68
+
69
+ if( $max_depth >= -1 && !empty( $elements ) && isset($args->_custom_menu_wizard) ){
70
+
71
+ $cmw =& $args->_custom_menu_wizard;
72
+ //in $cmw (array) :
73
+ // filter : 0 = none, 1 = kids of (current or specific item), 2 = current path
74
+ // filter_item : current menu item if zero, else a menu item id
75
+ // flat_output : true = equivalent of $max_depth == -1
76
+ // include_parent : true = include the filter_item menu item
77
+ // include_ancestors : true = include the filter_item menu item plus all it's ancestors
78
+ // title_from_parent : true = widget wants parent's title as title
79
+ // start_level : integer, 1+
80
+ // depth : integer, replacement for max_depth and also applied to 'flat' output
81
+ //$elements is an array of objects, indexed by position within the menu (menu_order),
82
+ //starting at 1 and incrementing sequentially regardless of parentage (ie. first item is [1],
83
+ //second item is [2] whether it's at root or subordinate to first item)
84
+
85
+ $find_any = empty( $cmw['filter'] );
86
+ $find_kids_of = $cmw['filter'] == 1;
87
+ $find_current_item = $find_kids_of && empty( $cmw['filter_item'] );
88
+ $find_current_path = $cmw['filter'] > 1; //ie. 2!
89
+
90
+ //are we looking for something in particular?...
91
+ if( $find_kids_of || $cmw['start_level'] > 1 ){
92
+ $id_field = $this->db_fields['id'];
93
+ $parent_field = $this->db_fields['parent'];
94
+
95
+ //start level applies to the *kids* of a find_kids_of search, not to the parent, so while we
96
+ //are still looking for the parent, the start_level for a find_kids_of search is actually one
97
+ //up from mw['start_level']...
98
+ $start_level = $find_kids_of ? $cmw['start_level'] - 1 : $cmw['start_level'];
99
+
100
+ $keep_ids = array();
101
+ $keep_items = array();
102
+ $temp = array();
103
+ foreach( $elements as $i=>$item ){
104
+ if( empty( $item->$parent_field ) ){
105
+ //set root level of menu, and no ancestors...
106
+ $temp[ $item->$id_field ] = array(
107
+ 'level' => 1,
108
+ //this is an array of indexes into $elements...
109
+ 'breadcrumb' => array( $i )
110
+ );
111
+ }elseif( isset( $temp[ $item->$parent_field ] ) ){
112
+ //set one greater than parent's level, and ancestors are parent's ancestors plus the parent...
113
+ $temp[ $item->$id_field ] = array(
114
+ 'level' => $temp[ $item->$parent_field ]['level'] + 1,
115
+ 'breadcrumb' => $temp[ $item->$parent_field ]['breadcrumb']
116
+ );
117
+ $temp[ $item->$id_field ]['breadcrumb'][] = $i;
118
+ }
119
+ //if $temp[] hasn't been set then it's an orphan; in order to keep orphans, max_depth must be 0 (ie. unlimited)
120
+ //note that if a child is an orphan then all descendants of that child are also considered to be orphans!
121
+ //also note that orphans (in the original menu) are ignored by this widget!
122
+
123
+ if( isset( $temp[ $item->$id_field ] ) ){
124
+ //are we at or below the start level?...
125
+ if( $temp[ $item->$id_field ]['level'] >= $start_level ){
126
+ //are we still looking for a starting point?...
127
+ if( empty( $keep_ids ) ){
128
+ if( //...we're looking for unspecific items starting at this level...
129
+ $find_any ||
130
+ //...we're looking for current item, and this is it...
131
+ ( $find_current_item && $item->current ) ||
132
+ //...we're looking for a particular menu item, and this is it...
133
+ ( $find_kids_of && $cmw['filter_item'] == $item->$id_field ) ||
134
+ //...we're looking for current path, and this is on it...
135
+ ( $find_current_path && ( $item->current || $item->current_item_parent || $item->current_item_ancestor ) )
136
+ ){
137
+ //NOTE : at this point I'm *keeping* the id of the parent of a find_kids_of search, but not the actual item!
138
+ $keep_ids[] = $item->$id_field;
139
+ if( !$find_kids_of ){
140
+ $keep_items[] = $item;
141
+ }
142
+ //depth, if set, kicks in at this point :
143
+ // if doing a find_kids_of search then this level counts as 0, and the next level (the kids) counts as 1
144
+ // otherwise, the current level counts as 1
145
+ if( $cmw['depth'] > 0 ){
146
+ $max_level = $temp[ $item->$id_field ]['level'] + $cmw['depth'] - ($find_kids_of ? 0 : 1);
147
+ }else{
148
+ //unlimited...
149
+ $max_level = 9999;
150
+ }
151
+ //...and reset start level...
152
+ $start_level = $cmw['start_level'];
153
+ }
154
+ //having found at least one, any more have to be:
155
+ // - within max_depth of the first one found, and
156
+ // - either it's an unspecific search, or we have the parent already
157
+ }elseif( $temp[ $item->$id_field ]['level'] <= $max_level && ($find_any || in_array( $item->$parent_field, $keep_ids ) ) ){
158
+ $keep_ids[] = $item->$id_field;
159
+ $keep_items[] = $item;
160
+ }
161
+ }
162
+ }
163
+ } //end foreach
164
+
165
+ unset( $keep_ids );
166
+ if( !empty( $keep_items) ){
167
+
168
+ //do we need to prepend parent or ancestors?...
169
+ $temp = $temp[ $keep_items[0]->$id_field ]['breadcrumb'];
170
+ //remove the last element, which is the item's own index...
171
+ array_pop( $temp );
172
+ $i = $j = count( $temp );
173
+ if( $find_kids_of && $i > 0 ){
174
+ if( $cmw['include_ancestors'] ){
175
+ $j = 0;
176
+ }elseif( $cmw['include_parent'] ){
177
+ --$j;
178
+ }
179
+ while( $i > $j ){
180
+ array_unshift( $keep_items, $elements[ $temp[ --$i ] ]);
181
+ }
182
+ }
183
+ //do we want the parent's title as the widget title?...
184
+ if( $find_kids_of && $cmw['title_from_parent'] && count( $temp ) > 0){
185
+ $cmw['parent_title'] = apply_filters(
186
+ 'the_title',
187
+ $elements[ $temp[ count( $temp ) - 1 ] ]->title,
188
+ $elements[ $temp[ count( $temp ) - 1 ] ]->ID
189
+ );
190
+ }
191
+ }
192
+
193
+ //for each item we're keeping, use the temp array to hold:
194
+ // [0] => the level within the new structure (starting at 1), and
195
+ // [1] => the number of kids each item has
196
+ $temp = array();
197
+ foreach( $keep_items as $item ){
198
+ if( isset( $temp[ $item->$parent_field ] ) ){
199
+ $temp[ $item->$id_field ] = array( $temp[ $item->$parent_field ][0] + 1, 0 );
200
+ $temp[ $item->$parent_field ][1] += 1;
201
+ }else{
202
+ $temp[ $item->$id_field ] = array( 1, 0 );
203
+ }
204
+ }
205
+
206
+ //transfer $keep back into $elements, resetting the index to increment from 1; also add
207
+ //new classes to indicate level (starting at 1) and whether any item has kids
208
+ //
209
+ //note that we have already filtered out real orphans, but we may have introduced top-level
210
+ //items that would appear to be orphans to the parent::walk() method, so we need to set all
211
+ //the top-level items to appear as if they are root-level items...
212
+ $elements = array();
213
+ $i = 1;
214
+ foreach( $keep_items as $item ){
215
+ $item->classes[] = 'cmw-level-' . $temp[ $item->$id_field ][0];
216
+ if( $temp[ $item->$id_field ][1] > 0 ){
217
+ $item->classes[] = 'cmw-has-submenu';
218
+ }
219
+ if( $temp[ $item->$id_field ][0] == 1 ){
220
+ //fake as root level item...
221
+ $item->$parent_field = 0;
222
+ }
223
+ $elements[ $i++ ] = $item;
224
+ }
225
+ unset( $keep_items, $temp );
226
+
227
+ //since we've done all the depth filtering, set max_depth to unlimited (unless 'flat' was requested!)...
228
+ if( !$cmw['flat_output'] ){
229
+ $max_depth = 0;
230
+ }
231
+ $elements = apply_filters( 'custom_menu_wizard_walker_items', $elements, $args );
232
+ }
233
+ }
234
+
235
+ return empty( $elements ) ? '' : parent::walk($elements, $max_depth, $args);
236
+ }
237
+
238
+ }
239
+
240
+ /**
241
+ * Custom Menu Wizard Widget class
242
+ */
243
+ class Custom_Menu_Wizard_Widget extends WP_Widget {
244
+
245
+ var $_cmw_switches = array(
246
+ 'hide_title',
247
+ 'flat_output',
248
+ 'include_parent',
249
+ 'include_ancestors',
250
+ 'hide_empty',
251
+ 'title_from_parent',
252
+ 'ol_root',
253
+ 'ol_sub',
254
+ //field section toggles...
255
+ 'fs_filter',
256
+ 'fs_output',
257
+ 'fs_container',
258
+ 'fs_classes',
259
+ 'fs_links'
260
+ );
261
+ var $_cmw_strings = array(
262
+ 'title' => '',
263
+ 'container' => 'div',
264
+ 'container_id' => '',
265
+ 'container_class' => '',
266
+ 'menu_class' => 'menu-widget',
267
+ 'widget_class' => ''
268
+ );
269
+ var $_cmw_html = array(
270
+ 'before' => '',
271
+ 'after' => '',
272
+ 'link_before' => '',
273
+ 'link_after' => ''
274
+ );
275
+ var $_cmw_integers = array(
276
+ 'depth' => 0,
277
+ 'filter' => 0,
278
+ 'filter_item' => 0,
279
+ 'menu' => 0,
280
+ 'start_level' => 1
281
+ );
282
+
283
+ /**
284
+ * class constructor
285
+ */
286
+ function __construct() {
287
+ parent::__construct(
288
+ 'custom-menu-wizard',
289
+ 'Custom Menu Wizard',
290
+ array(
291
+ 'classname' => 'widget_custom_menu_wizard',
292
+ 'description' => __('Add a custom menu, or part of one, as a widget')
293
+ // ),
294
+ // array(
295
+ // 'width'=>560
296
+ )
297
+ );
298
+ }
299
+
300
+ /**
301
+ * removes itself from the filters and, if available and requested, stores parent_title in the instance for use as the widget title
302
+ *
303
+ * @param array $items Filtered menu items
304
+ * @param object $args
305
+ * @return array Menu items
306
+ */
307
+ function cmw_filter_retain_parent_title($items, $args){
308
+ remove_filter('custom_menu_wizard_walker_items', array( $this, 'cmw_filter_retain_parent_title' ), 10, 2);
309
+ if( !empty( $args->_custom_menu_wizard['title_from_parent'] ) && !empty( $args->_custom_menu_wizard['parent_title'] ) ){
310
+ $this->cmw_title_from_parent = $args->_custom_menu_wizard['parent_title'];
311
+ }
312
+ return $items;
313
+ }
314
+
315
+ /**
316
+ * this merely removes itself from the filters and returns an empty string
317
+ * it gets added by the cmw_filter_wp_nav_menu_SLUG_items method below, and only
318
+ * ever gets run when hide_empty is set on the widget instance
319
+ *
320
+ * @param string $nav_menu HTML for the menu
321
+ * @param object $args
322
+ * @return string HTML for the menu
323
+ */
324
+ function cmw_filter_no_output_when_empty($nav_menu, $args){
325
+ remove_filter( 'wp_nav_menu', array( $this, 'cmw_filter_no_output_when_empty' ), 65532, 2 );
326
+ return empty( $args->_custom_menu_wizard ) ? $nav_menu : '';
327
+ }
328
+
329
+ /**
330
+ * this gets run if hide_empty is set
331
+ * if $items is empty then add a wp_nav_menu filter to do the actual return of an empty string
332
+ * it gets run before the wp_nav_menu filter, but it gets the $items array whereas the wp_nav_menu filter does not
333
+ * it gets added by $this->widget() before wp_nav_menu() is called, and removed immediately after wp_nav_menu() returns
334
+ *
335
+ * @param array $items Menu items
336
+ * @param object $args
337
+ * @return array Menu items
338
+ */
339
+ function cmw_filter_check_for_no_items($items, $args){
340
+ if( !empty( $args->_custom_menu_wizard ) && empty( $items ) ){
341
+ add_filter( 'wp_nav_menu', array( $this, 'cmw_filter_no_output_when_empty' ), 65532, 2 );
342
+ }
343
+ return $items;
344
+ }
345
+
346
+ /**
347
+ * produces the widget HTML at the front end
348
+ *
349
+ * @param object $args Widget arguments
350
+ * @param array $instance Configuration for this widget instance
351
+ */
352
+ function widget($args, $instance) {
353
+ extract( $args, EXTR_SKIP );
354
+
355
+ //switches...
356
+ foreach( $this->_cmw_switches as $k=>$v ){
357
+ $instance[ $v ] = !empty( $instance[ $v ] );
358
+ }
359
+ //integers...
360
+ foreach( $this->_cmw_integers as $k=>$v ){
361
+ $instance[ $k ] = max( $v, intval( $instance[ $k ] ) );
362
+ }
363
+ //strings...
364
+ foreach( $this->_cmw_strings as $k=>$v ){
365
+ $instance[ $k ] = empty( $instance[ $k ] ) ? $v : trim( $instance[ $k ] );
366
+ }
367
+ //html strings...
368
+ foreach( $this->_cmw_html as $k=>$v ){
369
+ $instance[ $k ] = empty( $instance[ $k ] ) ? $v : trim( $instance[ $k ] );
370
+ }
371
+
372
+ $this->cmw_title_from_parent = '';
373
+
374
+ //fetch menu...
375
+ if( !empty($instance['menu'] ) ){
376
+ $menu = wp_get_nav_menu_object( $instance['menu'] );
377
+
378
+ //no menu, no output...
379
+ if ( !empty( $menu ) ){
380
+
381
+ if( !empty( $instance['widget_class'] ) ){
382
+ //$before_widget is usually just a DIV start-tag, with an id and a class; if it
383
+ //gets more complicated than that then this may not work as expected...
384
+ if( preg_match( '/^<[^>]+?class=["\']/', $before_widget ) > 0 ){
385
+ $before_widget = preg_replace( '/(class=["\'])/', '$1' . $instance['widget_class'] . ' ', $before_widget, 1 );
386
+ }else{
387
+ $before_widget = preg_replace( '/^(<\w+)(\s|>)/', '$1 class="' . $instance['widget_class'] . '"$2', $before_widget );
388
+ }
389
+ }
390
+
391
+ if( !empty( $instance['container_class'] ) ){
392
+ $instance['container_class'] = "menu-{$menu->slug}-container {$instance['container_class']}";
393
+ }
394
+
395
+ if( $instance['title_from_parent'] ){
396
+ add_filter('custom_menu_wizard_walker_items', array( $this, 'cmw_filter_retain_parent_title' ), 10, 2);
397
+ }
398
+
399
+ if( $instance['hide_empty'] ){
400
+ add_filter( "wp_nav_menu_{$menu->slug}_items", array( $this, 'cmw_filter_check_for_no_items' ), 65532, 2 );
401
+ }
402
+
403
+ $walker = new Custom_Menu_Wizard_Walker;
404
+ $params = array(
405
+ 'menu' => $menu,
406
+ 'container' => $instance['container'] == 'none' ? false : $instance['container'],
407
+ 'container_id' => $instance['container_id'],
408
+ 'menu_class' => $instance['menu_class'],
409
+ 'echo' => false,
410
+ 'fallback_cb' => false,
411
+ 'before' => $instance['before'],
412
+ 'after' => $instance['after'],
413
+ 'link_before' => $instance['link_before'],
414
+ 'link_after' => $instance['link_after'],
415
+ 'depth' => empty( $instance['flat_output'] ) ? $instance['depth'] : -1,
416
+ 'walker' =>$walker,
417
+ //widget specific stuff...
418
+ '_custom_menu_wizard' => array(
419
+ 'filter' => $instance['filter'],
420
+ 'filter_item' => $instance['filter_item'],
421
+ 'include_parent' => $instance['include_parent'],
422
+ 'include_ancestors' => $instance['include_ancestors'],
423
+ 'title_from_parent' => $instance['title_from_parent'],
424
+ 'ol_root' => $instance['ol_root'],
425
+ 'ol_sub' => $instance['ol_sub'],
426
+ 'flat_output' => $instance['flat_output'],
427
+ 'start_level' => $instance['start_level'],
428
+ 'depth' => $instance['depth']
429
+ )
430
+ );
431
+ if( $instance['ol_root'] ){
432
+ $params['items_wrap'] = '<ol id="%1$s" class="%2$s">%3$s</ol>';
433
+ }
434
+ if( !empty( $instance['container_class'] ) ){
435
+ $params['container_class'] = $instance['container_class'];
436
+ }
437
+ $out = wp_nav_menu( $params );
438
+
439
+ if( $instance['hide_empty'] ){
440
+ remove_filter( "wp_nav_menu_{$menu->slug}_items", array( $this, 'cmw_filter_check_for_no_items' ), 65532, 2 );
441
+ }
442
+
443
+ //only put something out if there is something to put out...
444
+ if( !empty( $out ) ){
445
+
446
+ if( $instance['title_from_parent'] && isset( $this->cmw_title_from_parent ) ){
447
+ $title = $this->cmw_title_from_parent;
448
+ }
449
+ if( empty( $title ) ){
450
+ $title = $instance['hide_title'] ? '' : $instance['title'];
451
+ }
452
+
453
+ echo $before_widget;
454
+ if ( !empty($title) ){
455
+ echo $before_title . apply_filters('widget_title', $title, $instance, $this->id_base) . $after_title;
456
+ }
457
+ echo $out . $after_widget;
458
+ }
459
+ }
460
+ }
461
+ }
462
+
463
+ /**
464
+ * updates the widget settings sent from the backend admin
465
+ */
466
+ function update( $new_instance, $old_instance ) {
467
+ $instance = $old_instance;
468
+
469
+ //switches...
470
+ foreach( $this->_cmw_switches as $k=>$v ){
471
+ $instance[ $v ] = empty( $new_instance[ $v ] ) ? 0 : 1;
472
+ }
473
+ //integers...
474
+ foreach( $this->_cmw_integers as $k=>$v ){
475
+ $instance[ $k ] = isset( $new_instance[ $k ]) ? max( $v, intval( $new_instance[ $k ] ) ) : $v;
476
+ }
477
+ //strings...
478
+ foreach( $this->_cmw_strings as $k=>$v ){
479
+ $instance[ $k ] = isset( $new_instance[ $k ] ) ? strip_tags( trim( $new_instance[ $k ] ) ) : $v;
480
+ }
481
+ //html strings...
482
+ foreach( $this->_cmw_html as $k=>$v ){
483
+ $instance[ $k ] = isset( $new_instance[ $k ] ) ? trim( $new_instance[ $k ] ) : $v;
484
+ }
485
+
486
+ return $instance;
487
+ }
488
+
489
+ /**
490
+ * produces the backend admin form(s)
491
+ */
492
+ function form( $instance ) {
493
+
494
+ //switches...
495
+ foreach( $this->_cmw_switches as $k=>$v ){
496
+ $instance[ $v ] = !empty( $instance[ $v ] );
497
+ }
498
+ //integers...
499
+ foreach( $this->_cmw_integers as $k=>$v ){
500
+ $instance[ $k ] = isset( $instance[ $k ]) ? max( $v, intval( $instance[ $k ] ) ) : $v;
501
+ }
502
+ //strings...
503
+ foreach( $this->_cmw_strings as $k=>$v ){
504
+ $instance[ $k ] = isset( $instance[ $k ] ) ? esc_attr( trim( $instance[ $k ] ) ) : $v;
505
+ }
506
+ //html strings...
507
+ foreach( $this->_cmw_html as $k=>$v ){
508
+ $instance[ $k ] = isset( $instance[ $k ] ) ? esc_html( trim( $instance[ $k ] ) ) : $v;
509
+ }
510
+
511
+ //get menus...
512
+ $menus = get_terms( 'nav_menu', array( 'hide_empty' => false ) );
513
+
514
+ //if no menus exist, suggest the user go create one...
515
+ if( empty( $menus ) ){
516
+ echo '<p>'. sprintf( __('No menus have been created yet. <a href="%s">Create one</a>.'), admin_url('nav-menus.php') ) .'</p>';
517
+ return;
518
+ }
519
+ ?>
520
+ <p>
521
+ <label for="<?php echo $this->get_field_id('title'); ?>"><?php _e('Title:') ?></label>
522
+ <label for="<?php echo $this->get_field_id('hide_title'); ?>" class="alignright">
523
+ <input id="<?php echo $this->get_field_id('hide_title'); ?>" name="<?php echo $this->get_field_name('hide_title'); ?>" type="checkbox" value="1" <?php checked( $instance['hide_title'] ); ?> />
524
+ <?php _e('Hide'); ?></label>
525
+ <input id="<?php echo $this->get_field_id('title'); ?>" class="widefat" name="<?php echo $this->get_field_name('title'); ?>" type="text" value="<?php echo $instance['title']; ?>" />
526
+ <small><em><?php _e('Title can be set, but need not be displayed'); ?></em></small>
527
+ </p>
528
+
529
+ <p>
530
+ <label for="<?php echo $this->get_field_id('menu'); ?>"><?php _e('Select Menu:'); ?></label>
531
+ <select id="<?php echo $this->get_field_id('menu'); ?>" class="widget-<?php echo $this->id_base; ?>-select-menu" name="<?php echo $this->get_field_name('menu'); ?>">
532
+ <?php
533
+ foreach( $menus as $i=>$menu ){
534
+ $menus[ $i ]->_items = wp_get_nav_menu_items( $menu->term_id );
535
+ ?>
536
+ <option <?php selected($instance['menu'], $menu->term_id); ?> value="<?php echo $menu->term_id; ?>"><?php echo $menu->name; ?></option>
537
+ <?php
538
+ }
539
+ ?>
540
+ </select>
541
+ </p>
542
+
543
+ <?php $this->_open_a_field_section($instance, 'Filter', 'fs_filter'); ?>
544
+ <p>
545
+ <label for="<?php echo $this->get_field_id('filter'); ?>_0">
546
+ <input id="<?php echo $this->get_field_id('filter'); ?>_0" class="widget-<?php echo $this->id_base; ?>-filter-radio" name="<?php echo $this->get_field_name('filter'); ?>" type="radio" value="0" <?php checked($instance['filter'], 0); ?> />
547
+ <?php _e('Show all'); ?></label>
548
+ <br /><label for="<?php echo $this->get_field_id('filter'); ?>_1">
549
+ <input id="<?php echo $this->get_field_id('filter'); ?>_1" class="widget-<?php echo $this->id_base; ?>-filter-radio" name="<?php echo $this->get_field_name('filter'); ?>" type="radio" value="1" <?php checked($instance['filter'], 1); ?> />
550
+ <?php _e('Children of:'); ?></label>
551
+ <select id="<?php echo $this->get_field_id('filter_item'); ?>" class="widget-<?php echo $this->id_base; ?>-filter-radio-dep" name="<?php echo $this->get_field_name('filter_item'); ?>" <?php disabled($instance['filter'] == 0); ?>>
552
+ <option value="0" <?php selected( $instance['filter_item'], 0 ); ?>><?php _e('Current Item'); ?></option>
553
+ <?php
554
+ $maxlevel = 1;
555
+ foreach( $menus as $i=>$menu ){
556
+ $itemindents = array('0' => 3);
557
+ $style = ( $i == 0 && empty($instance['menu']) ) || $instance['menu'] == $menu->term_id ? '' : ' style="display:none;"';
558
+ ?>
559
+ <optgroup label="<?php echo $menu->name; ?>"<?php echo $style; ?>>
560
+ <?php
561
+ if( !empty( $menu->_items ) ){
562
+ foreach( $menu->_items as $item ){
563
+ //exclude orpans!
564
+ if( isset($itemindents[ $item->menu_item_parent ])){
565
+ $maxlevel = max( $maxlevel, ceil( $itemindents[ $item->menu_item_parent ] / 10 ) );
566
+ $itemindents[ $item->ID ] = $itemindents[ $item->menu_item_parent ] + 10;
567
+ ?>
568
+ <option style="padding-left:<?php echo $itemindents[ $item->menu_item_parent ] ?>px;" value="<?php echo $item->ID; ?>" <?php selected( $instance['filter_item'], $item->ID ); ?>><?php echo $item->title; ?></option>
569
+ <?php
570
+ }
571
+ }
572
+ }
573
+ ?>
574
+ </optgroup>
575
+ <?php
576
+ }
577
+ ?>
578
+ </select>
579
+ </p>
580
+
581
+ <p>
582
+ <label for="<?php echo $this->get_field_id('start_level'); ?>"><?php _e('Starting Level:'); ?></label>
583
+ <select id="<?php echo $this->get_field_id('start_level'); ?>" name="<?php echo $this->get_field_name('start_level'); ?>">
584
+ <?php
585
+ $j = max( $maxlevel, $instance['start_level'] );
586
+ for( $i = 1; $i <= $j; $i++ ){
587
+ ?>
588
+ <option value="<?php echo $i; ?>" <?php selected($instance['start_level'], $i); ?>><?php echo $i; ?></option>
589
+ <?php
590
+ }
591
+ ?>
592
+ </select>
593
+ <br /><small><em><?php _e('Level to start testing items for inclusion'); ?></em></small>
594
+ </p>
595
+
596
+ <p>
597
+ <label for="<?php echo $this->get_field_id('depth'); ?>"><?php _e('For Depth:'); ?></label>
598
+ <select id="<?php echo $this->get_field_id('depth'); ?>" name="<?php echo $this->get_field_name('depth'); ?>">
599
+ <option value="0" <?php selected( $instance['depth'], 0 ); ?>><?php _e('unlimited'); ?></option>
600
+ <?php
601
+ $j = max( $j, $instance['depth'] );
602
+ for( $i = 1; $i <= $j; $i++ ){
603
+ ?>
604
+ <option value="<?php echo $i; ?>" <?php selected( $instance['depth'], $i ); ?>><?php echo $i; ?> <?php _e($i > 1 ? 'levels' : 'level'); ?></option>
605
+ <?php
606
+ }
607
+ ?>
608
+ </select>
609
+ <br /><small><em><?php _e('Relative to the first Filtered item found'); ?></em></small>
610
+ </p>
611
+ <?php $this->_close_a_field_section(); ?>
612
+
613
+ <?php $this->_open_a_field_section($instance, 'Output', 'fs_output'); ?>
614
+ <p>
615
+ <label for="<?php echo $this->get_field_id('flat_output'); ?>_0">
616
+ <input id="<?php echo $this->get_field_id('flat_output'); ?>_0" name="<?php echo $this->get_field_name('flat_output'); ?>" type="radio" value="0" <?php checked(!$instance['flat_output']); ?> />
617
+ <?php _e('Hierarchical'); ?></label>
618
+ &nbsp;<label for="<?php echo $this->get_field_id('flat_output'); ?>_1">
619
+ <input id="<?php echo $this->get_field_id('flat_output'); ?>_1" name="<?php echo $this->get_field_name('flat_output'); ?>" type="radio" value="1" <?php checked($instance['flat_output']); ?> />
620
+ <?php _e('Flat'); ?></label>
621
+ </p>
622
+
623
+ <p>
624
+ <label for="<?php echo $this->get_field_id('include_parent'); ?>">
625
+ <input id="<?php echo $this->get_field_id('include_parent'); ?>" class="widget-<?php echo $this->id_base; ?>-filter-radio-dep" name="<?php echo $this->get_field_name('include_parent'); ?>" type="checkbox" value="1" <?php checked($instance['include_parent']); ?> <?php disabled($instance['filter'] == 0); ?> />
626
+ <?php _e('Include Parent'); ?></label>
627
+ <br /><label for="<?php echo $this->get_field_id('include_ancestors'); ?>">
628
+ <input id="<?php echo $this->get_field_id('include_ancestors'); ?>" class="widget-<?php echo $this->id_base; ?>-filter-radio-dep" name="<?php echo $this->get_field_name('include_ancestors'); ?>" type="checkbox" value="1" <?php checked($instance['include_ancestors']); ?> <?php disabled($instance['filter'] == 0); ?> />
629
+ <?php _e('Include Ancestors'); ?></label>
630
+ <br /><label for="<?php echo $this->get_field_id('title_from_parent'); ?>">
631
+ <input id="<?php echo $this->get_field_id('title_from_parent'); ?>" class="widget-<?php echo $this->id_base; ?>-filter-radio-dep" name="<?php echo $this->get_field_name('title_from_parent'); ?>" type="checkbox" value="1" <?php checked($instance['title_from_parent']); ?> <?php disabled($instance['filter'] == 0); ?> />
632
+ <?php _e('Title from Parent Item'); ?></label>
633
+ <br /><small><em><?php _e('Only if the &quot;Children of:&quot; Filter returns items'); ?></em></small>
634
+ </p>
635
+
636
+ <p>
637
+ <?php _e('Change UL to OL:'); ?>
638
+ <br /><label for="<?php echo $this->get_field_id('ol_root'); ?>">
639
+ <input id="<?php echo $this->get_field_id('ol_root'); ?>" name="<?php echo $this->get_field_name('ol_root'); ?>" type="checkbox" value="1" <?php checked($instance['ol_root']); ?> />
640
+ <?php _e('Top Level'); ?></label>
641
+ &nbsp;<label for="<?php echo $this->get_field_id('ol_sub'); ?>">
642
+ <input id="<?php echo $this->get_field_id('ol_sub'); ?>" name="<?php echo $this->get_field_name('ol_sub'); ?>" type="checkbox" value="1" <?php checked($instance['ol_sub']); ?> />
643
+ <?php _e('Sub-Levels'); ?></label>
644
+ </p>
645
+
646
+ <p>
647
+ <label for="<?php echo $this->get_field_id('hide_empty'); ?>">
648
+ <input id="<?php echo $this->get_field_id('hide_empty'); ?>" name="<?php echo $this->get_field_name('hide_empty'); ?>" type="checkbox" value="1" <?php checked($instance['hide_empty']); ?> />
649
+ <?php _e('Hide Widget if Empty'); ?></label>
650
+ <br /><small><em><?php _e('Prevents any output when no items are found'); ?></em></small>
651
+ </p>
652
+ <?php $this->_close_a_field_section(); ?>
653
+
654
+ <?php $this->_open_a_field_section($instance, 'Container', 'fs_container'); ?>
655
+ <p>
656
+ <label for="<?php echo $this->get_field_id('container'); ?>"><?php _e('Element:') ?></label>
657
+ <input id="<?php echo $this->get_field_id('container'); ?>" name="<?php echo $this->get_field_name('container'); ?>" type="text" value="<?php echo $instance['container']; ?>" />
658
+ <br /><small><em><?php _e( 'Eg. div or nav; leave empty for no container' ); ?></em></small></p>
659
+ </p>
660
+ <p>
661
+ <label for="<?php echo $this->get_field_id('container_id'); ?>"><?php _e('Unique ID:') ?></label>
662
+ <input id="<?php echo $this->get_field_id('container_id'); ?>" name="<?php echo $this->get_field_name('container_id'); ?>" type="text" value="<?php echo $instance['container_id']; ?>" />
663
+ <br /><small><em><?php _e( 'An optional ID for the container' ); ?></em></small></p>
664
+ </p>
665
+ <p>
666
+ <label for="<?php echo $this->get_field_id('container_class'); ?>"><?php _e('Class:') ?></label>
667
+ <input id="<?php echo $this->get_field_id('container_class'); ?>" name="<?php echo $this->get_field_name('container_class'); ?>" type="text" value="<?php echo $instance['container_class']; ?>" />
668
+ <br /><small><em><?php _e( 'Extra class for the container' ); ?></em></small></p>
669
+ </p>
670
+ <?php $this->_close_a_field_section(); ?>
671
+
672
+ <?php $this->_open_a_field_section($instance, 'Classes', 'fs_classes'); ?>
673
+ <p>
674
+ <label for="<?php echo $this->get_field_id('menu_class'); ?>"><?php _e('Menu Class:') ?></label>
675
+ <input id="<?php echo $this->get_field_id('menu_class'); ?>" name="<?php echo $this->get_field_name('menu_class'); ?>" type="text" value="<?php echo $instance['menu_class']; ?>" />
676
+ <br /><small><em><?php _e( 'Class for the list element forming the menu' ); ?></em></small></p>
677
+ </p>
678
+ <p>
679
+ <label for="<?php echo $this->get_field_id('widget_class'); ?>"><?php _e('Widget Class:') ?></label>
680
+ <input id="<?php echo $this->get_field_id('widget_class'); ?>" name="<?php echo $this->get_field_name('widget_class'); ?>" type="text" value="<?php echo $instance['widget_class']; ?>" />
681
+ <br /><small><em><?php _e( 'Extra class for the widget itself' ); ?></em></small></p>
682
+ </p>
683
+ <?php $this->_close_a_field_section(); ?>
684
+
685
+ <?php $this->_open_a_field_section($instance, 'Links', 'fs_links'); ?>
686
+ <p>
687
+ <label for="<?php echo $this->get_field_id('before'); ?>"><?php _e('Before the Link:') ?></label>
688
+ <input id="<?php echo $this->get_field_id('before'); ?>" class="widefat" name="<?php echo $this->get_field_name('before'); ?>" type="text" value="<?php echo $instance['before']; ?>" />
689
+ <small><em><?php _e( htmlspecialchars('Text/HTML to go before the <a> of the link') ); ?></em></small>
690
+ </p>
691
+ <p>
692
+ <label for="<?php echo $this->get_field_id('after'); ?>"><?php _e('After the Link:') ?></label>
693
+ <input id="<?php echo $this->get_field_id('after'); ?>" class="widefat" name="<?php echo $this->get_field_name('after'); ?>" type="text" value="<?php echo $instance['after']; ?>" />
694
+ <small><em><?php _e( htmlspecialchars('Text/HTML to go after the </a> of the link') ); ?></em></small>
695
+ </p>
696
+ <p>
697
+ <label for="<?php echo $this->get_field_id('link_before'); ?>"><?php _e('Before the Link Text:') ?></label>
698
+ <input id="<?php echo $this->get_field_id('link_before'); ?>" class="widefat" name="<?php echo $this->get_field_name('link_before'); ?>" type="text" value="<?php echo $instance['link_before']; ?>" />
699
+ <small><em><?php _e( 'Text/HTML to go before the link text' ); ?></em></small>
700
+ </p>
701
+ <p>
702
+ <label for="<?php echo $this->get_field_id('link_after'); ?>"><?php _e('After the Link Text:') ?></label>
703
+ <input id="<?php echo $this->get_field_id('link_after'); ?>" class="widefat" name="<?php echo $this->get_field_name('link_after'); ?>" type="text" value="<?php echo $instance['link_after']; ?>" />
704
+ <small><em><?php _e( 'Text/HTML to go after the link text' ); ?></em></small>
705
+ </p>
706
+ <?php $this->_close_a_field_section(); ?>
707
+
708
+ <?php
709
+ } //end form()
710
+
711
+ /**
712
+ * outputs the HTML to begin a collapsible/expandable group of settings
713
+ *
714
+ * @param array $instance
715
+ * @param string $text Label
716
+ * @param string $fname Field name
717
+ */
718
+ function _open_a_field_section( &$instance, $text, $fname ){
719
+ // the default is *not* collapsed (field $fname == 0)
720
+ $collapsed = !empty($instance[$fname]);
721
+ ?>
722
+ <div class="stuffbox widget-<?php echo $this->id_base; ?>-collapsible-fieldset" style="margin:0 0 0.5em;cursor:pointer;">
723
+ <input id="<?php echo $this->get_field_id($fname); ?>" class="hidden-field" name="<?php echo $this->get_field_name($fname); ?>" type="checkbox" value="1" <?php checked($collapsed); ?> />
724
+ <div style="background:transparent url(images/arrows.png) no-repeat 0 <?php echo $collapsed ? '0' : '-36px'; ?>;height:16px; width:16px;float:right;outline:0 none;"></div>
725
+ <h3 style="font-size:1em;margin:0;padding:2px 0.5em;"><?php echo $text; ?></h3>
726
+ </div>
727
+ <div class="hide-if-js"<?php echo !$collapsed ? ' style="display:block;"' : ''; ?>>
728
+ <?php
729
+ } //end _open_a_field_section()
730
+
731
+ /**
732
+ * outputs the HTML to close off a collapsible/expandable group of settings
733
+ */
734
+ function _close_a_field_section(){
735
+ ?>
736
+ </div>
737
+ <?php
738
+ } //end _close_a_field_section()
739
+
740
+ }
readme.txt ADDED
@@ -0,0 +1,194 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ === Custom Menu Wizard Widget ===
2
+ Contributors: wizzud
3
+ Tags: menu,widget,widgets,navigation,nav,custom menus,custom menu,partial menu,menu level,menu branch
4
+ Requires at least: 3.0.1
5
+ Tested up to: 3.5.1
6
+ Stable tag: 1.0.0
7
+ License: GPLv2 or Later
8
+
9
+ Custom Menu Wizard Widget : Show branches or levels of your menu in a widget, with full customisation.
10
+
11
+ == Description ==
12
+
13
+ This plugin is a boosted version of the WordPress "Custom Menu" widget.
14
+ It provides full control over most of the parameters available when calling WP's [wp_nav_menu()](http://codex.wordpress.org/Function_Reference/wp_nav_menu) function, as well as providing pre-filtering of the menu items in order to be able to select a specific portion of the custom menu. It also automatically adds a couple of custom classes.
15
+
16
+ Features include:
17
+
18
+ * Display the entire menu, just a branch of it, or even just a specific level of it
19
+ * Select a branch based on a specific menu item, or the "current" item (currently displayed page)
20
+ * Specify a level to start at, and the number of levels to output
21
+ * Select hierarchicial or flat output, both options still abiding by the specified number of levels to output
22
+ * Allow the widget title to be entered but not output, or even to be set from the parent item of a menu's sub-branch
23
+ * Optionally disable widget output completely if there are no matching menu items found
24
+ * Include a sub-branch's parent and/or ancestor item(s) in the output, over and above any start level setting
25
+ * Automatically add cmw-level-N and cmw-has-submenu classes to output menu items
26
+ * Add/specify custom class(es) for the widget block, the menu container, and the menu itself
27
+ * Modify the link's output with additional HTML around the link's text and/or the link element itself
28
+ * Use Ordered Lists (OL) for the top and/or sub levels instead of Unordered Lists (UL)
29
+
30
+ **Widget Options**
31
+
32
+ There are quite a few options, which makes the widget settings box very long. I have therefore grouped most of the options into
33
+ logical sections and made each section collapsible (with remembered state, open by default).
34
+
35
+ * **Title**
36
+
37
+ Set the title for your widget.
38
+
39
+ * **Hide** *(checkbox)*
40
+
41
+ Prevents the entered `Title` being displayed in the front-end widget output.
42
+
43
+ In the Widgets admin page, I find it useful to still be able to see the `Title` in the sidebar when the widget is collapsed, but I
44
+ don't necessarily want that `Title` to actually be output when the widget is displayed at the front-end. Hence this checkbox.
45
+
46
+ * **Select Menu** *(select)*
47
+
48
+ Choose the appropriate menu from the dropdown list of Custom Menus currently defined in your WordPress application. The
49
+ first one available (alphabetically) is already selected for you by default.
50
+
51
+ * **Filter**
52
+
53
+ * **Show all** *(radio, default)*
54
+
55
+ Don't apply the `Children of` filter. If you check this option, the `Children of` select will be disabled, as will the `Include Parent`,
56
+ `Include Ancestors` and `Title from Parent Item` checkboxes, as they are only applicable to a `Children of` filter.
57
+
58
+ * **Children of** *(radio & select)*
59
+
60
+ The dropdown list will present a "Current Item" option, followed by all the available items from the menu chosen in `Select Menu`.
61
+ The widget will output the *children* of the selected item, always assuming that they lie within the bounds of any other parameters set.
62
+ If you change `Select Menu`, the options presented in this dropdown will change accordingly.
63
+
64
+ * **Starting Level** *(select, default: "1")*
65
+
66
+ This is the level within the chosen menu (from `Select Menu`) that the widget will start looking for items to keep. Obviously, level 1
67
+ is the root level (ie. those items that have no parent item); level 2 is all the immediate children of the root level items, and so on.
68
+
69
+ * **For Depth** *(select, default: "unlimited")*
70
+
71
+ This is the maximum depth of the eventual output structure after filtering, and in the case of `Flat` output being requested it is
72
+ still applied - as if the output were `Hierarchical` and then flattened at the very last moment. You need to be aware that the
73
+ `For Depth` setting is applied relative to the level at which the first item to be kept is found. For example, say you were to set
74
+ `Children of` to "Current Item", `Starting Level` to "2", and `For Depth` to "2 levels"; if the current item was found at level 3,
75
+ then you would get the current item's immediate children (from level 4), plus *their* immediate children (from level 5).
76
+
77
+ * **Output**
78
+
79
+ * **Hierarchical** *(radio, default)*
80
+
81
+ Output in the standard nested list format.
82
+
83
+ * **Flat** *(radio)*
84
+
85
+ Output in a single list format, ignoring any parent-child relationship other than to maintain the same physical order as would be
86
+ presented in a `Hierarchical` output.
87
+
88
+ * **Include Parent** *(checkbox)*
89
+
90
+ If checked, include the parent item in the output. Only applies to a successful `Children of` filter.
91
+
92
+ * **Include Ancestors** *(checkbox)*
93
+
94
+ Same as `Include Parent` except that all ancestors, right back to root level, are included. Only applies to a successful
95
+ `Children of` filter.
96
+
97
+ * **Title from Parent Item** *(checkbox)*
98
+
99
+ Again, this only applies to a successful `Children of` filter. If checked, use the title of the parent item as the widget's
100
+ title when displaying the output. This will override (ie. ignore) the `Hide` checkbox setting!
101
+
102
+ * **Change UL to OL**
103
+
104
+ The standard for menus is to use UL (unordered list) elements to display the output. These settings give you the option to swap
105
+ the ULs out for OLs (ordered lists).
106
+
107
+ * **Top Level** *(checkbox)*
108
+
109
+ If checked, swap the outermost UL for an OL.
110
+
111
+ * **Sub-Levels** *(checkbox)*
112
+
113
+ If checked, swap any nested (ie. not the outermost) ULs for an OLs.
114
+
115
+ * **Hide Widget if Empty** *(checkbox)*
116
+
117
+ If checked, the widget will not output *any* HTML unless it finds at least one menu item that matches the Filter settings.
118
+
119
+ * **Container**
120
+
121
+ * **Element** *(default: "div")*
122
+
123
+ This menu list is usually wrapped in a "container" element, and this is the tag for that element. You may change it for another
124
+ tag, or you may clear it out and the container will be completely removed. Please note that WordPress is set by default to only
125
+ accept "div" or "nav", but that could be changed or extended by any template or plugin.
126
+
127
+ * **Unique ID**
128
+
129
+ This allows you to specify you own id (which should be unique) for the container.
130
+
131
+ * **Class**
132
+
133
+ This allows you to add your own class to the container element.
134
+
135
+ * **Classes**
136
+
137
+ * **Menu Class** *(default: "menu-widget")
138
+
139
+ This is the class that will be applied to the list element that holds the entire menu.
140
+
141
+ * **Widget Class**
142
+
143
+ This allows you to add your own class to the outermost element of the widget, the one that wraps the entire widget output.
144
+
145
+ * **Links**
146
+
147
+ * **Before the Link**
148
+
149
+ Text or HTML that will be placed immediately before each menu item's link.
150
+
151
+ * **After the Link**
152
+
153
+ Text or HTML that will be placed immediately after each menu item's link.
154
+
155
+ * **Before the Link Text**
156
+
157
+ Text or HTML that will be placed immediately before each menu item's link text.
158
+
159
+ * **After the Link Text**
160
+
161
+ Text or HTML that will be placed immediately after each menu item's link text.
162
+
163
+ == Installation ==
164
+
165
+ 1. EITHER Upload the zip package via 'Plugins > Add New > Upload' in your WP Admin
166
+
167
+ OR Extract the zip package and upload `custom-menu-wizard` folder to the `/wp-content/plugins/` directory
168
+
169
+ 1. Activate the plugin through the 'Plugins' menu in your WP Admin
170
+
171
+ The widget will now be available in the 'Widgets' admin page.
172
+ As long as you already have at least one Menu defined, you can add the new widget to a sidebar and configure it however you want.
173
+
174
+ == Frequently Asked Questions ==
175
+
176
+ If you have a question or problem, please use the integrated Support forum.
177
+
178
+ == Screenshots ==
179
+
180
+ 1. Widget options (A).
181
+
182
+ 2. Widget options (B).
183
+
184
+ 3. Widget options (C).
185
+
186
+ == Changelog ==
187
+
188
+ = 1.0.0 =
189
+ Initial release
190
+
191
+ == Upgrade Notice ==
192
+
193
+ = 1.0.0 =
194
+ Initial release