Version Description
-
! Rewrite, and Change of Approach ! The widget has had a major rewrite! The
Children of
filter has been replaced with aBranch
filter, with a subsequent shift in focus for the secondary filter parameters, from the children's level (0, 1 or more items) up to the branch level (a single item!). This should provide a more intuitive interface, and is definitely easier to code for. However, it only affects new instances of the widget; v2 instances are still fully supported.Please also note that the shortcode tag for v3 has changed to
[cmwizard]
, with a revised set of parameters. The old shortcode tag is still supported, but only with the v2 parameter set, and only providing v2 functionality, ie. it is the shortcode tag that determines which widget version to use, and the appropriate parameter set for that version.There is no automatic upgrade of widget settings from v2 to v3! I suggest bringing up the "assist" for the existing v2 widget, running it side-by-side with the "assist" of a new instance of the widget, and using them to the compare the desired outputs. I would also strongly recommend that you put your old widgets into the inactive area until you are completely happy with their new replacements. If you are upgrading from version 2, and you would like a bit more information, this article might help.
change : the minmum requirement for WordPress is v3.6
addition : more options for requiring that the "current" menu item be present at some point in the filter process
addition : Branch filter levels can be either relative (to the selected Branch item) or absolute (within the menu structure)
addition : menu items can now be excluded from the final output, either explicitly by id (optionally including descendants), or by level
addition : the ids of Items can be set to include all descendants
addition : the inclusion of branch ancestors, and optionally their siblings, can be set by absolute level or relative number of levels
addition : the widget title can now be automatically set from the root level item of the Branch item or current menu item
addition : the shortcode for a widget's current settings is now also displayed at the base of the widget (as well as at the base of the "assist")
addition : "title_tag" has been added to the shortcode options, enabling the default H2 to be changed without having to resort to coding a filter
addition : as an alternative to using the "assist", "findme" has been addded to the shortcode options to aid editors with the location of posts containing a CMW shortcode ([cmwizard findme=1])
This release includes an upgrade to v2.1.0 for all existing version 2 widgets/shortcodes - please read the v2.1.0 changes below.
Release Info
Developer | wizzud |
Plugin | Custom Menu Wizard Widget |
Version | 3.0.0 |
Comparing to | |
See all releases |
Code changes from version 2.0.6 to 3.0.0
- custom-menu-wizard.css +149 -38
- custom-menu-wizard.js +1456 -532
- custom-menu-wizard.min.js +52 -28
- custom-menu-wizard.php +715 -1441
- custom-menu-wizard.png +0 -0
- include/class.walker.php +1036 -0
- include/class.widget.php +2101 -0
- readme.txt +488 -334
- v210-readme.html +626 -0
@@ -1,47 +1,127 @@
|
|
1 |
/**
|
2 |
* custom-menu-wizard.css
|
3 |
-
* Version:
|
4 |
*/
|
5 |
/*widget admin style...*/
|
6 |
-
|
7 |
-
.
|
8 |
-
.widget-custom-menu-wizard-onchange {
|
9 |
-
.widget-custom-menu-wizard-onchange
|
10 |
-
.widget-custom-menu-wizard-onchange .
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
11 |
.widget-custom-menu-wizard-onchange .cmw-off-the-page {display:none; position:absolute; left:-5000px; top:-5000px;}
|
12 |
-
.widget-custom-menu-wizard-onchange .cmw-
|
13 |
-
.widget-custom-menu-wizard-
|
14 |
-
.widget-custom-menu-wizard-
|
15 |
-
.widget-custom-menu-wizard-
|
16 |
-
.widget-custom-menu-wizard-
|
17 |
-
.widget-custom-menu-wizard-
|
18 |
-
.
|
19 |
-
.widget-custom-menu-wizard-
|
20 |
-
.widget-custom-menu-wizard-
|
21 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
22 |
/*dialog style...*/
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
23 |
/*...menu...*/
|
24 |
-
.widget-custom-menu-wizard-dialog .cmw-demo-themenu {
|
25 |
-
.widget-custom-menu-wizard-dialog .cmw-demo-themenu
|
26 |
-
.widget-custom-menu-wizard-dialog .cmw-demo-themenu ul
|
27 |
-
.widget-custom-menu-wizard-dialog .cmw-demo-themenu
|
28 |
-
.widget-custom-menu-wizard-dialog .cmw-demo-themenu
|
29 |
-
.widget-custom-menu-wizard-dialog .cmw-demo-themenu a
|
30 |
-
.widget-custom-menu-wizard-dialog .cmw-demo-themenu
|
31 |
-
.widget-custom-menu-wizard-dialog .cmw-demo-themenu
|
32 |
-
.widget-custom-menu-wizard-dialog .cmw-demo-themenu
|
33 |
-
.widget-custom-menu-wizard-dialog .cmw-demo-themenu .current-menu-
|
34 |
-
.widget-custom-menu-wizard-dialog .cmw-demo-themenu .current-menu-
|
35 |
-
.widget-custom-menu-wizard-dialog .cmw-demo-themenu .
|
36 |
-
.widget-custom-menu-wizard-dialog .cmw-demo-
|
37 |
-
|
38 |
-
|
39 |
-
.widget-custom-menu-wizard-dialog .cmw-demo-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
40 |
/*...output...*/
|
41 |
-
.widget-custom-menu-wizard-dialog .cmw-demo-theoutput {float:right; margin:0 0
|
42 |
-
.widget-custom-menu-wizard-dialog .cmw-demo-theoutput h3 {border-bottom:1px solid #CCCCCC; margin:0 0
|
43 |
-
.widget-custom-menu-wizard-dialog .cmw-demo-theoutput-wrap {
|
44 |
-
.widget-custom-menu-wizard-dialog .cmw-demo-theoutput-wrap
|
|
|
|
|
45 |
.widget-custom-menu-wizard-dialog .cmw-demo-theoutput-wrap li {margin:0;}
|
46 |
.widget-custom-menu-wizard-dialog .cmw-demo-theoutput-wrap li ul {margin:0 0 0 1em;}
|
47 |
.widget-custom-menu-wizard-dialog .cmw-demo-theoutput-wrap li ol {margin:0 0 0 1.5em;}
|
@@ -55,5 +135,36 @@ select.widget-custom-menu-wizard-listen {max-width:100%;}
|
|
55 |
.widget-custom-menu-wizard-dialog .cmw-demo-theoutput-wrap ol ol ol {list-style-type:lower-alpha;}
|
56 |
.widget-custom-menu-wizard-dialog .cmw-demo-theoutput-wrap ol ol ol ol {list-style-type:lower-roman;}
|
57 |
.widget-custom-menu-wizard-dialog .cmw-demo-theoutput-wrap ol ol ol ol ol {list-style-type:decimal;}
|
58 |
-
.widget-custom-menu-wizard-dialog .cmw-demo-
|
59 |
-
.widget-custom-menu-wizard-dialog .cmw-demo-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
/**
|
2 |
* custom-menu-wizard.css
|
3 |
+
* Version: 3.0.0
|
4 |
*/
|
5 |
/*widget admin style...*/
|
6 |
+
.widget-custom-menu-wizard-onchange {line-height:1.5; margin:0 0 0.5em;}
|
7 |
+
.widget-custom-menu-wizard-onchange a,
|
8 |
+
.widget-custom-menu-wizard-onchange a.button {color:#0074a2;}
|
9 |
+
.widget-custom-menu-wizard-onchange a:hover,
|
10 |
+
.widget-custom-menu-wizard-onchange a.button:hover,
|
11 |
+
.widget-custom-menu-wizard-onchange a:active,
|
12 |
+
.widget-custom-menu-wizard-onchange a.button:active {border-color:#2ea2cc; color:#2ea2cc;}
|
13 |
+
.widget-custom-menu-wizard-onchange select,
|
14 |
+
.widget-custom-menu-wizard-onchange input[type="text"] {max-width:100%;}
|
15 |
+
.widget-custom-menu-wizard-onchange optgroup option {padding-left:0.75em;}
|
16 |
+
.widget-custom-menu-wizard-onchange .cmw-colour-grey,
|
17 |
+
.widget-custom-menu-wizard-onchange .cmw-colour-grey input {color:#7F7F7F}
|
18 |
+
.widget-custom-menu-wizard-onchange small.cmw-colour-grey {vertical-align:top;}
|
19 |
+
.widget-custom-menu-wizard-onchange .cmw-display-none {display:none;}
|
20 |
+
.widget-custom-menu-wizard-onchange .cmw-followed-by {margin-right:1em;}
|
21 |
+
.widget-custom-menu-wizard-onchange .cmw-indented {margin-left:1em;}
|
22 |
+
.widget-custom-menu-wizard-onchange .cmw-maxwidth-twothirds {max-width:66% !important;}
|
23 |
.widget-custom-menu-wizard-onchange .cmw-off-the-page {display:none; position:absolute; left:-5000px; top:-5000px;}
|
24 |
+
.widget-custom-menu-wizard-onchange .cmw-pseudo-para {margin:1em 0;}
|
25 |
+
.widget-custom-menu-wizard-onchange .cmw-small-block {display:block; font-size:0.769em;}
|
26 |
+
.widget-custom-menu-wizard-onchange .cmw-textalign-right {text-align:right;}
|
27 |
+
.widget-custom-menu-wizard-onchange .cmw-verticalalign-baseline {vertical-align:baseline;}
|
28 |
+
.widget-custom-menu-wizard-onchange .cmw-whitespace-nowrap {white-space:nowrap;}
|
29 |
+
.widget-custom-menu-wizard-onchange .widget-custom-menu-wizard-assist {float:right; font-size:0.77em; height:auto; line-height:1.5; margin:-0.4em 0 0 1em; padding:0 1em;}
|
30 |
+
.widget-custom-menu-wizard-onchange .cmw-fieldset > div {margin:1em 0;}
|
31 |
+
a.widget-custom-menu-wizard-fieldset {background-image:url("custom-menu-wizard.png"); background-repeat:no-repeat; background-position:100% -32px; border-bottom:1px solid #E5E5E5; border-top:1px solid #E5E5E5; display:block; font-weight:bold; line-height:2.5; margin:0.5em 0 0; text-decoration:none; text-transform:uppercase; -webkit-transition-duration:0s; transition-duration:0s; width:100%;}
|
32 |
+
a.widget-custom-menu-wizard-fieldset:hover,
|
33 |
+
a.widget-custom-menu-wizard-fieldset:active {background-position:100% -112px;}
|
34 |
+
a.widget-custom-menu-wizard-fieldset.cmw-collapsed-fieldset {background-position:100% 8px;}
|
35 |
+
a.widget-custom-menu-wizard-fieldset.cmw-collapsed-fieldset:hover,
|
36 |
+
a.widget-custom-menu-wizard-fieldset.cmw-collapsed-fieldset:active {background-position:100% -72px;}
|
37 |
+
.widget-custom-menu-wizard-onchange .cmw-start-fieldset-collapsed {display:none;}
|
38 |
+
/*...pre WP3.8...*/
|
39 |
+
.widget-custom-menu-wizard-onchange.cmw-pre-wp-v38 input[type="checkbox"],
|
40 |
+
.widget-custom-menu-wizard-onchange.cmw-pre-wp-v38 input[type="radio"] {margin-right:4px;}
|
41 |
+
.widget-custom-menu-wizard-onchange.cmw-pre-wp-v38 .cmw-fieldset {padding-top:1em;}
|
42 |
+
/*...accessibility...*/
|
43 |
+
.no-js a.widget-custom-menu-wizard-fieldset.cmw-collapsed-fieldset {background-position:100% -32px;}
|
44 |
+
.no-js a.widget-custom-menu-wizard-fieldset.cmw-collapsed-fieldset:hover,
|
45 |
+
.no-js a.widget-custom-menu-wizard-fieldset.cmw-collapsed-fieldset:active {background-position:100% -112px;}
|
46 |
+
.no-js .widget-custom-menu-wizard-onchange .cmw-start-fieldset-collapsed {display:block;}
|
47 |
+
.no-js a.widget-custom-menu-wizard-fieldset {background-image:none;}
|
48 |
+
.no-js .widget-custom-menu-wizard-assist {display:none;}
|
49 |
+
/*...customizer tweaks...*/
|
50 |
+
.wp-customizer .widget-custom-menu-wizard-onchange input[type="text"] {margin:1px 0;}
|
51 |
+
/*...warnings...*/
|
52 |
+
.widget-custom-menu-wizard-no-menus,
|
53 |
+
.widget-custom-menu-wizard-onchange .cmw-legacy-warn {background-color:#ffeecc; border-left:4px solid #DD3D36; -webkit-box-shadow:0 1px 1px 0 rgba(0, 0, 0, 0.1); box-shadow:0 1px 1px 0 rgba(0, 0, 0, 0.1); font-size:0.846em; margin:5px 0 15px; padding:1px 1em;}
|
54 |
+
.widget-custom-menu-wizard-onchange a.cmw-legacy-close {background-color:transparent; border-radius:1.3em; color:#cc0000; display:block; float:right; font-size:1.5em; font-weight:bold; line-height:1.3; margin:0 -0.6em 0 0.5em; text-align:center; text-decoration:none; width:1.3em;}
|
55 |
+
.widget-custom-menu-wizard-onchange a.cmw-legacy-close:hover {background-color:#ffffff; -webkit-box-shadow:1px 1px 1px 0 rgba(0, 0, 0, 0.2); box-shadow:1px 1px 1px 0 rgba(0, 0, 0, 0.2);}
|
56 |
+
.widget-custom-menu-wizard-no-menus {background-color:#ffffff; font-size:1em; padding:0.5em 1em;}
|
57 |
+
/*shortcodes...*/
|
58 |
+
.widget-custom-menu-wizard-dialog .cmw-demo-theshortcode {clear:both; margin:1em 0 0.5em; width:100%;}
|
59 |
+
.widget-custom-menu-wizard-onchange .cmw-shortcode-wrap {clear:both; margin:0.75em 0 1em; width:100%;}
|
60 |
+
.widget-custom-menu-wizard-dialog code,
|
61 |
+
.widget-custom-menu-wizard-onchange code {border:1px solid #CCCCCC; display:inline-block; line-height:1.5; padding:0.25em 0.5em;}
|
62 |
+
.widget-custom-menu-wizard-onchange code {padding:0.1em 0.2em; font-size:0.846em;}
|
63 |
/*dialog style...*/
|
64 |
+
.widget-custom-menu-wizard-dialog {font-size:0.8392em; line-height:1.5;}
|
65 |
+
.widget-custom-menu-wizard-dialog .cmw-demo-themenu,
|
66 |
+
.widget-custom-menu-wizard-dialog .cmw-demo-themenu *,
|
67 |
+
.widget-custom-menu-wizard-dialog .cmw-demo-theoutput,
|
68 |
+
.widget-custom-menu-wizard-dialog .cmw-demo-theoutput *,
|
69 |
+
.widget-custom-menu-wizard-dialog .cmw-demo-theshortcode,
|
70 |
+
.widget-custom-menu-wizard-dialog .cmw-demo-theshortcode * {position:relative;}
|
71 |
+
/*...fix for jquery UI's draggable problem in v1.10.3/4...*/
|
72 |
+
.cmw-assistance-dialog {position:absolute !important;}
|
73 |
+
.cmw-assistance-dialog.cmw-assistance-dialog-fixed {position:fixed !important;}
|
74 |
+
.cmw-assistance-dialog .cmw-dialog-fixed-absolute {height:20px; margin:-10px 0 0; position:absolute; right:2em; top:50%;}
|
75 |
+
.cmw-assistance-dialog .cmw-dialog-fixed-absolute .ui-button-text {line-height:1; padding:1px 0.35em 1px 1.3em;}
|
76 |
+
.cmw-assistance-dialog .cmw-dialog-fixed-absolute .ui-button-icon-primary {left:0.1em;}
|
77 |
+
.cmw-assistance-dialog .ui-dialog-title {width:65% !important;}
|
78 |
+
/*...for customizer, make sure the assist goes above .wp-full-overlay...*/
|
79 |
+
.wp-customizer .cmw-assistance-dialog {z-index:600000;}
|
80 |
/*...menu...*/
|
81 |
+
.widget-custom-menu-wizard-dialog .cmw-demo-themenu {float:left; margin:0 0.5em 0.5em 0;}
|
82 |
+
.widget-custom-menu-wizard-dialog .cmw-demo-themenu-ul {font-size:0.8333em; line-height:1.75;}
|
83 |
+
.widget-custom-menu-wizard-dialog .cmw-demo-themenu ul {list-style-type:none; margin:0.5em 0 0.5em 1.5em; padding:0;}
|
84 |
+
.widget-custom-menu-wizard-dialog .cmw-demo-themenu-ul ul {margin:0 0 0 2.4em;}
|
85 |
+
.widget-custom-menu-wizard-dialog .cmw-demo-themenu-ul li {display:block; margin:0; padding:1px 0; white-space:nowrap;}
|
86 |
+
.widget-custom-menu-wizard-dialog .cmw-demo-themenu-ul a {display:inline-block; text-align:center; text-decoration:none; vertical-align:top;}
|
87 |
+
.widget-custom-menu-wizard-dialog .cmw-demo-themenu-ul a:hover {text-decoration:none;}
|
88 |
+
.widget-custom-menu-wizard-dialog .cmw-demo-themenu-ul a:focus {outline:0 none;}
|
89 |
+
.widget-custom-menu-wizard-dialog .cmw-demo-themenu-ul span {display:block; width:10em; padding:0 2px; height:1.75em; overflow:hidden; text-overflow:ellipsis; white-space:nowrap; border:1px solid #999999; -webkit-box-shadow:2px 2px 2px 0px #666666; box-shadow:2px 2px 2px 0px #666666;}
|
90 |
+
.widget-custom-menu-wizard-dialog .cmw-demo-themenu-ul .current-menu-ancestor {border-color:#cccc00 !important; background-image:-webkit-gradient(linear, left top, left bottom, from(rgba(255, 255, 153, 0.7)), to(rgba(255, 255, 153, 0))); background-image:-webkit-linear-gradient(top, rgba(255, 255, 153, 0.7), rgba(255, 255, 153, 0)); background-image:-moz-linear-gradient(top, rgba(255, 255, 153, 0.7), rgba(255, 255, 153, 0)); background-image:-ms-linear-gradient(top, rgba(255, 255, 153, 0.7), rgba(255, 255, 153, 0)); background-image:-o-linear-gradient(top, rgba(255, 255, 153, 0.7), rgba(255, 255, 153, 0)); background-image:linear-gradient(to bottom, rgba(255, 255, 153, 0.7), rgba(255, 255, 153, 0)); filter:progid:DXImageTransform.Microsoft.gradient(startColorstr=#b2ffff99, endColorstr=#01ffff99); -ms-filter:"progid:DXImageTransform.Microsoft.gradient(startColorstr=#b2ffff99, endColorstr=#01ffff99)";}
|
91 |
+
.widget-custom-menu-wizard-dialog .cmw-demo-themenu-ul .current-menu-item {border-color:#cc0000 !important; background-image:-webkit-gradient(linear, left top, left bottom, from(rgba(255, 204, 204, 0.7)), to(rgba(255, 204, 204, 0))); background-image:-webkit-linear-gradient(top, rgba(255, 204, 204, 0.7), rgba(255, 204, 204, 0)); background-image:-moz-linear-gradient(top, rgba(255, 204, 204, 0.7), rgba(255, 204, 204, 0)); background-image:-ms-linear-gradient(top, rgba(255, 204, 204, 0.7), rgba(255, 204, 204, 0)); background-image:-o-linear-gradient(top, rgba(255, 204, 204, 0.7), rgba(255, 204, 204, 0)); background-image:linear-gradient(to bottom, rgba(255, 204, 204, 0.7), rgba(255, 204, 204, 0)); filter:progid:DXImageTransform.Microsoft.gradient(startColorstr=#b2ffcccc, endColorstr=#01ffcccc); -ms-filter:"progid:DXImageTransform.Microsoft.gradient(startColorstr=#b2ffcccc, endColorstr=#01ffcccc)";}
|
92 |
+
.widget-custom-menu-wizard-dialog .cmw-demo-themenu-ul .current-menu-parent {border-color:#ff9900 !important; background-image:-webkit-gradient(linear, left top, left bottom, from(rgba(255, 204, 153, 0.7)), to(rgba(255, 204, 153, 0))); background-image:-webkit-linear-gradient(top, rgba(255, 204, 153, 0.7), rgba(255, 204, 153, 0)); background-image:-moz-linear-gradient(top, rgba(255, 204, 153, 0.7), rgba(255, 204, 153, 0)); background-image:-ms-linear-gradient(top, rgba(255, 204, 153, 0.7), rgba(255, 204, 153, 0)); background-image:-o-linear-gradient(top, rgba(255, 204, 153, 0.7), rgba(255, 204, 153, 0)); background-image:linear-gradient(to bottom, rgba(255, 204, 153, 0.7), rgba(255, 204, 153, 0)); filter:progid:DXImageTransform.Microsoft.gradient(startColorstr=#b2ffcc99, endColorstr=#01ffcc99); -ms-filter:"progid:DXImageTransform.Microsoft.gradient(startColorstr=#b2ffcc99, endColorstr=#01ffcc99)";}
|
93 |
+
.widget-custom-menu-wizard-dialog .cmw-demo-themenu-ul a.cmw-item {color:#000000; margin:1px; padding:2px;}
|
94 |
+
.widget-custom-menu-wizard-dialog .cmw-demo-themenu-ul .picked > a.cmw-item {background-color:#333366; color:#ffffff;}
|
95 |
+
/*...ticks/crosses...*/
|
96 |
+
.widget-custom-menu-wizard-dialog .cmw-demo-themenu-ul a.cmw-tick,
|
97 |
+
.widget-custom-menu-wizard-dialog .cmw-demo-themenu-ul a.cmw-cross {background:transparent url("custom-menu-wizard.png") no-repeat 0 -160px; height:20px; margin:3px 2px 0px 0px; position:relative; -webkit-transition-duration:0s; transition-duration:0s; width:20px;}
|
98 |
+
.widget-custom-menu-wizard-dialog .cmw-demo-themenu-ul a.cmw-tick {background-position:0 -240px; margin-left:2px; margin-right:0; visibility:hidden;}
|
99 |
+
.widget-custom-menu-wizard-dialog .cmw-demo-filteritems a.cmw-tick {visibility:visible;}
|
100 |
+
.widget-custom-menu-wizard-dialog .cmw-version-210 a.cmw-cross {display:none;}
|
101 |
+
.widget-custom-menu-wizard-dialog .cmw-has-cross > a.cmw-cross,
|
102 |
+
.widget-custom-menu-wizard-dialog .cmw-has-cross.cmw-inherit-cross a.cmw-cross {background-position:0 -200px;}
|
103 |
+
.widget-custom-menu-wizard-dialog .cmw-has-cross.cmw-inherit-cross > a.cmw-cross {background-position:0 -320px;}
|
104 |
+
.widget-custom-menu-wizard-dialog .cmw-demo-themenu-ul a.cmw-cross:hover {background-position:0 -180px;}
|
105 |
+
.widget-custom-menu-wizard-dialog .cmw-has-cross > a.cmw-cross:hover,
|
106 |
+
.widget-custom-menu-wizard-dialog .cmw-has-cross.cmw-inherit-cross a.cmw-cross:hover {background-position:0 -220px;}
|
107 |
+
.widget-custom-menu-wizard-dialog .cmw-has-cross.cmw-inherit-cross > a.cmw-cross:hover {background-position:0 -360px;}
|
108 |
+
.widget-custom-menu-wizard-dialog .cmw-has-tick > a.cmw-tick,
|
109 |
+
.widget-custom-menu-wizard-dialog .cmw-has-tick.cmw-inherit-tick a.cmw-tick {background-position:0 -280px;}
|
110 |
+
.widget-custom-menu-wizard-dialog .cmw-has-tick.cmw-inherit-tick > a.cmw-tick {background-position:0 -340px;}
|
111 |
+
.widget-custom-menu-wizard-dialog .cmw-demo-themenu-ul a.cmw-tick:hover {background-position:0 -260px;}
|
112 |
+
.widget-custom-menu-wizard-dialog .cmw-has-tick > a.cmw-tick:hover,
|
113 |
+
.widget-custom-menu-wizard-dialog .cmw-has-tick.cmw-inherit-tick a.cmw-tick:hover {background-position:0 -300px;}
|
114 |
+
.widget-custom-menu-wizard-dialog .cmw-has-tick.cmw-inherit-tick > a.cmw-tick:hover {background-position:0 -380px;}
|
115 |
+
/*...expanders...*/
|
116 |
+
.widget-custom-menu-wizard-dialog .widget-custom-menu-wizard-colexp {position:absolute; top:0.5em; -webkit-transition-duration:0s; transition-duration:0s;}
|
117 |
+
.widget-custom-menu-wizard-dialog .widget-custom-menu-wizard-colexp.ui-icon-triangle-1-e {opacity:0.2;}
|
118 |
/*...output...*/
|
119 |
+
.widget-custom-menu-wizard-dialog .cmw-demo-theoutput {float:right; margin:0 0 3.5em 0.5em;}
|
120 |
+
.widget-custom-menu-wizard-dialog .cmw-demo-theoutput h3 {border-bottom:1px solid #CCCCCC; font-size:1.1667em; margin:0.25em 0; padding: 0 0.857em 0.25em 0.643em;}
|
121 |
+
.widget-custom-menu-wizard-dialog .cmw-demo-theoutput-wrap {border:1px solid #cccccc; margin:0.5em 0; min-height:3em; min-width:10em; padding:0 0 1px;}
|
122 |
+
.widget-custom-menu-wizard-dialog .cmw-demo-theoutput-wrap {border-left:4px solid #2ea2cc;}
|
123 |
+
.widget-custom-menu-wizard-dialog .cmw-demo-theoutput-wrap ul,
|
124 |
+
.widget-custom-menu-wizard-dialog .cmw-demo-theoutput-wrap ol {margin:0.5em 1em 0.5em 2em; padding:0;}
|
125 |
.widget-custom-menu-wizard-dialog .cmw-demo-theoutput-wrap li {margin:0;}
|
126 |
.widget-custom-menu-wizard-dialog .cmw-demo-theoutput-wrap li ul {margin:0 0 0 1em;}
|
127 |
.widget-custom-menu-wizard-dialog .cmw-demo-theoutput-wrap li ol {margin:0 0 0 1.5em;}
|
135 |
.widget-custom-menu-wizard-dialog .cmw-demo-theoutput-wrap ol ol ol {list-style-type:lower-alpha;}
|
136 |
.widget-custom-menu-wizard-dialog .cmw-demo-theoutput-wrap ol ol ol ol {list-style-type:lower-roman;}
|
137 |
.widget-custom-menu-wizard-dialog .cmw-demo-theoutput-wrap ol ol ol ol ol {list-style-type:decimal;}
|
138 |
+
.widget-custom-menu-wizard-dialog .cmw-demo-plugin-version {float:right; line-height:1;}
|
139 |
+
.widget-custom-menu-wizard-dialog .cmw-demo-small {font-size:0.8333em;}
|
140 |
+
.widget-custom-menu-wizard-dialog .cmw-demo-found-new,
|
141 |
+
.widget-custom-menu-wizard-dialog .cmw-demo-found-old,
|
142 |
+
.widget-custom-menu-wizard-dialog .cmw-demo-inclusions,
|
143 |
+
.widget-custom-menu-wizard-dialog .cmw-demo-exclusions,
|
144 |
+
.widget-custom-menu-wizard-dialog .cmw-demo-setcurrent,
|
145 |
+
.widget-custom-menu-wizard-dialog .cmw-demo-fallback {border-color:#7AD03A; border-left:4px solid #7AD03A; -webkit-box-shadow:0 1px 1px 0 rgba(0, 0, 0, 0.1); box-shadow:0 1px 1px 0 rgba(0, 0, 0, 0.1); display:none; font-style:italic; margin:0 0 2px 0; padding:1px 1em;}
|
146 |
+
.widget-custom-menu-wizard-dialog .cmw-demo-setcurrent {border-color:#DD3D36; border-left:4px solid #DD3D36; margin:2px 0 0;}
|
147 |
+
.widget-custom-menu-wizard-dialog .cmw-demo-setcurrent.error,
|
148 |
+
.widget-custom-menu-wizard-dialog .cmw-demo-inclusions.updated,
|
149 |
+
.widget-custom-menu-wizard-dialog .cmw-demo-exclusions.updated,
|
150 |
+
.widget-custom-menu-wizard-dialog .cmw-demo-fallback.updated {display:block;}
|
151 |
+
/*...find shortcodes...*/
|
152 |
+
.widget-custom-menu-wizard-find-shortcodes {overflow:hidden; text-align:center; width:50px;}
|
153 |
+
.widget-custom-menu-wizard-find-shortcodes span {display:block;}
|
154 |
+
.widget-custom-menu-wizard-find-shortcodes span.spinner {display:none; float:none;}
|
155 |
+
.cmw-ajax-showing .widget-custom-menu-wizard-find-shortcodes:after {background-color:#CC0000; content:""; display:block; height:2px; left:10%; position:absolute; top:50%; -webkit-transform:skew(0deg,-20deg); -ms-transform:skew(0deg,-20deg); -o-transform:skew(0deg,-20deg); transform:skew(0deg,-20deg); width:80%;}
|
156 |
+
.widget-custom-menu-wizard-dialog .cmw-find-shortcodes {position:absolute; right:0; top:-3em; z-index:10;}
|
157 |
+
.widget-custom-menu-wizard-dialog .cmw-demo-found-shortcodes {background-color:#FFFFFF; border:1px solid #666666; box-shadow:2px 2px 2px #666666; margin:0; max-width:70%; min-width:10em; opacity:0; padding:0 0 1px; position:absolute; right:5000px; top:-1000px;}
|
158 |
+
.widget-custom-menu-wizard-dialog .cmw-demo-found-shortcodes {border-right:4px solid #2EA2CC; -webkit-transition:opacity 1s linear 0s, right 0s linear 1s, top 0s linear 1s; transition:opacity 1s linear 0s, right 0s linear 1s, top 0s linear 1s;}
|
159 |
+
.widget-custom-menu-wizard-dialog .cmw-ajax-showing .cmw-demo-found-shortcodes {opacity:1;}
|
160 |
+
.widget-custom-menu-wizard-dialog .cmw-ajax-showing .cmw-demo-found-shortcodes,
|
161 |
+
.widget-custom-menu-wizard-dialog .cmw-ajax-fetching .cmw-demo-found-shortcodes {right:60px; top:-4em;}
|
162 |
+
.widget-custom-menu-wizard-dialog .cmw-ajax-fetching span.spinner {display:block !important;}
|
163 |
+
.widget-custom-menu-wizard-dialog .cmw-demo-found-shortcodes p {font-size:inherit; font-style:italic; margin:1em;}
|
164 |
+
.widget-custom-menu-wizard-dialog .cmw-demo-found-shortcodes dl {border:0 none; margin:0.5em 0; padding:0;}
|
165 |
+
.widget-custom-menu-wizard-dialog .cmw-demo-found-shortcodes a {display:block; overflow:hidden; padding:0 1em; text-overflow:ellipsis; white-space:nowrap;}
|
166 |
+
.widget-custom-menu-wizard-dialog .cmw-demo-found-shortcodes a:hover {background-color:#F0F0F0;}
|
167 |
+
.widget-custom-menu-wizard-dialog .cmw-demo-found-new,
|
168 |
+
.widget-custom-menu-wizard-dialog .cmw-demo-found-old {display:block; font-style:normal; padding:0; margin:2px 0;}
|
169 |
+
.widget-custom-menu-wizard-dialog .cmw-demo-found-new {border-color:#ffffff; border-left:4px solid #ffffff;}
|
170 |
+
.widget-custom-menu-wizard-dialog .cmw-demo-found-old {border-color:#DD3D36; border-left:4px solid #DD3D36;}
|
@@ -1,600 +1,1524 @@
|
|
1 |
/* Plugin Name: Custom Menu Wizard
|
2 |
-
* Version: 2.0.5
|
3 |
-
* Author: Roger Barrett
|
4 |
-
*
|
5 |
* Script for controlling this widget's options (in Admin -> Widgets)
|
6 |
*/
|
7 |
-
/*global jQuery, window, document */
|
8 |
-
/*jslint forin: true, nomen: true, plusplus: true, regexp: true, unparam: true,
|
|
|
9 |
jQuery(function($){
|
10 |
-
|
11 |
-
|
12 |
-
|
13 |
-
|
14 |
-
|
15 |
-
|
16 |
-
|
17 |
-
|
18 |
-
|
19 |
-
|
20 |
-
|
21 |
-
|
22 |
-
|
23 |
-
|
24 |
-
|
25 |
-
|
26 |
-
|
27 |
-
|
28 |
-
|
29 |
-
|
30 |
-
|
31 |
-
|
32 |
-
|
33 |
-
|
34 |
-
|
35 |
-
|
36 |
-
|
37 |
-
|
38 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
39 |
});
|
40 |
-
|
41 |
-
|
42 |
-
|
43 |
-
|
44 |
-
|
45 |
-
|
46 |
-
|
47 |
-
|
48 |
-
|
49 |
-
|
50 |
-
|
51 |
-
|
52 |
-
|
53 |
-
|
54 |
-
|
55 |
-
|
56 |
-
|
57 |
-
|
58 |
-
|
59 |
-
|
60 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
61 |
}
|
62 |
-
|
63 |
-
|
64 |
-
|
65 |
-
|
66 |
-
|
67 |
-
|
68 |
-
|
69 |
-
|
70 |
-
|
71 |
-
|
72 |
-
|
73 |
-
|
74 |
-
|
75 |
-
|
76 |
-
|
77 |
-
|
78 |
-
|
79 |
-
|
80 |
-
|
81 |
-
|
82 |
-
|
83 |
-
|
84 |
-
|
85 |
-
|
86 |
-
|
87 |
-
|
88 |
-
|
89 |
-
|
90 |
-
|
91 |
-
|
92 |
-
|
93 |
-
|
94 |
-
|
95 |
-
|
96 |
-
|
97 |
-
|
98 |
-
|
99 |
-
|
100 |
-
|
101 |
-
inPath.eq(i).children('a').find('span').addClass(n).each(appendCls);
|
102 |
-
if(cls.length > 1){
|
103 |
-
cls.shift();
|
104 |
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
105 |
}
|
106 |
-
|
107 |
-
|
108 |
-
|
109 |
-
|
110 |
-
|
111 |
-
|
112 |
-
|
113 |
-
|
114 |
-
|
115 |
-
|
116 |
-
|
117 |
-
|
118 |
-
|
119 |
-
|
120 |
-
|
121 |
-
|
122 |
-
|
123 |
-
|
124 |
-
|
125 |
-
|
126 |
-
|
127 |
-
|
128 |
-
|
129 |
-
|
130 |
-
|
131 |
-
|
132 |
-
|
133 |
-
|
134 |
-
|
135 |
-
|
136 |
-
|
137 |
-
|
138 |
-
|
139 |
-
|
140 |
}
|
141 |
-
}
|
142 |
-
|
143 |
-
|
144 |
-
|
145 |
-
|
146 |
-
|
147 |
-
|
148 |
-
|
149 |
-
|
150 |
-
|
151 |
-
|
152 |
-
|
153 |
-
|
154 |
-
|
155 |
-
|
156 |
-
|
157 |
-
|
158 |
-
|
159 |
-
|
160 |
-
|
161 |
-
|
162 |
-
|
163 |
-
|
164 |
-
|
165 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
166 |
}
|
167 |
-
}
|
|
|
|
|
|
|
|
|
168 |
}
|
169 |
-
}
|
170 |
-
|
171 |
-
|
172 |
-
|
173 |
-
|
174 |
-
|
175 |
-
|
176 |
-
|
177 |
-
|
178 |
-
|
179 |
-
|
180 |
-
|
181 |
-
|
182 |
-
|
183 |
-
|
184 |
-
|
185 |
-
|
186 |
-
|
187 |
-
|
188 |
-
|
189 |
-
|
190 |
-
|
191 |
-
|
192 |
-
|
193 |
-
|
194 |
-
|
195 |
-
|
196 |
-
|
197 |
-
|
198 |
-
|
199 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
200 |
}
|
201 |
-
|
202 |
-
|
203 |
-
|
204 |
-
|
205 |
-
|
206 |
-
|
207 |
-
|
208 |
-
|
209 |
-
|
210 |
-
|
211 |
-
|
212 |
-
|
213 |
-
|
214 |
-
|
215 |
-
|
216 |
-
|
217 |
-
|
218 |
-
|
219 |
-
|
220 |
-
|
221 |
-
|
222 |
-
|
223 |
-
|
224 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
225 |
}
|
226 |
-
|
227 |
-
|
|
|
|
|
228 |
}
|
229 |
-
|
230 |
-
|
231 |
-
|
232 |
-
|
233 |
-
|
234 |
-
|
235 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
236 |
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
237 |
}
|
238 |
-
|
239 |
-
|
240 |
-
|
241 |
-
|
242 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
243 |
}else{
|
244 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
245 |
}
|
|
|
|
|
|
|
|
|
246 |
}
|
247 |
-
|
248 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
249 |
}
|
250 |
-
|
251 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
252 |
}
|
253 |
-
|
254 |
-
|
|
|
|
|
255 |
}
|
256 |
-
|
257 |
-
|
258 |
-
|
259 |
-
|
260 |
-
|
261 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
262 |
}
|
263 |
-
|
264 |
-
|
265 |
}
|
266 |
-
|
267 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
268 |
}
|
269 |
}
|
270 |
-
|
271 |
-
|
272 |
-
|
273 |
-
|
274 |
-
|
275 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
276 |
}
|
277 |
-
|
278 |
-
|
|
|
|
|
|
|
|
|
279 |
}
|
280 |
-
|
281 |
-
|
282 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
283 |
}
|
|
|
|
|
284 |
}
|
285 |
-
|
286 |
-
|
287 |
-
|
288 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
289 |
}
|
290 |
}
|
291 |
-
|
292 |
-
|
293 |
-
|
294 |
-
|
295 |
-
|
|
|
|
|
|
|
|
|
296 |
}
|
297 |
-
|
298 |
-
|
299 |
-
|
300 |
-
|
301 |
-
|
302 |
-
|
303 |
-
|
304 |
-
|
305 |
-
|
306 |
-
*
|
307 |
-
* @this {Element}
|
308 |
-
* @param {Object} e Event object
|
309 |
-
* @param {Object} fm jQuery of widget form
|
310 |
-
* @param {Object} settings Form element values
|
311 |
-
*/
|
312 |
-
show : function(e, fm, settings){ //scope is a widget form element
|
313 |
-
//hide_empty is assumed to be On (WP < v3.6) or will automatically be On (WP v3.6+)
|
314 |
-
fm = fm || $(this).closest('form');
|
315 |
-
settings = settings || assist.getSettings(fm);
|
316 |
-
var dialog = assist.getDialog(fm),
|
317 |
-
themenu = dialog.find('.cmw-demo-themenu'),
|
318 |
-
items = themenu.find('.picked'),
|
319 |
-
html = '',
|
320 |
-
title = '',
|
321 |
-
currLevel = 0,
|
322 |
-
output = dialog.find('.cmw-demo-theoutput-wrap').empty(),
|
323 |
-
listClass = ['menu-widget'],
|
324 |
-
itemList = {};
|
325 |
-
if(items.length && output.length){
|
326 |
-
if(settings.filter > 0 && settings.title_from_parent){
|
327 |
-
title = themenu.find('.the-parent').children('a').text() || '';
|
328 |
}
|
329 |
-
if
|
330 |
-
|
|
|
|
|
331 |
}
|
332 |
-
|
333 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
334 |
}
|
335 |
-
|
336 |
-
|
337 |
-
|
338 |
-
|
339 |
-
iid = data.itemid.toString(),
|
340 |
-
level = 1,
|
341 |
-
anchor = self.children('a');
|
342 |
-
if(!settings.flat_output){
|
343 |
-
itemList[iid] = 1;
|
344 |
-
for(i = 0; i < trace.length; i++){
|
345 |
-
if(itemList[trace[i]]){
|
346 |
-
level++;
|
347 |
-
}
|
348 |
-
}
|
349 |
-
}
|
350 |
-
if(currLevel){
|
351 |
-
if(level > currLevel){
|
352 |
-
html += settings.ol_sub ? '<ol>' : '<ul>';
|
353 |
-
}else{
|
354 |
-
while(currLevel > level){
|
355 |
-
--currLevel;
|
356 |
-
html += '</li>' + (settings.ol_sub ? '</ol>' : '</ul>');
|
357 |
-
}
|
358 |
-
html += '</li>';
|
359 |
-
}
|
360 |
}
|
361 |
-
html += '<li class="cmw-level-' + level + (data.included || '') + '"><a href="#' + anchor.data('indx') + '">' + anchor.text() + '</a>';
|
362 |
-
currLevel = level;
|
363 |
-
});
|
364 |
-
while(currLevel > 1){
|
365 |
-
--currLevel;
|
366 |
-
html += '</li>' + (settings.ol_sub ? '</ol>' : '</ul>');
|
367 |
-
}
|
368 |
-
html += '</li>';
|
369 |
-
listClass.push( dialog.find('.cmw-demo-fallback').data('fellback') );
|
370 |
-
html = (settings.ol_root ? '<ol' : '<ul') + ' class="' + $.trim(listClass.join(' ')) + '">' + html + (settings.ol_root ? '</ol>' : '</ul>');
|
371 |
-
output.html(html);
|
372 |
-
if(title){
|
373 |
-
output.prepend('<h3>' + title + '</h3>');
|
374 |
-
}
|
375 |
-
output.find('li').filter(function(){
|
376 |
-
return !!$(this).children('ul, ol').length;
|
377 |
-
}).addClass('cmw-has-submenu');
|
378 |
-
}
|
379 |
-
assist.shortcode(fm, settings);
|
380 |
-
},
|
381 |
-
/**
|
382 |
-
* updates the graphic menu structure from the widget form data
|
383 |
-
* @this {Element} An input (radio or checkbox) or select element from the widget form
|
384 |
-
* @param {Object} e Event object
|
385 |
-
*/
|
386 |
-
update : function(e){
|
387 |
-
var fm = $(this).closest('form'),
|
388 |
-
dialog = assist.getDialog(fm),
|
389 |
-
maxLevel, settings, includeParent, includeParentSiblings, themenu, items,
|
390 |
-
currentItemLI, currentItemLevel, fallback, parent, i, j;
|
391 |
-
if(!dialog.length || !dialog.dialog('isOpen')){
|
392 |
-
return;
|
393 |
-
}
|
394 |
-
|
395 |
-
if($(e.target).hasClass(dotPrefix.substr(1) + '-selectmenu')){
|
396 |
-
assist.createMenu(dialog, fm);
|
397 |
-
}
|
398 |
-
settings = assist.getSettings(fm);
|
399 |
-
includeParent = settings.include_parent;
|
400 |
-
includeParentSiblings = settings.include_parent_siblings;
|
401 |
-
themenu = dialog.find('.cmw-demo-themenu');
|
402 |
-
maxLevel = themenu.data().maxLevel;
|
403 |
-
currentItemLI = themenu.find('.current-menu-item').closest('li');
|
404 |
-
currentItemLevel = currentItemLI.length ? currentItemLI.data().level : -1;
|
405 |
-
items = themenu.find('li').removeData('included').removeClass('the-parent');
|
406 |
-
|
407 |
-
if(settings.filter < 0){
|
408 |
-
items = items.filter(function(){
|
409 |
-
var checkbox = $(this).children('input'),
|
410 |
-
checked = (settings._items_sep + settings._items + settings._items_sep).indexOf(settings._items_sep + checkbox[0].value + settings._items_sep) > -1;
|
411 |
-
checkbox.prop('checked', checked);
|
412 |
-
return checked;
|
413 |
-
});
|
414 |
-
if(!settings._items){
|
415 |
-
items = $([]);
|
416 |
}
|
|
|
|
|
417 |
}
|
|
|
418 |
|
419 |
-
|
420 |
-
|
421 |
-
|
|
|
422 |
|
423 |
-
|
424 |
-
|
425 |
-
|
426 |
-
|
427 |
-
|
428 |
-
|
429 |
-
|
430 |
-
|
431 |
-
|
432 |
-
|
433 |
-
//fall back to current parent...
|
434 |
-
parent = themenu.find('.current-menu-parent').closest('li');
|
435 |
-
if(!parent.length){
|
436 |
-
parent = themenu; //beware!
|
437 |
-
}
|
438 |
-
includeParent = includeParent || settings.fallback_nc_include_parent;
|
439 |
-
includeParentSiblings = includeParentSiblings || settings.fallback_nc_include_parent_siblings;
|
440 |
-
fallback = 'cmw-fellback-to-parent';
|
441 |
-
}
|
442 |
-
}else{
|
443 |
-
//parent or root...
|
444 |
-
if(currentItemLevel === 1 && settings.fallback_no_ancestor){
|
445 |
-
parent = currentItemLI;
|
446 |
-
includeParent = includeParent || settings.fallback_include_parent;
|
447 |
-
includeParentSiblings = includeParentSiblings || settings.fallback_include_parent_siblings;
|
448 |
-
fallback = 'cmw-fellback-to-current';
|
449 |
-
}else if(currentItemLevel === 1){
|
450 |
-
parent = themenu; //beware!
|
451 |
-
}else if(settings.filter_item < -1){
|
452 |
-
parent = themenu.find('.current-menu-ancestor').eq(0).closest('li');
|
453 |
-
}else{
|
454 |
-
parent = themenu.find('.current-menu-parent').closest('li');
|
455 |
-
}
|
456 |
}
|
457 |
-
|
458 |
-
|
459 |
-
|
460 |
-
if(
|
461 |
-
|
462 |
-
|
463 |
-
|
464 |
-
|
465 |
-
|
466 |
-
|
467 |
-
|
468 |
-
if(
|
469 |
-
|
|
|
470 |
}
|
471 |
}
|
472 |
-
}else if(parent && parent.length){
|
473 |
-
//kids of...
|
474 |
-
if(settings.depth_rel_current && settings.depth && currentItemLI.length && parent.has(currentItemLI[0]).length){
|
475 |
-
j = currentItemLevel - 1 + settings.depth;
|
476 |
-
}else{
|
477 |
-
j = settings.depth ? Math.max( (parent.data().level || 0) + settings.depth, settings.start_level + settings.depth - 1 ) : 9999;
|
478 |
-
}
|
479 |
-
items = parent.find('li').filter(function(){
|
480 |
-
var level = $(this).data().level;
|
481 |
-
return level >= settings.start_level && level <= j;
|
482 |
-
});
|
483 |
-
}else if(settings.filter > 0){
|
484 |
-
//kids-of, but no parent found...
|
485 |
-
items = $([]);
|
486 |
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
487 |
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
488 |
|
489 |
-
|
490 |
-
|
491 |
-
|
492 |
-
|
493 |
-
|
494 |
-
|
495 |
-
|
496 |
-
|
497 |
-
|
498 |
-
|
499 |
-
|
500 |
-
|
501 |
-
|
|
|
|
|
|
|
|
|
|
|
502 |
}
|
503 |
}
|
|
|
|
|
|
|
|
|
|
|
|
|
504 |
}
|
|
|
505 |
|
506 |
-
|
507 |
-
|
508 |
-
|
509 |
-
|
510 |
|
511 |
-
|
512 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
513 |
}
|
514 |
-
fallback = items.length ? fallback : '';
|
515 |
-
dialog.find('.cmw-demo-fallback').data('fellback', fallback).toggleClass('cmw-demo-fellback', !!fallback);
|
516 |
-
themenu.toggleClass('cmw-demo-filteritems', settings.filter < 0)
|
517 |
-
.find('.picked').not( items.addClass('picked') ).removeClass('picked');
|
518 |
-
assist.show.call(this, e, fm, settings);
|
519 |
}
|
520 |
-
};
|
521 |
|
522 |
-
|
523 |
-
|
524 |
-
|
525 |
-
|
526 |
-
|
527 |
-
|
528 |
-
|
529 |
-
|
530 |
-
|
531 |
-
self.next('div')[collapse?'slideUp':'slideDown']();
|
532 |
-
}
|
533 |
-
this.blur();
|
534 |
-
return false;
|
535 |
-
})
|
536 |
-
//change of menu, and enableif / disableif...
|
537 |
-
.on('change', dotPrefix + '-listen', function(){
|
538 |
-
var fm = $(this.form),
|
539 |
-
selectMenu = fm.find(dotPrefix + '-selectmenu'),
|
540 |
-
showAll = fm.find(dotPrefix + '-showall').prop('checked'),
|
541 |
-
showSpecific = fm.find(dotPrefix + '-showspecific').prop('checked'),
|
542 |
-
filterItem = fm.find(dotPrefix + '-childrenof'),
|
543 |
-
fiVal = parseInt(filterItem.val(), 10),
|
544 |
-
groupClone;
|
545 |
-
if(selectMenu.is(this)){
|
546 |
-
//change of menu : swap out the childrenof's optgroup for the new one...
|
547 |
-
selectMenu = this.selectedIndex;
|
548 |
-
if(!filterItem.find('optgroup').filter(function(){
|
549 |
-
var keep = $(this).data('cmwOptgroupIndex') === selectMenu;
|
550 |
-
if(!keep){
|
551 |
-
$(this).remove();
|
552 |
-
}
|
553 |
-
return keep;
|
554 |
-
}).length){
|
555 |
-
groupClone = $('#' + filterItem.attr('id') + '_ignore').find('optgroup').eq(selectMenu).clone();
|
556 |
-
if(groupClone.length){
|
557 |
-
if(fiVal > 0){
|
558 |
-
fiVal = 0;
|
559 |
-
filterItem.val(fiVal);
|
560 |
-
}
|
561 |
-
groupClone.find('option[selected]').removeAttr('selected').prop('selected', false);
|
562 |
-
filterItem.append(groupClone);
|
563 |
-
}
|
564 |
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
565 |
}
|
566 |
$.each(
|
567 |
{ '' : showAll || showSpecific,
|
568 |
'-ss' : showSpecific,
|
569 |
-
'not-rp' : showAll || showSpecific ||
|
570 |
-
'not-ci' : showAll || showSpecific || !!
|
571 |
},
|
572 |
function(k, v){
|
573 |
-
|
574 |
});
|
575 |
-
})
|
576 |
-
|
577 |
-
|
578 |
-
|
579 |
-
|
580 |
-
|
581 |
-
|
582 |
-
|
583 |
-
|
584 |
-
|
585 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
586 |
}
|
587 |
-
}
|
588 |
-
|
589 |
-
|
590 |
-
|
591 |
-
|
592 |
-
|
593 |
-
|
594 |
-
|
595 |
-
|
|
|
|
|
596 |
}
|
597 |
-
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
598 |
});
|
599 |
|
600 |
});
|
1 |
/* Plugin Name: Custom Menu Wizard
|
|
|
|
|
|
|
2 |
* Script for controlling this widget's options (in Admin -> Widgets)
|
3 |
*/
|
4 |
+
/*global jQuery, window, document, ajaxurl */
|
5 |
+
/*jslint forin: true, nomen: true, plusplus: true, regexp: true, unparam: true, white: true */
|
6 |
+
/*jshint curly: true, eqeqeq: true, es3: true, freeze: true, immed: true, latedef: true, newcap: true, noarg: true, noempty: true, nonbsp: true, nonew: true, quotmark: single, undef: true, strict: true, trailing: true, laxbreak: true */
|
7 |
jQuery(function($){
|
8 |
+
'use strict';
|
9 |
+
var cmwAssist,
|
10 |
+
widgetCustomMenuWizardClass = function(suffix, dot){
|
11 |
+
return (!dot ? '' : '.') + 'widget-custom-menu-wizard-' + suffix;
|
12 |
+
},
|
13 |
+
/**
|
14 |
+
* updates the graphic menu structure from the widget settings
|
15 |
+
* @this {element} div.widget-custom-menu-wizard-onchange
|
16 |
+
* @param {object} e Event object
|
17 |
+
*/
|
18 |
+
assistance = function(e){
|
19 |
+
var v = $(this).data().cmwDialogVersion.replace(/\./g, '');
|
20 |
+
v = /^\d+$/.test(v) ? 'v' + v : v;
|
21 |
+
//run the update() method of the relevant assist object, based on a version number...
|
22 |
+
if(cmwAssist[v]){
|
23 |
+
cmwAssist[v].update(e ? e.target : this);
|
24 |
+
}else{
|
25 |
+
cmwAssist.update(e ? e.target : this);
|
26 |
+
}
|
27 |
+
}, //end assistance()
|
28 |
+
/**
|
29 |
+
* sets the tick or cross classes and returns a filtered set of the items that *are* ticked/crossed
|
30 |
+
* @param {object} items jQuery of elements to filter
|
31 |
+
* @param {array} settings Widget settings
|
32 |
+
* @param {string} tickOrCross Either 'tick' or 'cross'
|
33 |
+
* @return {object} jQuery of filtered items
|
34 |
+
*/
|
35 |
+
filterTickCross = function( items, settings, tickOrCross ){
|
36 |
+
var sep = tickOrCross === 'tick' ? settings._items_sep : settings._exclude_sep,
|
37 |
+
inheritance = [],
|
38 |
+
haystack = tickOrCross === 'tick' ? '_items' : '_exclude';
|
39 |
+
haystack = settings[haystack]
|
40 |
+
? //extract those with inheritance...
|
41 |
+
$.grep(settings[haystack].split(sep), function(v){
|
42 |
+
if(/\+$/.test(v)){
|
43 |
+
inheritance.push(parseInt(v, 10));
|
44 |
+
return !v;
|
45 |
+
}
|
46 |
+
return !!v;
|
47 |
+
})
|
48 |
+
: [];
|
49 |
+
haystack = sep + haystack.join(sep) + sep;
|
50 |
+
inheritance = sep + inheritance.join(sep) + sep;
|
51 |
+
//need to remember that we're turning off as well as on, because there's no generic clear-down...
|
52 |
+
items = items.each(function(){
|
53 |
+
var item = $(this),
|
54 |
+
data = item.data(),
|
55 |
+
inherit = inheritance.indexOf(sep + data.itemid + sep) > -1,
|
56 |
+
matched = inherit || haystack.indexOf(sep + data.itemid + sep) > -1;
|
57 |
+
item.toggleClass('cmw-has-' + tickOrCross, matched)
|
58 |
+
.toggleClass('cmw-inherit-' + tickOrCross, inherit);
|
59 |
});
|
60 |
+
//returning items that *are* ticked/crossed, so get the inheritance items...
|
61 |
+
return items.filter('.cmw-inherit-' + tickOrCross)
|
62 |
+
//...get their descendants and clear any tick/cross classes that may have been set...
|
63 |
+
.find('li').removeClass('cmw-has-' + tickOrCross + ' cmw-inherit-' + tickOrCross)
|
64 |
+
//...add back in (to the inheritance descendants) any (other) items that still have tick/cross
|
65 |
+
//set, which will include the uppermost of any inheritance items...
|
66 |
+
.add( items.filter('.cmw-has-' + tickOrCross) );
|
67 |
+
}, //end filterTickCross
|
68 |
+
/**
|
69 |
+
* gets the -onchange wrapper
|
70 |
+
* @param {object} below jQuery of element to search below (exclusive, ie. find())
|
71 |
+
* @param {object} above jQuery of element to search above (inclusive, ie. closest())
|
72 |
+
* @return {object} jQuery of the -onchange wrapper
|
73 |
+
*/
|
74 |
+
findOnchange = function(below, above){
|
75 |
+
return (!below ? above : below)[!below ? 'closest' : 'find'](widgetCustomMenuWizardClass('onchange', 1));
|
76 |
+
},
|
77 |
+
/**
|
78 |
+
* gets the widget's field values
|
79 |
+
* @param {object} oc jQuery of the widget's onchange wrapper
|
80 |
+
* @return {object} key=>value pairs of the field element values
|
81 |
+
*/
|
82 |
+
getSettings = function(oc){
|
83 |
+
var settings = {},
|
84 |
+
legacyVersion = oc.data('cmwDialogVersion') === '2.1.0',
|
85 |
+
csv = {items:1, exclude:1},
|
86 |
+
keepAsString = $.extend({branch_start:1, exclude_level:1}, csv);
|
87 |
+
$.each(oc.find(':input').serializeArray(), function(i, v){
|
88 |
+
var name = v.name.replace(/.*\[([^\]]+)\]$/, '$1'),
|
89 |
+
val = !keepAsString[name] && /^-?\d+$/.test(v.value) ? parseInt(v.value, 10) : v.value;
|
90 |
+
settings[name] = val;
|
91 |
+
if(name === 'hide_empty'){
|
92 |
+
settings[name] = !!oc.data().cmwV36plus || val;
|
93 |
+
}else if(csv[name]){
|
94 |
+
settings['_' + name + '_sep'] = !val || /(^\d+\+?$|,)/.test($.trim(val)) ? ',' : ' ';
|
95 |
+
val = $.map(val.split(/[,\s]+/), function(x){
|
96 |
+
var inherit = !legacyVersion && /\+$/.test(x);
|
97 |
+
x = x ? parseInt(x, 10) : 0;
|
98 |
+
return isNaN(x) || x < 1 ? null : (inherit ? x + '+' : x);
|
99 |
+
});
|
100 |
+
settings['_' + name] = val.join(settings['_' + name + '_sep']);
|
101 |
}
|
102 |
+
});
|
103 |
+
return settings;
|
104 |
+
}, //end getSettings()
|
105 |
+
/**
|
106 |
+
* produces the final output
|
107 |
+
* @param {object} dialog jQuery of target dialog
|
108 |
+
* @param {object} settings Field element values
|
109 |
+
*/
|
110 |
+
showOutput = function(dialog, settings){
|
111 |
+
var topOfMenu = dialog.find('.cmw-demo-themenu-ul'),
|
112 |
+
items = topOfMenu.find('.picked'),
|
113 |
+
html = '',
|
114 |
+
title = settings.hide_title ? '' : settings.title,
|
115 |
+
currLevel = 0,
|
116 |
+
output = dialog.find('.cmw-demo-theoutput-wrap').empty(),
|
117 |
+
listClass = ['menu-widget'],
|
118 |
+
itemList = {};
|
119 |
+
if(items.length && output.length){
|
120 |
+
//determine title: update() might have set a class for it...
|
121 |
+
title = topOfMenu.find('.title-from-item').children('.cmw-item').text() || '';
|
122 |
+
//...otherwise, check the actual widget title...
|
123 |
+
if(!title && !settings.hide_title){
|
124 |
+
title = settings.title || '';
|
125 |
+
}
|
126 |
+
|
127 |
+
items.each(function(i){
|
128 |
+
var self = $(this),
|
129 |
+
data = self.data(),
|
130 |
+
trace = data.trace ? data.trace.toString().split(',') : [],
|
131 |
+
iid = data.itemid.toString(),
|
132 |
+
level = 1,
|
133 |
+
anchor = self.children('.cmw-item');
|
134 |
+
if(!settings.flat_output){
|
135 |
+
itemList[iid] = 1;
|
136 |
+
for(i = 0; i < trace.length; i++){
|
137 |
+
if(itemList[trace[i]]){
|
138 |
+
level++;
|
139 |
+
}
|
140 |
+
}
|
|
|
|
|
|
|
141 |
}
|
142 |
+
if(currLevel){
|
143 |
+
if(level > currLevel){
|
144 |
+
html += settings.ol_sub ? '<ol>' : '<ul>';
|
145 |
+
}else{
|
146 |
+
while(currLevel > level){
|
147 |
+
--currLevel;
|
148 |
+
html += '</li>' + (settings.ol_sub ? '</ol>' : '</ul>');
|
149 |
+
}
|
150 |
+
html += '</li>';
|
151 |
+
}
|
152 |
+
}
|
153 |
+
html += '<li class="cmw-level-' + level + (data.included || '') + '"><a href="#' + anchor.data('indx') + '">' + anchor.text() + '</a>';
|
154 |
+
currLevel = level;
|
155 |
+
});
|
156 |
+
while(currLevel > 1){
|
157 |
+
--currLevel;
|
158 |
+
html += '</li>' + (settings.ol_sub ? '</ol>' : '</ul>');
|
159 |
}
|
160 |
+
html += '</li>';
|
161 |
+
listClass.push( dialog.find('.cmw-demo-fallback').data('fellback') );
|
162 |
+
html = (settings.ol_root ? '<ol' : '<ul') + ' class="' + $.trim(listClass.join(' ')) + '">' + html + (settings.ol_root ? '</ol>' : '</ul>');
|
163 |
+
output.html(html);
|
164 |
+
output.find('li').filter(function(){
|
165 |
+
return !!$(this).children('ul, ol').length;
|
166 |
+
}).addClass('cmw-has-submenu');
|
167 |
+
}
|
168 |
+
if(output.length && title && (items.length || !settings.hide_empty)){
|
169 |
+
output.prepend('<h3>' + title + '</h3>');
|
170 |
+
}
|
171 |
+
}, //end showOutput()
|
172 |
+
/**
|
173 |
+
* swap in the apropriate optgroup of items according to the selected menu
|
174 |
+
* @param {object} menuItems jQuery of the SELECT being modified
|
175 |
+
* @param {integer} selectedItem Currently selected item in menuItems
|
176 |
+
* @param {integer} selectedMenu Index of selected menu
|
177 |
+
* @return {integer} selectedItem
|
178 |
+
*/
|
179 |
+
swapItems = function(menuItems, selectedItem, selectedMenu){
|
180 |
+
var groupClone;
|
181 |
+
if(!menuItems.find('optgroup').filter(function(){
|
182 |
+
var keepit = $(this).data().cmwOptgroupIndex === selectedMenu;
|
183 |
+
if(!keepit){
|
184 |
+
$(this).remove();
|
185 |
+
}
|
186 |
+
return keepit;
|
187 |
+
}).length){
|
188 |
+
groupClone = $('#' + menuItems.attr('id') + '_ignore').find('optgroup').eq(selectedMenu).clone();
|
189 |
+
if(groupClone.length){
|
190 |
+
if(selectedItem > 0){
|
191 |
+
selectedItem = 0;
|
192 |
+
}
|
193 |
+
menuItems.append(groupClone).val(selectedItem);
|
194 |
}
|
195 |
+
}
|
196 |
+
return selectedItem;
|
197 |
+
}, //end swapItems()
|
198 |
+
/**
|
199 |
+
* toggles a set of widgets options open or closed
|
200 |
+
* @this {element} Header of the set
|
201 |
+
* @param {object} e Event object
|
202 |
+
* @return {boolean} false
|
203 |
+
*/
|
204 |
+
clickFieldset = function(e){
|
205 |
+
var self = $(this),
|
206 |
+
chkbox = self.next('.cmw-fieldset-state'),
|
207 |
+
collapse = !chkbox.prop('checked');
|
208 |
+
if(chkbox.length){
|
209 |
+
chkbox.prop('checked', collapse);
|
210 |
+
self.toggleClass('cmw-collapsed-fieldset', collapse);
|
211 |
+
chkbox.next('div')[collapse ? 'slideUp' : 'slideDown']();
|
212 |
+
}
|
213 |
+
this.blur();
|
214 |
+
return false;
|
215 |
+
}, //end clickFieldSet()
|
216 |
+
/**
|
217 |
+
* fetches and displays a list of posts that contain old/new shortcodes
|
218 |
+
* @this {element} The link/button
|
219 |
+
* @param {object} e Event object
|
220 |
+
* @return {boolean} false
|
221 |
+
*/
|
222 |
+
clickFindShortcodes = function(e){
|
223 |
+
var self = $(this),
|
224 |
+
grandad = self.parent().parent();
|
225 |
+
//if currently fetching, do nothing...
|
226 |
+
if(ajaxurl && !grandad.hasClass('cmw-ajax-fetching')){
|
227 |
+
//if currently showing previous results, remove the results from view...
|
228 |
+
if(grandad.hasClass('cmw-ajax-showing')){
|
229 |
+
grandad.removeClass('cmw-ajax-showing');
|
230 |
+
}else{
|
231 |
+
//fetch results via ajax, showing spinner while doing so...
|
232 |
+
grandad.addClass('cmw-ajax-fetching');
|
233 |
+
$.post(
|
234 |
+
ajaxurl,
|
235 |
+
{ 'action': 'cmw-find-shortcodes', '_wpnonce': self.data().nonce }
|
236 |
+
).done(function(response){
|
237 |
+
if(!!response && response !== '0'){
|
238 |
+
grandad.find('.cmw-demo-found-shortcodes').html($(response).find('response_data').text());
|
239 |
+
grandad.addClass('cmw-ajax-showing');
|
240 |
}
|
241 |
+
}
|
242 |
+
).always(function(response){
|
243 |
+
grandad.removeClass('cmw-ajax-fetching');
|
244 |
+
}
|
245 |
+
);
|
246 |
}
|
247 |
+
}
|
248 |
+
this.blur();
|
249 |
+
return false;
|
250 |
+
},
|
251 |
+
/**
|
252 |
+
* toggles fixed/absolute positioning for the dialog (work around for draggable problems in jQuery UI v1.10.3/4)
|
253 |
+
* @this {element} The "fixed" button
|
254 |
+
* @param {object} e Event object
|
255 |
+
* @return {boolean} false
|
256 |
+
*/
|
257 |
+
clickFixedAbsolute = function(e){
|
258 |
+
var self = $(this),
|
259 |
+
data = self.data(),
|
260 |
+
toAbsolute = !data.cmwAbsolute,
|
261 |
+
dialogBox = self.closest('.ui-dialog'),
|
262 |
+
dialog = dialogBox.find('.ui-dialog-content'),
|
263 |
+
//if fixed -> absolute, add scrollTop to [css]top; if absolute -> fixed, substract scrollTop from [css]top...
|
264 |
+
newTop = parseInt(dialogBox.css('top'), 10) + ( (toAbsolute ? 1 : -1) * $(document).scrollTop() );
|
265 |
+
data.cmwAbsolute = toAbsolute;
|
266 |
+
if(!data.cmwMaxHeight){
|
267 |
+
//store the initial maxHeight setting...
|
268 |
+
data.cmwMaxHeight = dialog.dialog('option', 'maxHeight');
|
269 |
+
}
|
270 |
+
//swap the icon...
|
271 |
+
self.button('option', 'icons', {primary:toAbsolute ? 'ui-icon-circle-close' : 'ui-icon-circle-check'});
|
272 |
+
//toggle the class to force either fixed (add class) or absolute (remove class)...
|
273 |
+
dialogBox.toggleClass('cmw-assistance-dialog-fixed', !toAbsolute);
|
274 |
+
//have to reset dialog's maxHeight here, *before* re-positioning, because UI will screw up the position when we set it!...
|
275 |
+
dialog.dialog('option', {maxHeight: toAbsolute ? !toAbsolute : data.cmwMaxHeight});
|
276 |
+
//re-position the dialog (have to use CSS because UI dialog's position option doesn't hack it!)...
|
277 |
+
dialogBox.css('top', newTop);
|
278 |
+
return false;
|
279 |
+
},
|
280 |
+
/**
|
281 |
+
* click handler for an item in the menu structure : sets or clears current menu item and its ancestors
|
282 |
+
* @this {element} Anchor element clicked on
|
283 |
+
* @param {object} e Event object
|
284 |
+
* @return {boolean} false
|
285 |
+
*/
|
286 |
+
clickMenu = function(e){
|
287 |
+
var self = $(this),
|
288 |
+
cls = ['current-menu-item', 'current-menu-parent', 'current-menu-ancestor'],
|
289 |
+
dialog = self.closest('.ui-dialog-content'),
|
290 |
+
topOfMenu = dialog.find('.cmw-demo-themenu-ul'),
|
291 |
+
inPath = self.find('span').not('.' + cls[0]).parentsUntil(topOfMenu, 'li'),
|
292 |
+
i, n,
|
293 |
+
appendCls = function(){
|
294 |
+
this.title = this.title + ' ' + n.replace(' ', ' & ').replace(/-/g, ' ');
|
295 |
+
};
|
296 |
+
topOfMenu.find('.' + cls.join(',.')).removeClass(cls.join(' ')).each(function(){
|
297 |
+
this.title = this.title.replace(/\s.*$/, '');
|
298 |
+
});
|
299 |
+
for(i = 0; i < inPath.length; i++){
|
300 |
+
n = i === 1 ? cls.join(' ') : cls[0];
|
301 |
+
inPath.eq(i).children('.cmw-item').find('span').addClass(n).each(appendCls);
|
302 |
+
if(cls.length > 1){
|
303 |
+
cls.shift();
|
304 |
}
|
305 |
+
}
|
306 |
+
//run update() via assistance()...
|
307 |
+
assistance.call( $(dialog.data().cmwOnchange).get(0) );
|
308 |
+
return false;
|
309 |
+
}, //end clickMenu()
|
310 |
+
/**
|
311 |
+
* click handler for an item in the Basic Output list : triggers a click on the respective menu structure item
|
312 |
+
* @this {element} Anchor element clicked on
|
313 |
+
* @param {object} e Event object
|
314 |
+
* @return {boolean} false
|
315 |
+
*/
|
316 |
+
clickOutput = function(e){
|
317 |
+
$(this).closest('.ui-dialog-content').find('.cmw-item')
|
318 |
+
.eq( this.href.split('#')[1] )
|
319 |
+
.not(':has(.current-menu-item)').trigger('click');
|
320 |
+
this.blur();
|
321 |
+
return false;
|
322 |
+
}, //end clickOutput()
|
323 |
+
/**
|
324 |
+
* click handler for assist's menu tree expander/collapser
|
325 |
+
*
|
326 |
+
* @this {element} Element clicked on
|
327 |
+
* @param {object} e Event object
|
328 |
+
* @return {boolean} false
|
329 |
+
*/
|
330 |
+
clickTreeExpander = function(e){
|
331 |
+
var direction = /1-e/.test(this.className) ? 'slideUp' : 'slideDown';
|
332 |
+
$(this).toggleClass('ui-icon-triangle-1-s ui-icon-triangle-1-e').prev('ul')[direction]();
|
333 |
+
return false;
|
334 |
+
},
|
335 |
+
/**
|
336 |
+
* click handler for a tick or cross against any item in the menu structure (does not modify any classes)
|
337 |
+
* @this {element} Tick or Cross clicked on
|
338 |
+
* @param {object} e Event object
|
339 |
+
* @return {boolean} false
|
340 |
+
*/
|
341 |
+
clickTickCross = function(e){
|
342 |
+
var self = $(this),
|
343 |
+
tickOrCross = self.hasClass('cmw-tick') ? 'tick' : 'cross',
|
344 |
+
item = self.parent(),
|
345 |
+
topOfMenu = item.closest('.cmw-demo-themenu-ul'),
|
346 |
+
hasInheritTickCross = item.hasClass('cmw-inherit-' + tickOrCross),
|
347 |
+
hasTickCross = hasInheritTickCross || item.hasClass('cmw-has-' + tickOrCross),
|
348 |
+
inheritsTickCrossFrom = hasTickCross ? $([]) : item.parentsUntil(topOfMenu, '.cmw-inherit-' + tickOrCross),
|
349 |
+
widgetField = $( item.closest('.ui-dialog-content').data().cmwOnchange )
|
350 |
+
.find(tickOrCross === 'tick' ? '.cmw-setitems' : '.cmw-exclusions'),
|
351 |
+
sampleSet;
|
352 |
+
if(widgetField.length){ //should never not find it!
|
353 |
+
//A. if this item hasInheritTickCross then this click will remove tickCross entirely and all inheritance will be lost
|
354 |
+
//B. else* if this item hasTickCross then this click will either
|
355 |
+
// B1. if the item has no descendants, or we're running legacy version, remove the tickCross
|
356 |
+
// B2. else add inheritance to it
|
357 |
+
//C. else* if this item inheritsTickCross then this click will
|
358 |
+
// - disinherit the relevant ancestor (keeping tickCross!)
|
359 |
+
// - and set all its descendants - bar this* item! - to tickCross
|
360 |
+
//D. else* this click will add tickCross (without inheritance) to this item
|
361 |
+
|
362 |
+
//find everything that currently has tickCross, and for (A) remove this item, or for (D) add this item...
|
363 |
+
//note : for (B) this item is already included, and for (C) this item is not already included and we don't want it to be
|
364 |
+
sampleSet = topOfMenu
|
365 |
+
.find('.cmw-has-' + tickOrCross)[ hasInheritTickCross || inheritsTickCrossFrom.length ? 'not' : 'add' ](item);
|
366 |
+
//(A) & (D) are now sorted and can be forgotten about
|
367 |
+
//for (B1), remove this item...
|
368 |
+
if(hasTickCross && (!item.children('ul').length || topOfMenu.parent().hasClass('cmw-version-210'))){
|
369 |
+
sampleSet = sampleSet.not(item);
|
370 |
}
|
371 |
+
else
|
372 |
+
//for (B2), because we're adding inheritance, any descendant of this item that is currently tickCross now needs to be excluded...
|
373 |
+
if(hasTickCross && !hasInheritTickCross){
|
374 |
+
sampleSet = sampleSet.not( item.find('.cmw-has-' + tickOrCross) );
|
375 |
}
|
376 |
+
//(B) is now also sorted and can be forgotten about
|
377 |
+
//for (C) we need to find the ancestor providing the inheritance and add in all its descendants bar this item...
|
378 |
+
sampleSet = sampleSet.add( inheritsTickCrossFrom.find('li').not(item) );
|
379 |
+
//map what's left to the associated item id, appending a plus sign for inheritance...
|
380 |
+
sampleSet = sampleSet.map(function(){
|
381 |
+
var plus = this === item[0] || this === inheritsTickCrossFrom.get(0) ? hasTickCross : $(this).hasClass('cmw-inherit-' + tickOrCross);
|
382 |
+
return $(this).data().itemid + (plus ? '+' : '');
|
383 |
+
})
|
384 |
+
.get().join( /(,|^\d+\+?$)/.test( $.trim(widgetField.val()) || ',' ) ? ',' : ' ' );
|
385 |
+
widgetField.val(sampleSet).trigger('change');
|
386 |
+
}
|
387 |
+
this.blur();
|
388 |
+
return false;
|
389 |
+
}, //end clickTickCross()
|
390 |
+
/**
|
391 |
+
* closes an open dialog when the widget is closed
|
392 |
+
* @this {element} The .widget-action or .widget-control-close clicked on
|
393 |
+
* @param {object} e Event object
|
394 |
+
*/
|
395 |
+
closeDialog = function(e){
|
396 |
+
var widgetContainer = $(this).closest('div.widget'),
|
397 |
+
containerParent = widgetContainer.parent();
|
398 |
+
//in widget customizer, opening one widget closes any other open widget without triggering anything that
|
399 |
+
//would make CMW close the assist ... which is good! however, I also don't want the assist to close when
|
400 |
+
//[re]opening a CMW widget, so for the customizer I need to check that the widget is "expanded" before
|
401 |
+
//making the assist close...
|
402 |
+
if(!containerParent.hasClass('customize-control-widget_form') || containerParent.hasClass('expanded')){
|
403 |
+
findOnchange(widgetContainer).each(function(){
|
404 |
+
var dialog = $('#' + $(this).data().cmwDialogId);
|
405 |
+
if(dialog.length && dialog.dialog('isOpen')){
|
406 |
+
dialog.dialog('close');
|
407 |
}
|
408 |
+
});
|
409 |
+
}
|
410 |
+
}, //end closeDialog()
|
411 |
+
/**
|
412 |
+
* creates the UI Dialog for the widget's assist
|
413 |
+
* @param {object} data Information required to build the dialog
|
414 |
+
* @return {object} jQuery object of the created Dialog
|
415 |
+
*/
|
416 |
+
createDialog = function(data){
|
417 |
+
var dialogOpts = {
|
418 |
+
autoOpen: false,
|
419 |
+
//initial width is the lowest of 600px and 90% of window width...
|
420 |
+
width: Math.min($(window).width() * 0.9, 600),
|
421 |
+
//starting out at fixed, so max the resizable height at 40px less than window height so that entire dialog box is visible...
|
422 |
+
maxHeight: $(window).height() - 40,
|
423 |
+
modal: false,
|
424 |
+
containment: 'window',
|
425 |
+
create: function(){
|
426 |
+
//add a "fixed" button to the titlebar, enabling switching between fixed and absolute positioning for the dialog...
|
427 |
+
var dialogBox = $(this).closest('.ui-dialog');
|
428 |
+
if(dialogBox.hasClass('cmw-assistance-dialog-fixed')){
|
429 |
+
$('<button/>').addClass('cmw-dialog-fixed-absolute')
|
430 |
+
.button({label:data.cmwDialogFixed, icons:{primary:'ui-icon-circle-check'}})
|
431 |
+
.appendTo( dialogBox.find('.ui-dialog-titlebar') )
|
432 |
+
.on('click', clickFixedAbsolute);
|
433 |
+
}
|
434 |
+
},
|
435 |
+
dialogClass: 'cmw-assistance-dialog cmw-assistance-dialog-fixed'
|
436 |
+
},
|
437 |
+
msgs = $.map(['SetCurrent', 'Inclusions', 'Exclusions', 'Fallback'], function(v){
|
438 |
+
return '<div class="cmw-demo-' + v.toLowerCase() + ' cmw-demo-small">' + (data['cmwDialog' + v] || '') + '</div>';
|
439 |
+
}),
|
440 |
+
dialog = $('<div/>', {id:data.cmwDialogId}).addClass(widgetCustomMenuWizardClass('dialog'))
|
441 |
+
.append(
|
442 |
+
$('<div/>').addClass('cmw-demo-themenu cmw-version-' + data.cmwDialogVersion.replace(/\./g, ''))
|
443 |
+
.html('<em class="cmw-demo-small">' + data.cmwDialogPrompt + '</em>')
|
444 |
+
)
|
445 |
+
.append(
|
446 |
+
$('<div/>').addClass('cmw-demo-theoutput')
|
447 |
+
.html('<em class="cmw-demo-small">' + data.cmwDialogOutput + '</em><em class="cmw-demo-plugin-version cmw-demo-small">v' + data.cmwDialogVersion + '</em>' + msgs.shift() + '<div class="cmw-demo-theoutput-wrap ui-corner-all"></div>' + msgs.join(''))
|
448 |
+
)
|
449 |
+
.append(
|
450 |
+
$('<div/>').addClass('cmw-demo-theshortcode')
|
451 |
+
.html('<code class="ui-corner-all"></code><div class="cmw-find-shortcodes"><a href="#" class="button-secondary ' + widgetCustomMenuWizardClass('find-shortcodes') + '" data-nonce="' + (data.cmwDialogNonce || '') + '" title="' + data.cmwDialogShortcodes + '"><span class="spinner"></span><span>[…]</span></a></div><div class="cmw-demo-found-shortcodes cmw-demo-small ui-corner-all"></div>')
|
452 |
+
);
|
453 |
+
dialog.dialog(dialogOpts);
|
454 |
+
dialog.find('.cmw-demo-themenu')
|
455 |
+
.on('click', '.cmw-tick,.cmw-cross', clickTickCross)
|
456 |
+
.on('click', '.cmw-item', clickMenu);
|
457 |
+
dialog.find('.cmw-demo-theoutput').on('click', 'a', clickOutput);
|
458 |
+
return dialog;
|
459 |
+
}, //end createDialog()
|
460 |
+
/**
|
461 |
+
* removes associated dialog when the widget is deleted
|
462 |
+
* @this {element} The .widget-control-remove clicked on
|
463 |
+
* @param {object} e Event object
|
464 |
+
*/
|
465 |
+
removeDialog = function(e){
|
466 |
+
findOnchange($(this).closest('div.widget')).each(function(){
|
467 |
+
var dialog = $('#' + $(this).data().cmwDialogId);
|
468 |
+
if(dialog.length){
|
469 |
+
dialog.dialog('destroy');
|
470 |
+
dialog.remove();
|
471 |
}
|
472 |
+
});
|
473 |
+
}, //end removeDialog()
|
474 |
+
/**
|
475 |
+
* (re)sets the dialog's title
|
476 |
+
* @param {object} dialog jQuery object of the dialog
|
477 |
+
* @param {object} oc jQuery object of the onchange wrapper
|
478 |
+
*/
|
479 |
+
setDialogTitle = function(dialog, oc){
|
480 |
+
dialog.dialog('option', 'title', 'CMW : ' + ( oc.find('.cmw-widget-title').val() || dialog.data().cmwUntitled ) + ' [' + oc.find('.cmw-select-menu').find('option:selected').text() + ']' );
|
481 |
+
},
|
482 |
+
/**
|
483 |
+
* creates a new list of menu items and inserts it into the dialog content in place of any previous one
|
484 |
+
* @param {object} dialog jQuery object of the dialog
|
485 |
+
*/
|
486 |
+
createMenu = function(dialog){
|
487 |
+
var oc = $(dialog.data().cmwOnchange),
|
488 |
+
menuid = parseInt(oc.find('.cmw-select-menu').val(), 10),
|
489 |
+
currentmenu = dialog.find('.cmw-demo-themenu-ul'),
|
490 |
+
trace = [],
|
491 |
+
maxLevel = 0,
|
492 |
+
menu = '',
|
493 |
+
outdentedExpander = function(x){
|
494 |
+
//x is the level of the *previous* item; so if previous item was at level 4, then its parent was at level 3, and
|
495 |
+
//was therefore indented twice (given that a level 1 item is not indented), so number of outdents is x - 2!
|
496 |
+
//each level is indented by 2.4em; subtract 2 from x and multiply by 2.4em, then add another 2em...
|
497 |
+
return x > 1 ? '<a href="#" class="' + widgetCustomMenuWizardClass('colexp') + ' ui-icon ui-icon-triangle-1-e" style="left:-' + (((x - 2) * 2.4) + 2) + 'em;"> </a>' : '';
|
498 |
+
};
|
499 |
+
if(!currentmenu.length || currentmenu.data('menuid') !== menuid){
|
500 |
+
oc.find('.cmw-assist-items optgroup').find('option').each(function(i){
|
501 |
+
var self = $(this),
|
502 |
+
level = self.data().cmwLevel;
|
503 |
+
while(level < trace.length){
|
504 |
+
menu += '</li></ul>' + outdentedExpander(trace.length);
|
505 |
+
trace.pop();
|
506 |
+
}
|
507 |
+
if(level > trace.length){
|
508 |
+
menu += '<ul>';
|
509 |
}else{
|
510 |
+
menu += '</li>';
|
511 |
+
trace.pop();
|
512 |
+
}
|
513 |
+
//data-level is 1-based, with 1 being root
|
514 |
+
//data-trace is the menu item ids of this item's ancestors, from root down to parent (inclusive)
|
515 |
+
menu += '<li class="level-' + level + '" data-itemid="' + this.value + '" data-level="' + level + '" data-trace="' + trace.join(',') + '">';
|
516 |
+
menu += '<a href="#" class="cmw-cross ui-corner-all"></a>';
|
517 |
+
menu += '<a class="cmw-item ui-corner-all" href="#" data-indx="' + i + '"><span class="ui-corner-all" title="#' + this.value + '">' + $.trim(self.text());
|
518 |
+
menu += '</span></a><a href="#" class="cmw-tick ui-corner-all"></a>';
|
519 |
+
trace.push(this.value);
|
520 |
+
if(level > maxLevel){
|
521 |
+
maxLevel = level;
|
522 |
}
|
523 |
+
});
|
524 |
+
while(trace.length){
|
525 |
+
menu += '</li></ul>' + outdentedExpander(trace.length);
|
526 |
+
trace.pop();
|
527 |
}
|
528 |
+
currentmenu.remove();
|
529 |
+
dialog.find('.cmw-demo-themenu')
|
530 |
+
.append( $(menu).addClass('cmw-demo-themenu-ul').data({maxLevel:maxLevel, menuid:menuid}) );
|
531 |
+
}
|
532 |
+
}, //end createMenu()
|
533 |
+
/**
|
534 |
+
* toggles the assist dialog open/closed, creating it if necessary
|
535 |
+
* @this {element} A The assist anchor
|
536 |
+
* @param {object} e Event object
|
537 |
+
* @return {boolean} false
|
538 |
+
*/
|
539 |
+
clickAssist = function(e){
|
540 |
+
var self = $(this),
|
541 |
+
oc = findOnchange(0, self),
|
542 |
+
data = oc.data(),
|
543 |
+
dialog = $( '#' + data.cmwDialogId );
|
544 |
+
if(!dialog.length){
|
545 |
+
dialog = createDialog(data).data({
|
546 |
+
cmwOnchange: '#' + oc.attr('id'),
|
547 |
+
cmwUntitled: '[' + data.cmwDialogUntitled + ']'
|
548 |
+
});
|
549 |
+
}
|
550 |
+
if(dialog.dialog('isOpen')){
|
551 |
+
dialog.dialog('close');
|
552 |
+
}else{
|
553 |
+
createMenu(dialog);
|
554 |
+
setDialogTitle(dialog, oc);
|
555 |
+
dialog.dialog('open');
|
556 |
+
assistance.call(oc[0]);
|
557 |
+
}
|
558 |
+
this.blur();
|
559 |
+
return false;
|
560 |
+
}; //end clickAssist()
|
561 |
+
|
562 |
+
/**
|
563 |
+
* The assist object, containing functions that do most of the version-specific work.
|
564 |
+
* There is a default set of functions, and any different legacy versions that are still
|
565 |
+
* supported should be under their own 'vNNN' object (eg. 'v210'). Which set of functions
|
566 |
+
* is called is determined by assistance(), which is the only entry point (into update()),
|
567 |
+
* and is governed by the widget form (specifically, the version property of the data
|
568 |
+
* attached to the -onchange wrapper).
|
569 |
+
*/
|
570 |
+
cmwAssist = {
|
571 |
+
/**
|
572 |
+
* sets any fields that are dependent on the selected menu
|
573 |
+
* @param {object} oc jQuery of the widget's onchange wrapper
|
574 |
+
* @param {integer} maxLevel Maximum level of the selected menu
|
575 |
+
*/
|
576 |
+
setLevels : function(oc, maxLevel){
|
577 |
+
if(!maxLevel){
|
578 |
+
return;
|
579 |
+
}
|
580 |
+
var theSelect = oc.find('.cmw-branch-start'),
|
581 |
+
level = theSelect.val();
|
582 |
+
theSelect.find('optgroup').each(function(i){
|
583 |
+
var self = $(this),
|
584 |
+
opts = self.find('option'),
|
585 |
+
ct = opts.length,
|
586 |
+
texts = self.data();
|
587 |
+
if(i){
|
588 |
+
//absolute...
|
589 |
+
opts.slice(maxLevel).remove();
|
590 |
+
while(ct < maxLevel){
|
591 |
+
++ct;
|
592 |
+
self.append( $('<option/>', {value:ct}).text(ct) );
|
593 |
}
|
594 |
+
}else{
|
595 |
+
//relative...
|
596 |
+
//if maxLevel is 1 : the item (1 option)
|
597 |
+
//if maxLevel is 2 : -1, the item, +1 (3 options)
|
598 |
+
//if maxLevel is 3 : -2, -1, the item, +1, +2 (5 options)
|
599 |
+
//etc, etc
|
600 |
+
ct = (ct + 1) / 2;
|
601 |
+
if(ct > maxLevel){
|
602 |
+
opts.each(function(i, el){
|
603 |
+
if(Math.abs(el.value) >= maxLevel){
|
604 |
+
$(el).remove();
|
605 |
+
}
|
606 |
+
});
|
607 |
}
|
608 |
+
while(ct < maxLevel){
|
609 |
+
self.prepend( $('<option/>', {value:-ct}).text(-ct + (ct > 1 ? '' : ' (' + texts.cmwTextParent + ')')) )
|
610 |
+
.append( $('<option/>', {value:'+' + ct}).text('+' + ct + (ct > 1 ? '' : ' (' + texts.cmwTextChildren + ')')) );
|
611 |
+
++ct;
|
612 |
}
|
613 |
+
}
|
614 |
+
});
|
615 |
+
//if level is absolute and > maxLevel, set to 1...
|
616 |
+
if(/^\d+$/.test(level)){
|
617 |
+
if(level > maxLevel){
|
618 |
+
theSelect.val('1');
|
619 |
+
}
|
620 |
+
//if level is relative, not 'the item', and absolutely >= maxLevel, set to '' (the item)...
|
621 |
+
}else if(level !== '' && Math.abs(level) >= maxLevel){
|
622 |
+
theSelect.val('');
|
623 |
+
}
|
624 |
+
|
625 |
+
oc.find('.cmw-ancestors,.cmw-ancestor-siblings').each(function(){
|
626 |
+
var self = $(this),
|
627 |
+
ct = (self.find('option').length + 1) / 2, //should never be below 2
|
628 |
+
v = self.val(),
|
629 |
+
minLevel = Math.max(2, maxLevel);
|
630 |
+
if(Math.abs(v) >= maxLevel){
|
631 |
+
self.val( v < 0 ? 1 - maxLevel : maxLevel - 1 );
|
632 |
+
}
|
633 |
+
if(ct !== minLevel){
|
634 |
+
self.find('optgroup').each(function(i, el){
|
635 |
+
var optgroup = $(el),
|
636 |
+
text = optgroup.data().cmwTextForOption,
|
637 |
+
j;
|
638 |
+
if(ct > minLevel){
|
639 |
+
optgroup.find('option').slice( minLevel - ct ).remove();
|
640 |
}
|
641 |
+
for(j = ct; j < minLevel; j++){
|
642 |
+
optgroup.append( $('<option/>', {value:i ? j : -j}).text( text.replace('%d', i ? j : -j) ) );
|
643 |
}
|
644 |
+
});
|
645 |
+
}
|
646 |
+
});
|
647 |
+
|
648 |
+
oc.find('.cmw-exclude-level').each(function(){
|
649 |
+
var self = $(this),
|
650 |
+
options = self.find('option'),
|
651 |
+
ct = (options.length - 1) / 3,
|
652 |
+
v = self.val(),
|
653 |
+
above = options.eq(2).text(),
|
654 |
+
below = options.eq(3).text();
|
655 |
+
options.slice( (maxLevel * 3) + 1 ).remove();
|
656 |
+
while(ct < maxLevel){
|
657 |
+
++ct;
|
658 |
+
self.append( $('<option/>', {value:ct}).text(ct) )
|
659 |
+
.append( $('<option/>', {value:ct + '-'}).text(above.replace(/\d+/, ct)) )
|
660 |
+
.append( $('<option/>', {value:ct + '+'}).text(below.replace(/\d+/, ct)) );
|
661 |
+
}
|
662 |
+
if(parseInt(v, 10) > maxLevel){
|
663 |
+
self.val('');
|
664 |
+
}
|
665 |
+
});
|
666 |
+
|
667 |
+
//do the easy levels...
|
668 |
+
oc.find('.cmw-level').each(function(){
|
669 |
+
var self = $(this),
|
670 |
+
ct = self.find('option').length;
|
671 |
+
if(self.val() > maxLevel){
|
672 |
+
self.val(1);
|
673 |
+
}
|
674 |
+
self.find('option').slice(maxLevel).remove();
|
675 |
+
while(ct < maxLevel){
|
676 |
+
++ct;
|
677 |
+
self.append( $('<option/>', {value:ct}).text(ct) );
|
678 |
+
}
|
679 |
+
});
|
680 |
+
oc.find('.cmw-depth,.cmw-fallback-depth').each(function(){
|
681 |
+
var self = $(this),
|
682 |
+
ct = self.find('option').length,
|
683 |
+
txt = ' ' + self.data().cmwTextLevels;
|
684 |
+
if(self.val() > maxLevel){
|
685 |
+
self.val(0);
|
686 |
+
}
|
687 |
+
self.find('option').slice(maxLevel + 1).remove();
|
688 |
+
while(ct <= maxLevel){
|
689 |
+
self.append( $('<option/>', {value:ct}).text(ct + txt) );
|
690 |
+
++ct;
|
691 |
+
}
|
692 |
+
});
|
693 |
+
}, //end cmwAssist.setLevels()
|
694 |
+
/**
|
695 |
+
* enables/disables fields and swaps selected menus
|
696 |
+
* @param {object} target jQuery of element responsible for 'change' event
|
697 |
+
* @param {object} oc jQuery of the widget's onchange wrapper
|
698 |
+
*/
|
699 |
+
setFields : function(target, oc){
|
700 |
+
var byBranchCheckbox = oc.find('.cmw-bybranch'),
|
701 |
+
byItems = oc.find('.cmw-byitems').prop('checked'),
|
702 |
+
notByBranch = byItems || !byBranchCheckbox.prop('checked'),
|
703 |
+
menuItems = oc.find('.cmw-assist-items'),
|
704 |
+
selectedItem = parseInt(menuItems.val(), 10);
|
705 |
+
//change of menu? : make sure the correct optgroup of menu items is used...
|
706 |
+
if(target.hasClass('cmw-select-menu')){
|
707 |
+
selectedItem = swapItems(menuItems, selectedItem, target[0].selectedIndex);
|
708 |
+
this.setLevels(oc, (menuItems.find('optgroup').data() || {}).cmwMaxLevel);
|
709 |
+
//if level is changed, switch to by-level filtering...
|
710 |
+
}else if(target.hasClass('cmw-level')){
|
711 |
+
notByBranch = true;
|
712 |
+
byItems = !notByBranch;
|
713 |
+
oc.find('.cmw-bylevel').prop('checked', notByBranch);
|
714 |
+
//if by-branch's branch is changed, switch to by-branch filtering...
|
715 |
+
}else if(target.is(menuItems)){
|
716 |
+
notByBranch = byItems = false;
|
717 |
+
byBranchCheckbox.prop('checked', !notByBranch);
|
718 |
+
//change of items?, switch to by-items filtering...
|
719 |
+
}else if(target.hasClass('cmw-setitems')){
|
720 |
+
byItems = true;
|
721 |
+
notByBranch = byItems;
|
722 |
+
oc.find('.cmw-byitems').prop('checked', byItems);
|
723 |
+
//if ancestors is cleared, clear ancestor siblings...
|
724 |
+
}else if(target.hasClass('cmw-ancestors') && target.val() === '0'){
|
725 |
+
oc.find('.cmw-ancestor-siblings').val('0');
|
726 |
+
//if include ancestor's siblings is changed to a value, and ancestors is empty, set ancestors from ancestor siblings...
|
727 |
+
}else if(target.hasClass('cmw-ancestor-siblings') && target.val() !== '0' && oc.find('.cmw-ancestors').val() === '0'){
|
728 |
+
oc.find('.cmw-ancestors').val( target.val() );
|
729 |
+
}
|
730 |
+
|
731 |
+
$.each( //disable if...
|
732 |
+
{ '-ss' : byItems, //...is Items
|
733 |
+
'-ud' : oc.find('.cmw-depth').val() < 1, //...is Unlimited Depth
|
734 |
+
'not-br' : notByBranch, //...is NOT Branch
|
735 |
+
'not-br-ci' : notByBranch || !!selectedItem, //...is NOT Branch:Current Item
|
736 |
+
'not-fb-pc' : !{'parent':1, 'current':1}[oc.find('.cmw-fallback').val()] //...is NOT fallback to parent or current
|
737 |
+
},
|
738 |
+
function(k, v){
|
739 |
+
oc.find('.cmw-disableif' + k).toggleClass('cmw-colour-grey', v).find('input,select').prop('disabled', v);
|
740 |
+
});
|
741 |
+
}, //end cmwAssist.setFields()
|
742 |
+
/**
|
743 |
+
* create and return the shortcode equivalent
|
744 |
+
* @param {object} settings Widget settings
|
745 |
+
* @return {string} Shortcode
|
746 |
+
*/
|
747 |
+
shortcode : function(settings){
|
748 |
+
var args = {
|
749 |
+
'menu' : settings.menu
|
750 |
+
},
|
751 |
+
byBranch = settings.filter === 'branch',
|
752 |
+
byItems = settings.filter === 'items',
|
753 |
+
byLevel = !byBranch && !byItems,
|
754 |
+
v, m, n;
|
755 |
+
//take notice of the widget's hide_title flag...
|
756 |
+
if(settings.title && !settings.hide_title){
|
757 |
+
args.title = [settings.title];
|
758 |
+
}
|
759 |
+
//byLevel is the default (no branch & no items), as is level=1, so we only *have* to specify level if it's greater than 1...
|
760 |
+
if(byLevel && settings.level > 1){
|
761 |
+
args.level = settings.level;
|
762 |
+
}
|
763 |
+
//specifying branch sets byBranch, overriding byLevel...
|
764 |
+
if(byBranch){
|
765 |
+
args.branch = settings.branch || 'current';
|
766 |
+
//start_at only *has* to be specified if not empty...
|
767 |
+
if(settings.branch_start){
|
768 |
+
args.start_at = [settings.branch_start];
|
769 |
+
}
|
770 |
+
//start_mode may be brought into play by a fallback so always specify it...
|
771 |
+
if(settings.start_mode === 'level'){
|
772 |
+
args.start_mode = 'level';
|
773 |
+
}
|
774 |
+
}
|
775 |
+
//specifying items set byItems, overriding byLevel & byBranch...
|
776 |
+
if(byItems){
|
777 |
+
args.items = [settings._items];
|
778 |
+
}
|
779 |
+
//depth if greater than 0...
|
780 |
+
if(settings.depth > 0){
|
781 |
+
args.depth = settings.depth;
|
782 |
+
}
|
783 |
+
//depth relative to current item is only applicable if depth is not unlimited...
|
784 |
+
if(settings.depth_rel_current && settings.depth > 0){
|
785 |
+
args.depth_rel_current = 1;
|
786 |
+
}
|
787 |
+
//fallbacks...
|
788 |
+
//no children : branch = current item...
|
789 |
+
if(byBranch && !settings.branch){
|
790 |
+
//format = quit|parent|current [,+siblings] [,depth] eg. "parent,+siblings,1" or "current,2" or "current,+siblings" or "parent" or "quit"
|
791 |
+
if(settings.fallback){
|
792 |
+
args.fallback = [settings.fallback];
|
793 |
+
if(settings.fallback !== 'quit'){
|
794 |
+
if(settings.fallback_siblings){
|
795 |
+
args.fallback.push('+siblings');
|
796 |
+
}
|
797 |
+
if(settings.fallback_depth){
|
798 |
+
args.fallback.push( settings.fallback_depth );
|
799 |
}
|
800 |
}
|
801 |
+
}
|
802 |
+
}
|
803 |
+
//branch ancestor inclusions...
|
804 |
+
if(byBranch && settings.ancestors){
|
805 |
+
args.ancestors = settings.ancestors;
|
806 |
+
if(settings.ancestor_siblings){
|
807 |
+
args.ancestor_siblings = settings.ancestor_siblings;
|
808 |
+
}
|
809 |
+
}
|
810 |
+
//exclusions by id...
|
811 |
+
if(settings._exclude){
|
812 |
+
args.exclude = [settings._exclude];
|
813 |
+
}
|
814 |
+
//...and by level...
|
815 |
+
if(settings.exclude_level){
|
816 |
+
args.exclude_level = [settings.exclude_level];
|
817 |
+
}
|
818 |
+
//title from...
|
819 |
+
n = [];
|
820 |
+
//...current and current root (in that order of priority) are exclusive...
|
821 |
+
if(settings.title_from_current){
|
822 |
+
n.push('current');
|
823 |
+
}else if(settings.title_from_current_root){
|
824 |
+
n.push('current-root');
|
825 |
+
}
|
826 |
+
//...branch and branch root (in that order of priority) are exclusive...
|
827 |
+
if(byBranch && settings.title_from_branch){
|
828 |
+
n.push('branch');
|
829 |
+
}else if(byBranch && settings.title_from_branch_root){
|
830 |
+
n.push('branch-root');
|
831 |
+
}
|
832 |
+
if(n.length){
|
833 |
+
args.title_from = n;
|
834 |
+
}
|
835 |
+
//switches...
|
836 |
+
for(n in {allow_all_root:1, siblings:1, include_root:1, flat_output:1, ol_root:1, ol_sub:1}){
|
837 |
+
if(settings[n]){
|
838 |
+
args[n] = 1;
|
839 |
+
}
|
840 |
+
}
|
841 |
+
//strings...
|
842 |
+
v = {contains_current:'', container:'div', container_id:'', container_class:'', menu_class:'menu-widget', widget_class:''};
|
843 |
+
for(n in v){
|
844 |
+
if(settings[n] !== v[n]){
|
845 |
+
args[n] = [settings[n]];
|
846 |
+
}
|
847 |
+
}
|
848 |
+
v = {wrap_link:'before', wrap_link_text:'link_before'};
|
849 |
+
for(n in v){
|
850 |
+
m = settings[v[n]].toString().match(/^<(\w+)/);
|
851 |
+
if(m && m[1]){
|
852 |
+
args[n] = [m[1]];
|
853 |
+
}
|
854 |
+
}
|
855 |
+
//build the shortcode...
|
856 |
+
v = [];
|
857 |
+
for(n in args){
|
858 |
+
//array indicates join (with comma sep) & surround it in double quotes, otherwise leave 'as-is'...
|
859 |
+
v.push( $.isArray(args[n]) ? n + '="' + args[n].join(',') + '"' : n + '=' + args[n] );
|
860 |
+
}
|
861 |
+
//NB at v3.0.0, the shortcode changed from custom_menu_wizard to cmwizard (the previous version is still supported)
|
862 |
+
return '[cmwizard ' + v.join(' ') + ']';
|
863 |
+
}, //end cmwAssist.shortcode()
|
864 |
+
/**
|
865 |
+
* updates the graphic menu structure from the widget data
|
866 |
+
* @param {element} el Element responsible for being here
|
867 |
+
*/
|
868 |
+
update : function(el){
|
869 |
+
var target = $(el),
|
870 |
+
oc = findOnchange(0, target),
|
871 |
+
dialog = $('#' + oc.data().cmwDialogId),
|
872 |
+
tobLevel = -1,
|
873 |
+
lastVisibleLevel = 9999,
|
874 |
+
hasIncl = 0,
|
875 |
+
hasExcl = 0,
|
876 |
+
fallback = '',
|
877 |
+
byLevel, byBranch, byItems, theBranchItem,
|
878 |
+
ciBranch, maxLevel, settings,
|
879 |
+
topOfMenu, items, exclusions,
|
880 |
+
local_depth, local_depth_rel_current,
|
881 |
+
currentItemLI, currentItemLevel, topOfBranch, i, j, k, x, y;
|
882 |
+
|
883 |
+
if(target.hasClass('cmw-listen')){
|
884 |
+
//the widget field that changed is likely to have an effect on other widget fields...
|
885 |
+
this.setFields(target, oc);
|
886 |
+
}
|
887 |
+
settings = getSettings(oc);
|
888 |
+
|
889 |
+
//dialog specific...
|
890 |
+
if(dialog.length && dialog.dialog('isOpen')){
|
891 |
+
|
892 |
+
dialog.dialog('moveToTop');
|
893 |
+
|
894 |
+
//if selected menu has changed, modify assist's structure...
|
895 |
+
if(target.hasClass('cmw-select-menu')){
|
896 |
+
createMenu(dialog);
|
897 |
+
}
|
898 |
+
byBranch = settings.filter === 'branch';
|
899 |
+
byItems = settings.filter === 'items';
|
900 |
+
byLevel = !byBranch && !byItems;
|
901 |
+
ciBranch = byBranch && !settings.branch;
|
902 |
+
topOfMenu = dialog.find('.cmw-demo-themenu-ul');
|
903 |
+
maxLevel = topOfMenu.data().maxLevel;
|
904 |
+
currentItemLI = topOfMenu.find('.current-menu-item').closest('li');
|
905 |
+
currentItemLevel = currentItemLI.length ? currentItemLI.data().level : -1;
|
906 |
+
items = topOfMenu.find('li').removeData('included').removeClass('title-from-item');
|
907 |
+
|
908 |
+
//don't want to alter settings at all (affects shortcode output), so create some local copies for use within this function...
|
909 |
+
local_depth = settings.depth;
|
910 |
+
local_depth_rel_current = settings.depth_rel_current;
|
911 |
+
|
912 |
+
//ticks and crosses (need to be run against the full set of items)...
|
913 |
+
exclusions = filterTickCross(items, settings, 'cross');
|
914 |
+
if(byItems){
|
915 |
+
//primary filter : items...
|
916 |
+
items = filterTickCross(items, settings, 'tick');
|
917 |
+
}
|
918 |
+
|
919 |
+
//if current item is definitely needed and is not present, cop out...
|
920 |
+
if(items.length && !currentItemLI.length && (!!settings.contains_current || ciBranch)){
|
921 |
+
items = $([]);
|
922 |
+
}
|
923 |
+
|
924 |
+
//primary filter : branch...
|
925 |
+
if(byBranch && items.length){
|
926 |
+
topOfBranch = ciBranch ? currentItemLI : items.filter('[data-itemid=' + settings.branch + ']');
|
927 |
+
if(topOfBranch.length){
|
928 |
+
tobLevel = topOfBranch.data().level || 0;
|
929 |
+
items = topOfBranch.add( topOfBranch.find('li') );
|
930 |
+
//since topOfBranch can change later on...
|
931 |
+
theBranchItem = topOfBranch;
|
932 |
+
}else{
|
933 |
+
items = $([]);
|
934 |
}
|
935 |
+
}
|
936 |
+
|
937 |
+
//primary filter : level...
|
938 |
+
if(byLevel && items.length && settings.level > 1){
|
939 |
+
for(i = 1, j = []; i < settings.level; i++){
|
940 |
+
j.push('.level-' + i);
|
941 |
}
|
942 |
+
items = items.not( j.join(',') );
|
943 |
+
}
|
944 |
+
|
945 |
+
//check for current item after primary...
|
946 |
+
if(settings.contains_current === 'primary' && items.length && !currentItemLI.is(items)){
|
947 |
+
items = $([]);
|
948 |
+
}
|
949 |
+
|
950 |
+
//secondary filter : level...
|
951 |
+
if(byLevel && items.length && local_depth){
|
952 |
+
i = local_depth_rel_current && currentItemLevel >= settings.level
|
953 |
+
//if the limited depth is relative to current item, and current item can be found at or below the start level...
|
954 |
+
? currentItemLevel
|
955 |
+
//set relative to start level...
|
956 |
+
: settings.level;
|
957 |
+
i += local_depth;
|
958 |
+
//note that i has been set to the first level *not* wanted!
|
959 |
+
if(i <= maxLevel){
|
960 |
+
for(j = []; i <= maxLevel; i++){
|
961 |
+
j.push('.level-' + i);
|
962 |
}
|
963 |
+
//filter to remove...
|
964 |
+
items = items.not( j.join(',') );
|
965 |
}
|
966 |
+
}
|
967 |
+
|
968 |
+
//secondary filter : branch...
|
969 |
+
if(byBranch && items.length){
|
970 |
+
//convert start level to integer...
|
971 |
+
j = parseInt(settings.branch_start, 10);
|
972 |
+
//convert relative to absolute (max'd against 1)...
|
973 |
+
j = isNaN(j) || !j ? tobLevel : (settings.branch_start.match(/^(\+|-)/) ? Math.max(1, tobLevel + j) : j);
|
974 |
+
|
975 |
+
//in order to be eligible for a no-kids fallback:
|
976 |
+
// - branch must be current item
|
977 |
+
// - fallback must be set
|
978 |
+
// - current item has no kids
|
979 |
+
if(ciBranch && settings.fallback && !currentItemLI.find('li').length){
|
980 |
+
//yes, we have a fallback situation...
|
981 |
+
fallback = 'cmw-fellback-to-' + settings.fallback;
|
982 |
+
if(settings.fallback === 'quit'){
|
983 |
+
//copout : just set secondary start level beyond maxLevel...
|
984 |
+
j = maxLevel + 1;
|
985 |
+
}else{
|
986 |
+
//for current, fall back to tob; for parent, fall back to tob - 1, ensuring that we don't fall back further than root...
|
987 |
+
j = settings.fallback === 'current' || tobLevel < 2 ? tobLevel : tobLevel - 1;
|
988 |
+
//if fallback depth is specified, override depth and set to relative-to-current...
|
989 |
+
if(settings.fallback_depth){
|
990 |
+
local_depth = settings.fallback_depth;
|
991 |
+
local_depth_rel_current = 1;
|
992 |
+
}
|
993 |
}
|
994 |
}
|
995 |
+
|
996 |
+
//j is the secondary start level, tobLevel is the primary level
|
997 |
+
//easy result : if j > maxLevel then there are no matches...
|
998 |
+
if(j > maxLevel){
|
999 |
+
items = $([]);
|
1000 |
+
}else{
|
1001 |
+
//if secondary start is higher up the structure than primary start, reset the tob...
|
1002 |
+
if(j < tobLevel){
|
1003 |
+
topOfBranch = topOfBranch.parentsUntil(topOfMenu, 'li.level-' + j);
|
1004 |
}
|
1005 |
+
//do we want (and need) to force starting with the entire level...
|
1006 |
+
// - only relevant if secondary start is at or above primary start
|
1007 |
+
// - and if secondary level is root then allow_all_root must be set
|
1008 |
+
if(settings.start_mode === 'level' && j <= tobLevel && (j > 1 || settings.allow_all_root)){
|
1009 |
+
//...reset items to eveything at tob's level, plus all their descendants...
|
1010 |
+
items = topOfBranch.parent().find('li');
|
1011 |
+
}else if(j < tobLevel){
|
1012 |
+
//tob has changed so reset items (to just tob and descendants)...
|
1013 |
+
items = topOfBranch.add( topOfBranch.find('li') );
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1014 |
}
|
1015 |
+
//if falling back and siblings are required, add them in...
|
1016 |
+
//note that root level sibling inclusion is still governed by allow_all_root!
|
1017 |
+
if(!!fallback && settings.fallback_siblings && items.length && (j > 1 || settings.allow_all_root)){
|
1018 |
+
items = items.add( topOfBranch.siblings('li.level-' + j) );
|
1019 |
}
|
1020 |
+
}
|
1021 |
+
//may have a tob but might not have any items!...
|
1022 |
+
if(items.length){
|
1023 |
+
//reset tob level (regardless of whether tob has changed)...
|
1024 |
+
tobLevel = j;
|
1025 |
+
//is depth unlimited?...
|
1026 |
+
k = 9999;
|
1027 |
+
if(local_depth){
|
1028 |
+
//is (limited) depth relative to current item, and is there an eligible current item to measure against?...
|
1029 |
+
k = local_depth_rel_current && currentItemLevel >= tobLevel && items.filter(currentItemLI).length
|
1030 |
+
? currentItemLevel
|
1031 |
+
: tobLevel;
|
1032 |
+
k += local_depth;
|
1033 |
+
lastVisibleLevel = k - 1;
|
1034 |
}
|
1035 |
+
//note that k has been set to the first level (after those wanted) that is *not* wanted!
|
1036 |
+
for(i = 1, j = []; i <= maxLevel; i++){
|
1037 |
+
if(i >= tobLevel && i < k){
|
1038 |
+
j.push('.level-' + i);
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1039 |
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1040 |
}
|
1041 |
+
//filter to keep...
|
1042 |
+
items = items.filter( j.join(',') );
|
1043 |
}
|
1044 |
+
}
|
1045 |
|
1046 |
+
//check for current item after secondary...
|
1047 |
+
if(settings.contains_current === 'secondary' && items.length && !currentItemLI.is(items)){
|
1048 |
+
items = $([]);
|
1049 |
+
}
|
1050 |
|
1051 |
+
//branch inclusions...
|
1052 |
+
if(byBranch && items.length){
|
1053 |
+
//branch ancestors, possibly with their siblings : but only if the original branch item is either
|
1054 |
+
//in items or is below lastVisibleLevel; ALSO, do not show ancestors below lastVisibleLevel!
|
1055 |
+
j = theBranchItem.data().level;
|
1056 |
+
if(settings.ancestors && (theBranchItem.is(items) || j > lastVisibleLevel)){
|
1057 |
+
x = settings.ancestors;
|
1058 |
+
//convert a relative level to an absolute one...
|
1059 |
+
if(x < 0){
|
1060 |
+
x = Math.max(1, j + x);
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1061 |
}
|
1062 |
+
//ancestor siblings?...
|
1063 |
+
y = settings.ancestor_siblings;
|
1064 |
+
//convert a relative level to an absolute one...
|
1065 |
+
if(y < 0){
|
1066 |
+
y = Math.max(1, j + y);
|
1067 |
+
}
|
1068 |
+
//get the level classes for ancestors and siblings that need to be included...
|
1069 |
+
for(i = x, j = [], k = []; i <= maxLevel; i++){
|
1070 |
+
if(i <= lastVisibleLevel){
|
1071 |
+
//ancestors...
|
1072 |
+
j.push('.level-' + i);
|
1073 |
+
if(y > 0 && i >= y){
|
1074 |
+
//siblings...
|
1075 |
+
k.push('.level-' + i);
|
1076 |
}
|
1077 |
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1078 |
}
|
1079 |
+
//store current length of items...
|
1080 |
+
x = items.length;
|
1081 |
+
//find the ancestors...
|
1082 |
+
j = theBranchItem.parentsUntil(topOfMenu, j.join(','));
|
1083 |
+
//add new ones into items...
|
1084 |
+
items = items.add( j.not(items).data('included', ' cmw-an-included-ancestor') );
|
1085 |
+
//got ancestors, now what about their siblings?...
|
1086 |
+
if(k.length){
|
1087 |
+
//filter ancestors for those we want siblings of, and add new siblings into items...
|
1088 |
+
items = items.add( j.filter( k.join(',') ).siblings('li').not(items).data('included', ' cmw-an-included-ancestor-sibling') );
|
1089 |
+
}
|
1090 |
+
//note how many have been added to items as a result of the includes...
|
1091 |
+
hasIncl += items.length - x;
|
1092 |
+
}
|
1093 |
+
//branch siblings : only if the original branch item is currently in items...
|
1094 |
+
if(settings.siblings && theBranchItem.is(items)){
|
1095 |
+
j = items.length;
|
1096 |
+
items = items.add( theBranchItem.siblings('li').data('included', ' cmw-an-included-sibling') );
|
1097 |
+
hasIncl += items.length - j;
|
1098 |
}
|
1099 |
+
}
|
1100 |
+
//other inclusions...
|
1101 |
+
if(items.length && settings.include_root){
|
1102 |
+
j = items.length;
|
1103 |
+
items = items.add( topOfMenu.find('.level-1') );
|
1104 |
+
hasIncl += items.length - j;
|
1105 |
+
}
|
1106 |
|
1107 |
+
//check for current item after inclusions...
|
1108 |
+
if(settings.contains_current === 'inclusions' && items.length && !currentItemLI.is(items)){
|
1109 |
+
items = $([]);
|
1110 |
+
}
|
1111 |
+
|
1112 |
+
//exclusions...
|
1113 |
+
if(items.length && exclusions.length){
|
1114 |
+
j = items.length;
|
1115 |
+
items = items.not(exclusions);
|
1116 |
+
hasExcl += j - items.length;
|
1117 |
+
}
|
1118 |
+
if(items.length && !!settings.exclude_level){
|
1119 |
+
k = settings.exclude_level.match(/^(\d+)(\+|-)?$/);
|
1120 |
+
k = k ? [parseInt(k[1], 10), k[2] || ''] : [];
|
1121 |
+
if(k[0] > 0){
|
1122 |
+
for(j = [], i = 1; i <= maxLevel; i++){
|
1123 |
+
if( i === k[0] || (k[1] === '-' && i < k[0]) || (k[1] === '+' && i > k[0]) ){
|
1124 |
+
j.push('.level-' + i);
|
1125 |
}
|
1126 |
}
|
1127 |
+
if(j.length){
|
1128 |
+
//filter to remove...
|
1129 |
+
k = items.length;
|
1130 |
+
items = items.not( j.join(',') );
|
1131 |
+
hasExcl += k - items.length;
|
1132 |
+
}
|
1133 |
}
|
1134 |
+
}
|
1135 |
|
1136 |
+
//final check for current item in output...
|
1137 |
+
if(settings.contains_current === 'output' && items.length && !currentItemLI.is(items)){
|
1138 |
+
items = $([]);
|
1139 |
+
}
|
1140 |
|
1141 |
+
//title from...
|
1142 |
+
//...check current then current root...
|
1143 |
+
if(settings.title_from_current && currentItemLI.length){
|
1144 |
+
currentItemLI.addClass('title-from-item');
|
1145 |
+
}else if(settings.title_from_current_root && currentItemLI.length){
|
1146 |
+
currentItemLI.closest('.level-1').addClass('title-from-item');
|
1147 |
+
}else if(byBranch && theBranchItem){
|
1148 |
+
//...then branch, then branch root...
|
1149 |
+
if(settings.title_from_branch){
|
1150 |
+
theBranchItem.addClass('title-from-item');
|
1151 |
+
}else if(settings.title_from_branch_root){
|
1152 |
+
theBranchItem.closest('.level-1').addClass('title-from-item');
|
1153 |
}
|
|
|
|
|
|
|
|
|
|
|
1154 |
}
|
|
|
1155 |
|
1156 |
+
//show/hide the fall back message...
|
1157 |
+
dialog.find('.cmw-demo-fallback').data('fellback', fallback).toggleClass('updated', !!fallback);
|
1158 |
+
//show/hide the 'select current item' prompt...
|
1159 |
+
dialog.find('.cmw-demo-setcurrent').toggleClass('error', !currentItemLI.length && (settings.contains_current || ciBranch));
|
1160 |
+
//...and the inclusions/exclusions messages...
|
1161 |
+
i = {inclusions:hasIncl, exclusions:hasExcl};
|
1162 |
+
for(j in i){
|
1163 |
+
k = dialog.find('.cmw-demo-' + j);
|
1164 |
+
k.text( k.text().replace(/\d+$/, i[j]) ).toggleClass('updated', i[j] > 0);
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1165 |
}
|
1166 |
+
|
1167 |
+
//toggle ticks and 'pick' the remaining items...
|
1168 |
+
topOfMenu.toggleClass('cmw-demo-filteritems', byItems)
|
1169 |
+
.find('.picked').not( items.addClass('picked') ).removeClass('picked');
|
1170 |
+
//produce output...
|
1171 |
+
setDialogTitle(dialog, oc);
|
1172 |
+
showOutput(dialog, settings);
|
1173 |
+
|
1174 |
+
} //end dialog specific
|
1175 |
+
|
1176 |
+
oc.add(dialog).find('code').text( this.shortcode( settings ) );
|
1177 |
+
|
1178 |
+
} //end cmwAssist.update()
|
1179 |
+
}; //end cmwAssist
|
1180 |
+
|
1181 |
+
/**
|
1182 |
+
* pre-v3.0.0 version
|
1183 |
+
*/
|
1184 |
+
cmwAssist.v210 = {
|
1185 |
+
/**
|
1186 |
+
* sets any fields that are dependent on the selected menu
|
1187 |
+
* @param {object} oc jQuery of the widget's onchange wrapper
|
1188 |
+
* @param {integer} maxLevel Maximum level of the selected menu
|
1189 |
+
*/
|
1190 |
+
setLevels : function(oc, maxLevel){
|
1191 |
+
var theSelect = oc.find('.cmw-start-level'),
|
1192 |
+
level = theSelect.val(),
|
1193 |
+
ct = theSelect.find('option').length,
|
1194 |
+
txt;
|
1195 |
+
if(level > maxLevel){
|
1196 |
+
theSelect.val(1);
|
1197 |
+
}
|
1198 |
+
theSelect.find('option').slice(maxLevel).remove();
|
1199 |
+
while(ct < maxLevel){
|
1200 |
+
++ct;
|
1201 |
+
theSelect.append( $('<option/>', {value:ct}).text(ct) );
|
1202 |
+
}
|
1203 |
+
theSelect = oc.find('.cmw-depth');
|
1204 |
+
level = theSelect.val();
|
1205 |
+
ct = theSelect.find('option').length;
|
1206 |
+
txt = ' ' + theSelect.data().cmwTextLevels;
|
1207 |
+
if(level > maxLevel){
|
1208 |
+
theSelect.val(0); //=unlimited
|
1209 |
+
}
|
1210 |
+
theSelect.find('option').slice(maxLevel + 1).remove();
|
1211 |
+
while(ct <= maxLevel){
|
1212 |
+
theSelect.append( $('<option/>', {value:ct}).text(ct + txt) );
|
1213 |
+
++ct;
|
1214 |
+
}
|
1215 |
+
}, //end cmwAssist.v210.setLevels()
|
1216 |
+
/**
|
1217 |
+
* enables/disables fields and swaps selected menus
|
1218 |
+
* @param {object} target jQuery of element responsible for 'change' event
|
1219 |
+
* @param {object} oc jQuery of the widget's onchange wrapper
|
1220 |
+
*/
|
1221 |
+
setFields : function(target, oc){
|
1222 |
+
var showAll = oc.find('.cmw-showall').prop('checked'),
|
1223 |
+
showSpecific = oc.find('.cmw-showspecific').prop('checked'),
|
1224 |
+
menuItems = oc.find('.cmw-assist-items'),
|
1225 |
+
selectedItem = parseInt(menuItems.val(), 10);
|
1226 |
+
//change of menu? : make sure the correct optgroup of menu items is used...
|
1227 |
+
if(target.hasClass('cmw-select-menu')){
|
1228 |
+
selectedItem = swapItems(menuItems, selectedItem, target[0].selectedIndex);
|
1229 |
+
this.setLevels(oc, (menuItems.find('optgroup').data() || {}).cmwMaxLevel);
|
1230 |
}
|
1231 |
$.each(
|
1232 |
{ '' : showAll || showSpecific,
|
1233 |
'-ss' : showSpecific,
|
1234 |
+
'not-rp' : showAll || showSpecific || selectedItem >= 0,
|
1235 |
+
'not-ci' : showAll || showSpecific || !!selectedItem
|
1236 |
},
|
1237 |
function(k, v){
|
1238 |
+
oc.find('.cmw-disableif' + k).toggleClass('cmw-colour-grey', v).find('input,select').prop('disabled', v);
|
1239 |
});
|
1240 |
+
}, //end cmwAssist.v210.setFields()
|
1241 |
+
/**
|
1242 |
+
* create and return the shortcode equivalent
|
1243 |
+
* @param {object} settings Widget settings
|
1244 |
+
* @return {string} Shortcode
|
1245 |
+
*/
|
1246 |
+
shortcode : function(settings){
|
1247 |
+
var args = {
|
1248 |
+
'menu' : settings.menu
|
1249 |
+
},
|
1250 |
+
byLevel = !settings.filter,
|
1251 |
+
byBranch = settings.filter > 0,
|
1252 |
+
byItems = !byLevel && !byBranch,
|
1253 |
+
v, m, n;
|
1254 |
+
if(settings.title){
|
1255 |
+
args.title = [settings.title];
|
1256 |
+
}
|
1257 |
+
if(byBranch){
|
1258 |
+
switch(settings.filter_item){
|
1259 |
+
case 0: args.children_of = ['current']; break;
|
1260 |
+
case -1: args.children_of = ['parent']; break;
|
1261 |
+
case -2: args.children_of = ['root']; break;
|
1262 |
+
default:
|
1263 |
+
args.children_of = settings.filter_item;
|
1264 |
}
|
1265 |
+
}
|
1266 |
+
if(byItems){
|
1267 |
+
args.items = [settings._items];
|
1268 |
+
}
|
1269 |
+
if(byBranch && settings.filter_item < 0 && settings.fallback_no_ancestor){
|
1270 |
+
if(settings.fallback_include_parent_siblings){
|
1271 |
+
args.fallback_parent = ['siblings'];
|
1272 |
+
}else if(settings.fallback_include_parent){
|
1273 |
+
args.fallback_parent = ['parent'];
|
1274 |
+
}else{
|
1275 |
+
args.fallback_parent = 1;
|
1276 |
}
|
1277 |
+
}
|
1278 |
+
if(byBranch && !settings.filter_item && settings.fallback_no_children){
|
1279 |
+
if(settings.fallback_nc_include_parent_siblings){
|
1280 |
+
args.fallback_current = ['siblings'];
|
1281 |
+
}else if(settings.fallback_nc_include_parent){
|
1282 |
+
args.fallback_current = ['parent'];
|
1283 |
+
}else{
|
1284 |
+
args.fallback_current = 1;
|
1285 |
+
}
|
1286 |
+
}
|
1287 |
+
if(settings.start_level > 1){
|
1288 |
+
args.start_level = settings.start_level;
|
1289 |
+
}
|
1290 |
+
if(settings.depth > 0){
|
1291 |
+
args.depth = settings.depth;
|
1292 |
+
}
|
1293 |
+
//depth relative to current item is only applicable if depth is not unlimited...
|
1294 |
+
if(settings.depth_rel_current && settings.depth > 0){
|
1295 |
+
args.depth_rel_current = 1;
|
1296 |
+
}
|
1297 |
+
n = [];
|
1298 |
+
if(byBranch){
|
1299 |
+
if(settings.include_parent_siblings){
|
1300 |
+
n.push('siblings');
|
1301 |
+
}else if(settings.include_parent){
|
1302 |
+
n.push('parent');
|
1303 |
+
}
|
1304 |
+
if(settings.include_ancestors){
|
1305 |
+
n.push('ancestors');
|
1306 |
+
}
|
1307 |
+
if(n.length){
|
1308 |
+
args.include = n;
|
1309 |
+
}
|
1310 |
+
}
|
1311 |
+
n = [];
|
1312 |
+
if(byBranch && settings.title_from_parent){
|
1313 |
+
n.push('parent');
|
1314 |
+
}
|
1315 |
+
if(settings.title_from_current){
|
1316 |
+
n.push('current');
|
1317 |
+
}
|
1318 |
+
if(n.length){
|
1319 |
+
args.title_from = n;
|
1320 |
+
}
|
1321 |
+
for(n in {flat_output:1, contains_current:1, ol_root:1, ol_sub:1}){
|
1322 |
+
if(settings[n]){
|
1323 |
+
args[n] = 1;
|
1324 |
+
}
|
1325 |
+
}
|
1326 |
+
v = {container:'div', container_id:'', container_class:'', menu_class:'menu-widget', widget_class:''};
|
1327 |
+
for(n in v){
|
1328 |
+
if(settings[n] !== v[n]){
|
1329 |
+
args[n] = [settings[n]];
|
1330 |
+
}
|
1331 |
+
}
|
1332 |
+
v = {wrap_link:'before', wrap_link_text:'link_before'};
|
1333 |
+
for(n in v){
|
1334 |
+
m = settings[v[n]].toString().match(/^<(\w+)/);
|
1335 |
+
if(m && m[1]){
|
1336 |
+
args[n] = [m[1]];
|
1337 |
+
}
|
1338 |
+
}
|
1339 |
+
v = [];
|
1340 |
+
for(n in args){
|
1341 |
+
//array indicates join (with space sep) & surround it in double quotes, otherwise leave 'as-is'...
|
1342 |
+
v.push( $.isArray(args[n]) ? n + '="' + args[n].join(' ') + '"' : n + '=' + args[n] );
|
1343 |
+
}
|
1344 |
+
return '[custom_menu_wizard ' + v.join(' ') + ']';
|
1345 |
+
}, //end cmwAssist.v210.shortcode()
|
1346 |
+
/**
|
1347 |
+
* updates the graphic menu structure from the widget data
|
1348 |
+
* @param {element} el Element responsible for being here
|
1349 |
+
*/
|
1350 |
+
update : function(el){
|
1351 |
+
var target = $(el),
|
1352 |
+
oc = findOnchange(0, target),
|
1353 |
+
dialog = $('#' + oc.data().cmwDialogId),
|
1354 |
+
byLevel, byBranch, byItems,
|
1355 |
+
maxLevel, settings, includeParent, includeParentSiblings, topOfMenu, items,
|
1356 |
+
currentItemLI, currentItemLevel, fallback, parent, i, j;
|
1357 |
+
|
1358 |
+
if(target.hasClass('cmw-listen')){
|
1359 |
+
//the widget field that changed is likely to have an effect on other widget fields...
|
1360 |
+
this.setFields(target, oc);
|
1361 |
+
}
|
1362 |
+
|
1363 |
+
//everything below this point is dialogue-related...
|
1364 |
+
if(!dialog.length || !dialog.dialog('isOpen')){
|
1365 |
+
return;
|
1366 |
+
}
|
1367 |
+
dialog.dialog('moveToTop');
|
1368 |
+
|
1369 |
+
//if selected menu has changed, modify assist's structure...
|
1370 |
+
if(target.hasClass('cmw-select-menu')){
|
1371 |
+
createMenu(dialog);
|
1372 |
+
}
|
1373 |
+
settings = getSettings(oc);
|
1374 |
+
byLevel = !settings.filter;
|
1375 |
+
byBranch = settings.filter > 0;
|
1376 |
+
byItems = !byLevel && !byBranch;
|
1377 |
+
includeParent = settings.include_parent;
|
1378 |
+
includeParentSiblings = settings.include_parent_siblings;
|
1379 |
+
topOfMenu = dialog.find('.cmw-demo-themenu-ul');
|
1380 |
+
maxLevel = topOfMenu.data().maxLevel;
|
1381 |
+
currentItemLI = topOfMenu.find('.current-menu-item').closest('li');
|
1382 |
+
currentItemLevel = currentItemLI.length ? currentItemLI.data().level : -1;
|
1383 |
+
items = topOfMenu.find('li').removeData('included').removeClass('title-from-item');
|
1384 |
+
|
1385 |
+
if(byItems){
|
1386 |
+
items = filterTickCross(items, settings, 'tick');
|
1387 |
+
}
|
1388 |
+
|
1389 |
+
if(items.length && !currentItemLI.length && (settings.contains_current || (byBranch && settings.filter_item < 1))){
|
1390 |
+
items = $([]);
|
1391 |
+
}
|
1392 |
+
|
1393 |
+
if(items.length && byBranch){
|
1394 |
+
//kids of...
|
1395 |
+
if(settings.filter_item > 0){
|
1396 |
+
//specific item...
|
1397 |
+
parent = items.filter('[data-itemid=' + settings.filter_item + ']');
|
1398 |
+
}else if(!settings.filter_item){
|
1399 |
+
//current...
|
1400 |
+
if(currentItemLI.find('li').length){
|
1401 |
+
parent = currentItemLI;
|
1402 |
+
}else if(settings.fallback_no_children){
|
1403 |
+
//fall back to current parent...
|
1404 |
+
parent = topOfMenu.find('.current-menu-parent').closest('li');
|
1405 |
+
if(!parent.length){
|
1406 |
+
parent = topOfMenu; //beware!
|
1407 |
+
}
|
1408 |
+
includeParent = includeParent || settings.fallback_nc_include_parent;
|
1409 |
+
includeParentSiblings = includeParentSiblings || settings.fallback_nc_include_parent_siblings;
|
1410 |
+
fallback = 'cmw-fellback-to-parent';
|
1411 |
+
}
|
1412 |
+
}else{
|
1413 |
+
//parent or root...
|
1414 |
+
if(currentItemLevel === 1 && settings.fallback_no_ancestor){
|
1415 |
+
parent = currentItemLI;
|
1416 |
+
includeParent = includeParent || settings.fallback_include_parent;
|
1417 |
+
includeParentSiblings = includeParentSiblings || settings.fallback_include_parent_siblings;
|
1418 |
+
fallback = 'cmw-fellback-to-current';
|
1419 |
+
}else if(currentItemLevel === 1){
|
1420 |
+
parent = topOfMenu; //beware!
|
1421 |
+
}else if(settings.filter_item < -1){
|
1422 |
+
parent = topOfMenu.find('.current-menu-ancestor').eq(0).closest('li');
|
1423 |
+
}else{
|
1424 |
+
parent = topOfMenu.find('.current-menu-parent').closest('li');
|
1425 |
+
}
|
1426 |
+
}
|
1427 |
+
}
|
1428 |
+
|
1429 |
+
if(items.length){
|
1430 |
+
if(byLevel){
|
1431 |
+
//showall : use the levels...
|
1432 |
+
if(settings.depth_rel_current && settings.depth && currentItemLI.length && currentItemLevel >= settings.start_level){
|
1433 |
+
j = currentItemLevel + settings.depth - 1;
|
1434 |
+
}else{
|
1435 |
+
j = settings.depth ? settings.start_level + settings.depth - 1 : 9999;
|
1436 |
+
}
|
1437 |
+
for(i = 1; i <= maxLevel; i++){
|
1438 |
+
if(i < settings.start_level || i > j){
|
1439 |
+
items = items.not('.level-' + i);
|
1440 |
+
}
|
1441 |
+
}
|
1442 |
+
}else if(parent && parent.length){
|
1443 |
+
//kids of...
|
1444 |
+
if(settings.depth_rel_current && settings.depth && currentItemLI.length && parent.has(currentItemLI[0]).length){
|
1445 |
+
j = currentItemLevel - 1 + settings.depth;
|
1446 |
+
}else{
|
1447 |
+
j = settings.depth ? Math.max( (parent.data().level || 0) + settings.depth, settings.start_level + settings.depth - 1 ) : 9999;
|
1448 |
+
}
|
1449 |
+
items = parent.find('li').filter(function(){
|
1450 |
+
var level = $(this).data().level;
|
1451 |
+
return level >= settings.start_level && level <= j;
|
1452 |
+
});
|
1453 |
+
}else if(byBranch){
|
1454 |
+
//kids-of, but no parent found...
|
1455 |
+
items = $([]);
|
1456 |
+
}
|
1457 |
+
}
|
1458 |
+
|
1459 |
+
if(items.length){
|
1460 |
+
if(byBranch && parent && parent.is('li')){
|
1461 |
+
//kids of an item...
|
1462 |
+
if(includeParentSiblings){
|
1463 |
+
items = items.add( parent.siblings('li').data('included', ' cmw-an-included-parent-sibling') );
|
1464 |
+
includeParent = true;
|
1465 |
+
}
|
1466 |
+
if(settings.include_ancestors){
|
1467 |
+
items = items.add( parent.parentsUntil(topOfMenu, 'li').data('included', ' cmw-an-included-ancestor') );
|
1468 |
+
includeParent = true;
|
1469 |
+
}
|
1470 |
+
if(includeParent){
|
1471 |
+
items = items.add( parent.data('included', ' cmw-the-included-parent') );
|
1472 |
+
}
|
1473 |
+
}
|
1474 |
+
}
|
1475 |
+
|
1476 |
+
//must contain current item?...
|
1477 |
+
if(items.length && settings.contains_current && (!currentItemLI.length || !items.filter(currentItemLI).length)){
|
1478 |
+
items = $([]);
|
1479 |
+
}
|
1480 |
+
|
1481 |
+
//title from parent has higher priority than title from current...
|
1482 |
+
if(settings.title_from_parent && items.length && parent && parent.is('li')){
|
1483 |
+
parent.addClass('title-from-item');
|
1484 |
+
}else if(settings.title_from_current && items.length){
|
1485 |
+
currentItemLI.addClass('title-from-item');
|
1486 |
+
}
|
1487 |
+
//fallback?...
|
1488 |
+
fallback = items.length ? fallback : '';
|
1489 |
+
dialog.find('.cmw-demo-fallback').data('fellback', fallback).toggleClass('updated', !!fallback);
|
1490 |
+
//show/hide the 'select current item' prompt...
|
1491 |
+
dialog.find('.cmw-demo-setcurrent').toggleClass('error', !currentItemLI.length && (settings.contains_current || (byBranch && settings.filter_item < 1)));
|
1492 |
+
|
1493 |
+
//toggle ticks and 'pick' the remaining items...
|
1494 |
+
topOfMenu.toggleClass('cmw-demo-filteritems', byItems)
|
1495 |
+
.find('.picked').not( items.addClass('picked') ).removeClass('picked');
|
1496 |
+
//produce output...
|
1497 |
+
setDialogTitle(dialog, oc);
|
1498 |
+
showOutput(dialog, settings);
|
1499 |
+
dialog.find('code').text( this.shortcode(settings) );
|
1500 |
+
} //end cmwAssist.v210.update()
|
1501 |
+
}; //end cmwAssist.v210
|
1502 |
+
|
1503 |
+
$(document)
|
1504 |
+
//any change event on widget's inputs or selects...
|
1505 |
+
.on('change', widgetCustomMenuWizardClass('onchange', 1), assistance)
|
1506 |
+
//open/close assist dialog...
|
1507 |
+
.on('click', widgetCustomMenuWizardClass('assist', 1), clickAssist)
|
1508 |
+
//expand/collapse fieldsets...
|
1509 |
+
.on('click', widgetCustomMenuWizardClass('fieldset', 1), clickFieldset)
|
1510 |
+
//when a widget is closed, close its open dialog...
|
1511 |
+
.on('click', '.widget-action,.widget-control-close', closeDialog)
|
1512 |
+
//when a widget is deleted, remove its dialog...
|
1513 |
+
.on('click', '.widget-control-remove', removeDialog)
|
1514 |
+
//collapse/expand assist menu tree items...
|
1515 |
+
.on('click', widgetCustomMenuWizardClass('colexp', 1), clickTreeExpander)
|
1516 |
+
//find posts containing shortcodes by ajax...
|
1517 |
+
.on('click', widgetCustomMenuWizardClass('find-shortcodes', 1), clickFindShortcodes)
|
1518 |
+
//remove the legacy warning...
|
1519 |
+
.on('click', widgetCustomMenuWizardClass('legacy-close', 1), function(){
|
1520 |
+
$(this).parent().remove();
|
1521 |
+
return false;
|
1522 |
});
|
1523 |
|
1524 |
});
|
@@ -1,28 +1,52 @@
|
|
1 |
-
/*
|
2 |
-
*
|
3 |
-
*
|
4 |
-
*
|
5 |
-
*
|
6 |
-
|
7 |
-
|
8 |
-
|
9 |
-
|
10 |
-
|
11 |
-
|
12 |
-
|
13 |
-
|
14 |
-
|
15 |
-
a.
|
16 |
-
"
|
17 |
-
|
18 |
-
|
19 |
-
|
20 |
-
|
21 |
-
|
22 |
-
|
23 |
-
|
24 |
-
|
25 |
-
|
26 |
-
|
27 |
-
|
28 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
/*Source: custom-menu-wizard.js
|
2 |
+
*Compiled: 2014-06-13, Google Closure Compiler...
|
3 |
+
*STATISTICS
|
4 |
+
* - originalSize: 61388
|
5 |
+
* - originalGzipSize: 15232
|
6 |
+
* - compressedSize: 22367
|
7 |
+
* - compressedGzipSize: 7096
|
8 |
+
*/
|
9 |
+
jQuery(function(f){var z,y=function(a,b){return(b?".":"")+"widget-custom-menu-wizard-"+a},D=function(a){var b=f(this).data().cmwDialogVersion.replace(/\./g,""),b=/^\d+$/.test(b)?"v"+b:b;z[b]?z[b].update(a?a.target:this):z.update(a?a.target:this)},E=function(a,b,d){var c="tick"===d?b._items_sep:b._exclude_sep,g=[],l="tick"===d?"_items":"_exclude",l=b[l]?f.grep(b[l].split(c),function(b){return/\+$/.test(b)?(g.push(parseInt(b,10)),!b):!!b}):[],l=c+l.join(c)+c,g=c+g.join(c)+c;a=a.each(function(){var b=
|
10 |
+
f(this),a=b.data(),s=-1<g.indexOf(c+a.itemid+c),a=s||-1<l.indexOf(c+a.itemid+c);b.toggleClass("cmw-has-"+d,a).toggleClass("cmw-inherit-"+d,s)});return a.filter(".cmw-inherit-"+d).find("li").removeClass("cmw-has-"+d+" cmw-inherit-"+d).add(a.filter(".cmw-has-"+d))},B=function(a,b){return(a?a:b)[a?"find":"closest"](y("onchange",1))},H=function(a){var b={},d="2.1.0"===a.data("cmwDialogVersion"),c={items:1,exclude:1},g=f.extend({branch_start:1,exclude_level:1},c);f.each(a.find(":input").serializeArray(),
|
11 |
+
function(l,e){var k=e.name.replace(/.*\[([^\]]+)\]$/,"$1"),s=!g[k]&&/^-?\d+$/.test(e.value)?parseInt(e.value,10):e.value;b[k]=s;"hide_empty"===k?b[k]=!!a.data().cmwV36plus||s:c[k]&&(b["_"+k+"_sep"]=!s||/(^\d+\+?$|,)/.test(f.trim(s))?",":" ",s=f.map(s.split(/[,\s]+/),function(b){var a=!d&&/\+$/.test(b);b=b?parseInt(b,10):0;return isNaN(b)||1>b?null:a?b+"+":b}),b["_"+k]=s.join(b["_"+k+"_sep"]))});return b},I=function(a,b){var d=a.find(".cmw-demo-themenu-ul"),c=d.find(".picked"),g="",l=b.hide_title?
|
12 |
+
"":b.title,e=0,k=a.find(".cmw-demo-theoutput-wrap").empty(),s=["menu-widget"],u={};if(c.length&&k.length){(l=d.find(".title-from-item").children(".cmw-item").text()||"")||b.hide_title||(l=b.title||"");for(c.each(function(a){var c=f(this),d=c.data(),l=d.trace?d.trace.toString().split(","):[];a=d.itemid.toString();var k=1,c=c.children(".cmw-item");if(!b.flat_output)for(u[a]=1,a=0;a<l.length;a++)u[l[a]]&&k++;if(e)if(k>e)g+=b.ol_sub?"<ol>":"<ul>";else{for(;e>k;)--e,g+="</li>"+(b.ol_sub?"</ol>":"</ul>");
|
13 |
+
g+="</li>"}g+='<li class="cmw-level-'+k+(d.included||"")+'"><a href="#'+c.data("indx")+'">'+c.text()+"</a>";e=k});1<e;)--e,g+="</li>"+(b.ol_sub?"</ol>":"</ul>");g+="</li>";s.push(a.find(".cmw-demo-fallback").data("fellback"));g=(b.ol_root?"<ol":"<ul")+' class="'+f.trim(s.join(" "))+'">'+g+(b.ol_root?"</ol>":"</ul>");k.html(g);k.find("li").filter(function(){return!!f(this).children("ul, ol").length}).addClass("cmw-has-submenu")}k.length&&l&&(c.length||!b.hide_empty)&&k.prepend("<h3>"+l+"</h3>")},J=
|
14 |
+
function(a,b,d){var c;a.find("optgroup").filter(function(){var b=f(this).data().cmwOptgroupIndex===d;b||f(this).remove();return b}).length||(c=f("#"+a.attr("id")+"_ignore").find("optgroup").eq(d).clone(),c.length&&(0<b&&(b=0),a.append(c).val(b)));return b},K=function(a){a=f(this);var b=a.data(),d=!b.cmwAbsolute,c=a.closest(".ui-dialog"),g=c.find(".ui-dialog-content"),l=parseInt(c.css("top"),10)+(d?1:-1)*f(document).scrollTop();b.cmwAbsolute=d;b.cmwMaxHeight||(b.cmwMaxHeight=g.dialog("option","maxHeight"));
|
15 |
+
a.button("option","icons",{primary:d?"ui-icon-circle-close":"ui-icon-circle-check"});c.toggleClass("cmw-assistance-dialog-fixed",!d);g.dialog("option",{maxHeight:d?!d:b.cmwMaxHeight});c.css("top",l);return!1},L=function(a){var b=f(this);a=["current-menu-item","current-menu-parent","current-menu-ancestor"];var d=b.closest(".ui-dialog-content"),c=d.find(".cmw-demo-themenu-ul"),b=b.find("span").not("."+a[0]).parentsUntil(c,"li"),g,l=function(){this.title=this.title+" "+g.replace(" "," & ").replace(/-/g,
|
16 |
+
" ")};c.find("."+a.join(",.")).removeClass(a.join(" ")).each(function(){this.title=this.title.replace(/\s.*$/,"")});for(c=0;c<b.length;c++)g=1===c?a.join(" "):a[0],b.eq(c).children(".cmw-item").find("span").addClass(g).each(l),1<a.length&&a.shift();D.call(f(d.data().cmwOnchange).get(0));return!1},M=function(a){f(this).closest(".ui-dialog-content").find(".cmw-item").eq(this.href.split("#")[1]).not(":has(.current-menu-item)").trigger("click");this.blur();return!1},N=function(a){a=f(this);var b=a.hasClass("cmw-tick")?
|
17 |
+
"tick":"cross",d=a.parent();a=d.closest(".cmw-demo-themenu-ul");var c=d.hasClass("cmw-inherit-"+b),g=c||d.hasClass("cmw-has-"+b),l=g?f([]):d.parentsUntil(a,".cmw-inherit-"+b),e=f(d.closest(".ui-dialog-content").data().cmwOnchange).find("tick"===b?".cmw-setitems":".cmw-exclusions"),k;e.length&&(k=a.find(".cmw-has-"+b)[c||l.length?"not":"add"](d),!g||d.children("ul").length&&!a.parent().hasClass("cmw-version-210")?g&&!c&&(k=k.not(d.find(".cmw-has-"+b))):k=k.not(d),k=k.add(l.find("li").not(d)),k=k.map(function(){var a=
|
18 |
+
this===d[0]||this===l.get(0)?g:f(this).hasClass("cmw-inherit-"+b);return f(this).data().itemid+(a?"+":"")}).get().join(/(,|^\d+\+?$)/.test(f.trim(e.val())||",")?",":" "),e.val(k).trigger("change"));this.blur();return!1},O=function(a){var b={autoOpen:!1,width:Math.min(.9*f(window).width(),600),maxHeight:f(window).height()-40,modal:!1,containment:"window",create:function(){var b=f(this).closest(".ui-dialog");if(b.hasClass("cmw-assistance-dialog-fixed"))f("<button/>").addClass("cmw-dialog-fixed-absolute").button({label:a.cmwDialogFixed,
|
19 |
+
icons:{primary:"ui-icon-circle-check"}}).appendTo(b.find(".ui-dialog-titlebar")).on("click",K)},dialogClass:"cmw-assistance-dialog cmw-assistance-dialog-fixed"},d=f.map(["SetCurrent","Inclusions","Exclusions","Fallback"],function(b){return'<div class="cmw-demo-'+b.toLowerCase()+' cmw-demo-small">'+(a["cmwDialog"+b]||"")+"</div>"}),d=f("<div/>",{id:a.cmwDialogId}).addClass(y("dialog")).append(f("<div/>").addClass("cmw-demo-themenu cmw-version-"+a.cmwDialogVersion.replace(/\./g,"")).html('<em class="cmw-demo-small">'+
|
20 |
+
a.cmwDialogPrompt+"</em>")).append(f("<div/>").addClass("cmw-demo-theoutput").html('<em class="cmw-demo-small">'+a.cmwDialogOutput+'</em><em class="cmw-demo-plugin-version cmw-demo-small">v'+a.cmwDialogVersion+"</em>"+d.shift()+'<div class="cmw-demo-theoutput-wrap ui-corner-all"></div>'+d.join(""))).append(f("<div/>").addClass("cmw-demo-theshortcode").html('<code class="ui-corner-all"></code><div class="cmw-find-shortcodes"><a href="#" class="button-secondary '+y("find-shortcodes")+'" data-nonce="'+
|
21 |
+
(a.cmwDialogNonce||"")+'" title="'+a.cmwDialogShortcodes+'"><span class="spinner"></span><span>[…]</span></a></div><div class="cmw-demo-found-shortcodes cmw-demo-small ui-corner-all"></div>'));d.dialog(b);d.find(".cmw-demo-themenu").on("click",".cmw-tick,.cmw-cross",N).on("click",".cmw-item",L);d.find(".cmw-demo-theoutput").on("click","a",M);return d},F=function(a,b){a.dialog("option","title","CMW : "+(b.find(".cmw-widget-title").val()||a.data().cmwUntitled)+" ["+b.find(".cmw-select-menu").find("option:selected").text()+
|
22 |
+
"]")},G=function(a){var b=f(a.data().cmwOnchange),d=parseInt(b.find(".cmw-select-menu").val(),10),c=a.find(".cmw-demo-themenu-ul"),g=[],l=0,e="",k=function(b){return 1<b?'<a href="#" class="'+y("colexp")+' ui-icon ui-icon-triangle-1-e" style="left:-'+(2.4*(b-2)+2)+'em;"> </a>':""};if(!c.length||c.data("menuid")!==d){for(b.find(".cmw-assist-items optgroup").find("option").each(function(b){for(var a=f(this),c=a.data().cmwLevel;c<g.length;)e+="</li></ul>"+k(g.length),g.pop();c>g.length?e+="<ul>":
|
23 |
+
(e+="</li>",g.pop());e+='<li class="level-'+c+'" data-itemid="'+this.value+'" data-level="'+c+'" data-trace="'+g.join(",")+'">';e+='<a href="#" class="cmw-cross ui-corner-all"></a>';e+='<a class="cmw-item ui-corner-all" href="#" data-indx="'+b+'"><span class="ui-corner-all" title="#'+this.value+'">'+f.trim(a.text());e+='</span></a><a href="#" class="cmw-tick ui-corner-all"></a>';g.push(this.value);c>l&&(l=c)});g.length;)e+="</li></ul>"+k(g.length),g.pop();c.remove();a.find(".cmw-demo-themenu").append(f(e).addClass("cmw-demo-themenu-ul").data({maxLevel:l,
|
24 |
+
menuid:d}))}};z={setLevels:function(a,b){if(b){var d=a.find(".cmw-branch-start"),c=d.val();d.find("optgroup").each(function(a){var c=f(this),d=c.find("option"),k=d.length,s=c.data();if(a)for(d.slice(b).remove();k<b;)++k,c.append(f("<option/>",{value:k}).text(k));else for(k=(k+1)/2,k>b&&d.each(function(a,c){Math.abs(c.value)>=b&&f(c).remove()});k<b;)c.prepend(f("<option/>",{value:-k}).text(-k+(1<k?"":" ("+s.cmwTextParent+")"))).append(f("<option/>",{value:"+"+k}).text("+"+k+(1<k?"":" ("+s.cmwTextChildren+
|
25 |
+
")"))),++k});/^\d+$/.test(c)?c>b&&d.val("1"):""!==c&&Math.abs(c)>=b&&d.val("");a.find(".cmw-ancestors,.cmw-ancestor-siblings").each(function(){var a=f(this),c=(a.find("option").length+1)/2,d=a.val(),k=Math.max(2,b);Math.abs(d)>=b&&a.val(0>d?1-b:b-1);c!==k&&a.find("optgroup").each(function(b,a){var d=f(a),g=d.data().cmwTextForOption,e;c>k&&d.find("option").slice(k-c).remove();for(e=c;e<k;e++)d.append(f("<option/>",{value:b?e:-e}).text(g.replace("%d",b?e:-e)))})});a.find(".cmw-exclude-level").each(function(){var a=
|
26 |
+
f(this),c=a.find("option"),d=(c.length-1)/3,k=a.val(),s=c.eq(2).text(),u=c.eq(3).text();for(c.slice(3*b+1).remove();d<b;)++d,a.append(f("<option/>",{value:d}).text(d)).append(f("<option/>",{value:d+"-"}).text(s.replace(/\d+/,d))).append(f("<option/>",{value:d+"+"}).text(u.replace(/\d+/,d)));parseInt(k,10)>b&&a.val("")});a.find(".cmw-level").each(function(){var a=f(this),c=a.find("option").length;a.val()>b&&a.val(1);for(a.find("option").slice(b).remove();c<b;)++c,a.append(f("<option/>",{value:c}).text(c))});
|
27 |
+
a.find(".cmw-depth,.cmw-fallback-depth").each(function(){var a=f(this),c=a.find("option").length,d=" "+a.data().cmwTextLevels;a.val()>b&&a.val(0);for(a.find("option").slice(b+1).remove();c<=b;)a.append(f("<option/>",{value:c}).text(c+d)),++c})}},setFields:function(a,b){var d=b.find(".cmw-bybranch"),c=b.find(".cmw-byitems").prop("checked"),g=c||!d.prop("checked"),l=b.find(".cmw-assist-items"),e=parseInt(l.val(),10);a.hasClass("cmw-select-menu")?(e=J(l,e,a[0].selectedIndex),this.setLevels(b,(l.find("optgroup").data()||
|
28 |
+
{}).cmwMaxLevel)):a.hasClass("cmw-level")?(g=!0,c=!g,b.find(".cmw-bylevel").prop("checked",g)):a.is(l)?(g=c=!1,d.prop("checked",!g)):a.hasClass("cmw-setitems")?(g=c=!0,b.find(".cmw-byitems").prop("checked",c)):a.hasClass("cmw-ancestors")&&"0"===a.val()?b.find(".cmw-ancestor-siblings").val("0"):a.hasClass("cmw-ancestor-siblings")&&"0"!==a.val()&&"0"===b.find(".cmw-ancestors").val()&&b.find(".cmw-ancestors").val(a.val());f.each({"-ss":c,"-ud":1>b.find(".cmw-depth").val(),"not-br":g,"not-br-ci":g||!!e,
|
29 |
+
"not-fb-pc":!{parent:1,current:1}[b.find(".cmw-fallback").val()]},function(a,c){b.find(".cmw-disableif"+a).toggleClass("cmw-colour-grey",c).find("input,select").prop("disabled",c)})},shortcode:function(a){var b={menu:a.menu},d="branch"===a.filter,c="items"===a.filter,g;a.title&&!a.hide_title&&(b.title=[a.title]);!d&&!c&&1<a.level&&(b.level=a.level);d&&(b.branch=a.branch||"current",a.branch_start&&(b.start_at=[a.branch_start]),"level"===a.start_mode&&(b.start_mode="level"));c&&(b.items=[a._items]);
|
30 |
+
0<a.depth&&(b.depth=a.depth);a.depth_rel_current&&0<a.depth&&(b.depth_rel_current=1);d&&!a.branch&&a.fallback&&(b.fallback=[a.fallback],"quit"!==a.fallback&&(a.fallback_siblings&&b.fallback.push("+siblings"),a.fallback_depth&&b.fallback.push(a.fallback_depth)));d&&a.ancestors&&(b.ancestors=a.ancestors,a.ancestor_siblings&&(b.ancestor_siblings=a.ancestor_siblings));a._exclude&&(b.exclude=[a._exclude]);a.exclude_level&&(b.exclude_level=[a.exclude_level]);c=[];a.title_from_current?c.push("current"):
|
31 |
+
a.title_from_current_root&&c.push("current-root");d&&a.title_from_branch?c.push("branch"):d&&a.title_from_branch_root&&c.push("branch-root");c.length&&(b.title_from=c);for(c in{allow_all_root:1,siblings:1,include_root:1,flat_output:1,ol_root:1,ol_sub:1})a[c]&&(b[c]=1);d={contains_current:"",container:"div",container_id:"",container_class:"",menu_class:"menu-widget",widget_class:""};for(c in d)a[c]!==d[c]&&(b[c]=[a[c]]);d={wrap_link:"before",wrap_link_text:"link_before"};for(c in d)(g=a[d[c]].toString().match(/^<(\w+)/))&&
|
32 |
+
g[1]&&(b[c]=[g[1]]);d=[];for(c in b)d.push(f.isArray(b[c])?c+'="'+b[c].join(",")+'"':c+"="+b[c]);return"[cmwizard "+d.join(" ")+"]"},update:function(a){var b=f(a);a=B(0,b);var d=f("#"+a.data().cmwDialogId),c=-1,g=9999,l=0,e=0,k="",s,u,r,v,x,m,t,h,y,A,z,w,C,q,p,n;b.hasClass("cmw-listen")&&this.setFields(b,a);m=H(a);if(d.length&&d.dialog("isOpen")){d.dialog("moveToTop");b.hasClass("cmw-select-menu")&&G(d);b="branch"===m.filter;u="items"===m.filter;s=!b&&!u;v=b&&!m.branch;t=d.find(".cmw-demo-themenu-ul");
|
33 |
+
x=t.data().maxLevel;w=t.find(".current-menu-item").closest("li");C=w.length?w.data().level:-1;h=t.find("li").removeData("included").removeClass("title-from-item");A=m.depth;z=m.depth_rel_current;y=E(h,m,"cross");u&&(h=E(h,m,"tick"));h.length&&!w.length&&(m.contains_current||v)&&(h=f([]));b&&h.length&&(q=v?w:h.filter("[data-itemid="+m.branch+"]"),q.length?(c=q.data().level||0,h=q.add(q.find("li")),r=q):h=f([]));if(s&&h.length&&1<m.level){p=1;for(n=[];p<m.level;p++)n.push(".level-"+p);h=h.not(n.join(","))}"primary"===
|
34 |
+
m.contains_current&&h.length&&!w.is(h)&&(h=f([]));if(s&&h.length&&A&&(p=z&&C>=m.level?C:m.level,p+=A,p<=x)){for(n=[];p<=x;p++)n.push(".level-"+p);h=h.not(n.join(","))}if(b&&h.length&&(n=parseInt(m.branch_start,10),n=isNaN(n)||!n?c:m.branch_start.match(/^(\+|-)/)?Math.max(1,c+n):n,v&&m.fallback&&!w.find("li").length&&(k="cmw-fellback-to-"+m.fallback,"quit"===m.fallback?n=x+1:(n="current"===m.fallback||2>c?c:c-1,m.fallback_depth&&(A=m.fallback_depth,z=1))),n>x?h=f([]):(n<c&&(q=q.parentsUntil(t,"li.level-"+
|
35 |
+
n)),"level"===m.start_mode&&n<=c&&(1<n||m.allow_all_root)?h=q.parent().find("li"):n<c&&(h=q.add(q.find("li"))),k&&m.fallback_siblings&&h.length&&(1<n||m.allow_all_root)&&(h=h.add(q.siblings("li.level-"+n)))),h.length)){c=n;q=9999;A&&(q=z&&C>=c&&h.filter(w).length?C:c,q+=A,g=q-1);p=1;for(n=[];p<=x;p++)p>=c&&p<q&&n.push(".level-"+p);h=h.filter(n.join(","))}"secondary"===m.contains_current&&h.length&&!w.is(h)&&(h=f([]));if(b&&h.length){n=r.data().level;if(m.ancestors&&(r.is(h)||n>g)){p=m.ancestors;0>
|
36 |
+
p&&(p=Math.max(1,n+p));c=m.ancestor_siblings;0>c&&(c=Math.max(1,n+c));n=[];for(q=[];p<=x;p++)p<=g&&(n.push(".level-"+p),0<c&&p>=c&&q.push(".level-"+p));p=h.length;n=r.parentsUntil(t,n.join(","));h=h.add(n.not(h).data("included"," cmw-an-included-ancestor"));q.length&&(h=h.add(n.filter(q.join(",")).siblings("li").not(h).data("included"," cmw-an-included-ancestor-sibling")));l+=h.length-p}m.siblings&&r.is(h)&&(n=h.length,h=h.add(r.siblings("li").data("included"," cmw-an-included-sibling")),l+=h.length-
|
37 |
+
n)}h.length&&m.include_root&&(n=h.length,h=h.add(t.find(".level-1")),l+=h.length-n);"inclusions"===m.contains_current&&h.length&&!w.is(h)&&(h=f([]));h.length&&y.length&&(n=h.length,h=h.not(y),e+=n-h.length);if(h.length&&m.exclude_level&&(q=(q=m.exclude_level.match(/^(\d+)(\+|-)?$/))?[parseInt(q[1],10),q[2]||""]:[],0<q[0])){n=[];for(p=1;p<=x;p++)(p===q[0]||"-"===q[1]&&p<q[0]||"+"===q[1]&&p>q[0])&&n.push(".level-"+p);n.length&&(q=h.length,h=h.not(n.join(",")),e+=q-h.length)}"output"===m.contains_current&&
|
38 |
+
h.length&&!w.is(h)&&(h=f([]));m.title_from_current&&w.length?w.addClass("title-from-item"):m.title_from_current_root&&w.length?w.closest(".level-1").addClass("title-from-item"):b&&r&&(m.title_from_branch?r.addClass("title-from-item"):m.title_from_branch_root&&r.closest(".level-1").addClass("title-from-item"));d.find(".cmw-demo-fallback").data("fellback",k).toggleClass("updated",!!k);d.find(".cmw-demo-setcurrent").toggleClass("error",!w.length&&(m.contains_current||v));p={inclusions:l,exclusions:e};
|
39 |
+
for(n in p)q=d.find(".cmw-demo-"+n),q.text(q.text().replace(/\d+$/,p[n])).toggleClass("updated",0<p[n]);t.toggleClass("cmw-demo-filteritems",u).find(".picked").not(h.addClass("picked")).removeClass("picked");F(d,a);I(d,m)}a.add(d).find("code").text(this.shortcode(m))},v210:{setLevels:function(a,b){var d=a.find(".cmw-start-level"),c=d.val(),g=d.find("option").length,l;c>b&&d.val(1);for(d.find("option").slice(b).remove();g<b;)++g,d.append(f("<option/>",{value:g}).text(g));d=a.find(".cmw-depth");c=d.val();
|
40 |
+
g=d.find("option").length;l=" "+d.data().cmwTextLevels;c>b&&d.val(0);for(d.find("option").slice(b+1).remove();g<=b;)d.append(f("<option/>",{value:g}).text(g+l)),++g},setFields:function(a,b){var d=b.find(".cmw-showall").prop("checked"),c=b.find(".cmw-showspecific").prop("checked"),g=b.find(".cmw-assist-items"),l=parseInt(g.val(),10);a.hasClass("cmw-select-menu")&&(l=J(g,l,a[0].selectedIndex),this.setLevels(b,(g.find("optgroup").data()||{}).cmwMaxLevel));f.each({"":d||c,"-ss":c,"not-rp":d||c||0<=l,
|
41 |
+
"not-ci":d||c||!!l},function(a,c){b.find(".cmw-disableif"+a).toggleClass("cmw-colour-grey",c).find("input,select").prop("disabled",c)})},shortcode:function(a){var b={menu:a.menu},d=0<a.filter,c=!!a.filter&&!d,g;a.title&&(b.title=[a.title]);if(d)switch(a.filter_item){case 0:b.children_of=["current"];break;case -1:b.children_of=["parent"];break;case -2:b.children_of=["root"];break;default:b.children_of=a.filter_item}c&&(b.items=[a._items]);d&&0>a.filter_item&&a.fallback_no_ancestor&&(b.fallback_parent=
|
42 |
+
a.fallback_include_parent_siblings?["siblings"]:a.fallback_include_parent?["parent"]:1);d&&!a.filter_item&&a.fallback_no_children&&(b.fallback_current=a.fallback_nc_include_parent_siblings?["siblings"]:a.fallback_nc_include_parent?["parent"]:1);1<a.start_level&&(b.start_level=a.start_level);0<a.depth&&(b.depth=a.depth);a.depth_rel_current&&0<a.depth&&(b.depth_rel_current=1);c=[];d&&(a.include_parent_siblings?c.push("siblings"):a.include_parent&&c.push("parent"),a.include_ancestors&&c.push("ancestors"),
|
43 |
+
c.length&&(b.include=c));c=[];d&&a.title_from_parent&&c.push("parent");a.title_from_current&&c.push("current");c.length&&(b.title_from=c);for(c in{flat_output:1,contains_current:1,ol_root:1,ol_sub:1})a[c]&&(b[c]=1);d={container:"div",container_id:"",container_class:"",menu_class:"menu-widget",widget_class:""};for(c in d)a[c]!==d[c]&&(b[c]=[a[c]]);d={wrap_link:"before",wrap_link_text:"link_before"};for(c in d)(g=a[d[c]].toString().match(/^<(\w+)/))&&g[1]&&(b[c]=[g[1]]);d=[];for(c in b)d.push(f.isArray(b[c])?
|
44 |
+
c+'="'+b[c].join(" ")+'"':c+"="+b[c]);return"[custom_menu_wizard "+d.join(" ")+"]"},update:function(a){var b=f(a);a=B(0,b);var d=f("#"+a.data().cmwDialogId),c,g,l,e,k,s,u,r,v,x,m,t,h;b.hasClass("cmw-listen")&&this.setFields(b,a);if(d.length&&d.dialog("isOpen")){d.dialog("moveToTop");b.hasClass("cmw-select-menu")&&G(d);e=H(a);c=!e.filter;b=0<e.filter;g=!c&&!b;k=e.include_parent;s=e.include_parent_siblings;u=d.find(".cmw-demo-themenu-ul");l=u.data().maxLevel;v=u.find(".current-menu-item").closest("li");
|
45 |
+
x=v.length?v.data().level:-1;r=u.find("li").removeData("included").removeClass("title-from-item");g&&(r=E(r,e,"tick"));r.length&&!v.length&&(e.contains_current||b&&1>e.filter_item)&&(r=f([]));r.length&&b&&(0<e.filter_item?t=r.filter("[data-itemid="+e.filter_item+"]"):e.filter_item?1===x&&e.fallback_no_ancestor?(t=v,k=k||e.fallback_include_parent,s=s||e.fallback_include_parent_siblings,m="cmw-fellback-to-current"):t=1===x?u:-1>e.filter_item?u.find(".current-menu-ancestor").eq(0).closest("li"):u.find(".current-menu-parent").closest("li"):
|
46 |
+
v.find("li").length?t=v:e.fallback_no_children&&(t=u.find(".current-menu-parent").closest("li"),t.length||(t=u),k=k||e.fallback_nc_include_parent,s=s||e.fallback_nc_include_parent_siblings,m="cmw-fellback-to-parent"));if(r.length)if(c)for(h=e.depth_rel_current&&e.depth&&v.length&&x>=e.start_level?x+e.depth-1:e.depth?e.start_level+e.depth-1:9999,c=1;c<=l;c++){if(c<e.start_level||c>h)r=r.not(".level-"+c)}else t&&t.length?(h=e.depth_rel_current&&e.depth&&v.length&&t.has(v[0]).length?x-1+e.depth:e.depth?
|
47 |
+
Math.max((t.data().level||0)+e.depth,e.start_level+e.depth-1):9999,r=t.find("li").filter(function(){var a=f(this).data().level;return a>=e.start_level&&a<=h})):b&&(r=f([]));r.length&&b&&t&&t.is("li")&&(s&&(r=r.add(t.siblings("li").data("included"," cmw-an-included-parent-sibling")),k=!0),e.include_ancestors&&(r=r.add(t.parentsUntil(u,"li").data("included"," cmw-an-included-ancestor")),k=!0),k&&(r=r.add(t.data("included"," cmw-the-included-parent"))));!r.length||!e.contains_current||v.length&&r.filter(v).length||
|
48 |
+
(r=f([]));e.title_from_parent&&r.length&&t&&t.is("li")?t.addClass("title-from-item"):e.title_from_current&&r.length&&v.addClass("title-from-item");m=r.length?m:"";d.find(".cmw-demo-fallback").data("fellback",m).toggleClass("updated",!!m);d.find(".cmw-demo-setcurrent").toggleClass("error",!v.length&&(e.contains_current||b&&1>e.filter_item));u.toggleClass("cmw-demo-filteritems",g).find(".picked").not(r.addClass("picked")).removeClass("picked");F(d,a);I(d,e);d.find("code").text(this.shortcode(e))}}}};
|
49 |
+
f(document).on("change",y("onchange",1),D).on("click",y("assist",1),function(a){a=f(this);a=B(0,a);var b=a.data(),d=f("#"+b.cmwDialogId);d.length||(d=O(b).data({cmwOnchange:"#"+a.attr("id"),cmwUntitled:"["+b.cmwDialogUntitled+"]"}));d.dialog("isOpen")?d.dialog("close"):(G(d),F(d,a),d.dialog("open"),D.call(a[0]));this.blur();return!1}).on("click",y("fieldset",1),function(a){a=f(this);var b=a.next(".cmw-fieldset-state"),d=!b.prop("checked");b.length&&(b.prop("checked",d),a.toggleClass("cmw-collapsed-fieldset",
|
50 |
+
d),b.next("div")[d?"slideUp":"slideDown"]());this.blur();return!1}).on("click",".widget-action,.widget-control-close",function(a){a=f(this).closest("div.widget");var b=a.parent();b.hasClass("customize-control-widget_form")&&!b.hasClass("expanded")||B(a).each(function(){var a=f("#"+f(this).data().cmwDialogId);a.length&&a.dialog("isOpen")&&a.dialog("close")})}).on("click",".widget-control-remove",function(a){B(f(this).closest("div.widget")).each(function(){var a=f("#"+f(this).data().cmwDialogId);a.length&&
|
51 |
+
(a.dialog("destroy"),a.remove())})}).on("click",y("colexp",1),function(a){a=/1-e/.test(this.className)?"slideUp":"slideDown";f(this).toggleClass("ui-icon-triangle-1-s ui-icon-triangle-1-e").prev("ul")[a]();return!1}).on("click",y("find-shortcodes",1),function(a){a=f(this);var b=a.parent().parent();ajaxurl&&!b.hasClass("cmw-ajax-fetching")&&(b.hasClass("cmw-ajax-showing")?b.removeClass("cmw-ajax-showing"):(b.addClass("cmw-ajax-fetching"),f.post(ajaxurl,{action:"cmw-find-shortcodes",_wpnonce:a.data().nonce}).done(function(a){a&&
|
52 |
+
"0"!==a&&(b.find(".cmw-demo-found-shortcodes").html(f(a).find("response_data").text()),b.addClass("cmw-ajax-showing"))}).always(function(a){b.removeClass("cmw-ajax-fetching")})));this.blur();return!1}).on("click",y("legacy-close",1),function(){f(this).parent().remove();return!1})});
|
@@ -3,13 +3,41 @@
|
|
3 |
* Plugin Name: Custom Menu Wizard
|
4 |
* Plugin URI: http://wordpress.org/plugins/custom-menu-wizard/
|
5 |
* Description: Show any part of a custom menu in a Widget, or in content using a Shortcode. Customise the output with extra classes or html; filter by current menu item or a specific item; set a depth, show the parent(s), change the list style, etc. Use the included emulator to assist with the filter settings.
|
6 |
-
* Version:
|
7 |
* Author: Roger Barrett
|
8 |
* Author URI: http://www.wizzud.com/
|
9 |
* License: GPL2+
|
10 |
*/
|
11 |
-
|
12 |
/*
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
13 |
* v2.0.6 change log:
|
14 |
* - modified determination of current item to cope better with multiple occurences (still first-found, but within prioritised groups)
|
15 |
* - replaced display of update information on plugins list with styled request (and link) to read changelog (update info sometimes didn't display, and some considered it "scary" for users)
|
@@ -72,387 +100,448 @@
|
|
72 |
* - moved the setting of 'disabled' attributes on INPUTs/SELECTs from PHP into javascript
|
73 |
*/
|
74 |
|
75 |
-
|
76 |
-
|
77 |
-
/**
|
78 |
-
* registers the widget and adds the shortcode
|
79 |
-
*/
|
80 |
-
function custom_menu_wizard_register_widget() {
|
81 |
-
register_widget('Custom_Menu_Wizard_Widget');
|
82 |
-
add_shortcode('custom_menu_wizard', 'custom_menu_wizard_widget_shortcode');
|
83 |
-
}
|
84 |
-
add_action('widgets_init', 'custom_menu_wizard_register_widget');
|
85 |
|
86 |
-
|
87 |
-
|
88 |
-
|
89 |
-
function custom_menu_wizard_widget_admin_script(){
|
90 |
-
global $wp_scripts, $Custom_Menu_Wizard_Widget_Version;
|
91 |
-
wp_enqueue_style('custom-menu-wizard-plugin-styles', plugins_url('/custom-menu-wizard.css', __FILE__), array(), $Custom_Menu_Wizard_Widget_Version);
|
92 |
-
wp_enqueue_script('custom-menu-wizard-plugin-script', plugins_url('/custom-menu-wizard.min.js', __FILE__), array('jquery-ui-dialog'), $Custom_Menu_Wizard_Widget_Version);
|
93 |
-
if( !wp_style_is( 'jquery-ui', 'registered' ) ) {
|
94 |
-
$jquery_ui_version = isset( $wp_scripts->registered['jquery-ui-core']->ver ) ? $wp_scripts->registered['jquery-ui-core']->ver : '1.9.2';
|
95 |
-
wp_register_style( 'jquery-ui', 'http://ajax.googleapis.com/ajax/libs/jqueryui/' . $jquery_ui_version . '/themes/smoothness/jquery-ui.css' );
|
96 |
-
}
|
97 |
-
wp_enqueue_style( 'jquery-ui' );
|
98 |
-
}
|
99 |
-
add_action('admin_print_scripts-widgets.php', 'custom_menu_wizard_widget_admin_script');
|
100 |
|
101 |
-
|
102 |
-
|
103 |
-
*/
|
104 |
-
function custom_menu_wizard_update_message($plugin_data, $r){
|
105 |
|
106 |
-
|
107 |
-
|
108 |
-
|
109 |
-
'
|
110 |
-
|
111 |
-
|
112 |
-
|
113 |
-
|
114 |
-
|
115 |
-
|
116 |
-
|
117 |
-
|
118 |
-
|
119 |
-
|
120 |
-
|
121 |
-
|
122 |
-
|
123 |
-
|
|
|
|
|
|
|
124 |
|
125 |
-
|
126 |
-
|
127 |
-
|
|
|
|
|
|
|
|
|
128 |
|
129 |
-
}
|
130 |
-
/**
|
131 |
-
* if the plugin has an update...
|
132 |
-
*/
|
133 |
-
function custom_menu_wizard_admin_menu(){
|
134 |
-
add_action('in_plugin_update_message-' . plugin_basename(__FILE__), 'custom_menu_wizard_update_message', 10, 2);
|
135 |
-
}
|
136 |
-
add_action('admin_menu', 'custom_menu_wizard_admin_menu');
|
137 |
|
|
|
|
|
|
|
|
|
138 |
|
139 |
-
|
140 |
-
|
141 |
-
|
142 |
-
|
143 |
-
|
144 |
-
|
|
|
|
|
145 |
|
146 |
-
|
147 |
-
|
148 |
-
|
149 |
-
|
150 |
-
|
151 |
-
|
152 |
-
|
153 |
-
|
154 |
-
|
155 |
-
|
156 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
157 |
|
158 |
-
|
159 |
-
|
160 |
-
|
161 |
-
* @param string $output Passed by reference. Used to append additional content.
|
162 |
-
* @param int $depth Depth of page. Used for padding.
|
163 |
-
*/
|
164 |
-
function end_lvl( &$output, $depth = 0, $args = array() ) {
|
165 |
-
$indent = str_repeat("\t", $depth);
|
166 |
-
$listtag = empty( $args->_custom_menu_wizard['ol_sub'] ) ? 'ul' : 'ol';
|
167 |
-
$output .= "$indent</$listtag>\n";
|
168 |
-
}
|
169 |
|
170 |
-
|
171 |
-
* pre-filters elements then calls parent::walk()
|
172 |
-
*
|
173 |
-
* @filters : custom_menu_wizard_walker_items array of filtered menu elements; array of args
|
174 |
-
*
|
175 |
-
* @param array $elements Menu items
|
176 |
-
* @param integer $max_depth
|
177 |
-
* @return string
|
178 |
-
*/
|
179 |
-
function walk($elements, $max_depth){
|
180 |
|
181 |
-
|
182 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
183 |
|
184 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
185 |
|
186 |
-
|
187 |
-
|
188 |
-
// filter : 0 = show all; 1 = kids of (current [root|parent] item or specific item); -1 = specific items (v2.0.0)
|
189 |
-
// filter_item : 0 = current item, -1 = parent of current (v1.1.0), -2 = root ancestor of current (v1.1.0); else a menu item id
|
190 |
-
// flat_output : true = equivalent of $max_depth == -1
|
191 |
-
// include_parent : true = include the filter_item menu item
|
192 |
-
// include_parent_siblings : true = include the siblings (& parent) of the filter_item menu item
|
193 |
-
// include_ancestors : true = include the filter_item menu item plus all it's ancestors
|
194 |
-
// title_from_parent : true = widget wants parent's title
|
195 |
-
// title_from_current : true = widget wants current item's title (v1.2.0)
|
196 |
-
// start_level : integer, 1+
|
197 |
-
// depth : integer, replacement for max_depth and also applied to 'flat' output
|
198 |
-
// depth_rel_current : true = changes depth calc from "relative to first filtered item found" to "relative to current item's level" (if current item is found below level/branch) (v2.0.0)
|
199 |
-
// fallback_no_ancestor : true = if looking for an ancestor (root or parent) of a top-level current item, fallback to current item (v1.1.0)
|
200 |
-
// fallback_include_parent : true = if fallback_no_ancestor comes into play then force include_parent to true (v1.1.0)
|
201 |
-
// fallback_include_parent_siblings : true = if fallback_no_ancestor comes into play then force include_parent_siblings to true (v1.1.0)
|
202 |
-
// fallback_no_children : true = if looking for a current item, and that item turns out to have no children, fallback to current parent (v1.2.0)
|
203 |
-
// fallback_nc_include_parent : true = if fallback_no_children comes into play then force include_parent to true (v1.2.0)
|
204 |
-
// fallback_nc_include_parent_siblings : true = if fallback_no_children comes into play then force include_parent_siblings to true (v1.2.0)
|
205 |
-
// contains_current : true = the output - both Filtered and any Included items - must contain the current menu item (v2.0.0)
|
206 |
-
// items : comma-or-space delimited list of item ids
|
207 |
-
//
|
208 |
-
// _walker (array) : for anything that only the walker can determine and that needs to be communicated back to the widget instance
|
209 |
-
//
|
210 |
-
//$elements is an array of objects, indexed by position within the menu (menu_order),
|
211 |
-
//starting at 1 and incrementing sequentially regardless of parentage (ie. first item is [1],
|
212 |
-
//second item is [2] whether it's at root or subordinate to first item)
|
213 |
-
$cmw['_walker']['fellback'] = false;
|
214 |
|
215 |
-
$
|
216 |
-
$find_specific_items = $cmw['filter'] < 0; //v2.0.0 //v2.0.1:bug fixed (changed < 1 to < 0)
|
217 |
-
$find_current_item = $find_kids_of && empty( $cmw['filter_item'] );
|
218 |
-
$find_current_parent = $find_kids_of && $cmw['filter_item'] == -1; //v1.1.0
|
219 |
-
$find_current_root = $find_kids_of && $cmw['filter_item'] == -2; //v1.1.0
|
220 |
-
$depth_rel_current = $cmw['depth_rel_current'] && $cmw['depth'] > 0; //v2.0.0
|
221 |
-
//these could change depending on whether a fallback comes into play (v1.1.0)
|
222 |
-
$include_parent = $cmw['include_parent'] || $cmw['include_ancestors'];
|
223 |
-
$include_parent_siblings = $cmw['include_parent_siblings'];
|
224 |
|
225 |
-
|
226 |
-
$
|
|
|
|
|
227 |
|
228 |
-
$
|
229 |
-
'
|
230 |
-
'
|
231 |
-
|
232 |
-
|
233 |
-
'
|
234 |
-
));
|
235 |
-
|
236 |
-
array() //for the artificial level-0
|
237 |
-
);
|
238 |
-
$allLevels = 9999;
|
239 |
-
$startWithKidsOf = -1;
|
240 |
-
$currentItem = array();
|
241 |
|
242 |
-
|
243 |
-
|
244 |
-
|
|
|
|
|
|
|
|
|
|
|
245 |
|
|
|
246 |
|
247 |
-
|
248 |
-
|
249 |
-
|
250 |
-
|
251 |
-
|
252 |
-
|
253 |
-
|
254 |
-
|
255 |
-
|
256 |
-
|
257 |
-
|
258 |
-
//failing that, look for a "current" item that is also marked as parent, and, again, use the first one found;
|
259 |
-
//failing that, look for a "current" item that is also marked as an ancestor, and, again, use the first one found.
|
260 |
-
//
|
261 |
-
//array keys, priority order : just current -> parent, not ancestor -> parent and ancestor -> ancestor
|
262 |
-
// first found...
|
263 |
-
// - a001 : just current
|
264 |
-
// - b001 : current & parent (not ancestor)
|
265 |
-
// - c001 : current & parent & ancestor
|
266 |
-
// - d001 : current & ancestor (not parent)
|
267 |
-
// next found...
|
268 |
-
// - a002 : just current
|
269 |
-
// - b002 : current & parent (not ancestor)
|
270 |
-
// - c002 : current & parent & ancestor
|
271 |
-
// - d002 : current & ancestor (not parent)
|
272 |
-
// etc
|
273 |
-
//example :
|
274 |
-
// - 1st found : current & ancestor = d001
|
275 |
-
// - 2nd found : current & parent & ancestor = c002
|
276 |
-
// - 3rd found : just current = a003
|
277 |
-
// - 4th found : just current & parent = b004
|
278 |
-
// - 5th found : just current = a005
|
279 |
-
//reverse sort keys alphabetically and a003 comes out on bottom, so third found gets used! (copes with 999 "current" items; should be enough!)
|
280 |
-
$j = $item->current_item_ancestor ? ( $item->current_item_parent ? 'c' : 'd') : ( $item->current_item_parent ? 'b' : 'a' );
|
281 |
-
$currentItem[ $j . sprintf( '%03d' , count( $currentItem ) + 1 ) ] = $itemID;
|
282 |
-
}
|
283 |
|
284 |
-
|
285 |
-
|
286 |
-
|
287 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
288 |
}
|
289 |
-
$
|
290 |
-
|
291 |
-
$
|
292 |
-
//level within structure...
|
293 |
-
'level' => $thisLevel,
|
294 |
-
//ancestors (from the artificial level-0, right down to parent, inclusive) within structure...
|
295 |
-
'ancestors' => $structure[ $parentID ]['ancestors'],
|
296 |
-
//kids within structure, ie array of itemID's...
|
297 |
-
'kids' => array(),
|
298 |
-
//item within elements...
|
299 |
-
'element' => $i,
|
300 |
-
//assume no matches...
|
301 |
-
'keep' => false
|
302 |
-
);
|
303 |
-
$structure[ $itemID ]['ancestors'][] = $parentID;
|
304 |
-
$structure[ $parentID ]['kids'][] = $itemID;
|
305 |
}
|
306 |
-
} //end foreach
|
307 |
|
308 |
-
|
309 |
-
$currentItem = false;
|
310 |
-
}else{
|
311 |
-
krsort( $currentItem );
|
312 |
-
$currentItem = array_pop( $currentItem );
|
313 |
}
|
314 |
|
315 |
-
//
|
316 |
-
$
|
317 |
-
|
318 |
-
$
|
319 |
-
|
320 |
-
$continue = false;
|
321 |
}
|
322 |
|
323 |
-
|
324 |
-
|
325 |
-
|
326 |
-
|
327 |
-
|
328 |
-
|
329 |
-
|
330 |
-
|
331 |
-
|
332 |
-
//
|
333 |
-
|
334 |
-
//
|
335 |
-
|
336 |
-
//
|
337 |
-
|
338 |
-
// The effects of this change are that previously, filtering for kids of an item that was at level 2, with a start level of 4,
|
339 |
-
// would fail to return any items because the immediate kids (at level 3) were outside the start level. Now, the returned items
|
340 |
-
// will begin with the grand-kids (ie. those at level 4).
|
341 |
-
// Note that neither start level nor depth are applicable to a specific items filter (also new at v2.0.0)!
|
342 |
|
343 |
-
|
344 |
-
|
345 |
-
|
346 |
-
|
347 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
348 |
}
|
349 |
-
|
350 |
-
|
351 |
-
|
352 |
-
|
353 |
-
|
354 |
-
|
355 |
-
|
356 |
-
|
357 |
-
$startWithKidsOf = $ancestor[0]; //can be zero!
|
358 |
-
$include_parent = $include_parent || $cmw['fallback_nc_include_parent'];
|
359 |
-
$include_parent_siblings = $include_parent_siblings || $cmw['fallback_nc_include_parent_siblings'];
|
360 |
-
$cmw['_walker']['fellback'] = 'to-parent';
|
361 |
-
}
|
362 |
-
}elseif( $find_current_parent || $find_current_root ){
|
363 |
-
//as of v2.0.0 the fallback to current item - for current menu items at the top level - is deprecated, but
|
364 |
-
//retained for a while to maintain backward compatibility
|
365 |
-
//if no parent : fall back to current item (if set)...
|
366 |
-
if( $structure[ $currentItem ]['level'] == 1 && $cmw['fallback_no_ancestor'] ){
|
367 |
-
$startWithKidsOf = $currentItem;
|
368 |
-
$include_parent = $include_parent || $cmw['fallback_include_parent'];
|
369 |
-
$include_parent_siblings = $include_parent_siblings || $cmw['fallback_include_parent_siblings'];
|
370 |
-
$cmw['_walker']['fellback'] = 'to-current';
|
371 |
-
}else{
|
372 |
-
//as of v2.0.0, the artificial level-0 counts as parent of a top-level current menu item...
|
373 |
-
if( $find_current_parent ){
|
374 |
-
$ancestor = -1;
|
375 |
-
}elseif( $structure[ $currentItem ]['level'] > 1 ){
|
376 |
-
$ancestor = 1;
|
377 |
-
}else{
|
378 |
-
$ancestor = 0;
|
379 |
-
}
|
380 |
-
$ancestor = array_slice( $structure[ $currentItem ]['ancestors'], $ancestor, 1 );
|
381 |
-
if( !empty( $ancestor ) ){
|
382 |
-
$startWithKidsOf = $ancestor[0]; //as of v2.0.0, this can now be zero!
|
383 |
-
}
|
384 |
}
|
385 |
}
|
386 |
}
|
|
|
387 |
|
388 |
-
if( $
|
389 |
-
|
390 |
-
|
391 |
-
|
392 |
-
|
393 |
-
|
394 |
-
|
395 |
-
|
396 |
-
|
397 |
-
|
398 |
-
|
399 |
-
|
400 |
-
|
401 |
-
if( $depth_rel_current && !empty( $currentItem ) && $structure[ $currentItem ]['level'] >= $cmw['start_level'] ){
|
402 |
-
$bottomLevel = $structure[ $currentItem ]['level'] + $cmw['depth'] - 1;
|
403 |
-
}else{
|
404 |
-
$bottomLevel = $cmw['depth'] > 0 ? $cmw['start_level'] + $cmw['depth'] - 1 : $allLevels;
|
405 |
}
|
406 |
-
|
407 |
-
|
408 |
-
|
409 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
410 |
}
|
411 |
}
|
412 |
-
//for kids-of filters, run a recursive through the structure's kids...
|
413 |
-
}elseif( $startWithKidsOf > -1 ){
|
414 |
-
//prior to v2.0.0, depth was always related to the first item found, and still is *unless* depth_rel_current is set
|
415 |
-
//NB the in_array() of ancestors prevents depth_rel_current when startWithKidsOf == currentItem
|
416 |
-
if( $depth_rel_current && !empty( $currentItem ) && $structure[ $currentItem ]['level'] >= $cmw['start_level']
|
417 |
-
&& in_array( $startWithKidsOf, $structure[ $currentItem ]['ancestors'] ) ){
|
418 |
-
$bottomLevel = $structure[ $currentItem ]['level'] - 1 + $cmw['depth'];
|
419 |
-
}else{
|
420 |
-
$bottomLevel = $cmw['depth'] > 0
|
421 |
-
? max( $structure[ $startWithKidsOf ]['level'] + $cmw['depth'], $cmw['start_level'] + $cmw['depth'] - 1 )
|
422 |
-
: $allLevels;
|
423 |
-
}
|
424 |
-
//$structure[0]['keepCount'] gets incremented in this recursive method...
|
425 |
-
$this->_cmw_set_keep_kids( $structure, $startWithKidsOf, $cmw['start_level'], $bottomLevel );
|
426 |
}
|
427 |
-
|
428 |
-
|
429 |
-
|
|
|
|
|
|
|
430 |
|
431 |
-
|
432 |
-
|
433 |
-
|
434 |
-
|
435 |
-
|
436 |
-
|
437 |
-
|
438 |
-
|
439 |
-
|
440 |
-
|
441 |
-
|
442 |
-
|
443 |
-
|
444 |
-
|
445 |
-
|
446 |
-
|
447 |
-
|
448 |
-
}
|
449 |
}
|
450 |
-
|
451 |
-
|
452 |
-
|
453 |
-
|
454 |
-
|
455 |
-
$
|
|
|
456 |
}
|
457 |
}
|
458 |
}
|
@@ -460,1140 +549,325 @@ class Custom_Menu_Wizard_Walker extends Walker_Nav_Menu {
|
|
460 |
}
|
461 |
}
|
462 |
|
463 |
-
$
|
464 |
-
|
465 |
-
|
466 |
-
|
467 |
-
|
468 |
-
|
469 |
-
|
470 |
-
'
|
471 |
-
|
472 |
-
$elements[ $structure[ $startWithKidsOf ]['element'] ]->ID
|
473 |
-
);
|
474 |
-
}
|
475 |
-
//might we want the current item's title as the widget title?...
|
476 |
-
if( !empty( $currentItem ) && $cmw['title_from_current'] ){
|
477 |
-
$cmw['_walker']['current_title'] = apply_filters(
|
478 |
-
'the_title',
|
479 |
-
$elements[ $structure[ $currentItem ]['element'] ]->title,
|
480 |
-
$elements[ $structure[ $currentItem ]['element'] ]->ID
|
481 |
-
);
|
482 |
-
}
|
483 |
-
|
484 |
-
//now we need to gather together all the 'keep' items from structure;
|
485 |
-
//while doing so, we need to set up levels and kids, ready for adding classes...
|
486 |
-
foreach( $structure as $k=>$v ){
|
487 |
-
if( $k > 0 && $v['keep'] ){
|
488 |
-
$substructure[ $k ] = $v;
|
489 |
-
//take a copy of the elements item...
|
490 |
-
$substructure[ $k ]['element'] = $elements[ $v['element'] ];
|
491 |
-
//use kids as a has-submenu flag...
|
492 |
-
$substructure[ $k ]['kids'] = 0;
|
493 |
-
//any surviving parent (except the artificial level-0) should have submenu class set on it...
|
494 |
-
array_shift( $v['ancestors'] ); //remove the level-0
|
495 |
-
for( $i = count( $v['ancestors'] ) - 1; $i >= 0; $i-- ){
|
496 |
-
if( isset( $substructure[ $v['ancestors'][ $i ] ] ) ){
|
497 |
-
$substructure[ $v['ancestors'][ $i ] ]['kids']++;
|
498 |
-
}else{
|
499 |
-
//not a 'kept' ancestor so remove it...
|
500 |
-
array_splice( $v['ancestors'], $i, 1 );
|
501 |
-
}
|
502 |
-
}
|
503 |
-
//ancestors now only has 'kept' ancestors...
|
504 |
-
$substructure[ $k ]['level'] = count( $v['ancestors'] ) + 1;
|
505 |
-
//need to ensure that the parent_field of all the new top-level (ie. root) items is set to
|
506 |
-
//zero, otherwise the parent::walk() will assume they're orphans and ignore them.
|
507 |
-
//however, we also need to check - especially for a specific-items filter (v2.0.0) - that parent_field of a
|
508 |
-
//child actually points to the closest 'kept' ancestor; otherwise, given A (kept) > B (not kept) > C (kept)
|
509 |
-
//the parent_field of C would point to a non-existent B and would subsequently be considered an orphan!
|
510 |
-
if( $substructure[ $k ]['level'] == 1){
|
511 |
-
$substructure[ $k ]['element']->$parent_field = 0;
|
512 |
-
}else{
|
513 |
-
//NB even though this really only needs to be done for $find_specific_items, I'm doing it regardless.
|
514 |
-
//set to the closest ancestor, ie. the new(?) parent...
|
515 |
-
$ancestor = array_slice( $v['ancestors'], -1, 1 );
|
516 |
-
$substructure[ $k ]['element']->$parent_field = $ancestor[0];
|
517 |
}
|
518 |
}
|
519 |
}
|
520 |
-
|
521 |
|
522 |
-
|
523 |
-
|
524 |
-
|
525 |
-
|
526 |
-
|
527 |
-
//add the submenu class?...
|
528 |
-
if( $v['kids'] > 0 ){
|
529 |
-
$elements[ $i ]->classes[] = 'cmw-has-submenu';
|
530 |
-
}else{
|
531 |
-
//3.7 adds a menu-item-has-children class to (original) menu items that have kids : remove it as the item is now childless...
|
532 |
-
$elements[ $i ]->classes = array_diff( $elements[ $i ]->classes, array('menu-item-has-children') );
|
533 |
}
|
534 |
-
|
535 |
-
$elements[ $i ]->classes[] = 'cmw-level-' . $v['level'];
|
536 |
-
$i++;
|
537 |
-
}
|
538 |
-
unset( $structure, $substructure );
|
539 |
-
|
540 |
-
//since we've done all the depth filtering, set max_depth to unlimited (unless 'flat' was requested!)...
|
541 |
-
if( !$cmw['flat_output'] ){
|
542 |
-
$max_depth = 0;
|
543 |
-
}
|
544 |
-
} //ends the check for bad max depth, empty elements, or empty cmw args
|
545 |
-
|
546 |
-
return empty( $elements ) ? '' : parent::walk( apply_filters( 'custom_menu_wizard_walker_items', $elements, $args ), $max_depth, $args );
|
547 |
-
}
|
548 |
|
549 |
-
|
550 |
-
|
551 |
-
|
552 |
-
|
553 |
-
|
554 |
-
for( $i = 0; $i < $ct; $i++ ){
|
555 |
-
$j = $structure[ $itemId ]['kids'][ $i ];
|
556 |
-
if( $structure[ $j ]['level'] <= $bottomLevel ){
|
557 |
-
$structure[ $j ]['keep'] = $structure[ $j ]['level'] >= $topLevel;
|
558 |
-
if( $structure[ $j ]['keep'] ){
|
559 |
-
$structure[0]['keepCount']++;
|
560 |
}
|
561 |
-
|
562 |
-
if( $structure[ $j ]['level'] < $bottomLevel ){
|
563 |
-
$this->_cmw_set_keep_kids( $structure, $j, $topLevel, $bottomLevel );
|
564 |
-
}
|
565 |
-
}
|
566 |
-
}
|
567 |
-
|
568 |
-
} //end Custom_Menu_Wizard_Walker class
|
569 |
-
|
570 |
-
/**
|
571 |
-
* Custom Menu Wizard Widget class
|
572 |
-
*/
|
573 |
-
class Custom_Menu_Wizard_Widget extends WP_Widget {
|
574 |
-
|
575 |
-
var $_cmw_switches = array(
|
576 |
-
'hide_title' => 0,
|
577 |
-
'contains_current' => 0, //v2.0.0 added
|
578 |
-
'depth_rel_current' => 0, //v2.0.0 added
|
579 |
-
'fallback_no_ancestor' => 0, //v1.1.0 added
|
580 |
-
'fallback_include_parent' => 0, //v1.1.0 added
|
581 |
-
'fallback_include_parent_siblings' => 0, //v1.1.0 added
|
582 |
-
'fallback_no_children' => 0, //v1.2.0 added
|
583 |
-
'fallback_nc_include_parent' => 0, //v1.2.0 added
|
584 |
-
'fallback_nc_include_parent_siblings' => 0, //v1.2.0 added
|
585 |
-
'flat_output' => 0,
|
586 |
-
'include_parent' => 0,
|
587 |
-
'include_parent_siblings' => 0, //v1.1.0 added
|
588 |
-
'include_ancestors' => 0,
|
589 |
-
'hide_empty' => 0, //v1.1.0: this now only has relevance prior to WP v3.6
|
590 |
-
'title_from_parent' => 0,
|
591 |
-
'title_from_current' => 0, //v1.2.0 added
|
592 |
-
'ol_root' => 0,
|
593 |
-
'ol_sub' => 0,
|
594 |
-
//field section toggles...
|
595 |
-
'fs_filter' => 0,
|
596 |
-
'fs_fallbacks' => 1, //v1.2.0 added
|
597 |
-
'fs_output' => 1,
|
598 |
-
'fs_container' => 1,
|
599 |
-
'fs_classes' => 1,
|
600 |
-
'fs_links' => 1
|
601 |
-
);
|
602 |
-
var $_cmw_strings = array(
|
603 |
-
'title' => '',
|
604 |
-
'items' => '', //v2.0.0 added
|
605 |
-
'container' => 'div',
|
606 |
-
'container_id' => '',
|
607 |
-
'container_class' => '',
|
608 |
-
'menu_class' => 'menu-widget',
|
609 |
-
'widget_class' => ''
|
610 |
-
);
|
611 |
-
var $_cmw_html = array(
|
612 |
-
'before' => '',
|
613 |
-
'after' => '',
|
614 |
-
'link_before' => '',
|
615 |
-
'link_after' => ''
|
616 |
-
);
|
617 |
-
var $_cmw_integers = array(
|
618 |
-
'depth' => 0,
|
619 |
-
'filter' => -1, //v2.0.0 changed from switch
|
620 |
-
'filter_item' => -2, //v1.1.0 changed from 0
|
621 |
-
'menu' => 0,
|
622 |
-
'start_level' => 1
|
623 |
-
);
|
624 |
-
|
625 |
-
//v1.2.1 holds information determined by the walker...
|
626 |
-
var $_cmw_walker = array();
|
627 |
-
|
628 |
-
/**
|
629 |
-
* class constructor
|
630 |
-
*/
|
631 |
-
function __construct() {
|
632 |
-
parent::__construct(
|
633 |
-
'custom-menu-wizard',
|
634 |
-
'Custom Menu Wizard',
|
635 |
-
array(
|
636 |
-
'classname' => 'widget_custom_menu_wizard',
|
637 |
-
'description' => __('Add a custom menu, or part of one, as a widget')
|
638 |
-
)
|
639 |
-
);
|
640 |
-
}
|
641 |
-
|
642 |
-
/**
|
643 |
-
* v1.2.1 stores any walker-determined information back into the widget instance
|
644 |
-
* gets run by the walker, on the filtered array of menu items, just before running parent::walk()
|
645 |
-
* only gets run *if* there are menu items found
|
646 |
-
*
|
647 |
-
* @param array $items Filtered menu items
|
648 |
-
* @param object $args
|
649 |
-
* @return array Menu items
|
650 |
-
*/
|
651 |
-
function cmw_filter_walker_items($items, $args){
|
652 |
-
if( !empty( $args->_custom_menu_wizard['_walker'] ) ){
|
653 |
-
$this->_cmw_walker = $args->_custom_menu_wizard['_walker'];
|
654 |
-
}
|
655 |
-
return $items;
|
656 |
-
}
|
657 |
-
|
658 |
-
/**
|
659 |
-
* this (filter: wp_nav_menu) merely removes itself from the filters and returns an empty string
|
660 |
-
* it gets added by the cmw_filter_check_for_no_items method below, and only
|
661 |
-
* ever gets run when hide_empty is set on the widget instance
|
662 |
-
*
|
663 |
-
* v1.1.0 As of WP v3.6 this method becomes superfluous because wp_nav_menu() has had code added to immediately
|
664 |
-
* cop out (return false) if the output from wp_nav_menu_{$menu->slug}_items filter(s) is empty.
|
665 |
-
* However, it stays in so as to cope with versions < 3.6
|
666 |
-
*
|
667 |
-
* @param string $nav_menu HTML for the menu
|
668 |
-
* @param object $args
|
669 |
-
* @return string HTML for the menu
|
670 |
-
*/
|
671 |
-
function cmw_filter_no_output_when_empty($nav_menu, $args){
|
672 |
-
remove_filter( 'wp_nav_menu', array( $this, 'cmw_filter_no_output_when_empty' ), 65532, 2 );
|
673 |
-
return empty( $args->_custom_menu_wizard ) ? $nav_menu : '';
|
674 |
-
}
|
675 |
-
|
676 |
-
/**
|
677 |
-
* this gets run (filter: wp_nav_menu_{$menu->slug}_items) if hide_empty is set
|
678 |
-
* if $items is empty then add a wp_nav_menu filter to do the actual return of an empty string
|
679 |
-
* it gets run before the wp_nav_menu filter, but it gets the $items array whereas the wp_nav_menu filter does not
|
680 |
-
* it gets added by $this->widget() before wp_nav_menu() is called, and removed immediately after wp_nav_menu() returns
|
681 |
-
*
|
682 |
-
* v1.1.0 As of WP v3.6 this method becomes superfluous because wp_nav_menu() has had code added to immediately
|
683 |
-
* cop out (return false) if the output from wp_nav_menu_{$menu->slug}_items filter(s) is empty.
|
684 |
-
* However, it stays in so as to cope with versions < 3.6
|
685 |
-
*
|
686 |
-
* @param array $items Menu items
|
687 |
-
* @param object $args
|
688 |
-
* @return array Menu items
|
689 |
-
*/
|
690 |
-
function cmw_filter_check_for_no_items($items, $args){
|
691 |
-
if( !empty( $args->_custom_menu_wizard ) && empty( $items ) ){
|
692 |
-
add_filter( 'wp_nav_menu', array( $this, 'cmw_filter_no_output_when_empty' ), 65532, 2 );
|
693 |
-
}
|
694 |
-
return $items;
|
695 |
-
}
|
696 |
-
|
697 |
-
/**
|
698 |
-
* produces the widget HTML at the front end
|
699 |
-
*
|
700 |
-
* @filters : custom_menu_wizard_nav_params array of params that will be sent to wp_nav_menu()
|
701 |
-
*
|
702 |
-
* @param object $args Widget arguments
|
703 |
-
* @param array $instance Configuration for this widget instance
|
704 |
-
*/
|
705 |
-
function widget($args, $instance) {
|
706 |
-
extract( $args, EXTR_SKIP );
|
707 |
-
|
708 |
-
//switches...
|
709 |
-
foreach( $this->_cmw_switches as $k=>$v ){
|
710 |
-
$instance[ $k ] = !empty( $instance[ $k ] );
|
711 |
-
}
|
712 |
-
//integers...
|
713 |
-
foreach( $this->_cmw_integers as $k=>$v ){
|
714 |
-
$instance[ $k ] = max( $v, intval( $instance[ $k ] ) );
|
715 |
-
}
|
716 |
-
//strings...
|
717 |
-
foreach( $this->_cmw_strings as $k=>$v ){
|
718 |
-
$instance[ $k ] = isset( $instance[ $k ] ) ? trim( $instance[ $k ] ) : $v; //bug in 2.0.2 fixed!
|
719 |
-
}
|
720 |
-
//html strings...
|
721 |
-
foreach( $this->_cmw_html as $k=>$v ){
|
722 |
-
$instance[ $k ] = empty( $instance[ $k ] ) ? $v : trim( $instance[ $k ] );
|
723 |
-
}
|
724 |
-
|
725 |
-
//v1.1.0 As of WP v3.6, wp_nav_menu() automatically prevents any HTML output if there are no items...
|
726 |
-
$instance['hide_empty'] = $instance['hide_empty'] && $this->_pre_3point6();
|
727 |
-
|
728 |
-
//fetch menu...
|
729 |
-
if( !empty($instance['menu'] ) ){
|
730 |
-
$menu = wp_get_nav_menu_object( $instance['menu'] );
|
731 |
-
|
732 |
-
//no menu, no output...
|
733 |
-
if ( !empty( $menu ) ){
|
734 |
|
|
|
|
|
|
|
|
|
|
|
|
|
735 |
if( !empty( $instance['widget_class'] ) ){
|
736 |
-
|
737 |
-
|
738 |
-
|
739 |
-
|
740 |
-
}
|
741 |
-
$before_widget = preg_replace( '/^(<\w+)(\s|>)/', '$1 class="' . $instance['widget_class'] . '"$2', $before_widget );
|
742 |
-
}
|
743 |
-
}
|
744 |
-
|
745 |
-
if( !empty( $instance['container_class'] ) ){
|
746 |
-
$instance['container_class'] = "menu-{$menu->slug}-container {$instance['container_class']}";
|
747 |
-
}
|
748 |
-
|
749 |
-
$instance['menu_class'] = preg_split( '/\s+/', $instance['menu_class'], -1, PREG_SPLIT_NO_EMPTY );
|
750 |
-
if( $instance['fallback_no_ancestor'] || $instance['fallback_no_children'] ){
|
751 |
-
//v1.2.1 add a cmw-fellback-maybe class to the menu and we'll remove or replace it later...
|
752 |
-
$instance['menu_class'][] = 'cmw-fellback-maybe';
|
753 |
}
|
754 |
-
|
755 |
|
756 |
-
|
757 |
-
$
|
758 |
-
|
759 |
-
'container' => $instance['container'] == 'none' ? false : $instance['container'],
|
760 |
-
'container_id' => $instance['container_id'],
|
761 |
-
'menu_class' => $instance['menu_class'],
|
762 |
-
'echo' => false,
|
763 |
-
'fallback_cb' => false,
|
764 |
-
'before' => $instance['before'],
|
765 |
-
'after' => $instance['after'],
|
766 |
-
'link_before' => $instance['link_before'],
|
767 |
-
'link_after' => $instance['link_after'],
|
768 |
-
'depth' => empty( $instance['flat_output'] ) ? $instance['depth'] : -1,
|
769 |
-
'walker' =>$walker,
|
770 |
-
//widget specific stuff...
|
771 |
-
'_custom_menu_wizard' => array(
|
772 |
-
'filter' => $instance['filter'],
|
773 |
-
'filter_item' => $instance['filter_item'],
|
774 |
-
'fallback_no_ancestor' => $instance['fallback_no_ancestor'], //v1.1.0
|
775 |
-
'fallback_include_parent' => $instance['fallback_include_parent'], //v1.1.0
|
776 |
-
'fallback_include_parent_siblings' => $instance['fallback_include_parent_siblings'], //v1.1.0
|
777 |
-
'fallback_no_children' => $instance['fallback_no_children'], //v1.2.0
|
778 |
-
'fallback_nc_include_parent' => $instance['fallback_nc_include_parent'], //v1.2.0
|
779 |
-
'fallback_nc_include_parent_siblings' => $instance['fallback_nc_include_parent_siblings'], //v1.2.0
|
780 |
-
'include_parent' => $instance['include_parent'],
|
781 |
-
'include_parent_siblings' => $instance['include_parent_siblings'], //v1.1.0
|
782 |
-
'include_ancestors' => $instance['include_ancestors'],
|
783 |
-
'title_from_parent' => $instance['title_from_parent'],
|
784 |
-
'title_from_current' => $instance['title_from_current'], //v1.2.0
|
785 |
-
'ol_root' => $instance['ol_root'],
|
786 |
-
'ol_sub' => $instance['ol_sub'],
|
787 |
-
'flat_output' => $instance['flat_output'],
|
788 |
-
'start_level' => $instance['start_level'],
|
789 |
-
'depth' => $instance['depth'],
|
790 |
-
'depth_rel_current' => $instance['depth_rel_current'], //v2.0.0
|
791 |
-
'contains_current' => $instance['contains_current'], //v2.0.0
|
792 |
-
'items' => $instance['items'], //v2.0.0
|
793 |
-
//v1.2.1 this is for the walker's use...
|
794 |
-
'_walker' => array()
|
795 |
-
)
|
796 |
-
);
|
797 |
-
if( $instance['ol_root'] ){
|
798 |
-
$params['items_wrap'] = '<ol id="%1$s" class="%2$s">%3$s</ol>';
|
799 |
-
}
|
800 |
-
if( !empty( $instance['container_class'] ) ){
|
801 |
-
$params['container_class'] = $instance['container_class'];
|
802 |
-
}
|
803 |
|
804 |
-
|
805 |
-
|
806 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
807 |
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
808 |
|
809 |
-
|
810 |
-
$out = wp_nav_menu( apply_filters( 'custom_menu_wizard_nav_params', $params ) );
|
811 |
|
812 |
-
|
813 |
-
|
814 |
-
|
|
|
|
|
|
|
|
|
|
|
815 |
}
|
816 |
-
|
817 |
-
|
818 |
-
|
819 |
-
|
820 |
-
|
821 |
-
|
822 |
-
|
823 |
-
|
824 |
-
if( $instance['title_from_parent'] && !empty( $this->_cmw_walker['parent_title'] ) ){
|
825 |
-
$title = $this->_cmw_walker['parent_title'];
|
826 |
-
}
|
827 |
-
if( empty( $title ) && $instance['title_from_current'] && !empty( $this->_cmw_walker['current_title'] ) ){
|
828 |
-
$title = $this->_cmw_walker['current_title'];
|
829 |
-
}
|
830 |
-
if( empty( $title ) ){
|
831 |
-
$title = $instance['hide_title'] ? '' : $instance['title'];
|
832 |
-
}
|
833 |
-
|
834 |
-
//remove/replace the cmw-fellback-maybe class...
|
835 |
-
$out = str_replace(
|
836 |
-
'cmw-fellback-maybe',
|
837 |
-
empty( $this->_cmw_walker['fellback'] ) ? '' : 'cmw-fellback-' . $this->_cmw_walker['fellback'],
|
838 |
-
$out );
|
839 |
-
|
840 |
-
echo $before_widget;
|
841 |
-
if ( !empty($title) ){
|
842 |
-
echo $before_title . apply_filters('widget_title', $title, $instance, $this->id_base) . $after_title;
|
843 |
}
|
844 |
-
echo $out . $after_widget;
|
845 |
}
|
846 |
}
|
847 |
-
|
848 |
-
}
|
849 |
-
|
850 |
-
/**
|
851 |
-
* updates the widget settings sent from the backend admin
|
852 |
-
*/
|
853 |
-
function update( $new_instance, $old_instance ) {
|
854 |
-
$instance = $old_instance;
|
855 |
|
856 |
-
|
857 |
-
|
858 |
-
|
859 |
-
|
860 |
-
|
861 |
-
|
862 |
-
|
863 |
-
|
864 |
-
|
865 |
-
|
866 |
-
|
867 |
-
|
868 |
-
|
869 |
-
|
870 |
-
|
871 |
-
|
872 |
-
|
873 |
-
|
874 |
-
|
875 |
-
|
876 |
-
|
877 |
-
|
878 |
-
|
879 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
880 |
}
|
|
|
881 |
}
|
882 |
-
$instance['items'] = implode( $sep, $a );
|
883 |
-
}
|
884 |
-
|
885 |
-
return $instance;
|
886 |
-
}
|
887 |
-
|
888 |
-
/**
|
889 |
-
* produces the backend admin form(s)
|
890 |
-
*/
|
891 |
-
function form( $instance ) {
|
892 |
-
|
893 |
-
//switches...
|
894 |
-
foreach( $this->_cmw_switches as $k=>$v ){
|
895 |
-
$instance[ $k ] = isset( $instance[ $k ] ) ? !empty( $instance[ $k ] ) : !empty( $v );
|
896 |
-
}
|
897 |
-
//integers...
|
898 |
-
foreach( $this->_cmw_integers as $k=>$v ){
|
899 |
-
$instance[ $k ] = isset( $instance[ $k ]) ? max( $v, intval( $instance[ $k ] ) ) : max($v, 0);
|
900 |
-
}
|
901 |
-
//strings...
|
902 |
-
foreach( $this->_cmw_strings as $k=>$v ){
|
903 |
-
$instance[ $k ] = isset( $instance[ $k ] ) ? esc_attr( trim( $instance[ $k ] ) ) : $v;
|
904 |
-
}
|
905 |
-
//html strings...
|
906 |
-
foreach( $this->_cmw_html as $k=>$v ){
|
907 |
-
$instance[ $k ] = isset( $instance[ $k ] ) ? esc_html( trim( $instance[ $k ] ) ) : $v;
|
908 |
-
}
|
909 |
|
910 |
-
|
911 |
-
|
912 |
-
|
913 |
-
|
914 |
-
|
915 |
-
|
916 |
-
|
917 |
-
|
|
|
|
|
|
|
|
|
|
|
918 |
}
|
919 |
-
|
920 |
-
|
921 |
-
|
922 |
-
|
923 |
-
|
924 |
-
|
925 |
-
|
926 |
-
|
927 |
-
|
928 |
-
|
929 |
-
<div class="widget-<?php echo $this->id_base; ?>-onchange"
|
930 |
-
data-cmw-dialog-title='<?php _e('Selected Menu : '); ?>'
|
931 |
-
data-cmw-dialog-prompt='<?php _e('Click an item to toggle "Current Menu Item"'); ?>'
|
932 |
-
data-cmw-dialog-output='<?php _e('Basic Output'); ?>'
|
933 |
-
data-cmw-dialog-fallback='<?php _e('Fallback invoked'); ?>'
|
934 |
-
data-cmw-dialog-trigger='#<?php echo $this->get_field_id('filter_item'); ?>'
|
935 |
-
data-cmw-dialog-id='<?php echo $this->get_field_id('dialog'); ?>'>
|
936 |
-
<?php
|
937 |
-
|
938 |
-
/**
|
939 |
-
* permanently visible section : Title (with Hide) and Menu
|
940 |
-
*/
|
941 |
-
?>
|
942 |
-
<p>
|
943 |
-
<label for="<?php echo $this->get_field_id('title'); ?>"><?php _e('Title:') ?></label>
|
944 |
-
<label class="alignright">
|
945 |
-
<input id="<?php echo $this->get_field_id('hide_title'); ?>" name="<?php echo $this->get_field_name('hide_title'); ?>"
|
946 |
-
type="checkbox" value="1" <?php checked( $instance['hide_title'] ); ?> />
|
947 |
-
<?php _e('Hide'); ?></label>
|
948 |
-
<input id="<?php echo $this->get_field_id('title'); ?>" class="widefat" name="<?php echo $this->get_field_name('title'); ?>"
|
949 |
-
type="text" value="<?php echo $instance['title']; ?>" />
|
950 |
-
<small><em><?php _e('Title can be set, but need not be displayed'); ?></em></small>
|
951 |
-
</p>
|
952 |
-
|
953 |
-
<p>
|
954 |
-
<small class="cmw-toggle-assist">
|
955 |
-
<a class="widget-<?php echo $this->id_base; ?>-toggle-assist" href="#"><?php _e('assist'); ?></a>
|
956 |
-
</small>
|
957 |
-
<label for="<?php echo $this->get_field_id('menu'); ?>"><?php _e('Select Menu:'); ?></label>
|
958 |
-
<select id="<?php echo $this->get_field_id('menu'); ?>"
|
959 |
-
class="widget-<?php echo $this->id_base; ?>-selectmenu widget-<?php echo $this->id_base; ?>-listen"
|
960 |
-
name="<?php echo $this->get_field_name('menu'); ?>">
|
961 |
-
<?php
|
962 |
-
foreach( $menus as $i=>$menu ){
|
963 |
-
if( !empty( $menu->_items ) ){
|
964 |
-
?>
|
965 |
-
<option <?php selected($instance['menu'], $menu->term_id); ?> value="<?php echo $menu->term_id; ?>"><?php echo $menu->name; ?></option>
|
966 |
-
<?php
|
967 |
-
}
|
968 |
-
}
|
969 |
-
?>
|
970 |
-
</select>
|
971 |
-
</p>
|
972 |
-
|
973 |
-
<?php
|
974 |
-
/**
|
975 |
-
* start collapsible section : 'Filter'
|
976 |
-
*/
|
977 |
-
$this->_open_a_field_section($instance, 'Filter', 'fs_filter');
|
978 |
-
?>
|
979 |
-
<p>
|
980 |
-
<small class="cmw-toggle-assist">
|
981 |
-
<a class="widget-<?php echo $this->id_base; ?>-toggle-assist" href="#"><?php _e('assist'); ?></a>
|
982 |
-
</small>
|
983 |
-
<label>
|
984 |
-
<input id="<?php echo $this->get_field_id('filter'); ?>_0"
|
985 |
-
class="widget-<?php echo $this->id_base; ?>-showall widget-<?php echo $this->id_base; ?>-listen"
|
986 |
-
name="<?php echo $this->get_field_name('filter'); ?>" type="radio" value="0" <?php checked($instance['filter'], 0); ?> />
|
987 |
-
<?php _e('Show all'); ?></label>
|
988 |
-
<br /><label>
|
989 |
-
<input id="<?php echo $this->get_field_id('filter'); ?>_1" class="widget-<?php echo $this->id_base; ?>-listen"
|
990 |
-
name="<?php echo $this->get_field_name('filter'); ?>" type="radio" value="1" <?php checked($instance['filter'], 1); ?> />
|
991 |
-
<?php _e('Children of:'); ?></label>
|
992 |
-
<select id="<?php echo $this->get_field_id('filter_item'); ?>"
|
993 |
-
class="widget-<?php echo $this->id_base; ?>-childrenof widget-<?php echo $this->id_base; ?>-listen"
|
994 |
-
name="<?php echo $this->get_field_name('filter_item'); ?>">
|
995 |
-
<option value="0" <?php selected( $instance['filter_item'], 0 ); ?>><?php _e('Current Item'); ?></option>
|
996 |
-
<option value="-2" <?php selected( $instance['filter_item'], -2 ); ?>><?php _e('Current Root Item'); ?></option>
|
997 |
-
<option value="-1" <?php selected( $instance['filter_item'], -1 ); ?>><?php _e('Current Parent Item'); ?></option>
|
998 |
-
<?php
|
999 |
-
//v1.1.0
|
1000 |
-
// IE is a pita when it comes to SELECTs because it ignores any styling on OPTGROUPs and OPTIONs, so I'm changing the way
|
1001 |
-
// that this SELECT works by introducing a copy from which the javascript can pick the relevant OPTGROUP
|
1002 |
-
$menuOptions = array();
|
1003 |
-
|
1004 |
-
$maxlevel = 1;
|
1005 |
-
foreach( $menus as $i=>$menu ){
|
1006 |
-
//as of v1.2.0 : no items, no optgroup!
|
1007 |
-
if( !empty( $menu->_items ) ){
|
1008 |
-
$grpdata = array();
|
1009 |
-
$itemindents = array( '0' => array( 'level'=>0, 'grpkey'=>'' ) );
|
1010 |
-
$menuGrpOpts = array();
|
1011 |
-
foreach( $menu->_items as $item ){
|
1012 |
-
//exclude orpans!
|
1013 |
-
if( isset($itemindents[ $item->menu_item_parent ])){
|
1014 |
-
$title = apply_filters( 'the_title', $item->title, $item->ID );
|
1015 |
-
$level = $itemindents[ $item->menu_item_parent ]['level'] + 1;
|
1016 |
-
$grpkey = $item->ID . '|' . $title;
|
1017 |
-
$grpdata[ $grpkey ] = array();
|
1018 |
-
if( !empty( $itemindents[ $item->menu_item_parent ]['grpkey'] )){
|
1019 |
-
$grpdata[ $itemindents[ $item->menu_item_parent ]['grpkey'] ][ $grpkey ] = array();
|
1020 |
}
|
1021 |
-
|
1022 |
-
$itemindents[ $item->ID ] = array( 'level'=>$level, 'grpkey'=>$grpkey );
|
1023 |
-
$maxlevel = max( $maxlevel, $level );
|
1024 |
-
//v2.0.0 indents changed to non-breaking spaces...
|
1025 |
-
$menuGrpOpts[] = '<option value="' . $item->ID . '" ' .
|
1026 |
-
selected( $instance['filter_item'], $item->ID, false ) . '>' .
|
1027 |
-
str_repeat( ' ', ($level - 1) * 3 ) . $title . '</option>';
|
1028 |
}
|
1029 |
}
|
1030 |
-
|
1031 |
-
//
|
1032 |
-
|
1033 |
-
|
1034 |
-
|
1035 |
-
|
1036 |
-
|
1037 |
-
|
1038 |
-
|
1039 |
-
|
1040 |
-
|
|
|
1041 |
}
|
1042 |
}
|
1043 |
-
$grpdata = json_encode( $grpdata );
|
1044 |
-
$menuOptions[] = '<optgroup label="' . $menu->name . '" data-cmw-optgroup-index="' . $i . '" data-cmw-items="' . esc_attr($grpdata) . '">';
|
1045 |
-
$menuOptions[] = implode("\n", $menuGrpOpts);
|
1046 |
-
$menuOptions[] = '</optgroup>';
|
1047 |
}
|
1048 |
-
unset( $
|
1049 |
-
|
1050 |
-
|
1051 |
-
|
1052 |
-
|
1053 |
-
|
1054 |
-
|
1055 |
-
|
1056 |
-
|
1057 |
-
|
1058 |
-
|
1059 |
-
<?php _e('Items:'); ?></label>
|
1060 |
-
<input id="<?php echo $this->get_field_id('items'); ?>" class="widget-<?php echo $this->id_base; ?>-setitems"
|
1061 |
-
name="<?php echo $this->get_field_name('items'); ?>" type="text" value="<?php echo $instance['items']; ?>" />
|
1062 |
-
|
1063 |
-
<select id="<?php echo $this->get_field_id('filter_item_ignore'); ?>" disabled="disabled"
|
1064 |
-
class='cmw-off-the-page' name="<?php echo $this->get_field_name('filter_item_ignore'); ?>">
|
1065 |
-
<?php echo $menuOptions; ?>
|
1066 |
-
</select>
|
1067 |
-
</p>
|
1068 |
-
|
1069 |
-
<p class="widget-<?php echo $this->id_base; ?>-disableif-ss">
|
1070 |
-
<label for="<?php echo $this->get_field_id('start_level'); ?>"><?php _e('Starting Level:'); ?></label>
|
1071 |
-
<select id="<?php echo $this->get_field_id('start_level'); ?>" name="<?php echo $this->get_field_name('start_level'); ?>">
|
1072 |
-
<?php
|
1073 |
-
$j = max( $maxlevel, $instance['start_level'] );
|
1074 |
-
for( $i = 1; $i <= $j; $i++ ){
|
1075 |
-
?>
|
1076 |
-
<option value="<?php echo $i; ?>" <?php selected($instance['start_level'], $i); ?>><?php echo $i; ?></option>
|
1077 |
-
<?php
|
1078 |
-
}
|
1079 |
-
?>
|
1080 |
-
</select>
|
1081 |
-
<br /><small><em><?php _e('Level to start testing items for inclusion'); ?></em></small>
|
1082 |
-
</p>
|
1083 |
-
|
1084 |
-
<p class="widget-<?php echo $this->id_base; ?>-disableif-ss">
|
1085 |
-
<label for="<?php echo $this->get_field_id('depth'); ?>"><?php _e('For Depth:'); ?></label>
|
1086 |
-
<select id="<?php echo $this->get_field_id('depth'); ?>" name="<?php echo $this->get_field_name('depth'); ?>">
|
1087 |
-
<option value="0" <?php selected( $instance['depth'], 0 ); ?>><?php _e('unlimited'); ?></option>
|
1088 |
-
<?php
|
1089 |
-
$j = max( $j, $instance['depth'] );
|
1090 |
-
for( $i = 1; $i <= $j; $i++ ){
|
1091 |
-
?>
|
1092 |
-
<option value="<?php echo $i; ?>" <?php selected( $instance['depth'], $i ); ?>><?php echo $i; ?> <?php _e($i > 1 ? 'levels' : 'level'); ?></option>
|
1093 |
-
<?php
|
1094 |
-
}
|
1095 |
-
?>
|
1096 |
-
</select>
|
1097 |
-
<br /><small><em><?php _e('Relative to first Filter item found, <strong>unless</strong>…'); ?></em></small>
|
1098 |
-
<br /><label>
|
1099 |
-
<input id="<?php echo $this->get_field_id('depth_rel_current'); ?>"
|
1100 |
-
name="<?php echo $this->get_field_name('depth_rel_current'); ?>" type="checkbox" value="1"
|
1101 |
-
<?php checked($instance['depth_rel_current']); ?> />
|
1102 |
-
<?php _e('Relative to "Current" Item <small><em>(if found)</em></small>'); ?></label>
|
1103 |
-
</p>
|
1104 |
-
<?php $this->_close_a_field_section(); ?>
|
1105 |
-
|
1106 |
-
<?php
|
1107 |
-
/**
|
1108 |
-
* v1.2.0 start collapsible section : 'Fallbacks'
|
1109 |
-
*/
|
1110 |
-
$this->_open_a_field_section($instance, 'Fallbacks', 'fs_fallbacks');
|
1111 |
-
?>
|
1112 |
-
<p class="clear widget-<?php echo $this->id_base; ?>-disableifnot-rp">
|
1113 |
-
<small class="cmw-toggle-assist">
|
1114 |
-
<a class="widget-<?php echo $this->id_base; ?>-toggle-assist" href="#"><?php _e('assist'); ?></a>
|
1115 |
-
</small>
|
1116 |
-
<small><strong><?php _e( 'If "Children of" is <em>Current Root / Parent Item</em>, and no ancestor exists' ); ?> :</strong></small>
|
1117 |
-
<br /><label>
|
1118 |
-
<input id="<?php echo $this->get_field_id('fallback_no_ancestor'); ?>"
|
1119 |
-
name="<?php echo $this->get_field_name('fallback_no_ancestor'); ?>" type="checkbox" value="1"
|
1120 |
-
<?php checked($instance['fallback_no_ancestor']); ?> />
|
1121 |
-
<?php _e('Switch to Current Item, and'); ?></label>
|
1122 |
-
<br /><label class="cmw-pad-left-1">
|
1123 |
-
<input id="<?php echo $this->get_field_id('fallback_include_parent'); ?>"
|
1124 |
-
name="<?php echo $this->get_field_name('fallback_include_parent'); ?>" type="checkbox" value="1"
|
1125 |
-
<?php checked($instance['fallback_include_parent']); ?> />
|
1126 |
-
<?php _e('Include Parent...'); ?> </label>
|
1127 |
-
<label>
|
1128 |
-
<input id="<?php echo $this->get_field_id('fallback_include_parent_siblings'); ?>"
|
1129 |
-
name="<?php echo $this->get_field_name('fallback_include_parent_siblings'); ?>" type="checkbox" value="1"
|
1130 |
-
<?php checked($instance['fallback_include_parent_siblings']); ?> />
|
1131 |
-
<?php _e('with Siblings'); ?></label>
|
1132 |
-
</p>
|
1133 |
-
|
1134 |
-
<p class="widget-<?php echo $this->id_base; ?>-disableifnot-ci">
|
1135 |
-
<small><strong><?php _e( 'If "Children of" is <em>Current Item</em>, and current item has no children' ); ?> :</strong></small>
|
1136 |
-
<br /><label>
|
1137 |
-
<input id="<?php echo $this->get_field_id('fallback_no_children'); ?>"
|
1138 |
-
name="<?php echo $this->get_field_name('fallback_no_children'); ?>" type="checkbox" value="1"
|
1139 |
-
<?php checked($instance['fallback_no_children']); ?> />
|
1140 |
-
<?php _e('Switch to Current Parent Item, and'); ?></label>
|
1141 |
-
<br /><label class="cmw-pad-left-1">
|
1142 |
-
<input id="<?php echo $this->get_field_id('fallback_nc_include_parent'); ?>"
|
1143 |
-
name="<?php echo $this->get_field_name('fallback_nc_include_parent'); ?>" type="checkbox" value="1"
|
1144 |
-
<?php checked($instance['fallback_nc_include_parent']); ?> />
|
1145 |
-
<?php _e('Include Parent...'); ?> </label>
|
1146 |
-
<label>
|
1147 |
-
<input id="<?php echo $this->get_field_id('fallback_nc_include_parent_siblings'); ?>"
|
1148 |
-
name="<?php echo $this->get_field_name('fallback_nc_include_parent_siblings'); ?>" type="checkbox" value="1"
|
1149 |
-
<?php checked($instance['fallback_nc_include_parent_siblings']); ?> />
|
1150 |
-
<?php _e('with Siblings'); ?></label>
|
1151 |
-
</p>
|
1152 |
-
|
1153 |
-
|
1154 |
-
<?php $this->_close_a_field_section(); ?>
|
1155 |
-
|
1156 |
-
<?php
|
1157 |
-
/**
|
1158 |
-
* start collapsible section : 'Output'
|
1159 |
-
*/
|
1160 |
-
$this->_open_a_field_section($instance, 'Output', 'fs_output');
|
1161 |
-
?>
|
1162 |
-
<p>
|
1163 |
-
<small class="cmw-toggle-assist">
|
1164 |
-
<a class="widget-<?php echo $this->id_base; ?>-toggle-assist" href="#"><?php _e('assist'); ?></a>
|
1165 |
-
</small>
|
1166 |
-
<label>
|
1167 |
-
<input id="<?php echo $this->get_field_id('flat_output'); ?>_0" name="<?php echo $this->get_field_name('flat_output'); ?>"
|
1168 |
-
type="radio" value="0" <?php checked(!$instance['flat_output']); ?> />
|
1169 |
-
<?php _e('Hierarchical'); ?></label>
|
1170 |
-
<label>
|
1171 |
-
<input id="<?php echo $this->get_field_id('flat_output'); ?>_1" name="<?php echo $this->get_field_name('flat_output'); ?>"
|
1172 |
-
type="radio" value="1" <?php checked($instance['flat_output']); ?> />
|
1173 |
-
<?php _e('Flat'); ?></label>
|
1174 |
-
</p>
|
1175 |
-
|
1176 |
-
<p>
|
1177 |
-
<label>
|
1178 |
-
<input id="<?php echo $this->get_field_id('contains_current'); ?>"
|
1179 |
-
name="<?php echo $this->get_field_name('contains_current'); ?>" type="checkbox"
|
1180 |
-
value="1" <?php checked($instance['contains_current']); ?> />
|
1181 |
-
<?php _e('Must Contain "Current" Item'); ?></label>
|
1182 |
-
<br /><small><em><?php _e('Checks both Filtered and Included items'); ?></em></small>
|
1183 |
-
</p>
|
1184 |
-
|
1185 |
-
<p class="widget-<?php echo $this->id_base; ?>-disableif">
|
1186 |
-
<label>
|
1187 |
-
<input id="<?php echo $this->get_field_id('include_parent'); ?>"
|
1188 |
-
name="<?php echo $this->get_field_name('include_parent'); ?>" type="checkbox"
|
1189 |
-
value="1" <?php checked($instance['include_parent']); ?> />
|
1190 |
-
<?php _e('Include Parent...'); ?> </label>
|
1191 |
-
<label>
|
1192 |
-
<input id="<?php echo $this->get_field_id('include_parent_siblings'); ?>"
|
1193 |
-
name="<?php echo $this->get_field_name('include_parent_siblings'); ?>" type="checkbox"
|
1194 |
-
value="1" <?php checked($instance['include_parent_siblings']); ?> />
|
1195 |
-
<?php _e('with Siblings'); ?></label>
|
1196 |
-
<br /><label>
|
1197 |
-
<input id="<?php echo $this->get_field_id('include_ancestors'); ?>"
|
1198 |
-
name="<?php echo $this->get_field_name('include_ancestors'); ?>" type="checkbox"
|
1199 |
-
value="1" <?php checked($instance['include_ancestors']); ?> />
|
1200 |
-
<?php _e('Include Ancestors'); ?></label>
|
1201 |
-
<br /><label>
|
1202 |
-
<input id="<?php echo $this->get_field_id('title_from_parent'); ?>"
|
1203 |
-
name="<?php echo $this->get_field_name('title_from_parent'); ?>" type="checkbox"
|
1204 |
-
value="1" <?php checked($instance['title_from_parent']); ?> />
|
1205 |
-
<?php _e('Title from Parent'); ?></label>
|
1206 |
-
<br /><small><em><?php _e('Only if the "Children of" Filter returns items'); ?></em></small>
|
1207 |
-
</p>
|
1208 |
-
|
1209 |
-
<p>
|
1210 |
-
<label>
|
1211 |
-
<input id="<?php echo $this->get_field_id('title_from_current'); ?>"
|
1212 |
-
name="<?php echo $this->get_field_name('title_from_current'); ?>" type="checkbox"
|
1213 |
-
value="1" <?php checked($instance['title_from_current']); ?> />
|
1214 |
-
<?php _e('Title from "Current" Item'); ?></label>
|
1215 |
-
<br /><small><em><?php _e('Lower priority than "Title from Parent"'); ?></em></small>
|
1216 |
-
</p>
|
1217 |
-
|
1218 |
-
<p>
|
1219 |
-
<?php _e('Change UL to OL:'); ?>
|
1220 |
-
<br /><label>
|
1221 |
-
<input id="<?php echo $this->get_field_id('ol_root'); ?>" name="<?php echo $this->get_field_name('ol_root'); ?>"
|
1222 |
-
type="checkbox" value="1" <?php checked($instance['ol_root']); ?> />
|
1223 |
-
<?php _e('Top Level'); ?></label>
|
1224 |
-
<label>
|
1225 |
-
<input id="<?php echo $this->get_field_id('ol_sub'); ?>" name="<?php echo $this->get_field_name('ol_sub'); ?>"
|
1226 |
-
type="checkbox" value="1" <?php checked($instance['ol_sub']); ?> />
|
1227 |
-
<?php _e('Sub-Levels'); ?></label>
|
1228 |
-
</p>
|
1229 |
-
|
1230 |
-
<?php
|
1231 |
-
//v1.1.0 As of WP v3.6, wp_nav_menu() automatically cops out (without outputting any HTML) if there are no items,
|
1232 |
-
// so the hide_empty option becomes superfluous; however, I'll keep the previous setting (if there was one)
|
1233 |
-
// in case of reversion to an earlier version of WP...
|
1234 |
-
if( $this->_pre_3point6() ){
|
1235 |
-
?>
|
1236 |
-
<p>
|
1237 |
-
<label>
|
1238 |
-
<input id="<?php echo $this->get_field_id('hide_empty'); ?>" name="<?php echo $this->get_field_name('hide_empty'); ?>"
|
1239 |
-
type="checkbox" value="1" <?php checked($instance['hide_empty']); ?> />
|
1240 |
-
<?php _e('Hide Widget if Empty'); ?></label>
|
1241 |
-
<br /><small><em><?php _e('Prevents any output when no items are found'); ?></em></small>
|
1242 |
-
</p>
|
1243 |
-
<?php }else{ ?>
|
1244 |
-
<input id="<?php echo $this->get_field_id('hide_empty'); ?>" name="<?php echo $this->get_field_name('hide_empty'); ?>"
|
1245 |
-
type="hidden" value="<?php echo $instance['hide_empty'] ? '1' : ''; ?>" />
|
1246 |
-
<?php } ?>
|
1247 |
-
|
1248 |
-
<?php $this->_close_a_field_section(); ?>
|
1249 |
-
|
1250 |
-
<?php
|
1251 |
-
/**
|
1252 |
-
* start collapsible section : 'Container'
|
1253 |
-
*/
|
1254 |
-
$this->_open_a_field_section($instance, 'Container', 'fs_container');
|
1255 |
-
?>
|
1256 |
-
<p>
|
1257 |
-
<label for="<?php echo $this->get_field_id('container'); ?>"><?php _e('Element:') ?></label>
|
1258 |
-
<input id="<?php echo $this->get_field_id('container'); ?>" name="<?php echo $this->get_field_name('container'); ?>"
|
1259 |
-
type="text" value="<?php echo $instance['container']; ?>" />
|
1260 |
-
<br /><small><em><?php _e( 'Eg. div or nav; leave empty for no container' ); ?></em></small>
|
1261 |
-
</p>
|
1262 |
-
<p>
|
1263 |
-
<label for="<?php echo $this->get_field_id('container_id'); ?>"><?php _e('Unique ID:') ?></label>
|
1264 |
-
<input id="<?php echo $this->get_field_id('container_id'); ?>" name="<?php echo $this->get_field_name('container_id'); ?>"
|
1265 |
-
type="text" value="<?php echo $instance['container_id']; ?>" />
|
1266 |
-
<br /><small><em><?php _e( 'An optional ID for the container' ); ?></em></small>
|
1267 |
-
</p>
|
1268 |
-
<p>
|
1269 |
-
<label for="<?php echo $this->get_field_id('container_class'); ?>"><?php _e('Class:') ?></label>
|
1270 |
-
<input id="<?php echo $this->get_field_id('container_class'); ?>" name="<?php echo $this->get_field_name('container_class'); ?>"
|
1271 |
-
type="text" value="<?php echo $instance['container_class']; ?>" />
|
1272 |
-
<br /><small><em><?php _e( 'Extra class for the container' ); ?></em></small>
|
1273 |
-
</p>
|
1274 |
-
<?php $this->_close_a_field_section(); ?>
|
1275 |
-
|
1276 |
-
<?php
|
1277 |
-
/**
|
1278 |
-
* start collapsible section : 'Classes'
|
1279 |
-
*/
|
1280 |
-
$this->_open_a_field_section($instance, 'Classes', 'fs_classes');
|
1281 |
-
?>
|
1282 |
-
<p>
|
1283 |
-
<label for="<?php echo $this->get_field_id('menu_class'); ?>"><?php _e('Menu Class:') ?></label>
|
1284 |
-
<input id="<?php echo $this->get_field_id('menu_class'); ?>" name="<?php echo $this->get_field_name('menu_class'); ?>"
|
1285 |
-
type="text" value="<?php echo $instance['menu_class']; ?>" />
|
1286 |
-
<br /><small><em><?php _e( 'Class for the list element forming the menu' ); ?></em></small>
|
1287 |
-
</p>
|
1288 |
-
<p>
|
1289 |
-
<label for="<?php echo $this->get_field_id('widget_class'); ?>"><?php _e('Widget Class:') ?></label>
|
1290 |
-
<input id="<?php echo $this->get_field_id('widget_class'); ?>" name="<?php echo $this->get_field_name('widget_class'); ?>"
|
1291 |
-
type="text" value="<?php echo $instance['widget_class']; ?>" />
|
1292 |
-
<br /><small><em><?php _e( 'Extra class for the widget itself' ); ?></em></small>
|
1293 |
-
</p>
|
1294 |
-
<?php $this->_close_a_field_section(); ?>
|
1295 |
-
|
1296 |
-
<?php
|
1297 |
-
/**
|
1298 |
-
* start collapsible section : 'Links'
|
1299 |
-
*/
|
1300 |
-
$this->_open_a_field_section($instance, 'Links', 'fs_links');
|
1301 |
-
?>
|
1302 |
-
<p>
|
1303 |
-
<label for="<?php echo $this->get_field_id('before'); ?>"><?php _e('Before the Link:') ?></label>
|
1304 |
-
<input id="<?php echo $this->get_field_id('before'); ?>" class="widefat" name="<?php echo $this->get_field_name('before'); ?>"
|
1305 |
-
type="text" value="<?php echo $instance['before']; ?>" />
|
1306 |
-
<small><em><?php _e( htmlspecialchars('Text/HTML to go before the <a> of the link') ); ?></em></small>
|
1307 |
-
</p>
|
1308 |
-
<p>
|
1309 |
-
<label for="<?php echo $this->get_field_id('after'); ?>"><?php _e('After the Link:') ?></label>
|
1310 |
-
<input id="<?php echo $this->get_field_id('after'); ?>" class="widefat" name="<?php echo $this->get_field_name('after'); ?>"
|
1311 |
-
type="text" value="<?php echo $instance['after']; ?>" />
|
1312 |
-
<small><em><?php _e( htmlspecialchars('Text/HTML to go after the </a> of the link') ); ?></em></small>
|
1313 |
-
</p>
|
1314 |
-
<p>
|
1315 |
-
<label for="<?php echo $this->get_field_id('link_before'); ?>"><?php _e('Before the Link Text:') ?></label>
|
1316 |
-
<input id="<?php echo $this->get_field_id('link_before'); ?>" class="widefat" name="<?php echo $this->get_field_name('link_before'); ?>"
|
1317 |
-
type="text" value="<?php echo $instance['link_before']; ?>" />
|
1318 |
-
<small><em><?php _e( 'Text/HTML to go before the link text' ); ?></em></small>
|
1319 |
-
</p>
|
1320 |
-
<p>
|
1321 |
-
<label for="<?php echo $this->get_field_id('link_after'); ?>"><?php _e('After the Link Text:') ?></label>
|
1322 |
-
<input id="<?php echo $this->get_field_id('link_after'); ?>" class="widefat" name="<?php echo $this->get_field_name('link_after'); ?>"
|
1323 |
-
type="text" value="<?php echo $instance['link_after']; ?>" />
|
1324 |
-
<small><em><?php _e( 'Text/HTML to go after the link text' ); ?></em></small>
|
1325 |
-
</p>
|
1326 |
-
<?php $this->_close_a_field_section(); ?>
|
1327 |
-
|
1328 |
-
<script type="text/javascript">jQuery(function($){$('#<?php echo $this->get_field_id('menu'); ?>').trigger('change');})</script>
|
1329 |
-
|
1330 |
-
</div>
|
1331 |
-
|
1332 |
-
<?php
|
1333 |
-
} //end form()
|
1334 |
-
|
1335 |
-
/**
|
1336 |
-
* outputs the HTML to begin a collapsible/expandable group of settings
|
1337 |
-
*
|
1338 |
-
* @param array $instance
|
1339 |
-
* @param string $text Label
|
1340 |
-
* @param string $fname Field name
|
1341 |
-
*/
|
1342 |
-
function _open_a_field_section( &$instance, $text, $fname ){
|
1343 |
-
?>
|
1344 |
-
<div class="stuffbox widget-<?php echo $this->id_base; ?>-collapsible-fieldset" title="<?php _e( 'Click to show/hide' ); ?>">
|
1345 |
-
<input id="<?php echo $this->get_field_id($fname); ?>" class="hidden-field" name="<?php echo $this->get_field_name($fname); ?>"
|
1346 |
-
type="checkbox" value="1" <?php checked( $instance[$fname] ); ?> />
|
1347 |
-
<div style="background-image:url(images/arrows.png);" class="<?php echo $instance[$fname] ? 'cmw-collapsed-fieldset' : ''; ?>"></div>
|
1348 |
-
<h4><?php _e( $text ); ?></h4>
|
1349 |
-
</div>
|
1350 |
-
<div class="<?php echo $instance[$fname] ? 'cmw-start-fieldset-collapsed' : ''; ?>">
|
1351 |
-
<?php
|
1352 |
-
} //end _open_a_field_section()
|
1353 |
-
|
1354 |
-
/**
|
1355 |
-
* outputs the HTML to close off a collapsible/expandable group of settings
|
1356 |
-
*/
|
1357 |
-
function _close_a_field_section(){
|
1358 |
-
?>
|
1359 |
-
</div>
|
1360 |
-
<?php
|
1361 |
-
} //end _close_a_field_section()
|
1362 |
-
|
1363 |
-
/**
|
1364 |
-
* returns true if the version of WP is lower than 3.6 (ie. 3.5* or below)
|
1365 |
-
*/
|
1366 |
-
function _pre_3point6(){
|
1367 |
-
global $wp_version;
|
1368 |
-
|
1369 |
-
return version_compare( strtolower( $wp_version ), '3.6a', '<' );
|
1370 |
-
} //end _pre_3point6()
|
1371 |
-
|
1372 |
-
} //end of class
|
1373 |
-
|
1374 |
-
/**
|
1375 |
-
* as of v1.2.0
|
1376 |
-
* shortcode processing for [custom_menu_wizard option="" option="" ...]
|
1377 |
-
* see wp-includes/widgets.php for the_widget() code
|
1378 |
-
* Note that hide_empty is set to ON and can not be overridden!
|
1379 |
-
*
|
1380 |
-
* default (ie. no options) is:
|
1381 |
-
* - show all
|
1382 |
-
* - of first populated menu found (alphabetically)
|
1383 |
-
* - from root, for unlimited depth
|
1384 |
-
* - as hierarchical nested ULs inside a DIV.widget_custom_menu_wizard.shortcode_custom_menu_wizard
|
1385 |
-
*
|
1386 |
-
* @filters : custom_menu_wizard_shortcode_attributes array of attributes supplied to the shortcode
|
1387 |
-
* custom_menu_wizard_shortcode_settings array of widget settings derived from the attributes
|
1388 |
-
* custom_menu_wizard_shortcode_widget_args array of the sidebar args used to wrap widgets and their titles (before|after_widget, before|after_title)
|
1389 |
-
*
|
1390 |
-
* @param array $atts options supplied to the shortcode
|
1391 |
-
* @param string $content Within start-end shortcode tags
|
1392 |
-
* @param string $tag Shortcode tag
|
1393 |
-
* @return string HTML
|
1394 |
-
*/
|
1395 |
-
function custom_menu_wizard_widget_shortcode($atts, $content, $tag){
|
1396 |
-
$html = '';
|
1397 |
-
$ok = false;
|
1398 |
-
$instance = shortcode_atts( array(
|
1399 |
-
'title' => '',
|
1400 |
-
'menu' => 0, // menu id, slug or name
|
1401 |
-
//determines filter & filter_item ('items' takes precedence over 'children_of' because it's more specific)...
|
1402 |
-
'children_of' => '', // empty = show all (dep. on 'items'); menu item id or title (caseless), or current|current-item|parent|current-parent|root|current-ancestor
|
1403 |
-
'items' => '', // v2.0.0 empty = show all (dep. on 'children_of'); comma- or space-separated list of menu item ids (start level and depth don't apply)
|
1404 |
-
'start_level' => 1,
|
1405 |
-
'depth' => 0, // 0 = unlimited
|
1406 |
-
//only if children_of is (parent|current-parent|root|current-ancestor); determines fallback_no_ancestor, fallback_include_parent & fallback_include_parent_siblings...
|
1407 |
-
'fallback_parent' => 0, // 1 = use current-item; 'parent' = *and* include parent, 'siblings' = *and* include both parent and its siblings
|
1408 |
-
//only if children_of is (current|current-item); determines fallback_no_children, fallback_nc_include_parent & fallback_nc_include_parent_siblings...
|
1409 |
-
'fallback_current' => 0, // 1 = use current-parent; 'parent' = *and* include parent (if available), 'siblings' = *and* include both parent (if available) and its siblings
|
1410 |
-
//switches...
|
1411 |
-
'flat_output' => 0,
|
1412 |
-
'contains_current' => 0, // v2.0.0
|
1413 |
-
//determines include_parent, include_parent_siblings & include_ancestors...
|
1414 |
-
'include' =>'', //comma|space|hyphen separated list of 'parent', 'siblings', 'ancestors'
|
1415 |
-
'ol_root' => 0,
|
1416 |
-
'ol_sub' => 0,
|
1417 |
-
//determines title_from_parent & title_from_current...
|
1418 |
-
'title_from' => '', //comma|space|hyphen separated list of 'parent', 'current'
|
1419 |
-
'depth_rel_current' => 0, // v2.0.0
|
1420 |
-
//strings...
|
1421 |
-
'container' => 'div', // a tag : div|nav are WP restrictions, not the widget's; '' = no container
|
1422 |
-
'container_id' => '',
|
1423 |
-
'container_class' => '',
|
1424 |
-
'menu_class' => 'menu-widget',
|
1425 |
-
'widget_class' => '',
|
1426 |
-
//determines before & after...
|
1427 |
-
'wrap_link' => '', // a tag name (eg. div, p, span, etc)
|
1428 |
-
//determines link_before & link_after...
|
1429 |
-
'wrap_link_text' => '' // a tag name (eg. span, em, strong)
|
1430 |
-
), $atts );
|
1431 |
-
|
1432 |
-
$instance = apply_filters( 'custom_menu_wizard_shortcode_attributes', $instance );
|
1433 |
-
|
1434 |
-
if( empty( $instance['menu'] ) ){
|
1435 |
-
//gonna find the first menu (alphabetically) that has items...
|
1436 |
-
$menus = wp_get_nav_menus( array( 'orderby' => 'name' ) );
|
1437 |
-
}else{
|
1438 |
-
//allow for menu being something other than an id (eg. slug or name), but we need the id for the widget...
|
1439 |
-
$menus = wp_get_nav_menu_object( $instance['menu'] );
|
1440 |
-
if( !empty( $menus) ){
|
1441 |
-
$menus = array( $menus );
|
1442 |
-
}
|
1443 |
-
}
|
1444 |
-
if( !empty( $menus ) ){
|
1445 |
-
foreach( $menus as $i=>$menu ){
|
1446 |
-
$items = wp_get_nav_menu_items( $menu->term_id );
|
1447 |
-
$ok = !empty( $items );
|
1448 |
-
if( $ok ){
|
1449 |
-
$instance['menu'] = $menu->term_id;
|
1450 |
-
break;
|
1451 |
-
}
|
1452 |
-
}
|
1453 |
-
}
|
1454 |
-
unset( $menus );
|
1455 |
-
|
1456 |
-
if( $ok ){
|
1457 |
-
$instance['filter'] = $instance['filter_item'] = 0;
|
1458 |
-
if( empty( $instance['items'] ) ){
|
1459 |
-
//children_of => filter & filter_item...
|
1460 |
-
if( empty( $instance['children_of'] ) ){
|
1461 |
-
$instance['children_of'] = '';
|
1462 |
-
}
|
1463 |
-
switch( $instance['children_of'] ){
|
1464 |
-
case '':
|
1465 |
-
break;
|
1466 |
-
case 'root': case 'current-ancestor':
|
1467 |
-
--$instance['filter_item']; //ends up as -2
|
1468 |
-
case 'parent': case 'current-parent':
|
1469 |
-
--$instance['filter_item']; //ends up as -1
|
1470 |
-
case 'current': case 'current-item':
|
1471 |
-
$instance['filter'] = 1;
|
1472 |
-
break;
|
1473 |
-
default:
|
1474 |
-
$instance['filter'] = 1;
|
1475 |
-
$instance['filter_item'] = strtolower( $instance['children_of'] );
|
1476 |
-
}
|
1477 |
-
//if filter_item is non-numeric then it could be the title of a menu item, but we need it to be the menu item's id...
|
1478 |
-
if( !is_numeric( $instance['filter_item'] ) ){
|
1479 |
-
foreach( $items as $item ){
|
1480 |
-
$ok = strtolower( $item->title ) == $instance['filter_item'];
|
1481 |
-
if( $ok ){
|
1482 |
-
$instance['filter_item'] = $item->ID;
|
1483 |
-
break;
|
1484 |
}
|
1485 |
}
|
1486 |
-
|
1487 |
-
|
1488 |
-
|
1489 |
-
|
1490 |
-
|
1491 |
-
|
1492 |
-
|
1493 |
-
if( $ok ){
|
1494 |
-
//fallback_parent => fallback_no_ancestor switch (and extension switches)...
|
1495 |
-
$instance['fallback_no_ancestor'] = $instance['fallback_include_parent'] = $instance['fallback_include_parent_siblings'] = 0;
|
1496 |
-
if( $instance['filter_item'] < 0 && !empty( $instance['fallback_parent'] ) ){
|
1497 |
-
$instance['fallback_no_ancestor'] = 1;
|
1498 |
-
$i = preg_split( '/[\s,-]+/', strtolower( $instance['fallback_parent'] ), -1, PREG_SPLIT_NO_EMPTY );
|
1499 |
-
foreach( $i as $j ){
|
1500 |
-
if( $j == 'parent' ){
|
1501 |
-
$instance['fallback_include_parent'] = 1;
|
1502 |
-
}elseif( $j == 'siblings' ){
|
1503 |
-
$instance['fallback_include_parent_siblings'] = 1;
|
1504 |
}
|
1505 |
-
|
1506 |
-
|
1507 |
-
|
1508 |
-
|
1509 |
-
|
1510 |
-
|
1511 |
-
$i = preg_split( '/[\s,-]+/', strtolower( $instance['fallback_current'] ), -1, PREG_SPLIT_NO_EMPTY );
|
1512 |
-
foreach( $i as $j ){
|
1513 |
-
if( $j == 'parent' ){
|
1514 |
-
$instance['fallback_nc_include_parent'] = 1;
|
1515 |
-
}elseif( $j == 'siblings' ){
|
1516 |
-
$instance['fallback_nc_include_parent_siblings'] = 1;
|
1517 |
}
|
1518 |
-
|
1519 |
-
|
1520 |
-
|
1521 |
-
|
1522 |
-
|
1523 |
-
|
1524 |
-
|
1525 |
-
|
1526 |
-
|
1527 |
-
|
1528 |
-
|
1529 |
-
|
1530 |
-
|
1531 |
-
$instance['include_ancestors'] = 1;
|
1532 |
}
|
|
|
|
|
|
|
1533 |
}
|
1534 |
-
|
1535 |
-
|
1536 |
-
|
1537 |
-
|
1538 |
-
|
1539 |
-
|
1540 |
-
|
1541 |
-
|
1542 |
-
|
1543 |
-
|
1544 |
-
|
1545 |
-
|
|
|
|
|
|
|
|
|
1546 |
}
|
1547 |
-
|
1548 |
-
unset( $instance['title_from'] );
|
1549 |
-
//wrap_link => before & after...
|
1550 |
-
$instance['before'] = $instance['after'] = '';
|
1551 |
-
$instance['wrap_link'] = esc_attr( trim( $instance['wrap_link'] ) );
|
1552 |
-
if( !empty( $instance['wrap_link'] ) ){
|
1553 |
-
$instance['before'] = '<' . $instance['wrap_link'] . '>';
|
1554 |
-
$instance['after'] = '</' . $instance['wrap_link'] . '>';
|
1555 |
-
}
|
1556 |
-
//wrap_link_text => link_before & link_after...
|
1557 |
-
$instance['link_before'] = $instance['link_after'] = '';
|
1558 |
-
$instance['wrap_link_text'] = esc_attr( trim( $instance['wrap_link_text'] ) );
|
1559 |
-
if( !empty( $instance['wrap_link_text'] ) ){
|
1560 |
-
$instance['link_before'] = '<' . $instance['wrap_link_text'] . '>';
|
1561 |
-
$instance['link_after'] = '</' . $instance['wrap_link_text'] . '>';
|
1562 |
-
}
|
1563 |
|
1564 |
-
//
|
1565 |
-
|
1566 |
-
|
1567 |
-
'shortcode_custom_menu_wizard'
|
1568 |
-
);
|
1569 |
-
$instance['widget_class'] = empty( $instance['widget_class'] ) ? '' : esc_attr( trim ( $instance['widget_class'] ) );
|
1570 |
-
if( !empty( $instance['widget_class'] ) ){
|
1571 |
-
foreach( explode(' ', $instance['widget_class'] ) as $i ){
|
1572 |
-
if( !empty( $i ) && !in_array( $i, $before_widget_class ) ){
|
1573 |
-
$before_widget_class[] = $i;
|
1574 |
-
}
|
1575 |
-
}
|
1576 |
-
}
|
1577 |
-
$instance['widget_class'] = '';
|
1578 |
-
//turn on hide_empty...
|
1579 |
-
$instance['hide_empty'] = 1;
|
1580 |
-
}
|
1581 |
|
1582 |
-
if( $ok ){
|
1583 |
-
//apart from before_title, these are lifted from the_widget()...
|
1584 |
-
$sidebar_args = array(
|
1585 |
-
'before_widget' => '<div class="' . implode( ' ', $before_widget_class ) . '">',
|
1586 |
-
'after_widget' => '</div>',
|
1587 |
-
'before_title' => '<h2 class="widgettitle">',
|
1588 |
-
'after_title' => '</h2>'
|
1589 |
-
);
|
1590 |
-
ob_start();
|
1591 |
-
the_widget(
|
1592 |
-
'Custom_Menu_Wizard_Widget',
|
1593 |
-
apply_filters('custom_menu_wizard_shortcode_settings', $instance ),
|
1594 |
-
apply_filters('custom_menu_wizard_shortcode_widget_args', $sidebar_args )
|
1595 |
-
);
|
1596 |
-
$html = ob_get_clean();
|
1597 |
-
}
|
1598 |
-
return empty($html) ? '' : $html;
|
1599 |
}
|
3 |
* Plugin Name: Custom Menu Wizard
|
4 |
* Plugin URI: http://wordpress.org/plugins/custom-menu-wizard/
|
5 |
* Description: Show any part of a custom menu in a Widget, or in content using a Shortcode. Customise the output with extra classes or html; filter by current menu item or a specific item; set a depth, show the parent(s), change the list style, etc. Use the included emulator to assist with the filter settings.
|
6 |
+
* Version: 3.0.0
|
7 |
* Author: Roger Barrett
|
8 |
* Author URI: http://www.wizzud.com/
|
9 |
* License: GPL2+
|
10 |
*/
|
11 |
+
defined( 'ABSPATH' ) or exit();
|
12 |
/*
|
13 |
+
* v3.0.0 change log
|
14 |
+
* - Major rethink/rewrite : the Children Of filter is now a Branch filter, and the selected menu item becomes the key focus point rather
|
15 |
+
* than its children. The Levels available for a Branch filter now include relative levels as well as absolute levels, and there are more
|
16 |
+
* options available for requiring that the menu contains the current menu item. With the exception of some anomalies (edge cases) the
|
17 |
+
* output achievable with v2 of the widget is still available with v3. Although there is no automatice upgrade available, v2 is still
|
18 |
+
* fully supported; however, any new instances of the widget will be created as v3 only. Note that the shortcode for v3 has changed to
|
19 |
+
* [cmwizard ... ], but, again, v2's [custom_menu_wizard] is still supported! NB: There is no separate 2.1.0 release - it is incorporated
|
20 |
+
* into this release.
|
21 |
+
* Simplest examples : "Children Of = Current Item" becomes "Branch = Current Item, Starting at +1 (children)"
|
22 |
+
* "Children Of = Current Item, with Include Parent" becomes "Branch = Current Item, Starting at the Current Item"
|
23 |
+
* - menu items can now be specifically excluded from the final output
|
24 |
+
* - ids for Items and Exclusions can be set to include all descendants
|
25 |
+
* - widget title can be set from the root of Branch or current item
|
26 |
+
* - the inclusion of branch ancestors, and optionally their siblings, can be set by absolute or relative level
|
27 |
+
* - compatibile with Widget Customizer plugin, and its implementation in WP 3.9 core
|
28 |
+
* - added title_tag to shortcode options
|
29 |
+
* - added findme to shortcode options, [cmwizard findme=1], output restricted to edit_pages capability
|
30 |
+
*
|
31 |
+
* v2.1.0 change log
|
32 |
+
* - fixed bug where duplicate menu item ids were causing elements to be ignored
|
33 |
+
* - fixed IE8 bug with levels indentation in assist
|
34 |
+
* - removed automatic selection of shortcode text (inconsistent cross-browser, so just triple click as usual; paste-as-text if possible!)
|
35 |
+
* - swapped the Items' checkboxes for clickable Ticks
|
36 |
+
* - tweaked dialog styling, and make more responsive to re-sizing
|
37 |
+
* - added collapsible menu structures to dialog, and set fixed position (with toggle back to absolute)
|
38 |
+
* - added utility to "assist" to locate posts containing a CMW shortcode
|
39 |
+
* - minimum requirement for WP raised to v3.6
|
40 |
+
*
|
41 |
* v2.0.6 change log:
|
42 |
* - modified determination of current item to cope better with multiple occurences (still first-found, but within prioritised groups)
|
43 |
* - replaced display of update information on plugins list with styled request (and link) to read changelog (update info sometimes didn't display, and some considered it "scary" for users)
|
100 |
* - moved the setting of 'disabled' attributes on INPUTs/SELECTs from PHP into javascript
|
101 |
*/
|
102 |
|
103 |
+
if( !class_exists( 'Custom_Menu_Wizard_Plugin' ) ){
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
104 |
|
105 |
+
//include the widget class and its walker...
|
106 |
+
include( plugin_dir_path( __FILE__ ) . 'include/class.widget.php' );
|
107 |
+
include( plugin_dir_path( __FILE__ ) . 'include/class.walker.php' );
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
108 |
|
109 |
+
//instantiate...
|
110 |
+
add_action( 'plugins_loaded', array( 'Custom_Menu_Wizard_Plugin', 'init' ) );
|
|
|
|
|
111 |
|
112 |
+
//declare the main plugin class...
|
113 |
+
class Custom_Menu_Wizard_Plugin {
|
114 |
+
|
115 |
+
public static $version = '3.0.0';
|
116 |
+
protected static $instance;
|
117 |
+
|
118 |
+
/**
|
119 |
+
* constructor : adds actions
|
120 |
+
*/
|
121 |
+
public function __construct(){
|
122 |
+
|
123 |
+
add_action( 'widgets_init', array( &$this, 'widget_and_shortcode' ) );
|
124 |
+
add_action( 'wp_ajax_cmw-find-shortcodes', array( &$this, 'ajax_find_shortcodes' ) );
|
125 |
+
add_action( 'admin_print_styles-widgets.php', array( &$this, 'enqueue_styles' ) );
|
126 |
+
add_action( 'admin_print_scripts-widgets.php', array( &$this, 'enqueue_scripts' ) );
|
127 |
+
add_action( 'admin_menu', array( &$this, 'admin_menu' ) );
|
128 |
+
//add customizer support...
|
129 |
+
add_action( 'customize_controls_enqueue_scripts', array( &$this, 'enqueue_styles' ) );
|
130 |
+
add_action( 'customize_controls_enqueue_scripts', array( &$this, 'enqueue_scripts' ) );
|
131 |
+
|
132 |
+
} //end __construct()
|
133 |
|
134 |
+
/**
|
135 |
+
* hooked into plugins_loaded action : creates the plugin instance
|
136 |
+
*/
|
137 |
+
public static function init(){
|
138 |
+
|
139 |
+
is_null( self::$instance ) && self::$instance = new self;
|
140 |
+
return self::$instance;
|
141 |
|
142 |
+
} //end init()
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
143 |
|
144 |
+
/**
|
145 |
+
* hooked into admin_menu action : add action for when an update to this plugin is available
|
146 |
+
*/
|
147 |
+
public function admin_menu(){
|
148 |
|
149 |
+
add_action( 'in_plugin_update_message-' . plugin_basename( __FILE__ ), array( &$this, 'update_message' ), 10, 2 );
|
150 |
+
|
151 |
+
} //end admin_menu()
|
152 |
+
|
153 |
+
/**
|
154 |
+
* hooked into admin_print_scripts-widgets.php & customize_controls_enqueue_scripts actions : queues scripts needed by the plugin
|
155 |
+
*/
|
156 |
+
public function enqueue_scripts(){
|
157 |
|
158 |
+
$min = defined( 'WP_DEBUG' ) && WP_DEBUG ? '' : '.min';
|
159 |
+
wp_enqueue_script( 'custom-menu-wizard-plugin-script', plugins_url( "/custom-menu-wizard$min.js", __FILE__ ), array('jquery-ui-dialog'), self::$version );
|
160 |
+
|
161 |
+
} //end enqueue_scripts()
|
162 |
+
|
163 |
+
/**
|
164 |
+
* hooked into admin_print_styles-widgets.php & customize_controls_enqueue_scripts actions : queues styles needed by the plugin
|
165 |
+
*/
|
166 |
+
public function enqueue_styles(){
|
167 |
+
global $wp_scripts;
|
168 |
+
|
169 |
+
wp_enqueue_style( 'custom-menu-wizard-plugin-styles', plugins_url( '/custom-menu-wizard.css', __FILE__ ), array(), self::$version );
|
170 |
+
//if there's no jquery-ui style already registered, register Smoothness...
|
171 |
+
if( !wp_style_is( 'jquery-ui', 'registered' ) ) {
|
172 |
+
//get the jquery ui core version (default to 1.9.2 if not found)...
|
173 |
+
$jquery_ui_version = isset( $wp_scripts->registered['jquery-ui-core']->ver ) ? $wp_scripts->registered['jquery-ui-core']->ver : '1.9.2';
|
174 |
+
//register Smoothness theme for the determined ui version...
|
175 |
+
// wp_register_style( 'jquery-ui', '//ajax.googleapis.com/ajax/libs/jqueryui/' . $jquery_ui_version . '/themes/smoothness/jquery-ui.css' );
|
176 |
+
wp_register_style( 'jquery-ui', '//code.jquery.com/ui/' . $jquery_ui_version . '/themes/smoothness/jquery-ui.css' );
|
177 |
+
}
|
178 |
+
wp_enqueue_style( 'jquery-ui' );
|
179 |
+
|
180 |
+
} //end enqueue_styles()
|
181 |
+
|
182 |
+
/**
|
183 |
+
* hooked into in_plugin_update_message-custom-menu-wizard action : request read changelog before updating
|
184 |
+
* @param array $plugin_data Plugin metadata
|
185 |
+
* @param array $r Metadata about the available plugin update
|
186 |
+
*/
|
187 |
+
public function update_message( $plugin_data, $r ){
|
188 |
+
|
189 |
+
$url = 'http://wordpress.org/plugins/' . $r->slug. '/changelog/';
|
190 |
+
$style = implode( ';', array(
|
191 |
+
'-webkit-box-sizing:border-box',
|
192 |
+
'-moz-box-sizing:border-box',
|
193 |
+
'box-sizing:border-box',
|
194 |
+
'background-color:#D54E21',
|
195 |
+
'border-radius:2px',
|
196 |
+
'color:#FFFFFF',
|
197 |
+
'display:inline-block',
|
198 |
+
'margin:0',
|
199 |
+
'max-width:100%',
|
200 |
+
'overflow:hidden',
|
201 |
+
'padding:0 0.5em',
|
202 |
+
'text-overflow:ellipsis',
|
203 |
+
'text-shadow:0 1px 0 rgba(0, 0, 0, 0.5)',
|
204 |
+
'vertical-align:text-bottom',
|
205 |
+
'white-space:nowrap'
|
206 |
+
) ) . ';';
|
207 |
|
208 |
+
?>
|
209 |
+
<p style="<?php echo $style; ?>"><em><?php printf( __('Please <a href="%s" style="color:#FFFFFF;text-decoration:underline;" target="_blank">read the Changelog</a> <strong>before</strong> updating!'), $url ); ?></em></p>
|
210 |
+
<?php
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
211 |
|
212 |
+
} //end update_message()
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
213 |
|
214 |
+
/**
|
215 |
+
* hooked into wp_ajax_cmw-find-shortcodes action : handle ajax request to find posts containing CMW shortcodes
|
216 |
+
*/
|
217 |
+
public function ajax_find_shortcodes(){
|
218 |
+
|
219 |
+
check_admin_referer( 'cmw-find-shortcodes' );
|
220 |
+
$response = array(
|
221 |
+
'what' => 'cmw_find_shortcodes',
|
222 |
+
'action' => 'list_posts',
|
223 |
+
'id' => '1',
|
224 |
+
'data' => $this->find_shortcodes()
|
225 |
+
);
|
226 |
+
$xmlResponse = new WP_Ajax_Response($response);
|
227 |
+
$xmlResponse->send();
|
228 |
|
229 |
+
}
|
230 |
+
|
231 |
+
/**
|
232 |
+
* list any post that contains a CMW shortcode; can be called from a shortcode or via an ajax call
|
233 |
+
*
|
234 |
+
* @param array $shortcodeInst Array of shortcode attributes
|
235 |
+
* @return string HTML
|
236 |
+
*/
|
237 |
|
238 |
+
public function find_shortcodes( $shortcodeInst = false ){
|
239 |
+
global $wpdb;
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
240 |
|
241 |
+
$html = '';
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
242 |
|
243 |
+
//from a shortcode, the user must have edit_pages capability (implies Editor or above)...
|
244 |
+
if( $shortcodeInst !== false && !current_user_can( 'edit_pages' ) ){
|
245 |
+
return $html;
|
246 |
+
}
|
247 |
|
248 |
+
$codes = array(
|
249 |
+
'cmw-demo-found-old' => '[custom_menu_wizard',
|
250 |
+
'cmw-demo-found-new' => '[cmwizard'
|
251 |
+
);
|
252 |
+
foreach( $codes as $k => $v ){
|
253 |
+
$j = str_replace( '-', '_', $k );
|
254 |
+
$$j = '%' . like_escape( esc_sql ( $v ) ) . '%';
|
255 |
+
}
|
|
|
|
|
|
|
|
|
|
|
256 |
|
257 |
+
//search in all custom fields...
|
258 |
+
$sql = "SELECT DISTINCT post_id FROM {$wpdb->postmeta}";
|
259 |
+
$sql .= " WHERE meta_value LIKE '%s' OR meta_value LIKE '%s'";
|
260 |
+
$post_ids_meta = $wpdb->get_col( $wpdb->prepare( $sql, $cmw_demo_found_old, $cmw_demo_found_new ) );
|
261 |
+
//search in post_content...
|
262 |
+
$sql = "SELECT DISTINCT ID FROM {$wpdb->posts}";
|
263 |
+
$sql .= " WHERE post_content LIKE '%s' OR post_content LIKE '%s'";
|
264 |
+
$post_ids_post = $wpdb->get_col( $wpdb->prepare( $sql, $cmw_demo_found_old, $cmw_demo_found_new ) );
|
265 |
|
266 |
+
$post_ids = array_merge( $post_ids_meta, $post_ids_post );
|
267 |
|
268 |
+
if( empty( $post_ids ) ){
|
269 |
+
$html .= '<p>' . __('No CMW shortcodes found.') . '</p>';
|
270 |
+
}else{
|
271 |
+
$args = array(
|
272 |
+
'ignore_sticky_posts' => true,
|
273 |
+
'nopaging' => true,
|
274 |
+
'orderby' => 'date',
|
275 |
+
'post_type' => 'any',
|
276 |
+
'post_status' => array( 'publish', 'draft', 'future', 'pending', 'private' ),
|
277 |
+
'post__in' => $post_ids
|
278 |
+
);
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
279 |
|
280 |
+
$the_query = new WP_Query( $args );
|
281 |
+
if( $the_query->have_posts() ){
|
282 |
+
$html .= '<dl>';
|
283 |
+
while( $the_query->have_posts() ){
|
284 |
+
$the_query->the_post();
|
285 |
+
$id = get_the_ID();
|
286 |
+
$inPost = in_array( $id, $post_ids_post );
|
287 |
+
$inMeta = in_array( $id, $post_ids_meta );
|
288 |
+
$dtClass = array();
|
289 |
+
$anchorTitle = array();
|
290 |
+
if( $inPost ){
|
291 |
+
$content = get_the_content();
|
292 |
+
foreach( $codes as $k => $v ){
|
293 |
+
if( strpos( $content, $v ) !== false ){
|
294 |
+
$dtClass[ $k ] = 1;
|
295 |
+
$anchorTitle[ $v . ']' ] = 1;
|
296 |
+
}
|
297 |
+
}
|
298 |
+
}
|
299 |
+
if( $inMeta ){
|
300 |
+
$content = get_post_meta( $id );
|
301 |
+
foreach( $content as $k => $v ){
|
302 |
+
$content[ $k ] = implode(' ', $v );
|
303 |
+
}
|
304 |
+
$content = implode( ' ', $content );
|
305 |
+
foreach( $codes as $k => $v ){
|
306 |
+
if( strpos( $content, $v ) !== false ){
|
307 |
+
$dtClass[ $k ] = 1;
|
308 |
+
$anchorTitle[ $v . ']' ] = 1;
|
309 |
+
}
|
310 |
+
}
|
311 |
+
}
|
312 |
+
$anchorTarget = get_post_type( $id );
|
313 |
+
if( empty( $anchorTarget ) ){
|
314 |
+
$anchorTarget = __('unknown type');
|
315 |
+
}else{
|
316 |
+
$anchorTarget = (string)$anchorTarget;
|
317 |
+
}
|
318 |
+
$content = $inPost ? ( $inMeta ? __( 'content+meta' ) : __( 'content' ) ) : __( 'meta' );
|
319 |
+
$anchorTitle = $anchorTarget . ' #' . $id . ', ' . $content . ', ' . implode( __(' and '), array_keys( $anchorTitle ) );
|
320 |
+
$anchorTarget = '';
|
321 |
+
if( $shortcodeInst === false ){
|
322 |
+
//is from assistant via ajax...
|
323 |
+
$anchorTarget = 'target="_blank"';
|
324 |
+
$anchorTitle .= ' ... ' . __('opens new tab/window');
|
325 |
+
}
|
326 |
+
$html .= '<dt class="' . implode( ' ', array_keys( $dtClass ) ) . '"><a href="' . get_permalink() . '" ' . $anchorTarget . ' title="' . $anchorTitle . '">' . get_the_title() . '</a></dt>';
|
327 |
}
|
328 |
+
$html .= '</dl>';
|
329 |
+
}else{
|
330 |
+
$html .= '<p>' . __('No CMW shortcodes found.') . '</p>';
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
331 |
}
|
|
|
332 |
|
333 |
+
wp_reset_postdata();
|
|
|
|
|
|
|
|
|
334 |
}
|
335 |
|
336 |
+
//if originator is shortcode, put a simple wrapper (no styling!) around the results, and optionally an H3 title...
|
337 |
+
if( $shortcodeInst !== false ){
|
338 |
+
$anchorTitle = is_array( $shortcodeInst ) && !empty( $shortcodeInst['title'] ) ? esc_attr( strip_tags( trim( $shortcodeInst['title'] ) ) ) : '';
|
339 |
+
$anchorTitle = empty( $anchorTitle ) ? '' : '<h3>' . $anchorTitle . '</h3>';
|
340 |
+
$html = '<div class="cmw-list-posts-with-shortcodes">' . $anchorTitle . $html . '</div>';
|
|
|
341 |
}
|
342 |
|
343 |
+
return $html;
|
344 |
+
|
345 |
+
} //end find_shortcodes()
|
346 |
+
|
347 |
+
/**
|
348 |
+
* hooked into widgets_init action : registers widget and adds shortcode(s)
|
349 |
+
*/
|
350 |
+
public function widget_and_shortcode(){
|
351 |
+
|
352 |
+
//register the widget class...
|
353 |
+
register_widget( 'Custom_Menu_Wizard_Widget' );
|
354 |
+
//add shortcode...
|
355 |
+
add_shortcode( 'cmwizard', array( &$this, 'shortcode' ) );
|
356 |
+
//add shortcode, v2.1.0 version (deprecated!)...
|
357 |
+
add_shortcode( 'custom_menu_wizard', array( &$this, 'shortcode_legacy' ) );
|
|
|
|
|
|
|
|
|
358 |
|
359 |
+
} //end widget_and_shortcode()
|
360 |
+
|
361 |
+
/**
|
362 |
+
* shortcode processing for [cmwizard option="" option="" ...] (as of v3.0.0)
|
363 |
+
*
|
364 |
+
* see wp-includes/widgets.php for the_widget() code
|
365 |
+
* Note that hide_empty is set to ON and can not be overridden!
|
366 |
+
*
|
367 |
+
* differences from [custom_menu_wizard] shortcode (ie. v2.1.0)
|
368 |
+
* deprecated:
|
369 |
+
* - children_of : now branch, and limited to current[-item] or digits; parent|current-parent|root|current-ancestor all require conversion
|
370 |
+
* - start_level : now level (integer) for a by-level filter, or start_at (string) for a by-branch filter (determining branch_start)
|
371 |
+
* changed:
|
372 |
+
* - contains_current : was a switch, now a string (empty or menu|primary|secondary|output); switch ON = 'output'
|
373 |
+
* - include : now accepts siblings, ancestors and/or ancestor-siblings (csv); parent is gone, and hyphen separator no longer allowed
|
374 |
+
* - title_from : should now be csv, hyphen separator no longer allowed
|
375 |
+
* added:
|
376 |
+
* - title_tag & findme
|
377 |
+
*
|
378 |
+
* default (ie. no options) is:
|
379 |
+
* - show all
|
380 |
+
* - of first populated menu found (alphabetically)
|
381 |
+
* - from root, for unlimited depth
|
382 |
+
* - as hierarchical nested ULs inside a DIV.widget_custom_menu_wizard.shortcode_custom_menu_wizard
|
383 |
+
*
|
384 |
+
* @filters : custom_menu_wizard_shortcode_attributes array of attributes (unfiltered!) supplied to the shortcode
|
385 |
+
* shortcode_atts_cmwizard array of output attributes, array of supported attributes, array of supplied attributes
|
386 |
+
* custom_menu_wizard_shortcode_settings array of widget settings derived from the attributes
|
387 |
+
* custom_menu_wizard_shortcode_widget_args array of the sidebar args used to wrap widgets and their titles (before|after_widget, before|after_title)
|
388 |
+
* NB each of the arrays passed to the above filters has a extra key-value pair of 'cmwv' => the current plugin version, eg. '3.0.0'
|
389 |
+
*
|
390 |
+
* @param array $atts options supplied to the shortcode
|
391 |
+
* @param string $content Within start-end shortcode tags
|
392 |
+
* @param string $tag Shortcode tag
|
393 |
+
* @return string HTML that comes from running the_widget()
|
394 |
+
*/
|
395 |
+
public function shortcode($atts, $content, $tag){
|
396 |
+
|
397 |
+
$html = '';
|
398 |
+
$ok = false;
|
399 |
+
|
400 |
+
// NB csv = comma or space separated list...
|
401 |
+
$instance = shortcode_atts( array(
|
402 |
+
'title' => '',
|
403 |
+
'menu' => 0, // menu id, slug or name
|
404 |
+
'level' => 0,
|
405 |
+
//determines filter (in conjunction with items)...
|
406 |
+
'branch' => 0, // a menu item id, or current|current-item
|
407 |
+
//determines filter (in conjunction with branch)...
|
408 |
+
'items' => '', // csv of menu item ids (an id may have a '+' appended, for inheritance, eg. '23+')
|
409 |
+
'depth' => 0, // 0 = unlimited
|
410 |
+
'depth_rel_current' => 0,
|
411 |
+
//determines branch_start...
|
412 |
+
'start_at' => '',
|
413 |
+
'start_mode' => '', // 'level' or empty
|
414 |
+
'allow_all_root' => 0,
|
415 |
+
//inclusions...
|
416 |
+
'ancestors' => 0, //integer (negative = relative)
|
417 |
+
'ancestor_siblings' => 0, //integer (negative = relative)
|
418 |
+
'include_root' => 0, //switch (means *all* root items!)
|
419 |
+
'siblings' => 0, //switch
|
420 |
+
//exclusions...
|
421 |
+
'exclude' => '', // csv of menu item ids (an id may have a '+' appended, for inheritance, eg. '23+')
|
422 |
+
'exclude_level' => '', // digit, possibly appended with a '+' or '-', eg. '2', '2+', or '2-'
|
423 |
+
'contains_current' => '', // menu|primary|secondary|output
|
424 |
+
//determines fallback (current|parent|quit) and, optionally, fallback_siblings and/or fallback_depth...
|
425 |
+
'fallback' => '', //eg. 'quit', or 'current' or 'current+siblings' or 'parent+siblings,2' or 'parent,1'
|
426 |
+
//switches...
|
427 |
+
'flat_output' => 0,
|
428 |
+
//determines title_from_[branch|current|branch-root|current-root]...
|
429 |
+
'title_from' => '', // csv of branch|current|branch-root|current-root
|
430 |
+
'ol_root' => 0,
|
431 |
+
'ol_sub' => 0,
|
432 |
+
//strings...
|
433 |
+
'container' => 'div', // a tag : div|nav are WP restrictions, not the widget's; '' = no container
|
434 |
+
'container_id' => '',
|
435 |
+
'container_class' => '',
|
436 |
+
'menu_class' => 'menu-widget',
|
437 |
+
'widget_class' => '',
|
438 |
+
//determines before & after...
|
439 |
+
'wrap_link' => '', // a tag name (eg. div, p, span, etc)
|
440 |
+
//determines link_before & link_after...
|
441 |
+
'wrap_link_text' => '', // a tag name (eg. span, em, strong)
|
442 |
+
//modifies the before/after_title $sidebar_args, changing the default H2 tag to something else(?)...
|
443 |
+
'title_tag' => '', // a tag name (eg. h1, h3, etc)
|
444 |
+
//utility : doesn't run widget! instead, lists all posts/pages that contain a CMW shortcode...
|
445 |
+
'findme' => 0
|
446 |
+
),
|
447 |
+
apply_filters(
|
448 |
+
'custom_menu_wizard_shortcode_attributes',
|
449 |
+
array_merge( (array)$atts, array('cmwv' => self::$version) )
|
450 |
+
),
|
451 |
+
$tag // since WP3.6 this allows use of shortcode_atts_cmwizard filter, applied by shortcode_atts()
|
452 |
+
);
|
453 |
+
|
454 |
+
if( !empty( $instance['findme'] ) ){
|
455 |
+
return $this->find_shortcodes( $instance );
|
456 |
+
}
|
457 |
+
|
458 |
+
//in order of priority...
|
459 |
+
$byItems = !empty( $instance['items'] );
|
460 |
+
$byBranch = !$byItems && !empty( $instance['branch'] );
|
461 |
+
$byLevel = !$byItems && !$byBranch;
|
462 |
+
|
463 |
+
if( empty( $instance['menu'] ) ){
|
464 |
+
//gonna find the first menu (alphabetically) that has items...
|
465 |
+
$menus = wp_get_nav_menus( array( 'orderby' => 'name' ) );
|
466 |
+
}else{
|
467 |
+
//allow for menu being something other than an id (eg. slug or name), but we need the id for the widget...
|
468 |
+
$menus = wp_get_nav_menu_object( $instance['menu'] );
|
469 |
+
if( !empty( $menus) ){
|
470 |
+
$menus = array( $menus );
|
471 |
}
|
472 |
+
}
|
473 |
+
if( !empty( $menus ) ){
|
474 |
+
foreach( $menus as $i=>$menu ){
|
475 |
+
$items = wp_get_nav_menu_items( $menu->term_id );
|
476 |
+
$ok = !empty( $items );
|
477 |
+
if( $ok ){
|
478 |
+
$instance['menu'] = $menu->term_id;
|
479 |
+
break;
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
480 |
}
|
481 |
}
|
482 |
}
|
483 |
+
unset( $menus );
|
484 |
|
485 |
+
if( $ok ){
|
486 |
+
if( $byItems ){
|
487 |
+
$instance['filter'] = 'items';
|
488 |
+
}
|
489 |
+
if( $byBranch ){
|
490 |
+
$instance['filter'] = 'branch';
|
491 |
+
switch( "{$instance['start_at']}" ){
|
492 |
+
case '0':
|
493 |
+
case 'branch': $instance['branch_start'] = ''; break;
|
494 |
+
case 'root' : $instance['branch_start'] = '1'; break;
|
495 |
+
case 'children': $instance['branch_start'] = '+1'; break;
|
496 |
+
case 'parent': $instance['branch_start'] = '-1'; break;
|
497 |
+
default: $instance['branch_start'] = "{$instance['start_at']}";
|
|
|
|
|
|
|
|
|
498 |
}
|
499 |
+
if( $instance['branch'] == 'current' || $instance['branch'] == 'current-item' ){
|
500 |
+
$instance['branch'] = 0;
|
501 |
+
}elseif( !is_numeric( $instance['branch'] ) ){
|
502 |
+
//if branch is non-numeric then it could be the title of a menu item, but we need it to be the menu item's id...
|
503 |
+
$instance['branch'] = strtolower( $instance['branch'] );
|
504 |
+
foreach( $items as $item ){
|
505 |
+
$ok = strtolower( $item->title ) == $instance['branch'];
|
506 |
+
if( $ok ){
|
507 |
+
$instance['branch'] = $item->ID;
|
508 |
+
break;
|
509 |
+
}
|
510 |
}
|
511 |
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
512 |
}
|
513 |
+
if( $byLevel ){
|
514 |
+
$instance['filter'] = '';
|
515 |
+
$instance['level'] = max(1, intval( $instance['level'] ) );
|
516 |
+
}
|
517 |
+
unset( $instance['start_at'] );
|
518 |
+
}
|
519 |
|
520 |
+
if( $ok ){
|
521 |
+
//fallback => fallback and fallback_siblings and fallback_depth...
|
522 |
+
//allows "X", "X,Y" or "X,Y,Z" where comma could be space, and X|Y|Z could be "quit"|"current"|"parent", or "+siblings", or digit(s)
|
523 |
+
//but "quit", "current" or "parent" must be present (others are optional)
|
524 |
+
if( $byBranch && empty( $instance['branch'] ) && !empty( $instance['fallback'] ) ){
|
525 |
+
$i = preg_split( '/[\s,]+/', strtolower( $instance['fallback'] ), -1, PREG_SPLIT_NO_EMPTY );
|
526 |
+
$instance['fallback'] = '';
|
527 |
+
if( in_array( 'quit', $i ) ){
|
528 |
+
$instance['fallback'] = 'quit';
|
529 |
+
}elseif( in_array( 'parent', $i ) ){
|
530 |
+
$instance['fallback'] = 'parent';
|
531 |
+
}elseif( in_array( 'current', $i ) ){
|
532 |
+
$instance['fallback'] = 'current';
|
533 |
+
}
|
534 |
+
if( !empty( $instance['fallback'] ) && $instance['fallback'] != 'quit' ){
|
535 |
+
if( in_array( '+siblings', $i ) ){
|
536 |
+
$instance['fallback_siblings'] = 1;
|
|
|
537 |
}
|
538 |
+
$i = array_diff( $i, array( 'quit', 'parent', 'current', '+siblings' ) );
|
539 |
+
if( !empty( $i ) ){
|
540 |
+
foreach( $i as $v ){
|
541 |
+
$v = trim( $v );
|
542 |
+
if( preg_match( '/^\d+$/', $v ) > 0 && intval( $v ) > 0 ){
|
543 |
+
$instance['fallback_depth'] = intval( $v );
|
544 |
+
break;
|
545 |
}
|
546 |
}
|
547 |
}
|
549 |
}
|
550 |
}
|
551 |
|
552 |
+
if( $ok ){
|
553 |
+
//title_from => title_from_...
|
554 |
+
if( !empty( $instance['title_from'] ) ){
|
555 |
+
$i = preg_split( '/[\s,]+/', strtolower( $instance['title_from'] ), -1, PREG_SPLIT_NO_EMPTY );
|
556 |
+
foreach( $i as $j ){
|
557 |
+
if( $j == 'branch' || $j == 'current' ){
|
558 |
+
$instance[ 'title_from_' . $j ] = 1;
|
559 |
+
}elseif( $j == 'branch-root' || $j == 'current-root' ){
|
560 |
+
$instance[ 'title_from_' . str_replace( '-', '_', $j ) ] = 1;
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
561 |
}
|
562 |
}
|
563 |
}
|
564 |
+
unset( $instance['title_from'] );
|
565 |
|
566 |
+
//wrap_link => before & after...
|
567 |
+
$instance['wrap_link'] = esc_attr( trim( $instance['wrap_link'] ) );
|
568 |
+
if( !empty( $instance['wrap_link'] ) ){
|
569 |
+
$instance['before'] = '<' . $instance['wrap_link'] . '>';
|
570 |
+
$instance['after'] = '</' . $instance['wrap_link'] . '>';
|
|
|
|
|
|
|
|
|
|
|
|
|
571 |
}
|
572 |
+
unset( $instance['wrap_link'] );
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
573 |
|
574 |
+
//wrap_link_text => link_before & link_after...
|
575 |
+
$instance['wrap_link_text'] = esc_attr( trim( $instance['wrap_link_text'] ) );
|
576 |
+
if( !empty( $instance['wrap_link_text'] ) ){
|
577 |
+
$instance['link_before'] = '<' . $instance['wrap_link_text'] . '>';
|
578 |
+
$instance['link_after'] = '</' . $instance['wrap_link_text'] . '>';
|
|
|
|
|
|
|
|
|
|
|
|
|
579 |
}
|
580 |
+
unset( $instance['wrap_link_text'] );
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
581 |
|
582 |
+
//handle widget_class here because we have full control over $before_widget...
|
583 |
+
$before_widget_class = array(
|
584 |
+
'widget_custom_menu_wizard',
|
585 |
+
'shortcode_custom_menu_wizard'
|
586 |
+
);
|
587 |
+
$instance['widget_class'] = empty( $instance['widget_class'] ) ? '' : esc_attr( trim ( $instance['widget_class'] ) );
|
588 |
if( !empty( $instance['widget_class'] ) ){
|
589 |
+
foreach( explode(' ', $instance['widget_class'] ) as $i ){
|
590 |
+
if( !empty( $i ) && !in_array( $i, $before_widget_class ) ){
|
591 |
+
$before_widget_class[] = $i;
|
592 |
+
}
|
593 |
+
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
594 |
}
|
595 |
+
unset( $instance['widget_class'] );
|
596 |
|
597 |
+
//turn on hide_empty...
|
598 |
+
$instance['hide_empty'] = 1;
|
599 |
+
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
600 |
|
601 |
+
if( $ok ){
|
602 |
+
//not used by the plugin, but could be used in the widget code to tell whether it was being
|
603 |
+
//run as a result of a widget or a shortcode?...
|
604 |
+
$instance['shortcode'] = true;
|
605 |
+
//allow the element that wraps the widget title to be changed from an h2 (the WP default) to another tag...
|
606 |
+
//note : does not allow for changing the class, or for removing the wrapping element
|
607 |
+
// for a class override, add CSS rule for
|
608 |
+
// .shortcode_custom_menu_wizard .widgettitle { ..... }
|
609 |
+
// can also be overriden using the 'custom_menu_wizard_shortcode_widget_args' filter (applied below)
|
610 |
+
$instance['title_tag'] = esc_attr( trim( $instance['title_tag'] ) );
|
611 |
+
if( empty( $instance['title_tag'] ) ){
|
612 |
+
//default to H2...
|
613 |
+
$instance['title_tag'] = 'h2';
|
614 |
}
|
615 |
+
//apart from before_widget, these are lifted from the_widget() (wp-includes/widgets.php)...
|
616 |
+
$sidebar_args = array(
|
617 |
+
'before_widget' => '<div class="' . implode( ' ', $before_widget_class ) . '">',
|
618 |
+
'after_widget' => '</div>',
|
619 |
+
'before_title' => '<' . $instance['title_tag'] . ' class="widgettitle">',
|
620 |
+
'after_title' => '</' . $instance['title_tag'] . '>'
|
621 |
+
);
|
622 |
+
unset( $instance['title_tag'] );
|
623 |
+
|
624 |
+
ob_start();
|
625 |
+
the_widget(
|
626 |
+
'Custom_Menu_Wizard_Widget',
|
627 |
+
apply_filters(
|
628 |
+
'custom_menu_wizard_shortcode_settings',
|
629 |
+
array_merge( $instance, array('cmwv' => self::$version) )
|
630 |
+
),
|
631 |
+
apply_filters(
|
632 |
+
'custom_menu_wizard_shortcode_widget_args',
|
633 |
+
array_merge( $sidebar_args, array('cmwv' => self::$version) )
|
634 |
+
) );
|
635 |
+
$html = ob_get_clean();
|
636 |
+
}
|
637 |
+
return empty($html) ? '' : $html;
|
638 |
+
|
639 |
+
} //end shortcode()
|
640 |
+
|
641 |
+
/**
|
642 |
+
* shortcode processing for [custom_menu_wizard option="" option="" ...] (as of v2.1.0)
|
643 |
+
* see wp-includes/widgets.php for the_widget() code
|
644 |
+
* Note that hide_empty is set to ON and can not be overridden!
|
645 |
+
*
|
646 |
+
* default (ie. no options) is:
|
647 |
+
* - show all
|
648 |
+
* - of first populated menu found (alphabetically)
|
649 |
+
* - from root, for unlimited depth
|
650 |
+
* - as hierarchical nested ULs inside a DIV.widget_custom_menu_wizard.shortcode_custom_menu_wizard
|
651 |
+
*
|
652 |
+
* @filters : custom_menu_wizard_shortcode_attributes array of attributes supplied to the shortcode
|
653 |
+
* custom_menu_wizard_shortcode_settings array of widget settings derived from the attributes
|
654 |
+
* custom_menu_wizard_shortcode_widget_args array of the sidebar args used to wrap widgets and their titles (before|after_widget, before|after_title)
|
655 |
+
*
|
656 |
+
* @param array $atts options supplied to the shortcode
|
657 |
+
* @param string $content Within start-end shortcode tags
|
658 |
+
* @param string $tag Shortcode tag
|
659 |
+
* @return string HTML that comes from running the_widget()
|
660 |
+
*/
|
661 |
+
function shortcode_legacy($atts, $content, $tag){
|
662 |
+
$html = '';
|
663 |
+
$ok = false;
|
664 |
+
$instance = shortcode_atts( array(
|
665 |
+
'title' => '',
|
666 |
+
'menu' => 0, // menu id, slug or name
|
667 |
+
//determines filter & filter_item ('items' takes precedence over 'children_of' because it's more specific)...
|
668 |
+
'children_of' => '', // empty = show all (dep. on 'items'); menu item id or title (caseless), or current|current-item|parent|current-parent|root|current-ancestor
|
669 |
+
'items' => '', // v2.0.0 empty = show all (dep. on 'children_of'); comma- or space-separated list of menu item ids (start level and depth don't apply)
|
670 |
+
'start_level' => 1,
|
671 |
+
'depth' => 0, // 0 = unlimited
|
672 |
+
//only if children_of is (parent|current-parent|root|current-ancestor); determines fallback_no_ancestor, fallback_include_parent & fallback_include_parent_siblings...
|
673 |
+
'fallback_parent' => 0, // 1 = use current-item; 'parent' = *and* include parent, 'siblings' = *and* include both parent and its siblings
|
674 |
+
//only if children_of is (current|current-item); determines fallback_no_children, fallback_nc_include_parent & fallback_nc_include_parent_siblings...
|
675 |
+
'fallback_current' => 0, // 1 = use current-parent; 'parent' = *and* include parent (if available), 'siblings' = *and* include both parent (if available) and its siblings
|
676 |
+
//switches...
|
677 |
+
'flat_output' => 0,
|
678 |
+
'contains_current' => 0, // v2.0.0
|
679 |
+
//determines include_parent, include_parent_siblings & include_ancestors...
|
680 |
+
'include' =>'', //comma|space|hyphen separated list of 'parent', 'siblings', 'ancestors'
|
681 |
+
'ol_root' => 0,
|
682 |
+
'ol_sub' => 0,
|
683 |
+
//determines title_from_parent & title_from_current...
|
684 |
+
'title_from' => '', //comma|space|hyphen separated list of 'parent', 'current'
|
685 |
+
'depth_rel_current' => 0, // v2.0.0
|
686 |
+
//strings...
|
687 |
+
'container' => 'div', // a tag : div|nav are WP restrictions, not the widget's; '' = no container
|
688 |
+
'container_id' => '',
|
689 |
+
'container_class' => '',
|
690 |
+
'menu_class' => 'menu-widget',
|
691 |
+
'widget_class' => '',
|
692 |
+
//determines before & after...
|
693 |
+
'wrap_link' => '', // a tag name (eg. div, p, span, etc)
|
694 |
+
//determines link_before & link_after...
|
695 |
+
'wrap_link_text' => '' // a tag name (eg. span, em, strong)
|
696 |
+
),
|
697 |
+
$atts,
|
698 |
+
$tag // since WP3.6 this allows use of shortcode_atts_custom_menu_wizard filter, applied by shortcode_atts()
|
699 |
+
);
|
700 |
|
701 |
+
$instance = apply_filters( 'custom_menu_wizard_shortcode_attributes', $instance );
|
|
|
702 |
|
703 |
+
if( empty( $instance['menu'] ) ){
|
704 |
+
//gonna find the first menu (alphabetically) that has items...
|
705 |
+
$menus = wp_get_nav_menus( array( 'orderby' => 'name' ) );
|
706 |
+
}else{
|
707 |
+
//allow for menu being something other than an id (eg. slug or name), but we need the id for the widget...
|
708 |
+
$menus = wp_get_nav_menu_object( $instance['menu'] );
|
709 |
+
if( !empty( $menus) ){
|
710 |
+
$menus = array( $menus );
|
711 |
}
|
712 |
+
}
|
713 |
+
if( !empty( $menus ) ){
|
714 |
+
foreach( $menus as $i=>$menu ){
|
715 |
+
$items = wp_get_nav_menu_items( $menu->term_id );
|
716 |
+
$ok = !empty( $items );
|
717 |
+
if( $ok ){
|
718 |
+
$instance['menu'] = $menu->term_id;
|
719 |
+
break;
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
720 |
}
|
|
|
721 |
}
|
722 |
}
|
723 |
+
unset( $menus );
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
724 |
|
725 |
+
if( $ok ){
|
726 |
+
$instance['filter'] = $instance['filter_item'] = 0;
|
727 |
+
if( empty( $instance['items'] ) ){
|
728 |
+
//children_of => filter & filter_item...
|
729 |
+
if( empty( $instance['children_of'] ) ){
|
730 |
+
$instance['children_of'] = '';
|
731 |
+
}
|
732 |
+
switch( $instance['children_of'] ){
|
733 |
+
case '':
|
734 |
+
break;
|
735 |
+
case 'root': case 'current-ancestor':
|
736 |
+
--$instance['filter_item']; //ends up as -2
|
737 |
+
case 'parent': case 'current-parent':
|
738 |
+
--$instance['filter_item']; //ends up as -1
|
739 |
+
case 'current': case 'current-item':
|
740 |
+
$instance['filter'] = 1;
|
741 |
+
break;
|
742 |
+
default:
|
743 |
+
$instance['filter'] = 1;
|
744 |
+
$instance['filter_item'] = strtolower( $instance['children_of'] );
|
745 |
+
}
|
746 |
+
//if filter_item is non-numeric then it could be the title of a menu item, but we need it to be the menu item's id...
|
747 |
+
if( !is_numeric( $instance['filter_item'] ) ){
|
748 |
+
foreach( $items as $item ){
|
749 |
+
$ok = strtolower( $item->title ) == $instance['filter_item'];
|
750 |
+
if( $ok ){
|
751 |
+
$instance['filter_item'] = $item->ID;
|
752 |
+
break;
|
753 |
+
}
|
754 |
+
}
|
755 |
+
}
|
756 |
+
}else{
|
757 |
+
$instance['filter'] = -1;
|
758 |
}
|
759 |
+
unset( $instance['children_of'] );
|
760 |
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
761 |
|
762 |
+
if( $ok ){
|
763 |
+
//fallback_parent => fallback_no_ancestor switch (and extension switches)...
|
764 |
+
$instance['fallback_no_ancestor'] = $instance['fallback_include_parent'] = $instance['fallback_include_parent_siblings'] = 0;
|
765 |
+
if( $instance['filter_item'] < 0 && !empty( $instance['fallback_parent'] ) ){
|
766 |
+
$instance['fallback_no_ancestor'] = 1;
|
767 |
+
$i = preg_split( '/[\s,-]+/', strtolower( $instance['fallback_parent'] ), -1, PREG_SPLIT_NO_EMPTY );
|
768 |
+
foreach( $i as $j ){
|
769 |
+
if( $j == 'parent' ){
|
770 |
+
$instance['fallback_include_parent'] = 1;
|
771 |
+
}elseif( $j == 'siblings' ){
|
772 |
+
$instance['fallback_include_parent_siblings'] = 1;
|
773 |
+
}
|
774 |
+
}
|
775 |
}
|
776 |
+
//fallback_current => fallback_no_children switch (and extension switches)...
|
777 |
+
$instance['fallback_no_children'] = $instance['fallback_nc_include_parent'] = $instance['fallback_nc_include_parent_siblings'] = 0;
|
778 |
+
if( $instance['filter'] == 1 && $instance['filter_item'] == 0 && !empty( $instance['fallback_current'] ) ){
|
779 |
+
$instance['fallback_no_children'] = 1;
|
780 |
+
$i = preg_split( '/[\s,-]+/', strtolower( $instance['fallback_current'] ), -1, PREG_SPLIT_NO_EMPTY );
|
781 |
+
foreach( $i as $j ){
|
782 |
+
if( $j == 'parent' ){
|
783 |
+
$instance['fallback_nc_include_parent'] = 1;
|
784 |
+
}elseif( $j == 'siblings' ){
|
785 |
+
$instance['fallback_nc_include_parent_siblings'] = 1;
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
786 |
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
787 |
}
|
788 |
}
|
789 |
+
unset( $instance['fallback_parent'], $instance['fallback_current'] );
|
790 |
+
//include => include_* ...
|
791 |
+
$instance['include_parent'] = $instance['include_parent_siblings'] = $instance['include_ancestors'] = 0;
|
792 |
+
if( $instance['filter'] == 1 && !empty( $instance['include'] ) ){
|
793 |
+
$i = preg_split( '/[\s,-]+/', strtolower( $instance['include'] ), -1, PREG_SPLIT_NO_EMPTY );
|
794 |
+
foreach( $i as $j ){
|
795 |
+
if( $j == 'parent' ){
|
796 |
+
$instance['include_parent'] = 1;
|
797 |
+
}elseif( $j == 'siblings' ){
|
798 |
+
$instance['include_parent_siblings'] = 1;
|
799 |
+
}elseif( $j == 'ancestors' ){
|
800 |
+
$instance['include_ancestors'] = 1;
|
801 |
}
|
802 |
}
|
|
|
|
|
|
|
|
|
803 |
}
|
804 |
+
unset( $instance['include'] );
|
805 |
+
//title_from => title_from_parent, title_from_current ...
|
806 |
+
$instance['title_from_parent'] = $instance['title_from_current'] = 0;
|
807 |
+
if( !empty( $instance['title_from'] ) ){
|
808 |
+
$i = preg_split( '/[\s,-]+/', strtolower( $instance['title_from'] ), -1, PREG_SPLIT_NO_EMPTY );
|
809 |
+
foreach( $i as $j ){
|
810 |
+
if( $j == 'parent' ){
|
811 |
+
$instance['title_from_parent'] = 1;
|
812 |
+
}elseif( $j == 'current' ){
|
813 |
+
$instance['title_from_current'] = 1;
|
814 |
+
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
815 |
}
|
816 |
}
|
817 |
+
unset( $instance['title_from'] );
|
818 |
+
//wrap_link => before & after...
|
819 |
+
$instance['before'] = $instance['after'] = '';
|
820 |
+
$instance['wrap_link'] = esc_attr( trim( $instance['wrap_link'] ) );
|
821 |
+
if( !empty( $instance['wrap_link'] ) ){
|
822 |
+
$instance['before'] = '<' . $instance['wrap_link'] . '>';
|
823 |
+
$instance['after'] = '</' . $instance['wrap_link'] . '>';
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
824 |
}
|
825 |
+
//wrap_link_text => link_before & link_after...
|
826 |
+
$instance['link_before'] = $instance['link_after'] = '';
|
827 |
+
$instance['wrap_link_text'] = esc_attr( trim( $instance['wrap_link_text'] ) );
|
828 |
+
if( !empty( $instance['wrap_link_text'] ) ){
|
829 |
+
$instance['link_before'] = '<' . $instance['wrap_link_text'] . '>';
|
830 |
+
$instance['link_after'] = '</' . $instance['wrap_link_text'] . '>';
|
|
|
|
|
|
|
|
|
|
|
|
|
831 |
}
|
832 |
+
|
833 |
+
//handle widget_class here because we have full control over $before_widget...
|
834 |
+
$before_widget_class = array(
|
835 |
+
'widget_custom_menu_wizard',
|
836 |
+
'shortcode_custom_menu_wizard'
|
837 |
+
);
|
838 |
+
$instance['widget_class'] = empty( $instance['widget_class'] ) ? '' : esc_attr( trim ( $instance['widget_class'] ) );
|
839 |
+
if( !empty( $instance['widget_class'] ) ){
|
840 |
+
foreach( explode(' ', $instance['widget_class'] ) as $i ){
|
841 |
+
if( !empty( $i ) && !in_array( $i, $before_widget_class ) ){
|
842 |
+
$before_widget_class[] = $i;
|
843 |
+
}
|
844 |
+
}
|
|
|
845 |
}
|
846 |
+
$instance['widget_class'] = '';
|
847 |
+
//turn on hide_empty...
|
848 |
+
$instance['hide_empty'] = 1;
|
849 |
}
|
850 |
+
|
851 |
+
if( $ok ){
|
852 |
+
//apart from before_title, these are lifted from the_widget()...
|
853 |
+
$sidebar_args = array(
|
854 |
+
'before_widget' => '<div class="' . implode( ' ', $before_widget_class ) . '">',
|
855 |
+
'after_widget' => '</div>',
|
856 |
+
'before_title' => '<h2 class="widgettitle">',
|
857 |
+
'after_title' => '</h2>'
|
858 |
+
);
|
859 |
+
ob_start();
|
860 |
+
the_widget(
|
861 |
+
'Custom_Menu_Wizard_Widget',
|
862 |
+
apply_filters('custom_menu_wizard_shortcode_settings', $instance ),
|
863 |
+
apply_filters('custom_menu_wizard_shortcode_widget_args', $sidebar_args )
|
864 |
+
);
|
865 |
+
$html = ob_get_clean();
|
866 |
}
|
867 |
+
return empty($html) ? '' : $html;
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
868 |
|
869 |
+
} //end shortcode_legacy()
|
870 |
+
|
871 |
+
} //end class Custom_Menu_Wizard_Plugin
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
872 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
873 |
}
|
Binary file
|
@@ -0,0 +1,1036 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
<?php
|
2 |
+
/*
|
3 |
+
* Plugin Name: Custom Menu Wizard
|
4 |
+
*
|
5 |
+
* Custom Menu Wizard Walker class
|
6 |
+
* NB: Walker_Nav_Menu class is in wp-includes/nav-menu-template.php, and is itself an
|
7 |
+
* extension of the Walker class (wp-includes/class-wp-walker.php)
|
8 |
+
*/
|
9 |
+
class Custom_Menu_Wizard_Walker extends Walker_Nav_Menu {
|
10 |
+
|
11 |
+
/**
|
12 |
+
* CMW custom variables
|
13 |
+
*/
|
14 |
+
var $_cmw_tree;
|
15 |
+
var $_cmw_lowest;
|
16 |
+
var $_cmw_highest;
|
17 |
+
|
18 |
+
/**
|
19 |
+
* opens a sub-level with a UL or OL start-tag
|
20 |
+
*
|
21 |
+
* @param string $output Passed by reference. Used to append additional content.
|
22 |
+
* @param int $depth Depth of page. Used for padding.
|
23 |
+
*/
|
24 |
+
function start_lvl( &$output, $depth = 0, $args = array() ) {
|
25 |
+
|
26 |
+
$indent = str_repeat("\t", $depth);
|
27 |
+
$listtag = empty( $args->_custom_menu_wizard['ol_sub'] ) ? 'ul' : 'ol';
|
28 |
+
$output .= "\n$indent<$listtag class=\"sub-menu\">\n";
|
29 |
+
|
30 |
+
} //end start_lvl()
|
31 |
+
|
32 |
+
/**
|
33 |
+
* closes a sub-level with a UL or OL end-tag
|
34 |
+
*
|
35 |
+
* @param string $output Passed by reference. Used to append additional content.
|
36 |
+
* @param int $depth Depth of page. Used for padding.
|
37 |
+
*/
|
38 |
+
function end_lvl( &$output, $depth = 0, $args = array() ) {
|
39 |
+
|
40 |
+
$indent = str_repeat("\t", $depth);
|
41 |
+
$listtag = empty( $args->_custom_menu_wizard['ol_sub'] ) ? 'ul' : 'ol';
|
42 |
+
$output .= "$indent</$listtag>\n";
|
43 |
+
|
44 |
+
} //end end_lvl()
|
45 |
+
|
46 |
+
/**
|
47 |
+
* pre-filters elements then calls parent::walk()
|
48 |
+
*
|
49 |
+
* @filters : custom_menu_wizard_walker_items array of filtered menu elements; array of args
|
50 |
+
*
|
51 |
+
* @param array $elements Menu items
|
52 |
+
* @param integer $max_depth
|
53 |
+
* @return string
|
54 |
+
*/
|
55 |
+
function walk($elements, $max_depth){
|
56 |
+
|
57 |
+
$args = array_slice(func_get_args(), 2);
|
58 |
+
$args = $args[0];
|
59 |
+
|
60 |
+
if( $max_depth >= -1 && !empty( $elements ) && isset($args->_custom_menu_wizard) ){
|
61 |
+
|
62 |
+
if( empty( $args->_custom_menu_wizard['cmwv'] ) ){
|
63 |
+
$elements = $this->_cmw_walk_legacy( $args, $elements );
|
64 |
+
}else{
|
65 |
+
$elements = $this->_cmw_walk( $args, $elements );
|
66 |
+
}
|
67 |
+
|
68 |
+
//since we've done all the depth filtering, set max_depth to unlimited (unless flat output was requested!)...
|
69 |
+
if( empty( $args->_custom_menu_wizard['flat_output'] ) ){
|
70 |
+
$max_depth = 0;
|
71 |
+
}
|
72 |
+
|
73 |
+
} //ends the check for bad max depth, empty elements, or empty cmw args
|
74 |
+
|
75 |
+
return empty( $elements ) ? '' : parent::walk( apply_filters( 'custom_menu_wizard_walker_items', $elements, $args ), $max_depth, $args );
|
76 |
+
|
77 |
+
} //end walk()
|
78 |
+
|
79 |
+
/**
|
80 |
+
* current & legacy : finds and returns ID of current menu item while creating the tree and levels arrays
|
81 |
+
*
|
82 |
+
* @param array $elements Array of menu items
|
83 |
+
* @param array $cmw Array of widget instance settings
|
84 |
+
* @return integer ID of current menu item (false if not found)
|
85 |
+
*/
|
86 |
+
function _cmw_find_current_item( &$elements, &$cmw ){
|
87 |
+
//$elements is an array of objects, indexed by position within the menu (menu_order),
|
88 |
+
//starting at 1 and incrementing sequentially regardless of parentage (ie. first item is [1],
|
89 |
+
//second item is [2] whether it's at root or subordinate to first item)
|
90 |
+
|
91 |
+
$id_field = $this->db_fields['id']; //eg. = 'db_id'
|
92 |
+
$parent_field = $this->db_fields['parent']; //eg. = 'menu_item_parent'
|
93 |
+
$currentItem = array();
|
94 |
+
|
95 |
+
$this->_cmw_tree = array(
|
96 |
+
0 => array(
|
97 |
+
'level' => 0,
|
98 |
+
'ancestors' => array(),
|
99 |
+
'kids' => array(),
|
100 |
+
'element' => array(),
|
101 |
+
'keepCount' => 0,
|
102 |
+
'keep' => false
|
103 |
+
)
|
104 |
+
);
|
105 |
+
$this->_cmw_levels = array(
|
106 |
+
array() //for the artificial level-0
|
107 |
+
);
|
108 |
+
|
109 |
+
if( isset( $cmw['_exclude'] ) ){ //only came in at v3.0.0!
|
110 |
+
//v3+ allows for inheritance on the $cmw items and exclude csv fields, which means that the _items and _exclude
|
111 |
+
//arrays do not necessarly contain all the relevant items ids, eg. an element such as '23+' in the _exclude array means
|
112 |
+
//that menu item id = 23 is excluded ... AND so are all its descendants!
|
113 |
+
$cmw['__items'] = array();
|
114 |
+
$cmw['__exclude'] = array();
|
115 |
+
$inheritItems = array();
|
116 |
+
$inheritExclude = array();
|
117 |
+
foreach( $cmw['_items'] as $i ){
|
118 |
+
if( substr( $i, -1 ) == '+' ){
|
119 |
+
$i = substr( $i, 0, -1 );
|
120 |
+
$inheritItems[] = $i;
|
121 |
+
}
|
122 |
+
$cmw['__items'][] = $i;
|
123 |
+
}
|
124 |
+
foreach( $cmw['_exclude'] as $i ){
|
125 |
+
if( substr( $i, -1 ) == '+' ){
|
126 |
+
$i = substr( $i, 0, -1 );
|
127 |
+
$inheritExclude[] = $i;
|
128 |
+
}
|
129 |
+
$cmw['__exclude'][] = $i;
|
130 |
+
}
|
131 |
+
}
|
132 |
+
|
133 |
+
foreach( $elements as $i => $item ){
|
134 |
+
$itemID = $item->$id_field;
|
135 |
+
$parentID = empty( $item->$parent_field ) ? 0 : $item->$parent_field;
|
136 |
+
|
137 |
+
//if $this->_cmw_tree[] for the parent hasn't been set then it's an orphan...
|
138 |
+
//NOTE The parent Walker will only handle orphans in a "hierarchical Show All" situation (ie. non-flat output, unlimited depth)
|
139 |
+
// and it does so by appending each orphan as a new top-level item (and note that a child of an orphan is also an orphan!).
|
140 |
+
// However, CMW excludes all orphans (which includes descendants of orphans) so they never reach the parent Walker.
|
141 |
+
// If orphans are required, use WordPress's own Custom Menu widget.
|
142 |
+
if( isset( $this->_cmw_tree[ $parentID ] ) ){
|
143 |
+
//check for current item (as a menu item ID, ie. a key into the tree)...
|
144 |
+
if( $item->current ){
|
145 |
+
//should(!) never get either parent and/or ancestor on an item marked as "current", but unfortunately it does occur (grrr!).
|
146 |
+
//so this has to cope, not only with more than 1 "current" item, but also with "current" items that are incorrectly marked
|
147 |
+
//as (their own?!) parent and/or ancestor.
|
148 |
+
//we're going to look for correctly (solely) marked "current" items and take the first one found;
|
149 |
+
//failing that, look for a "current" item that is also marked as parent, and, again, use the first one found;
|
150 |
+
//failing that, look for a "current" item that is also marked as an ancestor, and, again, use the first one found.
|
151 |
+
//
|
152 |
+
//array keys, priority order : just current -> parent, not ancestor -> parent and ancestor -> ancestor
|
153 |
+
// first found...
|
154 |
+
// - a001 : just current
|
155 |
+
// - b001 : current & parent (not ancestor)
|
156 |
+
// - c001 : current & parent & ancestor
|
157 |
+
// - d001 : current & ancestor (not parent)
|
158 |
+
// next found...
|
159 |
+
// - a002 : just current
|
160 |
+
// - b002 : current & parent (not ancestor)
|
161 |
+
// - c002 : current & parent & ancestor
|
162 |
+
// - d002 : current & ancestor (not parent)
|
163 |
+
// etc
|
164 |
+
//example :
|
165 |
+
// - 1st found : current & ancestor = d001
|
166 |
+
// - 2nd found : current & parent & ancestor = c002
|
167 |
+
// - 3rd found : just current = a003
|
168 |
+
// - 4th found : just current & parent = b004
|
169 |
+
// - 5th found : just current = a005
|
170 |
+
//reverse sort keys alphabetically and a003 comes out on bottom, so third found gets used! (copes with 999 "current" items; should be enough!)
|
171 |
+
$j = $item->current_item_ancestor ? ( $item->current_item_parent ? 'c' : 'd') : ( $item->current_item_parent ? 'b' : 'a' );
|
172 |
+
$currentItem[ $j . sprintf( '%03d' , count( $currentItem ) + 1 ) ] = $itemID;
|
173 |
+
}
|
174 |
+
|
175 |
+
//because it is possible for $itemID not to be unique, we have to play canny :
|
176 |
+
//we need to be able to store multiple references back into $elements for each $itemID, and we therefore have to
|
177 |
+
//check whether we already have a $this->_cmw_tree entry for the $itemID, and if we do then simply store the pointer
|
178 |
+
//back to $elements in the existing $this->_cmw_tree entry for the item ID.
|
179 |
+
//This has consequences :
|
180 |
+
// - the individual menu items (for non-unique item IDs) will be in or out as a group, not as individual items
|
181 |
+
// - if we happen to need, say, the branch title from the branch being filtered, we have to take it from the
|
182 |
+
// first of the group and there need not be any relation between that item's title and the original menu item's
|
183 |
+
// title (as set on the WP Menu Admin page). Can't help that.
|
184 |
+
// - any child will be a child of the group, which actually means it *should* become (at some point?!) the child
|
185 |
+
// of the last member of the group(?!). BUT what if the child is actually intended to be the child of the item it follows,
|
186 |
+
// eg. itemID N, child, itemID N, child, itemID N, itemID N, child, child, itemID N, etc?
|
187 |
+
// CMW can't cope with this : its position is that if WP's Walker can't cope with it then there is no reason why CMW should
|
188 |
+
// attempt to rectify the few (rare) occasions where these situations may arise. (It's possible, but I have chosen not to).
|
189 |
+
// NB The parent Walker assigns children of a non-unique-id menu item to the 1st occurence of the item ID (1st in group)
|
190 |
+
if( isset( $this->_cmw_tree[ $itemID ] ) ){
|
191 |
+
//it's a non-unique item ID! just add the $elements pointer to the element array...
|
192 |
+
$this->_cmw_tree[ $itemID ]['element'][] = $i;
|
193 |
+
}else{
|
194 |
+
//this level...
|
195 |
+
$thisLevel = $this->_cmw_tree[ $parentID ]['level'] + 1;
|
196 |
+
if( empty( $this->_cmw_levels[ $thisLevel ] ) ){
|
197 |
+
$this->_cmw_levels[ $thisLevel ] = array();
|
198 |
+
}
|
199 |
+
$this->_cmw_levels[ $thisLevel ][] = $itemID;
|
200 |
+
|
201 |
+
$this->_cmw_tree[ $itemID ] = array(
|
202 |
+
//level within structure...
|
203 |
+
'level' => $thisLevel,
|
204 |
+
//ancestors (from the artificial level-0, right down to parent, inclusive) within structure...
|
205 |
+
'ancestors' => $this->_cmw_tree[ $parentID ]['ancestors'],
|
206 |
+
//kids within structure, ie array of itemID's...
|
207 |
+
'kids' => array(),
|
208 |
+
//index of item within elements...
|
209 |
+
'element' => array( $i ),
|
210 |
+
//classes added by widget...
|
211 |
+
'classes' => array(),
|
212 |
+
//assume no match...
|
213 |
+
'keep' => false
|
214 |
+
);
|
215 |
+
//append this item's parent onto its ancestors...
|
216 |
+
$this->_cmw_tree[ $itemID ]['ancestors'][] = $parentID;
|
217 |
+
//add this item to its parent's kids...
|
218 |
+
$this->_cmw_tree[ $parentID ]['kids'][] = $itemID;
|
219 |
+
|
220 |
+
//check for inheritance on items and exclude...
|
221 |
+
if( isset( $inheritItems ) ){
|
222 |
+
if( in_array( $parentID, $inheritItems ) ){
|
223 |
+
$inheritItems[] = $itemID;
|
224 |
+
$cmw['__items'][] = $itemID;
|
225 |
+
}
|
226 |
+
if( in_array( $parentID, $inheritExclude ) ){
|
227 |
+
$inheritExclude[] = $itemID;
|
228 |
+
$cmw['__exclude'][] = $itemID;
|
229 |
+
}
|
230 |
+
}
|
231 |
+
}
|
232 |
+
}
|
233 |
+
} //end foreach
|
234 |
+
|
235 |
+
if( isset( $inheritItems ) ){
|
236 |
+
unset( $inheritItems, $inheritExclude );
|
237 |
+
}
|
238 |
+
|
239 |
+
if( empty( $currentItem ) ){
|
240 |
+
$currentItem = false;
|
241 |
+
}else{
|
242 |
+
krsort( $currentItem );
|
243 |
+
$currentItem = array_pop( $currentItem );
|
244 |
+
}
|
245 |
+
|
246 |
+
return $currentItem;
|
247 |
+
|
248 |
+
} //end _cmw_find_current_item()
|
249 |
+
|
250 |
+
/**
|
251 |
+
* current: test for one item being below another item and/or its siblings
|
252 |
+
*
|
253 |
+
* @param integer $lookBelow Menu item ID that needs checking, possibly its siblings as well
|
254 |
+
* @param integer $searchFor Menu item ID that is being looked for
|
255 |
+
* @param boolean $andSiblings Whether to check in $lookBelow's siblings as well
|
256 |
+
* @return boolean Found (or not)
|
257 |
+
*/
|
258 |
+
function _cmw_check_contains_item( $lookBelow, $searchFor, $andSiblings ){
|
259 |
+
|
260 |
+
$rtn = in_array( $lookBelow, $this->_cmw_tree[ $searchFor ]['ancestors'] );
|
261 |
+
if( !$rtn && $andSiblings ){
|
262 |
+
foreach( $this->_cmw_tree[ $this->_cmw_get_parent( $lookBelow ) ]['kids'] as $kid ){
|
263 |
+
//check whether one of $searchFor's ancestors is $kid...
|
264 |
+
if( $kid != $lookBelow && in_array( $kid, $this->_cmw_tree[ $searchFor ]['ancestors'] ) ){
|
265 |
+
$rtn = true;
|
266 |
+
break;
|
267 |
+
}
|
268 |
+
}
|
269 |
+
}
|
270 |
+
return $rtn;
|
271 |
+
|
272 |
+
}
|
273 |
+
|
274 |
+
/**
|
275 |
+
* returns the menu item id if an item's parent
|
276 |
+
*
|
277 |
+
* @param integer $kid Menu item ID
|
278 |
+
* @return integer Menu item ID of kid's parent
|
279 |
+
*/
|
280 |
+
function _cmw_get_parent( $kid ){
|
281 |
+
|
282 |
+
$immediateParent = array_slice( $this->_cmw_tree[ $kid ]['ancestors'], -1, 1);
|
283 |
+
return $immediateParent[0];
|
284 |
+
|
285 |
+
}
|
286 |
+
|
287 |
+
/**
|
288 |
+
* current: set keep flag of an item's siblings
|
289 |
+
*
|
290 |
+
* @param integer $itemID Menu item ID
|
291 |
+
* @param string $classSuffix Suffix of class to be added to the kept items
|
292 |
+
*/
|
293 |
+
function _cmw_include_siblings_of( $itemID, $classSuffix='sibling' ){
|
294 |
+
|
295 |
+
foreach( $this->_cmw_tree[ $this->_cmw_get_parent( $itemID ) ]['kids'] as $i ){
|
296 |
+
if( !$this->_cmw_tree[ $i ]['keep'] ){
|
297 |
+
$this->_cmw_tree[ $i ]['keep'] = true;
|
298 |
+
$this->_cmw_tree[0]['keepCount']++;
|
299 |
+
if( !empty( $classSuffix ) ){
|
300 |
+
$this->_cmw_tree[ $i ]['classes'][] = 'cmw-an-included-' . $classSuffix;
|
301 |
+
}
|
302 |
+
}
|
303 |
+
}
|
304 |
+
|
305 |
+
} //end _cmw_include_siblings_of()
|
306 |
+
|
307 |
+
/**
|
308 |
+
* current : recursively set the keep flag if within specified level/depth
|
309 |
+
* if item passed in is eligible, sets that item as kept and runs through its kids recursively
|
310 |
+
*
|
311 |
+
* @param integer $itemID Menu item ID
|
312 |
+
*/
|
313 |
+
function _cmw_set_keep_recursive( $itemID ){
|
314 |
+
|
315 |
+
//at or above lowest?...
|
316 |
+
if( $this->_cmw_tree[ $itemID ]['level'] <= $this->_cmw_lowest ){
|
317 |
+
//at or below highest?...
|
318 |
+
if( $this->_cmw_tree[ $itemID ]['level'] >= $this->_cmw_highest ){
|
319 |
+
//keep (if not already)...
|
320 |
+
if( !$this->_cmw_tree[ $itemID ]['keep'] ){
|
321 |
+
$this->_cmw_tree[ $itemID ]['keep'] = true;
|
322 |
+
$this->_cmw_tree[0]['keepCount']++;
|
323 |
+
}
|
324 |
+
}
|
325 |
+
//unless this item is above the lowest level there's no point checking its kids...
|
326 |
+
if( $this->_cmw_tree[ $itemID ]['level'] < $this->_cmw_lowest ){
|
327 |
+
for( $i = 0, $ct = count( $this->_cmw_tree[ $itemID ]['kids'] ); $i < $ct; $i++ ){
|
328 |
+
$this->_cmw_set_keep_recursive( $this->_cmw_tree[ $itemID ]['kids'][ $i ] );
|
329 |
+
}
|
330 |
+
}
|
331 |
+
}
|
332 |
+
|
333 |
+
} //end _cmw_set_keep_recursive()
|
334 |
+
|
335 |
+
/**
|
336 |
+
* legacy : recursively set the keep flag if within specified level/depth
|
337 |
+
* runs through kids of item passed in : if kid is eligible, sets kid to kept; if grandkids might be eligible, recurse with kid
|
338 |
+
*
|
339 |
+
* @param integer $itemID Menu item ID
|
340 |
+
* @param integer $topLevel Uppermost level that can be kept
|
341 |
+
* @param integer $bottomLevel Lowermost level that can be kept
|
342 |
+
*/
|
343 |
+
function _cmw_legacy_set_keep_kids( $itemId, $topLevel, $bottomLevel ){
|
344 |
+
|
345 |
+
for( $i = 0, $ct = count( $this->_cmw_tree[ $itemId ]['kids'] ); $i < $ct; $i++ ){
|
346 |
+
$j = $this->_cmw_tree[ $itemId ]['kids'][ $i ];
|
347 |
+
if( $this->_cmw_tree[ $j ]['level'] <= $bottomLevel ){
|
348 |
+
if( ( $this->_cmw_tree[ $j ]['keep'] = $this->_cmw_tree[ $j ]['level'] >= $topLevel ) !== false){
|
349 |
+
$this->_cmw_tree[0]['keepCount']++;
|
350 |
+
}
|
351 |
+
}
|
352 |
+
if( $this->_cmw_tree[ $j ]['level'] < $bottomLevel ){
|
353 |
+
$this->_cmw_legacy_set_keep_kids( $j, $topLevel, $bottomLevel );
|
354 |
+
}
|
355 |
+
}
|
356 |
+
|
357 |
+
} //end _cmw_legacy_set_keep_kids()
|
358 |
+
|
359 |
+
/**
|
360 |
+
* pre-filters elements
|
361 |
+
*
|
362 |
+
* @param {object} $args Params supplied to wp_nav_menu()
|
363 |
+
* @param {array} $elements Menu items
|
364 |
+
* @return {array} Modified menu items
|
365 |
+
*/
|
366 |
+
function _cmw_walk( &$args, $elements ){
|
367 |
+
|
368 |
+
$cmw =& $args->_custom_menu_wizard;
|
369 |
+
|
370 |
+
$cmw['_walker']['fellback'] = false;
|
371 |
+
|
372 |
+
$find_items = $cmw['filter'] == 'items';
|
373 |
+
$find_branch = $cmw['filter'] == 'branch';
|
374 |
+
$find_level = !$find_items && !$find_branch;
|
375 |
+
$find_current = $find_branch && empty( $cmw['branch'] );
|
376 |
+
|
377 |
+
//find the current menu item while creating the tree and levels arrays...
|
378 |
+
$currentItem = $this->_cmw_find_current_item( $elements, $cmw );
|
379 |
+
|
380 |
+
//measuring depth relative to the current item only applies if depth is *not* unlimited...
|
381 |
+
$depth = intval( $cmw['depth'] );
|
382 |
+
$depth_rel_current = $cmw['depth_rel_current'] && $depth > 0 && !empty( $currentItem ); //v2.0.0
|
383 |
+
//no-kids fallback?...
|
384 |
+
$canFallback = $find_current && in_array( $cmw['fallback'], array('current', 'parent', 'quit') );
|
385 |
+
|
386 |
+
$id_field = $this->db_fields['id']; //eg. = 'db_id'
|
387 |
+
$parent_field = $this->db_fields['parent']; //eg. = 'menu_item_parent'
|
388 |
+
|
389 |
+
$unlimited = 65532;
|
390 |
+
$topOfBranch = -1;
|
391 |
+
|
392 |
+
$continue = true;
|
393 |
+
//no point doing much more if we need the current item and we haven't found it...
|
394 |
+
//handles contains_current == 'menu'...
|
395 |
+
if( empty( $currentItem ) && ( $find_current || !empty( $cmw['contains_current'] ) ) ){
|
396 |
+
$continue = false;
|
397 |
+
}
|
398 |
+
|
399 |
+
//PRIMARY FILTERS...
|
400 |
+
if( $continue ){
|
401 |
+
//levels...
|
402 |
+
if( $find_level ){
|
403 |
+
$continue = $cmw['level'] < count( $this->_cmw_levels );
|
404 |
+
}
|
405 |
+
//items...
|
406 |
+
if( $find_items ){
|
407 |
+
$continue = !empty( $cmw['__items'] );
|
408 |
+
}
|
409 |
+
//branch...
|
410 |
+
if( $find_branch ){
|
411 |
+
$topOfBranch = $find_current
|
412 |
+
? $currentItem
|
413 |
+
: ( isset( $this->_cmw_tree[ $cmw['branch'] ] )
|
414 |
+
? $cmw['branch']
|
415 |
+
: -1
|
416 |
+
);
|
417 |
+
$theBranchItem = $topOfBranch;
|
418 |
+
$continue = $topOfBranch > 0;
|
419 |
+
}
|
420 |
+
} //end PRIMARIES
|
421 |
+
|
422 |
+
//check for current item...
|
423 |
+
if( $continue && ( $cmw['contains_current'] == 'primary' ) ){
|
424 |
+
if( $find_level ){
|
425 |
+
$continue = $this->_cmw_tree[ $currentItem ]['level'] >= $cmw['level'];
|
426 |
+
}
|
427 |
+
if( $find_items ){
|
428 |
+
$continue = in_array( $currentItem, $cmw['__items'] );
|
429 |
+
}
|
430 |
+
if( $find_branch ){
|
431 |
+
$continue = $topOfBranch == $currentItem || in_array( $topOfBranch, $this->_cmw_tree[ $currentItem ]['ancestors'] );
|
432 |
+
}
|
433 |
+
}
|
434 |
+
|
435 |
+
//SECONDARY FILTERS...
|
436 |
+
if( $continue ){
|
437 |
+
//right, let's set some keep flags
|
438 |
+
//for specific items, go straight in on the item id (levels and depth don't apply here)...
|
439 |
+
if( $find_items ){
|
440 |
+
foreach( $cmw['__items'] as $itemID ){
|
441 |
+
$itemID = intval( $itemID );
|
442 |
+
//avoid double counting of duplicates...
|
443 |
+
if( !empty( $itemID ) && isset( $this->_cmw_tree[ $itemID ] ) && !$this->_cmw_tree[ $itemID ]['keep'] ){
|
444 |
+
$this->_cmw_tree[ $itemID ]['keep'] = true;
|
445 |
+
$this->_cmw_tree[0]['keepCount']++;
|
446 |
+
}
|
447 |
+
}
|
448 |
+
}
|
449 |
+
//for by-level filter, use the levels...
|
450 |
+
if( $find_level ){
|
451 |
+
//prior to v2.0.0, depth was always related to the first item found, and still is *unless* depth_rel_current is set
|
452 |
+
if( $depth_rel_current && $this->_cmw_tree[ $currentItem ]['level'] >= $cmw['level'] ){
|
453 |
+
$bottomLevel = $this->_cmw_tree[ $currentItem ]['level'] + $depth - 1;
|
454 |
+
}else{
|
455 |
+
$bottomLevel = $depth > 0 ? $cmw['level'] + $depth - 1 : $unlimited;
|
456 |
+
}
|
457 |
+
for( $i = $cmw['level']; isset( $this->_cmw_levels[ $i ] ) && $i <= $bottomLevel; $i++ ){
|
458 |
+
foreach( $this->_cmw_levels[ $i ] as $itemID ){
|
459 |
+
$this->_cmw_tree[ $itemID ]['keep'] = true;
|
460 |
+
$this->_cmw_tree[0]['keepCount']++;
|
461 |
+
}
|
462 |
+
}
|
463 |
+
}
|
464 |
+
//for branch filters, run a recursive through the structure...
|
465 |
+
if( $find_branch ){
|
466 |
+
$i = $this->_cmw_tree[ $topOfBranch ]['level'];
|
467 |
+
//convert branch_start to an actual level...
|
468 |
+
$j = intval( $cmw['branch_start'] );
|
469 |
+
//convert relative to absolute (max'd against 1)...
|
470 |
+
$j = empty( $j ) ? $i : ( preg_match( '/^(\+|-)/', $cmw['branch_start'] ) > 0 ? max( 1, $i + $j ) : $j );
|
471 |
+
|
472 |
+
//do we have a current-item-no-kids fallback?...
|
473 |
+
if( $canFallback && empty( $this->_cmw_tree[ $currentItem ]['kids'] ) ){
|
474 |
+
//yes, we do...
|
475 |
+
$cmw['_walker']['fellback'] = 'to-' . $cmw['fallback'];
|
476 |
+
//is it a copout?...
|
477 |
+
if( $cmw['fallback'] == 'quit' ){
|
478 |
+
//just set the secondary start level beyond the maximum level available...
|
479 |
+
$j = count( $this->_cmw_levels );
|
480 |
+
}else{
|
481 |
+
//for current, fall back to primary start level; for parent, fall back to primary start level - 1, ensuring
|
482 |
+
//that we don't fall back further than root...
|
483 |
+
$j = $cmw['fallback'] == 'current' || $i < 2 ? $i : $i - 1;
|
484 |
+
//if fallback_depth is specified, override depth and set to depth-rel-current...
|
485 |
+
if( !empty( $cmw['fallback_depth'] ) ){
|
486 |
+
$depth = intval( $cmw['fallback_depth'] );
|
487 |
+
$depth_rel_current = true;
|
488 |
+
}
|
489 |
+
}
|
490 |
+
}
|
491 |
+
|
492 |
+
//$i is the primary level, and $j is the secondary start level
|
493 |
+
//easy result : if secondary start level > max level then there are no matches...
|
494 |
+
if( $j < count( $this->_cmw_levels ) ){
|
495 |
+
//if secondary start level is higher up the tree than the primary level, then
|
496 |
+
//reset the tob to be the current tob's ancestor at the level of $j...
|
497 |
+
if( $j < $i ){
|
498 |
+
$topOfBranch = array_slice( $this->_cmw_tree[ $topOfBranch ]['ancestors'], $j, 1 );
|
499 |
+
$topOfBranch = $topOfBranch[0];
|
500 |
+
//NB $theBranchItem is still set to the original branch item!
|
501 |
+
}
|
502 |
+
|
503 |
+
$this->_cmw_lowest = $unlimited;
|
504 |
+
$this->_cmw_highest = $j;
|
505 |
+
|
506 |
+
//$topOfBranch is a menu item id.
|
507 |
+
//if secondary start is at or above primary, and start_mode is set to "level" then it effectively means that
|
508 |
+
//the top of branch becomes the current topOfBranch *plus* all its siblings. the one qualifier for
|
509 |
+
//this is that if topOfBranch's current level is 1 (root) then the allow_all_root switch must be
|
510 |
+
//enabled in order to expand to all root items
|
511 |
+
$forceLevel = $j <= $i && $cmw['start_mode'] == 'level' && ( $j > 1 || $cmw['allow_all_root'] );
|
512 |
+
|
513 |
+
//prior to v2.0.0, depth was always related to the first item found, and still is *unless* depth_rel_current is set
|
514 |
+
//NB for depth_rel_current to be applicable we need a current item that is :
|
515 |
+
// (a) at or below the secondary start level, and
|
516 |
+
// (b) within the (modified?) branch (ie. has topOfBranch - or possibly one of its siblings! - as an ancestor)
|
517 |
+
if( $depth_rel_current
|
518 |
+
//...this is the (a) part...
|
519 |
+
&& $this->_cmw_tree[ $currentItem ]['level'] >= $this->_cmw_highest
|
520 |
+
//...this is the (b) part, and it might be complicated by the setting of $forceLevel, which would
|
521 |
+
// require the testing, not only of topOfBranch, but also topOfBranch's siblings...
|
522 |
+
&& $this->_cmw_check_contains_item( $topOfBranch, $currentItem, $forceLevel ) ){
|
523 |
+
$this->_cmw_lowest = $this->_cmw_tree[ $currentItem ]['level'];
|
524 |
+
}elseif( $depth > 0 ){
|
525 |
+
$this->_cmw_lowest = $this->_cmw_highest;
|
526 |
+
}
|
527 |
+
$this->_cmw_lowest += $depth - 1;
|
528 |
+
//$this->_cmw_tree[0]['keepCount'] gets incremented during this recursive...
|
529 |
+
if( $forceLevel ){
|
530 |
+
foreach( $this->_cmw_tree[ $this->_cmw_get_parent( $topOfBranch ) ]['kids'] as $k ){
|
531 |
+
$this->_cmw_set_keep_recursive( $k );
|
532 |
+
}
|
533 |
+
}else{
|
534 |
+
$this->_cmw_set_keep_recursive( $topOfBranch );
|
535 |
+
}
|
536 |
+
//if falling back and siblings are required, add them in...
|
537 |
+
//note that root level sibling inclusion is still governed by allow_all_root!
|
538 |
+
if( !empty( $cmw['_walker']['fellback'] ) && $cmw['fallback_siblings'] && $this->_cmw_tree[0]['keepCount'] > 0
|
539 |
+
&& ( $j > 1 || $cmw['allow_all_root'] ) ){
|
540 |
+
$this->_cmw_include_siblings_of( $topOfBranch );
|
541 |
+
}
|
542 |
+
}
|
543 |
+
}
|
544 |
+
$continue = $this->_cmw_tree[0]['keepCount'] > 0;
|
545 |
+
} //end SECONDARIES
|
546 |
+
|
547 |
+
//check for current item...
|
548 |
+
if( $continue && $cmw['contains_current'] == 'secondary' ){
|
549 |
+
$continue = $this->_cmw_tree[ $currentItem ]['keep'];
|
550 |
+
}
|
551 |
+
|
552 |
+
//INCLUSIONS...
|
553 |
+
if( $continue ){
|
554 |
+
if( $find_branch ){
|
555 |
+
//branch ancestors, possibly with their siblings : but only if the original branch item is either being kept or
|
556 |
+
//is below the lowest visible level; ALSO, do not keep any ancestors below the lowest visible level...
|
557 |
+
if( $cmw['ancestors'] != 0 && ( $this->_cmw_tree[ $theBranchItem ]['keep'] || $this->_cmw_tree[ $theBranchItem ]['level'] > $this->_cmw_lowest ) ){
|
558 |
+
//convert relative to absolute...
|
559 |
+
$absAncestors = $cmw['ancestors'] < 0
|
560 |
+
? max( 1, $this->_cmw_tree[ $theBranchItem ]['level'] + $cmw['ancestors'] )
|
561 |
+
: $cmw['ancestors'];
|
562 |
+
//convert relative to absolute...
|
563 |
+
$absSiblings = $cmw['ancestor_siblings'] < 0
|
564 |
+
? max( 1, $this->_cmw_tree[ $theBranchItem ]['level'] + $cmw['ancestor_siblings'] )
|
565 |
+
: $cmw['ancestor_siblings'];
|
566 |
+
foreach( $this->_cmw_tree[ $theBranchItem ]['ancestors'] as $itemID ){
|
567 |
+
if( $itemID > 0
|
568 |
+
&& $this->_cmw_tree[ $itemID ]['level'] >= $absAncestors
|
569 |
+
&& $this->_cmw_tree[ $itemID ]['level'] <= $this->_cmw_lowest ){
|
570 |
+
if( !$this->_cmw_tree[ $itemID ]['keep'] ){
|
571 |
+
$this->_cmw_tree[ $itemID ]['keep'] = true;
|
572 |
+
$this->_cmw_tree[ $itemID ]['classes'][] = 'cmw-an-included-ancestor';
|
573 |
+
$this->_cmw_tree[0]['keepCount']++;
|
574 |
+
}
|
575 |
+
//only keep ancestor siblings if the ancestor itself is being kept
|
576 |
+
if( $absSiblings > 0
|
577 |
+
&& $this->_cmw_tree[ $itemID ]['level'] >= $absSiblings
|
578 |
+
&& $this->_cmw_tree[ $itemID ]['keep'] ){
|
579 |
+
$this->_cmw_include_siblings_of( $itemID, 'ancestor-sibling' );
|
580 |
+
}
|
581 |
+
}
|
582 |
+
}
|
583 |
+
}
|
584 |
+
//branch siblings : only if the original branch item is being kept...
|
585 |
+
if( $cmw['siblings'] && $this->_cmw_tree[ $theBranchItem ]['keep'] ){
|
586 |
+
$this->_cmw_include_siblings_of( $theBranchItem );
|
587 |
+
}
|
588 |
+
}
|
589 |
+
if( $cmw['include_root'] ){
|
590 |
+
//all root items...
|
591 |
+
foreach( $this->_cmw_levels[1] as $itemID ){
|
592 |
+
if( !$this->_cmw_tree[ $itemID ]['keep'] ){
|
593 |
+
$this->_cmw_tree[ $itemID ]['keep'] = true;
|
594 |
+
$this->_cmw_tree[ $itemID ]['classes'][] = 'cmw-an-included-root-item';
|
595 |
+
$this->_cmw_tree[0]['keepCount']++;
|
596 |
+
}
|
597 |
+
}
|
598 |
+
}
|
599 |
+
} //end INCLUSIONS
|
600 |
+
|
601 |
+
//check for current item...
|
602 |
+
if( $continue && $cmw['contains_current'] == 'inclusions' ){
|
603 |
+
$continue = $this->_cmw_tree[ $currentItem ]['keep'];
|
604 |
+
}
|
605 |
+
|
606 |
+
//EXCLUSIONS...
|
607 |
+
if( $continue){
|
608 |
+
if( !empty( $cmw['__exclude'] )){
|
609 |
+
foreach( $cmw['__exclude'] as $itemID ){
|
610 |
+
if( $itemID > 0 && isset( $this->_cmw_tree[ $itemID ] ) && $this->_cmw_tree[ $itemID ]['keep'] ){
|
611 |
+
$this->_cmw_tree[ $itemID ]['keep'] = false;
|
612 |
+
$this->_cmw_tree[0]['keepCount']--;
|
613 |
+
}
|
614 |
+
}
|
615 |
+
$continue = $this->_cmw_tree[0]['keepCount'] > 0;
|
616 |
+
}
|
617 |
+
if( $continue && !empty( $cmw['exclude_level'] ) && preg_match( '/^(\d+)(\+|-)?$/', $cmw['exclude_level'], $i ) > 0 ){
|
618 |
+
if( empty( $i[2] ) ){
|
619 |
+
$i = $i[1];
|
620 |
+
$j = $i + 1;
|
621 |
+
}elseif( $i[2] == '+' ){
|
622 |
+
$i = $i[1];
|
623 |
+
$j = count( $this->_cmw_levels );
|
624 |
+
}else{
|
625 |
+
$j = $i[1] + 1;
|
626 |
+
$i = 1;
|
627 |
+
}
|
628 |
+
while( $i > 0 && isset( $this->_cmw_levels[ $i ] ) && $i < $j ){
|
629 |
+
foreach( $this->_cmw_levels[ $i ] as $itemID ){
|
630 |
+
if( $this->_cmw_tree[ $itemID ]['keep'] ){
|
631 |
+
$this->_cmw_tree[ $itemID ]['keep'] = false;
|
632 |
+
$this->_cmw_tree[0]['keepCount']--;
|
633 |
+
}
|
634 |
+
}
|
635 |
+
$i++;
|
636 |
+
}
|
637 |
+
$continue = $this->_cmw_tree[0]['keepCount'] > 0;
|
638 |
+
}
|
639 |
+
} //end EXCLUSIONS
|
640 |
+
|
641 |
+
//check for current item...
|
642 |
+
if( $continue && $cmw['contains_current'] == 'output' ){
|
643 |
+
$continue = $this->_cmw_tree[ $currentItem ]['keep'];
|
644 |
+
}
|
645 |
+
|
646 |
+
//check for title_from...
|
647 |
+
if( $continue ){
|
648 |
+
//might we want the (original) branch item's, or root item's, title as the widget title?...
|
649 |
+
if( $find_branch && $theBranchItem > 0 ){
|
650 |
+
$cmw['_walker']['branch_title'] = apply_filters(
|
651 |
+
'the_title',
|
652 |
+
$elements[ $this->_cmw_tree[ $theBranchItem ]['element'][0] ]->title,
|
653 |
+
$elements[ $this->_cmw_tree[ $theBranchItem ]['element'][0] ]->ID
|
654 |
+
);
|
655 |
+
if( $this->_cmw_tree[ $theBranchItem ]['level'] > 1 ){
|
656 |
+
$topOfBranch = array_slice( $this->_cmw_tree[ $theBranchItem ]['ancestors'], 1, 1 );
|
657 |
+
$topOfBranch = $topOfBranch[0];
|
658 |
+
$cmw['_walker']['branch_root_title'] = apply_filters(
|
659 |
+
'the_title',
|
660 |
+
$elements[ $this->_cmw_tree[ $topOfBranch ]['element'][0] ]->title,
|
661 |
+
$elements[ $this->_cmw_tree[ $topOfBranch ]['element'][0] ]->ID
|
662 |
+
);
|
663 |
+
}else{
|
664 |
+
$cmw['_walker']['branch_root_title'] = $cmw['_walker']['branch_title'];
|
665 |
+
}
|
666 |
+
}
|
667 |
+
//might we want the current item's, or root item's, title as the widget title?...
|
668 |
+
if( !empty( $currentItem ) ){
|
669 |
+
$cmw['_walker']['current_title'] = apply_filters(
|
670 |
+
'the_title',
|
671 |
+
$elements[ $this->_cmw_tree[ $currentItem ]['element'][0] ]->title,
|
672 |
+
$elements[ $this->_cmw_tree[ $currentItem ]['element'][0] ]->ID
|
673 |
+
);
|
674 |
+
if( $this->_cmw_tree[ $currentItem ]['level'] > 1 ){
|
675 |
+
$topOfBranch = array_slice( $this->_cmw_tree[ $currentItem ]['ancestors'], 1, 1 );
|
676 |
+
$topOfBranch = $topOfBranch[0];
|
677 |
+
$cmw['_walker']['current_root_title'] = apply_filters(
|
678 |
+
'the_title',
|
679 |
+
$elements[ $this->_cmw_tree[ $topOfBranch ]['element'][0] ]->title,
|
680 |
+
$elements[ $this->_cmw_tree[ $topOfBranch ]['element'][0] ]->ID
|
681 |
+
);
|
682 |
+
}else{
|
683 |
+
$cmw['_walker']['current_root_title'] = $cmw['_walker']['current_title'];
|
684 |
+
}
|
685 |
+
}
|
686 |
+
}
|
687 |
+
|
688 |
+
$this->_cmw_levels = null;
|
689 |
+
$substructure = array();
|
690 |
+
if( $continue ){
|
691 |
+
//now we need to gather together all the 'keep' items from the tree;
|
692 |
+
//while doing so, we need to set up levels and kids, ready for adding classes...
|
693 |
+
foreach( $this->_cmw_tree as $k => $v ){
|
694 |
+
if( $v['keep'] ){
|
695 |
+
$substructure[ $k ] = $v;
|
696 |
+
//use kids as a has-submenu flag...
|
697 |
+
$substructure[ $k ]['kids'] = 0;
|
698 |
+
//any surviving parent (except the artificial level-0) should have submenu class set on it...
|
699 |
+
array_shift( $v['ancestors'] ); //remove the level-0
|
700 |
+
for( $i = count( $v['ancestors'] ) - 1; $i >= 0; $i-- ){
|
701 |
+
if( isset( $substructure[ $v['ancestors'][ $i ] ] ) ){
|
702 |
+
$substructure[ $v['ancestors'][ $i ] ]['kids']++;
|
703 |
+
}else{
|
704 |
+
//not a 'kept' ancestor so remove it...
|
705 |
+
array_splice( $v['ancestors'], $i, 1 );
|
706 |
+
}
|
707 |
+
}
|
708 |
+
//ancestors now only has 'kept' ancestors...
|
709 |
+
$substructure[ $k ]['level'] = count( $v['ancestors'] ) + 1;
|
710 |
+
//need to ensure that the parent_field of all the new top-level (ie. root) items is set to
|
711 |
+
//zero, otherwise the parent::walk() will assume they're orphans.
|
712 |
+
//however, we also need to check that parent_field of a child actually points to the closest
|
713 |
+
//'kept' ancestor; otherwise, given A (kept) > B (not kept) > C (kept) the parent_field of C
|
714 |
+
//would point to a non-existent B and would subsequently be considered an orphan!
|
715 |
+
if( $substructure[ $k ]['level'] == 1){
|
716 |
+
$ancestor = 0;
|
717 |
+
}else{
|
718 |
+
//set to the closest ancestor, ie. the new(?) parent...
|
719 |
+
$ancestor = array_slice( $v['ancestors'], -1, 1 );
|
720 |
+
$ancestor = $ancestor[0];
|
721 |
+
}
|
722 |
+
//take a copy of the elements item(s)...
|
723 |
+
$substructure[ $k ]['element'] = array();
|
724 |
+
foreach( $v['element'] as $i => $j ){
|
725 |
+
$elements[ $j ]->$parent_field = $ancestor;
|
726 |
+
$substructure[ $k ]['element'][] = $elements[ $j ];
|
727 |
+
}
|
728 |
+
}
|
729 |
+
}
|
730 |
+
}
|
731 |
+
$this->_cmw_tree = null;
|
732 |
+
|
733 |
+
//put substructure's elements back into $elements (remember that $elements is a 1-based array!)...
|
734 |
+
$elements = array();
|
735 |
+
$n = 1;
|
736 |
+
foreach( $substructure as $k => $v ){
|
737 |
+
$ct = count( $v['element'] ) - 1;
|
738 |
+
foreach( $v['element'] as $i => $j ){
|
739 |
+
$elements[ $n ] = $j;
|
740 |
+
//add the level class...
|
741 |
+
$elements[ $n ]->classes[] = 'cmw-level-' . $v['level'];
|
742 |
+
//add the submenu class? (only to last in group!)...
|
743 |
+
if( $v['kids'] > 0 && $i == $ct ){
|
744 |
+
$elements[ $n ]->classes[] = 'cmw-has-submenu';
|
745 |
+
}else{
|
746 |
+
//3.7 adds a menu-item-has-children class to (original) menu items that have kids : remove it as the item is now childless...
|
747 |
+
$elements[ $n ]->classes = array_diff( $elements[ $n ]->classes, array('menu-item-has-children') );
|
748 |
+
}
|
749 |
+
//add any other CMW classes...
|
750 |
+
$elements[ $n ]->classes = array_merge( $elements[ $n ]->classes, $v['classes'] );
|
751 |
+
$n++;
|
752 |
+
}
|
753 |
+
}
|
754 |
+
unset( $substructure );
|
755 |
+
|
756 |
+
return $elements;
|
757 |
+
|
758 |
+
} //end _cmw_walk()
|
759 |
+
|
760 |
+
/**
|
761 |
+
* pre-filters elements (v2.1.0)
|
762 |
+
*
|
763 |
+
* @param {object} $args Params supplied to wp_nav_menu()
|
764 |
+
* @param {array} $elements Menu items
|
765 |
+
* @return {array} Modified menu items
|
766 |
+
*/
|
767 |
+
function _cmw_walk_legacy( &$args, $elements ){
|
768 |
+
|
769 |
+
//NB : $elements is an array of objects, indexed by position within the menu (menu_order),
|
770 |
+
//starting at 1 and incrementing sequentially regardless of parentage (ie. first item is [1],
|
771 |
+
//second item is [2] whether it's at root or subordinate to first item)
|
772 |
+
|
773 |
+
$cmw =& $args->_custom_menu_wizard;
|
774 |
+
|
775 |
+
$cmw['_walker']['fellback'] = false;
|
776 |
+
|
777 |
+
$find_kids_of = $cmw['filter'] > 0;
|
778 |
+
$find_specific_items = $cmw['filter'] < 0; //v2.0.0 //v2.0.1:bug fixed (changed < 1 to < 0)
|
779 |
+
$find_current_item = $find_kids_of && empty( $cmw['filter_item'] );
|
780 |
+
$find_current_parent = $find_kids_of && $cmw['filter_item'] == -1; //v1.1.0
|
781 |
+
$find_current_root = $find_kids_of && $cmw['filter_item'] == -2; //v1.1.0
|
782 |
+
$depth_rel_current = $cmw['depth_rel_current'] && $cmw['depth'] > 0; //v2.0.0
|
783 |
+
//these could change depending on whether a fallback comes into play (v1.1.0)
|
784 |
+
$include_parent = $cmw['include_parent'] || $cmw['include_ancestors'];
|
785 |
+
$include_parent_siblings = $cmw['include_parent_siblings'];
|
786 |
+
|
787 |
+
$id_field = $this->db_fields['id']; //eg. = 'db_id'
|
788 |
+
$parent_field = $this->db_fields['parent']; //eg. = 'menu_item_parent'
|
789 |
+
|
790 |
+
//find the current menu item while creating the tree and levels arrays...
|
791 |
+
$currentItem = $this->_cmw_find_current_item( $elements, $cmw );
|
792 |
+
|
793 |
+
$allLevels = 9999;
|
794 |
+
$startWithKidsOf = -1;
|
795 |
+
|
796 |
+
//no point doing much more if we need the current item and we haven't found it, or if we're looking for specific items with none given...
|
797 |
+
$continue = true;
|
798 |
+
if( empty( $currentItem ) && ( $find_current_item || $find_current_parent || $find_current_root || $cmw['contains_current'] ) ){
|
799 |
+
$continue = false;
|
800 |
+
}elseif( $find_specific_items && empty( $cmw['items'] ) ){
|
801 |
+
$continue = false;
|
802 |
+
}
|
803 |
+
|
804 |
+
// IMPORTANT : as of v2.0.0, start level has been rationalised so that it acts the same across all filters (except for specific items!).
|
805 |
+
// Previously ...
|
806 |
+
// start level for a show-all filter literally started at the specified level and reported all levels until depth was reached.
|
807 |
+
// however, start level for a kids-of filter specified the level that the *immediate* kids of the selected filter had to be at
|
808 |
+
// or below. That was consistent for a specific item, current-item and current-parent filter, but for a current-root filter what
|
809 |
+
// it actually did was test the current item against the start level, not the current item's root ancestor! Inconsistent!
|
810 |
+
// But regardless of the current-root filter's use of start level, there was still the inconsistency between show-all and
|
811 |
+
// kids-of usage.
|
812 |
+
// Now (as of v2.0.0) ...
|
813 |
+
// start level and depth have been changed to definitively be secondary filters to the show-all & kids-of primary filter.
|
814 |
+
// The primary filter - show-all, or a kids-of - will provide the initial set of items, and the secondary - start level & depth -
|
815 |
+
// will further refine that set, with start level being an absolute, and depth still being relative to the first item found.
|
816 |
+
// The sole exception to this is when Depth Relative to Current Menu Item is set, which modifies the calculation of depth (only)
|
817 |
+
// such that it becomes relative to the level at which the current menu item can be found (but only if it can be found at or
|
818 |
+
// below start level).
|
819 |
+
// The effects of this change are that previously, filtering for kids of an item that was at level 2, with a start level of 4,
|
820 |
+
// would fail to return any items because the immediate kids (at level 3) were outside the start level. Now, the returned items
|
821 |
+
// will begin with the grand-kids (ie. those at level 4).
|
822 |
+
// Note that neither start level nor depth are applicable to a specific items filter (also new at v2.0.0)!
|
823 |
+
|
824 |
+
//the kids-of filters...
|
825 |
+
if( $continue && $find_kids_of ){
|
826 |
+
//specific item...
|
827 |
+
if( $cmw['filter_item'] > 0 && isset( $this->_cmw_tree[ $cmw['filter_item'] ] ) && !empty( $this->_cmw_tree[ $cmw['filter_item'] ]['kids'] ) ){
|
828 |
+
$startWithKidsOf = $cmw['filter_item'];
|
829 |
+
}
|
830 |
+
if( $find_current_item ){
|
831 |
+
if( !empty( $this->_cmw_tree[ $currentItem ]['kids'] ) ){
|
832 |
+
$startWithKidsOf = $currentItem;
|
833 |
+
}elseif( $cmw['fallback_no_children'] ){
|
834 |
+
//no kids, and fallback to current parent is set...
|
835 |
+
//note that there is no "double fallback", so current parent "can" be the artifical zero element (level-0) *if*
|
836 |
+
// the current item is a singleton( ie. no kids & no ancestors)!
|
837 |
+
$ancestor = array_slice( $this->_cmw_tree[ $currentItem ]['ancestors'], -1, 1 );
|
838 |
+
$startWithKidsOf = $ancestor[0]; //can be zero!
|
839 |
+
$include_parent = $include_parent || $cmw['fallback_nc_include_parent'];
|
840 |
+
$include_parent_siblings = $include_parent_siblings || $cmw['fallback_nc_include_parent_siblings'];
|
841 |
+
$cmw['_walker']['fellback'] = 'to-parent';
|
842 |
+
}
|
843 |
+
}elseif( $find_current_parent || $find_current_root ){
|
844 |
+
//as of v2.0.0 the fallback to current item - for current menu items at the top level - is deprecated, but
|
845 |
+
//retained for a while to maintain backward compatibility
|
846 |
+
//if no parent : fall back to current item (if set)...
|
847 |
+
if( $this->_cmw_tree[ $currentItem ]['level'] == 1 && $cmw['fallback_no_ancestor'] ){
|
848 |
+
$startWithKidsOf = $currentItem;
|
849 |
+
$include_parent = $include_parent || $cmw['fallback_include_parent'];
|
850 |
+
$include_parent_siblings = $include_parent_siblings || $cmw['fallback_include_parent_siblings'];
|
851 |
+
$cmw['_walker']['fellback'] = 'to-current';
|
852 |
+
}else{
|
853 |
+
//as of v2.0.0, the artificial level-0 counts as parent of a top-level current menu item...
|
854 |
+
if( $find_current_parent ){
|
855 |
+
$ancestor = -1;
|
856 |
+
}elseif( $this->_cmw_tree[ $currentItem ]['level'] > 1 ){
|
857 |
+
$ancestor = 1;
|
858 |
+
}else{
|
859 |
+
$ancestor = 0;
|
860 |
+
}
|
861 |
+
$ancestor = array_slice( $this->_cmw_tree[ $currentItem ]['ancestors'], $ancestor, 1 );
|
862 |
+
if( !empty( $ancestor ) ){
|
863 |
+
$startWithKidsOf = $ancestor[0]; //as of v2.0.0, this can now be zero!
|
864 |
+
}
|
865 |
+
}
|
866 |
+
}
|
867 |
+
}
|
868 |
+
|
869 |
+
if( $continue ){
|
870 |
+
//right, let's set the keep flags
|
871 |
+
//for specific items, go straight in on the item id (start level and depth do not apply here)...
|
872 |
+
if( $find_specific_items ){
|
873 |
+
foreach( preg_split('/[,\s]+/', $cmw['items'] ) as $itemID ){
|
874 |
+
if( isset( $this->_cmw_tree[ $itemID ] ) ){
|
875 |
+
$this->_cmw_tree[ $itemID ]['keep'] = true;
|
876 |
+
$this->_cmw_tree[0]['keepCount']++;
|
877 |
+
}
|
878 |
+
}
|
879 |
+
//for show-all filter, just use the levels...
|
880 |
+
}elseif( !$find_kids_of ){
|
881 |
+
//prior to v2.0.0, depth was always related to the first item found, and still is *unless* depth_rel_current is set
|
882 |
+
if( $depth_rel_current && !empty( $currentItem ) && $this->_cmw_tree[ $currentItem ]['level'] >= $cmw['start_level'] ){
|
883 |
+
$bottomLevel = $this->_cmw_tree[ $currentItem ]['level'] + $cmw['depth'] - 1;
|
884 |
+
}else{
|
885 |
+
$bottomLevel = $cmw['depth'] > 0 ? $cmw['start_level'] + $cmw['depth'] - 1 : $allLevels;
|
886 |
+
}
|
887 |
+
for( $i = $cmw['start_level']; isset( $this->_cmw_levels[ $i ] ) && $i <= $bottomLevel; $i++ ){
|
888 |
+
foreach( $this->_cmw_levels[ $i ] as $itemID ){
|
889 |
+
$this->_cmw_tree[ $itemID ]['keep'] = true;
|
890 |
+
$this->_cmw_tree[0]['keepCount']++;
|
891 |
+
}
|
892 |
+
}
|
893 |
+
//for kids-of filters, run a recursive through the structure's kids...
|
894 |
+
}elseif( $startWithKidsOf > -1 ){
|
895 |
+
//prior to v2.0.0, depth was always related to the first item found, and still is *unless* depth_rel_current is set
|
896 |
+
//NB the in_array() of ancestors prevents depth_rel_current when startWithKidsOf == currentItem
|
897 |
+
if( $depth_rel_current && !empty( $currentItem ) && $this->_cmw_tree[ $currentItem ]['level'] >= $cmw['start_level']
|
898 |
+
&& in_array( $startWithKidsOf, $this->_cmw_tree[ $currentItem ]['ancestors'] ) ){
|
899 |
+
$bottomLevel = $this->_cmw_tree[ $currentItem ]['level'] - 1 + $cmw['depth'];
|
900 |
+
}else{
|
901 |
+
$bottomLevel = $cmw['depth'] > 0
|
902 |
+
? max( $this->_cmw_tree[ $startWithKidsOf ]['level'] + $cmw['depth'], $cmw['start_level'] + $cmw['depth'] - 1 )
|
903 |
+
: $allLevels;
|
904 |
+
}
|
905 |
+
//$this->_cmw_tree[0]['keepCount'] gets incremented in this recursive method...
|
906 |
+
$this->_cmw_legacy_set_keep_kids( $startWithKidsOf, $cmw['start_level'], $bottomLevel );
|
907 |
+
}
|
908 |
+
|
909 |
+
if( $this->_cmw_tree[0]['keepCount'] > 0 ){
|
910 |
+
//we have some items! we now may need to set some more keep flags, depending on the include settings...
|
911 |
+
|
912 |
+
//do we need to include parent, parent siblings, and/or ancestors?...
|
913 |
+
//NB these are not restricted by start_level!
|
914 |
+
if( $find_kids_of && $startWithKidsOf > 0 ){
|
915 |
+
if( $include_parent ){
|
916 |
+
$this->_cmw_tree[ $startWithKidsOf ]['keep'] = true;
|
917 |
+
$this->_cmw_tree[ $startWithKidsOf ]['classes'][] = 'cmw-the-included-parent';
|
918 |
+
}
|
919 |
+
if( $include_parent_siblings ){
|
920 |
+
$ancestor = array_slice( $this->_cmw_tree[ $startWithKidsOf ]['ancestors'], -1, 1);
|
921 |
+
foreach($this->_cmw_tree[ $ancestor[0] ]['kids'] as $itemID ){
|
922 |
+
//may have already been kept by include_parent...
|
923 |
+
if( !$this->_cmw_tree[ $itemID ]['keep'] ){
|
924 |
+
$this->_cmw_tree[ $itemID ]['keep'] = true;
|
925 |
+
$this->_cmw_tree[ $itemID ]['classes'][] = 'cmw-an-included-parent-sibling';
|
926 |
+
}
|
927 |
+
}
|
928 |
+
}
|
929 |
+
if( $cmw['include_ancestors'] ){
|
930 |
+
foreach( $this->_cmw_tree[ $startWithKidsOf ]['ancestors'] as $itemID ){
|
931 |
+
if( $itemID > 0 && !$this->_cmw_tree[ $itemID ]['keep'] ){
|
932 |
+
$this->_cmw_tree[ $itemID ]['keep'] = true;
|
933 |
+
$this->_cmw_tree[ $itemID ]['classes'][] = 'cmw-an-included-parent-ancestor';
|
934 |
+
}
|
935 |
+
}
|
936 |
+
}
|
937 |
+
}
|
938 |
+
}
|
939 |
+
}
|
940 |
+
|
941 |
+
//check that (a) we have items, and (b) if we must have current menu item, we've got it...
|
942 |
+
$continue = $this->_cmw_tree[0]['keepCount'] > 0 && ( !$cmw['contains_current'] || $this->_cmw_tree[ $currentItem ]['keep'] );
|
943 |
+
//check for title_from...
|
944 |
+
if( $continue ){
|
945 |
+
//might we want the parent's title as the widget title?...
|
946 |
+
if( $find_kids_of && $cmw['title_from_parent'] && $startWithKidsOf > 0 ){
|
947 |
+
$cmw['_walker']['parent_title'] = apply_filters(
|
948 |
+
'the_title',
|
949 |
+
$elements[ $this->_cmw_tree[ $startWithKidsOf ]['element'][0] ]->title,
|
950 |
+
$elements[ $this->_cmw_tree[ $startWithKidsOf ]['element'][0] ]->ID
|
951 |
+
);
|
952 |
+
}
|
953 |
+
//might we want the current item's title as the widget title?...
|
954 |
+
if( !empty( $currentItem ) && $cmw['title_from_current'] ){
|
955 |
+
$cmw['_walker']['current_title'] = apply_filters(
|
956 |
+
'the_title',
|
957 |
+
$elements[ $this->_cmw_tree[ $currentItem ]['element'][0] ]->title,
|
958 |
+
$elements[ $this->_cmw_tree[ $currentItem ]['element'][0] ]->ID
|
959 |
+
);
|
960 |
+
}
|
961 |
+
}
|
962 |
+
|
963 |
+
$this->_cmw_levels = null;
|
964 |
+
$substructure = array();
|
965 |
+
if( $continue ){
|
966 |
+
//now we need to gather together all the 'keep' items from the tree;
|
967 |
+
//while doing so, we need to set up levels and kids, ready for adding classes...
|
968 |
+
foreach( $this->_cmw_tree as $k => $v ){
|
969 |
+
if( $k > 0 && $v['keep'] ){
|
970 |
+
$substructure[ $k ] = $v;
|
971 |
+
//use kids as a has-submenu flag...
|
972 |
+
$substructure[ $k ]['kids'] = 0;
|
973 |
+
//any surviving parent (except the artificial level-0) should have submenu class set on it...
|
974 |
+
array_shift( $v['ancestors'] ); //remove the level-0
|
975 |
+
for( $i = count( $v['ancestors'] ) - 1; $i >= 0; $i-- ){
|
976 |
+
if( isset( $substructure[ $v['ancestors'][ $i ] ] ) ){
|
977 |
+
$substructure[ $v['ancestors'][ $i ] ]['kids']++;
|
978 |
+
}else{
|
979 |
+
//not a 'kept' ancestor so remove it...
|
980 |
+
array_splice( $v['ancestors'], $i, 1 );
|
981 |
+
}
|
982 |
+
}
|
983 |
+
//ancestors now only has 'kept' ancestors...
|
984 |
+
$substructure[ $k ]['level'] = count( $v['ancestors'] ) + 1;
|
985 |
+
//need to ensure that the parent_field of all the new top-level (ie. root) items is set to
|
986 |
+
//zero, otherwise the parent::walk() will assume they're orphans.
|
987 |
+
//however, we also need to check that parent_field of a child actually points to the closest
|
988 |
+
//'kept' ancestor; otherwise, given A (kept) > B (not kept) > C (kept) the parent_field of C
|
989 |
+
//would point to a non-existent B and would subsequently be considered an orphan!
|
990 |
+
if( $substructure[ $k ]['level'] == 1){
|
991 |
+
$ancestor = 0;
|
992 |
+
}else{
|
993 |
+
//set to the closest ancestor, ie. the new(?) parent...
|
994 |
+
$ancestor = array_slice( $v['ancestors'], -1, 1 );
|
995 |
+
$ancestor = $ancestor[0];
|
996 |
+
}
|
997 |
+
//take a copy of the elements item(s)...
|
998 |
+
$substructure[ $k ]['element'] = array();
|
999 |
+
foreach( $v['element'] as $i => $j ){
|
1000 |
+
$elements[ $j ]->$parent_field = $ancestor;
|
1001 |
+
$substructure[ $k ]['element'][] = $elements[ $j ];
|
1002 |
+
}
|
1003 |
+
}
|
1004 |
+
}
|
1005 |
+
}
|
1006 |
+
$this->_cmw_tree = null;
|
1007 |
+
|
1008 |
+
//put substructure's elements back into $elements (remember that $elements is a 1-based array!)...
|
1009 |
+
$elements = array();
|
1010 |
+
$n = 1;
|
1011 |
+
foreach( $substructure as $k => $v ){
|
1012 |
+
$ct = count( $v['element'] ) - 1;
|
1013 |
+
foreach( $v['element'] as $i => $j ){
|
1014 |
+
$elements[ $n ] = $j;
|
1015 |
+
//add the level class...
|
1016 |
+
$elements[ $n ]->classes[] = 'cmw-level-' . $v['level'];
|
1017 |
+
//add the submenu class? (only to last in group!)...
|
1018 |
+
if( $v['kids'] > 0 && $i == $ct ){
|
1019 |
+
$elements[ $n ]->classes[] = 'cmw-has-submenu';
|
1020 |
+
}elseif( $v['kids'] == 0 ){
|
1021 |
+
//3.7 adds a menu-item-has-children class to (original) menu items that have kids : remove it as the item is now childless...
|
1022 |
+
$elements[ $n ]->classes = array_diff( $elements[ $n ]->classes, array('menu-item-has-children') );
|
1023 |
+
}
|
1024 |
+
//add any other CMW classes...
|
1025 |
+
$elements[ $n ]->classes = array_merge( $elements[ $n ]->classes, $v['classes'] );
|
1026 |
+
$n++;
|
1027 |
+
}
|
1028 |
+
}
|
1029 |
+
unset( $substructure );
|
1030 |
+
|
1031 |
+
return $elements;
|
1032 |
+
|
1033 |
+
} //end _cmw_walk_legacy()
|
1034 |
+
|
1035 |
+
} //end Custom_Menu_Wizard_Walker class
|
1036 |
+
?>
|
@@ -0,0 +1,2101 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
<?php
|
2 |
+
/*
|
3 |
+
* Plugin Name: Custom Menu Wizard
|
4 |
+
*
|
5 |
+
* Custom Menu Wizard Widget class
|
6 |
+
*/
|
7 |
+
class Custom_Menu_Wizard_Widget extends WP_Widget {
|
8 |
+
|
9 |
+
/**
|
10 |
+
* class constructor
|
11 |
+
*/
|
12 |
+
function __construct() {
|
13 |
+
|
14 |
+
parent::__construct(
|
15 |
+
'custom-menu-wizard',
|
16 |
+
'Custom Menu Wizard',
|
17 |
+
array(
|
18 |
+
'classname' => 'widget_custom_menu_wizard',
|
19 |
+
'description' => __('Add a custom menu, or part of one, as a widget'),
|
20 |
+
'customizer_support' => true
|
21 |
+
)
|
22 |
+
);
|
23 |
+
$this->_cmw_allow_legacy_update = true;
|
24 |
+
$this->_cmw_legacy_warnreadmore = 'http://wordpress.org/plugins/' . $this->id_base . '/changelog/';
|
25 |
+
//accessibility mode doesn't necessarily mean that javascript is disabled, but if javascript *is* disabled
|
26 |
+
//then accessibility mode *will* be on...
|
27 |
+
$this->_cmw_accessibility = isset( $_GET['editwidget'] ) && $_GET['editwidget'];
|
28 |
+
$this->_cmw_hash_ct = 0;
|
29 |
+
|
30 |
+
} //end __construct()
|
31 |
+
|
32 |
+
/**
|
33 |
+
* produces the backend admin form(s)
|
34 |
+
*
|
35 |
+
* @param array $instance Widget settings
|
36 |
+
*/
|
37 |
+
function form( $instance ) {
|
38 |
+
|
39 |
+
//only call the legacy form method if the widget already exists and doesn't have a version number (old format)...
|
40 |
+
if( !empty( $instance ) && empty( $instance['cmwv'] ) ){
|
41 |
+
$this->cmw_legacy_form( $instance );
|
42 |
+
return;
|
43 |
+
}
|
44 |
+
|
45 |
+
//sanitize $instance...
|
46 |
+
$instance = $this->cmw_settings( $instance, array(), __FUNCTION__ );
|
47 |
+
|
48 |
+
//if no populated menus exist, suggest the user go create one...
|
49 |
+
if( ( $menus = $this->cmw_scan_menus( $instance['menu'], $instance['branch'] ) ) === false ){
|
50 |
+
?>
|
51 |
+
<p class="widget-<?php echo $this->id_base; ?>-no-menus">
|
52 |
+
<em><?php printf( __('No populated menus have been created yet! <a href="%s">Create one...</a>'), admin_url('nav-menus.php') ); ?></em>
|
53 |
+
<input id="<?php echo $this->get_field_id('cmwv'); ?>" name="<?php echo $this->get_field_name('cmwv'); ?>"
|
54 |
+
type="hidden" value="<?php echo Custom_Menu_Wizard_Plugin::$version; ?>" />
|
55 |
+
<?php foreach( array('filters', 'fallbacks', 'output', 'container', 'classes', 'links') as $v ){ ?>
|
56 |
+
<input id="<?php echo $this->get_field_id("fs_$v"); ?>" name="<?php echo $this->get_field_name("fs_$v"); ?>"
|
57 |
+
type="hidden" value="<?php echo $instance["fs_$v"] ? '1' : '0' ?>" />
|
58 |
+
<?php } ?>
|
59 |
+
</p>
|
60 |
+
<?php
|
61 |
+
//all done : quit...
|
62 |
+
return;
|
63 |
+
}
|
64 |
+
|
65 |
+
//create the OPTIONs for the relative & absolute optgroups in the branch level select...
|
66 |
+
$absGroup = array();
|
67 |
+
$relGroup = array();
|
68 |
+
if( empty( $instance['branch_start'] ) ){
|
69 |
+
$branchLevel = '';
|
70 |
+
}else{
|
71 |
+
$branchLevel = $instance['branch_start'];
|
72 |
+
$i = substr( $branchLevel, 0, 1 );
|
73 |
+
//is it currently set relative?...
|
74 |
+
if( $i == '+' || $i == '-' ){
|
75 |
+
//if we only have 1 level then set to branch item...
|
76 |
+
if( $menus['selectedLevels'] < 2 ){
|
77 |
+
$branchLevel = '';
|
78 |
+
//otherwise, limit the 'relativeness' to 1 less than the number of levels
|
79 |
+
//available (ie. 5 levels available gives a range -4 thru to +4)...
|
80 |
+
}elseif( abs( intval( $branchLevel ) ) > $menus['selectedLevels'] - 1 ){
|
81 |
+
$branchLevel = $i . ($menus['selectedLevels'] - 1);
|
82 |
+
}
|
83 |
+
//max an absolute against the number of levels available...
|
84 |
+
}elseif( intval( $branchLevel ) > $menus['selectedLevels'] ){
|
85 |
+
$branchLevel = $menus['selectedLevels'];
|
86 |
+
}
|
87 |
+
}
|
88 |
+
//start with the middle option of the relatives (the level of the branch item)...
|
89 |
+
$relGroup[] = '<option value="" ' . selected( $branchLevel, '', false ) . '>' . __('the Branch') . '</option>';
|
90 |
+
//now do the absolutes and relatives...
|
91 |
+
for( $i = 1; $i <= $menus['selectedLevels']; $i++ ){
|
92 |
+
//topmost of the absolutes gets ' (root)' appended to its descriptor...
|
93 |
+
$t = $i == 1 ? "$i (" . __('root') . ')' : $i;
|
94 |
+
//append to the absolutes...
|
95 |
+
$absGroup[] = '<option value="' . $i . '" ' . selected( $branchLevel, "$i", false ) . '>' . $t . '</option>';
|
96 |
+
//for anything LESS THAN the number of levels...
|
97 |
+
if( $i < $menus['selectedLevels'] ){
|
98 |
+
//immediately above the branch item gets ' (parent)' appended to its descriptor...
|
99 |
+
$t = $i == 1 ? "-$i (" . __('parent') . ')' : "-$i";
|
100 |
+
//prepend to the relatives...
|
101 |
+
array_unshift( $relGroup, '<option value="-' . $i . '" ' . selected( $branchLevel, "-$i", false ) . '>' . $t . '</option>' );
|
102 |
+
//immediately below the branch item gets ' (children)' appended to its descriptor...
|
103 |
+
$t = $i == 1 ? "+$i (" . __('children') . ')' : "+$i";
|
104 |
+
//append to the relatives...
|
105 |
+
array_push( $relGroup, '<option value="+' . $i . '" ' . selected( $branchLevel, "+$i", false ) . '>' . $t . '</option>' );
|
106 |
+
}
|
107 |
+
}
|
108 |
+
|
109 |
+
//set up some simple booleans for use at the disableif___ classes...
|
110 |
+
$isByItems = $instance['filter'] == 'items'; // disableif-ss (IS Items filter)
|
111 |
+
$isUnlimitedDepth = empty( $instance['depth'] ); // disableif-ud (IS unlimited depth)
|
112 |
+
$isNotByBranch = $instance['filter'] != 'branch'; // disableifnot-br (is NOT Branch filter)
|
113 |
+
$isNotBranchCurrentItem = $isNotByBranch || !empty( $instance['branch'] ); // disableifnot-br-ci (is NOT "Branch:Current Item")
|
114 |
+
$isNotFallbackParentCurrent = !in_array( $instance['fallback'], array('parent', 'current') ); //disableifnot-fb-pc (is NOT set to fall back to parent or current)
|
115 |
+
|
116 |
+
//NB the 'onchange' wrapper holds any text required by the "assist"
|
117 |
+
?>
|
118 |
+
<div id="<?php echo $this->get_field_id('onchange'); ?>"
|
119 |
+
class="widget-<?php echo $this->id_base; ?>-onchange<?php echo $this->cmw_wp_version('3.8') ? ' cmw-pre-wp-v38' : ''; ?>"
|
120 |
+
data-cmw-v36plus='<?php echo $this->cmw_wp_version('3.6', true) ? 'true' : 'false'; ?>'
|
121 |
+
data-cmw-dialog-prompt='<?php _e('Click an item to toggle "Current Menu Item"'); ?>'
|
122 |
+
data-cmw-dialog-output='<?php _e('Basic Output'); ?>'
|
123 |
+
data-cmw-dialog-fallback='<?php _e('Fallback invoked'); ?>'
|
124 |
+
data-cmw-dialog-inclusions='<?php _e('Inclusions : 0'); ?>'
|
125 |
+
data-cmw-dialog-exclusions='<?php _e('Exclusions : 0'); ?>'
|
126 |
+
data-cmw-dialog-set-current='<?php _e('No Current Item!'); ?>'
|
127 |
+
data-cmw-dialog-shortcodes='<?php _e('Find posts/pages containing a CMW shortcode'); ?>'
|
128 |
+
data-cmw-dialog-untitled='<?php _e('untitled'); ?>'
|
129 |
+
data-cmw-dialog-fixed='<?php _e('fixed'); ?>'
|
130 |
+
data-cmw-dialog-nonce='<?php echo wp_create_nonce( 'cmw-find-shortcodes' ); ?>'
|
131 |
+
data-cmw-dialog-version='<?php echo Custom_Menu_Wizard_Plugin::$version; ?>'
|
132 |
+
data-cmw-dialog-id='<?php echo $this->get_field_id('dialog'); ?>'>
|
133 |
+
|
134 |
+
<?php
|
135 |
+
/**
|
136 |
+
* permanently visible section : Title (with Hide) and Menu
|
137 |
+
*/
|
138 |
+
?>
|
139 |
+
<p>
|
140 |
+
<input id="<?php echo $this->get_field_id('cmwv'); ?>" name="<?php echo $this->get_field_name('cmwv'); ?>"
|
141 |
+
type="hidden" value="<?php echo Custom_Menu_Wizard_Plugin::$version; ?>" />
|
142 |
+
<label for="<?php echo $this->get_field_id('title'); ?>"><?php _e('Title:') ?></label>
|
143 |
+
<?php $this->cmw_formfield_checkbox( $instance, 'hide_title',
|
144 |
+
array(
|
145 |
+
'label' => __('Hide'),
|
146 |
+
'lclass' => 'alignright'
|
147 |
+
) ); ?>
|
148 |
+
<?php $this->cmw_formfield_textbox( $instance, 'title',
|
149 |
+
array(
|
150 |
+
'fclass' => 'widefat cmw-widget-title'
|
151 |
+
) ); ?>
|
152 |
+
</p>
|
153 |
+
|
154 |
+
<p>
|
155 |
+
<label for="<?php echo $this->get_field_id('menu'); ?>"><?php _e('Select Menu:'); ?></label>
|
156 |
+
<select id="<?php echo $this->get_field_id('menu'); ?>"
|
157 |
+
class="cmw-select-menu cmw-listen" name="<?php echo $this->get_field_name('menu'); ?>">
|
158 |
+
<?php echo $menus['names']; ?>
|
159 |
+
</select>
|
160 |
+
</p>
|
161 |
+
|
162 |
+
<?php
|
163 |
+
/**
|
164 |
+
* start collapsible section : 'Filter'
|
165 |
+
*/
|
166 |
+
$this->cmw_open_a_field_section( $instance, __('Filters'), 'fs_filters' ); ?>
|
167 |
+
|
168 |
+
<div>
|
169 |
+
<?php $this->cmw_assist_link(); ?>
|
170 |
+
<strong><?php _e('Primary Filter'); ?></strong>
|
171 |
+
|
172 |
+
<br />
|
173 |
+
<label class="cmw-verticalalign-baseline">
|
174 |
+
<input id="<?php echo $this->get_field_id('filter'); ?>_0" class="cmw-bylevel cmw-listen"
|
175 |
+
<?php $this->cmw_disableif(); ?> name="<?php echo $this->get_field_name('filter'); ?>"
|
176 |
+
type="radio" value="" <?php checked( $instance['filter'], '' ); ?>
|
177 |
+
/><?php _e('Level:'); ?></label>
|
178 |
+
<select id="<?php echo $this->get_field_id('level'); ?>" class="cmw-level cmw-listen"
|
179 |
+
<?php $this->cmw_disableif(); ?> name="<?php echo $this->get_field_name('level'); ?>">
|
180 |
+
<?php for( $i = 1, $j = $instance['level'] > $menus['selectedLevels'] ? 1 : $instance['level']; $i <= $menus['selectedLevels']; $i++ ){ ?>
|
181 |
+
<option value="<?php echo $i; ?>" <?php selected( $j, $i ); ?>><?php echo $i > 1 ? $i : $i . __(' (root)'); ?></option>
|
182 |
+
<?php } ?>
|
183 |
+
</select>
|
184 |
+
|
185 |
+
<br />
|
186 |
+
<label class="cmw-verticalalign-baseline">
|
187 |
+
<input id="<?php echo $this->get_field_id('filter'); ?>_1" class="cmw-bybranch cmw-listen"
|
188 |
+
<?php $this->cmw_disableif(); ?> name="<?php echo $this->get_field_name('filter'); ?>"
|
189 |
+
type="radio" value="branch" <?php checked( $instance['filter'], 'branch' ); ?>
|
190 |
+
/><?php _e('Branch:'); ?></label>
|
191 |
+
<select id="<?php echo $this->get_field_id('branch'); ?>" class="cmw-branches cmw-assist-items cmw-listen"
|
192 |
+
<?php $this->cmw_disableif(); ?> name="<?php echo $this->get_field_name('branch'); ?>">
|
193 |
+
<option value="0" <?php selected( $instance['branch'], 0 ); ?>><?php _e('Current Item'); ?></option>
|
194 |
+
<?php echo $menus['selectedOptgroup']; ?>
|
195 |
+
</select>
|
196 |
+
<select id="<?php echo $this->get_field_id('branch_ignore'); ?>" class='cmw-off-the-page' disabled="disabled"
|
197 |
+
name="<?php echo $this->get_field_name('branch_ignore'); ?>">
|
198 |
+
<?php echo $menus['optgroups']; ?>
|
199 |
+
</select>
|
200 |
+
|
201 |
+
<br />
|
202 |
+
<label class="cmw-verticalalign-baseline">
|
203 |
+
<input id="<?php echo $this->get_field_id('filter'); ?>_2" class="cmw-byitems cmw-listen"
|
204 |
+
<?php $this->cmw_disableif(); ?> name="<?php echo $this->get_field_name('filter'); ?>"
|
205 |
+
type="radio" value="items" <?php checked( $instance['filter'], 'items' ); ?>
|
206 |
+
/><?php _e('Items:'); ?></label>
|
207 |
+
<?php $this->cmw_formfield_textbox( $instance, 'items',
|
208 |
+
array(
|
209 |
+
'fclass' => 'cmw-maxwidth-twothirds cmw-setitems cmw-listen'
|
210 |
+
) ); ?>
|
211 |
+
</div>
|
212 |
+
|
213 |
+
<div class="cmw-disableif-ss<?php $this->cmw_disableif( 'push', $isByItems ); ?>">
|
214 |
+
<?php $this->cmw_assist_link(); ?>
|
215 |
+
<strong><?php _e('Secondary Filter'); ?></strong>
|
216 |
+
|
217 |
+
<br />
|
218 |
+
<label class="cmw-disableifnot-br<?php $this->cmw_disableif( 'push', $isNotByBranch ); ?>"><?php _e('Starting at:'); ?>
|
219 |
+
<select id="<?php echo $this->get_field_id('branch_start'); ?>" class="cmw-branch-start cmw-listen"
|
220 |
+
<?php $this->cmw_disableif(); ?> name="<?php echo $this->get_field_name('branch_start'); ?>">
|
221 |
+
<optgroup label="<?php _e('relative...'); ?>" data-cmw-text-children="<?php _e('children'); ?>"
|
222 |
+
data-cmw-text-parent="<?php _e('parent'); ?>">
|
223 |
+
<?php echo implode( '', $relGroup ); ?>
|
224 |
+
</optgroup>
|
225 |
+
<optgroup label="<?php _e('absolute...'); ?>">
|
226 |
+
<?php echo implode( '', $absGroup ); ?>
|
227 |
+
</optgroup>
|
228 |
+
</select></label><!-- end .cmw-disableifnot-br --><?php $this->cmw_disableif( 'pop' ); ?>
|
229 |
+
|
230 |
+
<div class="cmw-indented">
|
231 |
+
<label class="cmw-followed-by">
|
232 |
+
<input id="<?php echo $this->get_field_id('start_mode'); ?>_0"
|
233 |
+
name="<?php echo $this->get_field_name('start_mode'); ?>"
|
234 |
+
<?php $this->cmw_disableif(); ?> type="radio" value="" <?php checked( $instance['start_mode'] !== 'level' ); ?>
|
235 |
+
/><?php printf( __('Item %1$s(if possible)%2$s'), '<small>', '</small>' ); ?></label>
|
236 |
+
|
237 |
+
<label class="cmw-whitespace-nowrap">
|
238 |
+
<input id="<?php echo $this->get_field_id('start_mode'); ?>_1" name="<?php echo $this->get_field_name('start_mode'); ?>"
|
239 |
+
<?php $this->cmw_disableif(); ?> type="radio" value="level" <?php checked( $instance['start_mode'] === 'level' ); ?>
|
240 |
+
/><?php _e('Level'); ?></label>
|
241 |
+
|
242 |
+
<br />
|
243 |
+
<?php $this->cmw_formfield_checkbox( $instance, 'allow_all_root',
|
244 |
+
array(
|
245 |
+
'label' => __('Allow all Root Items'),
|
246 |
+
'lclass' => 'cmw-disableifnot-br',
|
247 |
+
'disableif' => $isNotByBranch
|
248 |
+
) ); ?>
|
249 |
+
</div>
|
250 |
+
|
251 |
+
<label><?php _e('For Depth:'); ?>
|
252 |
+
<select id="<?php echo $this->get_field_id('depth'); ?>" data-cmw-text-levels="<?php _e('levels'); ?>"
|
253 |
+
<?php $this->cmw_disableif(); ?> class="cmw-depth cmw-listen" name="<?php echo $this->get_field_name('depth'); ?>">
|
254 |
+
<option value="0" <?php selected( $instance['depth'] > $menus['selectedLevels'] ? 0 : $instance['depth'], 0 ); ?>><?php _e('unlimited'); ?></option>
|
255 |
+
<?php for( $i = 1; $i <= $menus['selectedLevels']; $i++ ){ ?>
|
256 |
+
<option value="<?php echo $i; ?>" <?php selected( $instance['depth'], $i ); ?>><?php printf( _n('%d level', '%d levels', $i), $i ); ?></option>
|
257 |
+
<?php } ?>
|
258 |
+
</select></label>
|
259 |
+
|
260 |
+
<div class="cmw-indented">
|
261 |
+
<?php $this->cmw_formfield_checkbox( $instance, 'depth_rel_current',
|
262 |
+
array(
|
263 |
+
'label' => __('Relative to Current Item'),
|
264 |
+
'lclass' => 'cmw-disableif-ud',
|
265 |
+
'disableif' => $isUnlimitedDepth
|
266 |
+
) ); ?>
|
267 |
+
</div>
|
268 |
+
</div><!-- end .cmw-disableif-ss --><?php $this->cmw_disableif( 'pop' ); ?>
|
269 |
+
|
270 |
+
<div>
|
271 |
+
<?php $this->cmw_assist_link(); ?>
|
272 |
+
<strong><?php _e('Inclusions'); ?></strong>
|
273 |
+
<br />
|
274 |
+
<label class="cmw-disableifnot-br<?php $this->cmw_disableif( 'push', $isNotByBranch ); ?>"><?php _e('Branch Ancestors:'); ?>
|
275 |
+
<select id="<?php echo $this->get_field_id('ancestors'); ?>" class="cmw-ancestors cmw-listen"
|
276 |
+
<?php $this->cmw_disableif(); ?> name="<?php echo $this->get_field_name('ancestors'); ?>"
|
277 |
+
data-cmw-text-tolevel="<?php _e('to level'); ?>">
|
278 |
+
<option value="0" <?php selected( $j, 0 ); ?>> </option>
|
279 |
+
<?php
|
280 |
+
$j = $instance['ancestors'];
|
281 |
+
$j = max( min( $j, $menus['selectedLevels'] - 1 ), 1 - $menus['selectedLevels'] ); ?>
|
282 |
+
<optgroup label="<?php _e('relative...'); ?>" data-cmw-text-for-option=" <?php _e('%d levels'); ?>">
|
283 |
+
<option value="-1" <?php selected( $j, -1 ); ?>><?php printf( __('%d level (parent)'), -1 ); ?></option>
|
284 |
+
<?php for( $i = -2; $i > 0 - $menus['selectedLevels']; $i-- ){ ?>
|
285 |
+
<option value="<?php echo $i; ?>" <?php selected( $j, $i ); ?>><?php printf( __('%d levels'), $i ); ?></option>
|
286 |
+
<?php } ?>
|
287 |
+
</optgroup>
|
288 |
+
<optgroup label="<?php _e('absolute...'); ?>" data-cmw-text-for-option="<?php _e('to level %d'); ?> ">
|
289 |
+
<option value="1" <?php selected( $j, 1 ); ?>><?php printf( __('to level %d (root)'), 1 ); ?></option>
|
290 |
+
<?php for( $i = 2; $i < $menus['selectedLevels']; $i++ ){ ?>
|
291 |
+
<option value="<?php echo $i; ?>" <?php selected( $j, $i ); ?>><?php printf( __('to level %d'), $i ); ?></option>
|
292 |
+
<?php } ?>
|
293 |
+
</optgroup>
|
294 |
+
</select></label><!-- end .cmw-disableifnot-br --><?php $this->cmw_disableif( 'pop' ); ?>
|
295 |
+
|
296 |
+
<div class="cmw-indented cmw-disableifnot-br<?php $this->cmw_disableif( 'push', $isNotByBranch ); ?>">
|
297 |
+
<label><?php _e('... with Siblings:'); ?>
|
298 |
+
<select id="<?php echo $this->get_field_id('ancestor_siblings'); ?>" class="cmw-ancestor-siblings cmw-listen"
|
299 |
+
<?php $this->cmw_disableif(); ?> name="<?php echo $this->get_field_name('ancestor_siblings'); ?>">
|
300 |
+
<option value="0" <?php selected( $j, 0 ); ?>> </option>
|
301 |
+
<?php
|
302 |
+
$j = $instance['ancestor_siblings'];
|
303 |
+
$j = max( min( $j, $menus['selectedLevels'] - 1 ), 1 - $menus['selectedLevels'] ); ?>
|
304 |
+
<optgroup label="<?php _e('relative...'); ?>" data-cmw-text-for-option=" <?php _e('%d levels'); ?>">
|
305 |
+
<option value="-1" <?php selected( $j, -1 ); ?>><?php printf( __('%d level (parent)'), -1 ); ?></option>
|
306 |
+
<?php for( $i = -2; $i > 0 - $menus['selectedLevels']; $i-- ){ ?>
|
307 |
+
<option value="<?php echo $i; ?>" <?php selected( $j, $i ); ?>><?php printf( __('%d levels'), $i ); ?></option>
|
308 |
+
<?php } ?>
|
309 |
+
</optgroup>
|
310 |
+
<optgroup label="<?php _e('absolute...'); ?>" data-cmw-text-for-option="<?php _e('to level %d'); ?> ">
|
311 |
+
<option value="1" <?php selected( $j, 1 ); ?>><?php printf( __('to level %d (root)'), 1 ); ?></option>
|
312 |
+
<?php for( $i = 2; $i < $menus['selectedLevels']; $i++ ){ ?>
|
313 |
+
<option value="<?php echo $i; ?>" <?php selected( $j, $i ); ?>><?php printf( __('to level %d'), $i ); ?></option>
|
314 |
+
<?php } ?>
|
315 |
+
</optgroup>
|
316 |
+
</select></label>
|
317 |
+
</div><!-- end .cmw-disableifnot-br --><?php $this->cmw_disableif( 'pop' ); ?>
|
318 |
+
|
319 |
+
<?php $this->cmw_formfield_checkbox( $instance, 'siblings',
|
320 |
+
array(
|
321 |
+
'label' => __('Branch Siblings'),
|
322 |
+
'lclass' => 'cmw-disableifnot-br',
|
323 |
+
'disableif' => $isNotByBranch
|
324 |
+
) ); ?>
|
325 |
+
|
326 |
+
<br />
|
327 |
+
<?php $this->cmw_formfield_checkbox( $instance, 'include_root',
|
328 |
+
array(
|
329 |
+
'label' => __('All Root Items')
|
330 |
+
) ); ?>
|
331 |
+
</div>
|
332 |
+
|
333 |
+
<div>
|
334 |
+
<?php $this->cmw_assist_link(); ?>
|
335 |
+
<strong><?php _e('Exclusions'); ?></strong>
|
336 |
+
<br />
|
337 |
+
<?php $this->cmw_formfield_textbox( $instance, 'exclude',
|
338 |
+
array(
|
339 |
+
'label' => __('Item Ids:'),
|
340 |
+
'fclass' => 'cmw-maxwidth-twothirds cmw-exclusions'
|
341 |
+
) ); ?>
|
342 |
+
<br />
|
343 |
+
<label><?php _e('By Level:'); ?>
|
344 |
+
<select id="<?php echo $this->get_field_id('exclude_level'); ?>" class="cmw-exclude-level"
|
345 |
+
name="<?php echo $this->get_field_name('exclude_level'); ?>">
|
346 |
+
<?php $j = intval($instance['exclude_level']) > $menus['selectedLevels'] ? '' : $instance['exclude_level']; ?>
|
347 |
+
<option value="" <?php selected( $j, '' ); ?>> </option>
|
348 |
+
<?php for( $i = 1; $i <= $menus['selectedLevels']; $i++ ){ ?>
|
349 |
+
<option value="<?php echo $i; ?>" <?php selected( $j, "$i" ); ?>><?php echo $i; ?></option>
|
350 |
+
<option value="<?php echo $i . '-'; ?>" <?php selected( $j, $i . '-' ); ?>> <?php echo $i . __(' and above'); ?></option>
|
351 |
+
<option value="<?php echo $i . '+'; ?>" <?php selected( $j, $i . '+' ); ?>> <?php echo $i . __(' and below'); ?></option>
|
352 |
+
<?php } ?>
|
353 |
+
</select></label>
|
354 |
+
</div>
|
355 |
+
|
356 |
+
<div>
|
357 |
+
<?php $this->cmw_assist_link(); ?>
|
358 |
+
<strong><?php _e('Qualifier'); ?></strong>
|
359 |
+
<br /><label for="<?php echo $this->get_field_id('contains_current'); ?>"><?php _e('Current Item is in:'); ?></label>
|
360 |
+
<select id="<?php echo $this->get_field_id('contains_current'); ?>"
|
361 |
+
<?php $this->cmw_disableif(); ?> name="<?php echo $this->get_field_name('contains_current'); ?>">
|
362 |
+
<option value="" <?php selected( $instance['contains_current'], '' ); ?>> </option>
|
363 |
+
<option value="menu" <?php selected( $instance['contains_current'], 'menu' ); ?>><?php echo _e('Menu'); ?></option>
|
364 |
+
<option value="primary" <?php selected( $instance['contains_current'], 'primary' ); ?>><?php echo _e('Primary Filter'); ?></option>
|
365 |
+
<option value="secondary" <?php selected( $instance['contains_current'], 'secondary' ); ?>><?php echo _e('Secondary Filter'); ?></option>
|
366 |
+
<option value="inclusions" <?php selected( $instance['contains_current'], 'inclusions' ); ?>><?php echo _e('Inclusions'); ?></option>
|
367 |
+
<option value="output" <?php selected( $instance['contains_current'], 'output' ); ?>><?php echo _e('Final Output'); ?></option>
|
368 |
+
</select>
|
369 |
+
</div>
|
370 |
+
|
371 |
+
<?php $this->cmw_close_a_field_section(); ?>
|
372 |
+
|
373 |
+
<?php
|
374 |
+
/**
|
375 |
+
* v1.2.0 start collapsible section : 'Fallbacks'
|
376 |
+
*/
|
377 |
+
$this->cmw_open_a_field_section( $instance, __('Fallbacks'), 'fs_fallbacks' ); ?>
|
378 |
+
|
379 |
+
<div class="cmw-disableifnot-br-ci<?php $this->cmw_disableif( 'push', $isNotBranchCurrentItem ); ?>">
|
380 |
+
<?php $this->cmw_assist_link(); ?>
|
381 |
+
|
382 |
+
<label for="<?php echo $this->get_field_id('fallback'); ?>"><?php _e('If Current Item has no children:'); ?></label>
|
383 |
+
<select id="<?php echo $this->get_field_id('fallback'); ?>" class="cmw-fallback cmw-listen"
|
384 |
+
<?php $this->cmw_disableif(); ?> name="<?php echo $this->get_field_name('fallback'); ?>">
|
385 |
+
<option value="" <?php selected( $instance['fallback'], '' ); ?>> </option>
|
386 |
+
<option value="parent" <?php selected( $instance['fallback'], 'parent' ); ?>><?php _e('Start at : -1 (parent)'); ?></option>
|
387 |
+
<option value="current" <?php selected( $instance['fallback'], 'current' ); ?>><?php _e('Start at : the Current Item'); ?></option>
|
388 |
+
<option value="quit" <?php selected( $instance['fallback'], 'quit' ); ?>><?php _e('No output!'); ?></option>
|
389 |
+
</select>
|
390 |
+
|
391 |
+
<div class="cmw-indented cmw-disableifnot-fb-pc<?php $this->cmw_disableif( 'push', $isNotFallbackParentCurrent ); ?>">
|
392 |
+
<?php $this->cmw_formfield_checkbox( $instance, 'fallback_siblings',
|
393 |
+
array(
|
394 |
+
'label' => '…' . __('and Include its Siblings')
|
395 |
+
) ); ?>
|
396 |
+
|
397 |
+
<br />
|
398 |
+
<label><?php _e('For Depth:'); ?>
|
399 |
+
<select id="<?php echo $this->get_field_id('fallback_depth'); ?>" data-cmw-text-levels="<?php _e('levels'); ?>"
|
400 |
+
<?php $this->cmw_disableif(); ?> class="cmw-fallback-depth" name="<?php echo $this->get_field_name('fallback_depth'); ?>">
|
401 |
+
<option value="0" <?php selected( $instance['fallback_depth'] > $menus['selectedLevels'] ? 0 : $instance['fallback_depth'], 0 ); ?>> </option>
|
402 |
+
<?php for( $i = 1; $i <= $menus['selectedLevels']; $i++ ){ ?>
|
403 |
+
<option value="<?php echo $i; ?>" <?php selected( $instance['fallback_depth'], $i ); ?>><?php printf( _n('%d level', '%d levels', $i), $i ); ?></option>
|
404 |
+
<?php } ?>
|
405 |
+
</select></label>
|
406 |
+
<span class="cmw-small-block"><em class="cmw-colour-grey"><?php _e('Fallback Depth is Relative to Current Item!'); ?></em></span>
|
407 |
+
</div><!-- end .cmw-disableifnot-fb-pc --><?php $this->cmw_disableif( 'pop' ); ?>
|
408 |
+
|
409 |
+
</div><!-- end .cmw-disableifnot-br-ci --><?php $this->cmw_disableif( 'pop' ); ?>
|
410 |
+
|
411 |
+
<?php $this->cmw_close_a_field_section(); ?>
|
412 |
+
|
413 |
+
<?php
|
414 |
+
/**
|
415 |
+
* start collapsible section : 'Output'
|
416 |
+
*/
|
417 |
+
$this->cmw_open_a_field_section( $instance, __('Output'), 'fs_output' ); ?>
|
418 |
+
|
419 |
+
<div>
|
420 |
+
<?php $this->cmw_assist_link(); ?>
|
421 |
+
<label class="cmw-followed-by">
|
422 |
+
<input id="<?php echo $this->get_field_id('flat_output'); ?>_0"
|
423 |
+
name="<?php echo $this->get_field_name('flat_output'); ?>"
|
424 |
+
<?php $this->cmw_disableif(); ?> type="radio" value="0" <?php checked( !$instance['flat_output'] ); ?>
|
425 |
+
/><?php _e('Hierarchical'); ?></label>
|
426 |
+
<label class="cmw-whitespace-nowrap">
|
427 |
+
<input id="<?php echo $this->get_field_id('flat_output'); ?>_1"
|
428 |
+
name="<?php echo $this->get_field_name('flat_output'); ?>"
|
429 |
+
<?php $this->cmw_disableif(); ?> type="radio" value="1" <?php checked( $instance['flat_output'] ); ?>
|
430 |
+
/><?php _e('Flat'); ?></label>
|
431 |
+
</div>
|
432 |
+
|
433 |
+
<div>
|
434 |
+
Set Title from:
|
435 |
+
<br>
|
436 |
+
<?php $this->cmw_formfield_checkbox( $instance, 'title_from_current',
|
437 |
+
array(
|
438 |
+
'label' => __('Current Item'),
|
439 |
+
'lclass' => 'cmw-followed-by'
|
440 |
+
) ); ?>
|
441 |
+
<?php $this->cmw_formfield_checkbox( $instance, 'title_from_current_root',
|
442 |
+
array(
|
443 |
+
'label' => '…' . __('or its Root'),
|
444 |
+
'lclass' => 'cmw-whitespace-nowrap'
|
445 |
+
) ); ?>
|
446 |
+
<br />
|
447 |
+
<?php $this->cmw_formfield_checkbox( $instance, 'title_from_branch',
|
448 |
+
array(
|
449 |
+
'label' => __('Branch'),
|
450 |
+
'lclass' => 'cmw-followed-by cmw-disableifnot-br',
|
451 |
+
'disableif' => $isNotByBranch
|
452 |
+
) ); ?>
|
453 |
+
<?php $this->cmw_formfield_checkbox( $instance, 'title_from_branch_root',
|
454 |
+
array(
|
455 |
+
'label' => '…' . __('or its Root'),
|
456 |
+
'lclass' => 'cmw-whitespace-nowrap cmw-disableifnot-br',
|
457 |
+
'disableif' => $isNotByBranch
|
458 |
+
) ); ?>
|
459 |
+
</div>
|
460 |
+
|
461 |
+
<div>
|
462 |
+
Change UL to OL:
|
463 |
+
<br />
|
464 |
+
<?php $this->cmw_formfield_checkbox( $instance, 'ol_root',
|
465 |
+
array(
|
466 |
+
'label' => __('Top Level'),
|
467 |
+
'lclass' => 'cmw-followed-by'
|
468 |
+
) ); ?>
|
469 |
+
<?php $this->cmw_formfield_checkbox( $instance, 'ol_sub',
|
470 |
+
array(
|
471 |
+
'label' => __('Sub-Levels'),
|
472 |
+
'lclass' => 'cmw-whitespace-nowrap'
|
473 |
+
) ); ?>
|
474 |
+
</div>
|
475 |
+
|
476 |
+
<?php
|
477 |
+
//v1.1.0 As of WP v3.6, wp_nav_menu() automatically cops out (without outputting any HTML) if there are no items,
|
478 |
+
// so the hide_empty option becomes superfluous; however, I'll keep the previous setting (if there was one)
|
479 |
+
// in case of reversion to an earlier version of WP...
|
480 |
+
if( $this->cmw_wp_version('3.6') ){
|
481 |
+
?>
|
482 |
+
<div>
|
483 |
+
<?php $this->cmw_formfield_checkbox( $instance, 'hide_empty',
|
484 |
+
array(
|
485 |
+
'label' => __('Hide Widget if Empty'),
|
486 |
+
'desc' => __('Prevents any output when no items are found')
|
487 |
+
) ); ?>
|
488 |
+
</div>
|
489 |
+
<?php }else{ ?>
|
490 |
+
<input id="<?php echo $this->get_field_id('hide_empty'); ?>" name="<?php echo $this->get_field_name('hide_empty'); ?>"
|
491 |
+
type="hidden" value="<?php echo $instance['hide_empty'] ? '1' : ''; ?>" />
|
492 |
+
<?php } ?>
|
493 |
+
|
494 |
+
<?php $this->cmw_close_a_field_section(); ?>
|
495 |
+
|
496 |
+
<?php
|
497 |
+
/**
|
498 |
+
* start collapsible section : 'Container'
|
499 |
+
*/
|
500 |
+
$this->cmw_open_a_field_section( $instance, __('Container'), 'fs_container' ); ?>
|
501 |
+
|
502 |
+
<div>
|
503 |
+
<?php $this->cmw_formfield_textbox( $instance, 'container',
|
504 |
+
array(
|
505 |
+
'label' => __('Element:'),
|
506 |
+
'desc' => __('Eg. div or nav; leave empty for no container')
|
507 |
+
) ); ?>
|
508 |
+
</div>
|
509 |
+
<div>
|
510 |
+
<?php $this->cmw_formfield_textbox( $instance, 'container_id',
|
511 |
+
array(
|
512 |
+
'label' => __('Unique ID:'),
|
513 |
+
'desc' => __('An optional ID for the container')
|
514 |
+
) ); ?>
|
515 |
+
</div>
|
516 |
+
<div>
|
517 |
+
<?php $this->cmw_formfield_textbox( $instance, 'container_class',
|
518 |
+
array(
|
519 |
+
'label' => __('Class:'),
|
520 |
+
'desc' => __('Extra class for the container')
|
521 |
+
) ); ?>
|
522 |
+
</div>
|
523 |
+
|
524 |
+
<?php $this->cmw_close_a_field_section(); ?>
|
525 |
+
|
526 |
+
<?php
|
527 |
+
/**
|
528 |
+
* start collapsible section : 'Classes'
|
529 |
+
*/
|
530 |
+
$this->cmw_open_a_field_section( $instance, __('Classes'), 'fs_classes' ); ?>
|
531 |
+
|
532 |
+
<div>
|
533 |
+
<?php $this->cmw_formfield_textbox( $instance, 'menu_class',
|
534 |
+
array(
|
535 |
+
'label' => __('Menu Class:'),
|
536 |
+
'desc' => __('Class for the list element forming the menu')
|
537 |
+
) ); ?>
|
538 |
+
</div>
|
539 |
+
<div>
|
540 |
+
<?php $this->cmw_formfield_textbox( $instance, 'widget_class',
|
541 |
+
array(
|
542 |
+
'label' => __('Widget Class:'),
|
543 |
+
'desc' => __('Extra class for the widget itself')
|
544 |
+
) ); ?>
|
545 |
+
</div>
|
546 |
+
|
547 |
+
<?php $this->cmw_close_a_field_section(); ?>
|
548 |
+
|
549 |
+
<?php
|
550 |
+
/**
|
551 |
+
* start collapsible section : 'Links'
|
552 |
+
*/
|
553 |
+
$this->cmw_open_a_field_section( $instance, __('Links'), 'fs_links' ); ?>
|
554 |
+
|
555 |
+
<div>
|
556 |
+
<?php $this->cmw_formfield_textbox( $instance, 'before',
|
557 |
+
array(
|
558 |
+
'label' => __('Before the Link:'),
|
559 |
+
'desc' =>__( htmlspecialchars('Text/HTML to go before the </a> of the link') ),
|
560 |
+
'fclass' => 'widefat'
|
561 |
+
) ); ?>
|
562 |
+
</div>
|
563 |
+
<div>
|
564 |
+
<?php $this->cmw_formfield_textbox( $instance, 'after',
|
565 |
+
array(
|
566 |
+
'label' => __('After the Link:'),
|
567 |
+
'desc' => __( htmlspecialchars('Text/HTML to go after the </a> of the link') ),
|
568 |
+
'fclass' => 'widefat'
|
569 |
+
) ); ?>
|
570 |
+
</div>
|
571 |
+
<div>
|
572 |
+
<?php $this->cmw_formfield_textbox( $instance, 'link_before',
|
573 |
+
array(
|
574 |
+
'label' => __('Before the Link Text:'),
|
575 |
+
'desc' => __('Text/HTML to go before the link text'),
|
576 |
+
'fclass' => 'widefat'
|
577 |
+
) ); ?>
|
578 |
+
</div>
|
579 |
+
<div>
|
580 |
+
<?php $this->cmw_formfield_textbox( $instance, 'link_after',
|
581 |
+
array(
|
582 |
+
'label' => __('After the Link Text:'),
|
583 |
+
'desc' => __('Text/HTML to go after the link text'),
|
584 |
+
'fclass' => 'widefat'
|
585 |
+
) ); ?>
|
586 |
+
</div>
|
587 |
+
|
588 |
+
<?php $this->cmw_close_a_field_section(); ?>
|
589 |
+
|
590 |
+
<div class="cmw-shortcode-wrap"><code class="widget-<?php echo $this->id_base; ?>-shortcode ui-corner-all" title="<?php _e('shortcode'); ?>"><?php echo $this->cmw_shortcode( $instance ); ?></code></div>
|
591 |
+
|
592 |
+
</div>
|
593 |
+
<?php
|
594 |
+
|
595 |
+
if( $this->_cmw_accessibility ){
|
596 |
+
?>
|
597 |
+
<script type="text/javascript">jQuery(function($){ $('#<?php echo $this->get_field_id('menu'); ?>').trigger('change'); });</script>
|
598 |
+
<?php
|
599 |
+
}
|
600 |
+
|
601 |
+
} //end form()
|
602 |
+
|
603 |
+
/**
|
604 |
+
* sanitizes/updates the widget settings sent from the backend admin
|
605 |
+
*
|
606 |
+
* @param array $new_instance New widget settings
|
607 |
+
* @param array $old_instance Old widget settings
|
608 |
+
* @return array Sanitized widget settings
|
609 |
+
*/
|
610 |
+
function update( $new_instance, $old_instance ) {
|
611 |
+
|
612 |
+
//call the legacy update method for updates to existing widgets that don't have a version number (old format)...
|
613 |
+
if( empty( $new_instance['cmwv'] ) ){
|
614 |
+
return $this->cmw_legacy_update( $new_instance, $old_instance );
|
615 |
+
}
|
616 |
+
|
617 |
+
return $this->cmw_settings( $new_instance, $old_instance, __FUNCTION__ );
|
618 |
+
|
619 |
+
} //end update()
|
620 |
+
|
621 |
+
/**
|
622 |
+
* produces the widget HTML at the front end
|
623 |
+
*
|
624 |
+
* @filters : custom_menu_wizard_nav_params array of params that will be sent to wp_nav_menu(), array of instance settings, id base
|
625 |
+
* custom_menu_wizard_settings_pre_widget array of instance settings, id base
|
626 |
+
* custom_menu_wizard_widget_output HTML output string, array of instance settings, id base
|
627 |
+
*
|
628 |
+
* @param object $args Widget arguments
|
629 |
+
* @param array $instance Configuration for this widget instance
|
630 |
+
*/
|
631 |
+
function widget( $args, $instance ) {
|
632 |
+
|
633 |
+
//call the legacy widget method for producing existing widgets that don't have a version number (old format)...
|
634 |
+
if( empty( $instance['cmwv'] ) ){
|
635 |
+
$this->cmw_legacy_widget( $args, $instance );
|
636 |
+
return;
|
637 |
+
}
|
638 |
+
|
639 |
+
//sanitize $instance...
|
640 |
+
$instance = $this->cmw_settings( $instance, array(), __FUNCTION__ );
|
641 |
+
|
642 |
+
extract( $args, EXTR_SKIP );
|
643 |
+
|
644 |
+
//v1.1.0 As of WP v3.6, wp_nav_menu() automatically prevents any HTML output if there are no items...
|
645 |
+
$instance['hide_empty'] = $instance['hide_empty'] && $this->cmw_wp_version('3.6');
|
646 |
+
|
647 |
+
//allow a filter to amend the instance settings prior to producing the widget output...
|
648 |
+
//eg. add_filter( 'custom_menu_wizard_settings_pre_widget', [filter_function], 10, 2 ) => $instance (array)
|
649 |
+
$instance = apply_filters( 'custom_menu_wizard_settings_pre_widget', $instance, $this->id_base );
|
650 |
+
|
651 |
+
//fetch menu...
|
652 |
+
if( !empty( $instance['menu'] ) ){
|
653 |
+
$menu = wp_get_nav_menu_object( $instance['menu'] );
|
654 |
+
|
655 |
+
//no menu, no output...
|
656 |
+
if ( !empty( $menu ) ){
|
657 |
+
|
658 |
+
if( !empty( $instance['container_class'] ) ){
|
659 |
+
//the menu-[menu->slug]-container class gets applied by WP UNLESS an alternative
|
660 |
+
//container class is supplied in the params - I'm going to set the param such that
|
661 |
+
//this instance's container class (if specified) gets applied IN ADDITION TO the
|
662 |
+
//default one...
|
663 |
+
$instance['container_class'] = "menu-{$menu->slug}-container {$instance['container_class']}";
|
664 |
+
}
|
665 |
+
|
666 |
+
$instance['menu_class'] = preg_split( '/\s+/', $instance['menu_class'], -1, PREG_SPLIT_NO_EMPTY );
|
667 |
+
if( $instance['fallback'] ){
|
668 |
+
//add a cmw-fellback-maybe class to the menu and we'll remove or replace it later...
|
669 |
+
$instance['menu_class'][] = 'cmw-fellback-maybe';
|
670 |
+
}
|
671 |
+
$instance['menu_class'] = implode( ' ', $instance['menu_class'] );
|
672 |
+
|
673 |
+
$walker = new Custom_Menu_Wizard_Walker;
|
674 |
+
$params = array(
|
675 |
+
'menu' => $menu,
|
676 |
+
'container' => empty( $instance['container'] ) ? false : $instance['container'],
|
677 |
+
'container_id' => $instance['container_id'],
|
678 |
+
'menu_class' => $instance['menu_class'],
|
679 |
+
'echo' => false,
|
680 |
+
'fallback_cb' => false,
|
681 |
+
'before' => $instance['before'],
|
682 |
+
'after' => $instance['after'],
|
683 |
+
'link_before' => $instance['link_before'],
|
684 |
+
'link_after' => $instance['link_after'],
|
685 |
+
'depth' => $instance['flat_output'] ? -1 : $instance['depth'],
|
686 |
+
'walker' =>$walker,
|
687 |
+
//widget specific stuff...
|
688 |
+
'_custom_menu_wizard' => $instance
|
689 |
+
);
|
690 |
+
//for the walker's use...
|
691 |
+
$params['_custom_menu_wizard']['_walker'] = array();
|
692 |
+
//set wrapper to UL or OL...
|
693 |
+
$dataCMWS = empty( $instance['cmws_off'] ) ? " data-cmws='" . esc_attr( $this->cmw_shortcode( $instance, true ) ) . "'" : '';
|
694 |
+
if( $instance['ol_root'] ){
|
695 |
+
$params['items_wrap'] = '<ol id="%1$s" class="%2$s" data-cmwv="' . $instance['cmwv'] . '"' . $dataCMWS . '>%3$s</ol>';
|
696 |
+
}else{
|
697 |
+
$params['items_wrap'] = '<ul id="%1$s" class="%2$s" data-cmwv="' . $instance['cmwv'] . '"' . $dataCMWS . '>%3$s</ul>';
|
698 |
+
}
|
699 |
+
//add a container class...
|
700 |
+
if( !empty( $instance['container_class'] ) ){
|
701 |
+
$params['container_class'] = $instance['container_class'];
|
702 |
+
}
|
703 |
+
|
704 |
+
//add my filters...
|
705 |
+
add_filter('custom_menu_wizard_walker_items', array( $this, 'cmw_filter_walker_items' ), 10, 2);
|
706 |
+
if( $instance['hide_empty'] ){
|
707 |
+
add_filter( "wp_nav_menu_{$menu->slug}_items", array( $this, 'cmw_filter_check_for_no_items' ), 65532, 2 );
|
708 |
+
}
|
709 |
+
|
710 |
+
//allow a filter to amend the wp_nav_menu() params prior to calling it...
|
711 |
+
//eg. add_filter( 'custom_menu_wizard_nav_params', [filter_function], 10, 3 ) => $params (array)
|
712 |
+
//NB: wp_nav_menu() is in wp-includes/nav-menu-template.php
|
713 |
+
$out = wp_nav_menu( apply_filters( 'custom_menu_wizard_nav_params', $params, $instance, $this->id_base ) );
|
714 |
+
|
715 |
+
//remove my filters...
|
716 |
+
remove_filter('custom_menu_wizard_walker_items', array( $this, 'cmw_filter_walker_items' ), 10, 2);
|
717 |
+
if( $instance['hide_empty'] ){
|
718 |
+
remove_filter( "wp_nav_menu_{$menu->slug}_items", array( $this, 'cmw_filter_check_for_no_items' ), 65532, 2 );
|
719 |
+
}
|
720 |
+
|
721 |
+
//only put something out if there is something to put out...
|
722 |
+
if( !empty( $out ) ){
|
723 |
+
|
724 |
+
//title from : priority is current -> current root -> branch -> branch root...
|
725 |
+
//note that none actually have to be present in the results
|
726 |
+
foreach( array('current', 'current_root', 'branch', 'branch_root') as $v){
|
727 |
+
if( $instance[ 'title_from_' . $v ] && !empty( $this->_cmw_walker[ $v . '_title' ] ) ){
|
728 |
+
$title = $this->_cmw_walker[ $v . '_title' ];
|
729 |
+
break;
|
730 |
+
}
|
731 |
+
}
|
732 |
+
if( empty( $title ) ){
|
733 |
+
$title = $instance['hide_title'] ? '' : $instance['title'];
|
734 |
+
}
|
735 |
+
//allow the widget_title filter to override anything we've set up...
|
736 |
+
$title = apply_filters('widget_title', $title, $instance, $this->id_base);
|
737 |
+
|
738 |
+
//remove/replace the cmw-fellback-maybe class...
|
739 |
+
$out = str_replace(
|
740 |
+
'cmw-fellback-maybe',
|
741 |
+
empty( $this->_cmw_walker['fellback'] ) ? '' : 'cmw-fellback-' . $this->_cmw_walker['fellback'],
|
742 |
+
$out );
|
743 |
+
|
744 |
+
//try to add widget_class (if specified) to before_widget...
|
745 |
+
if( !empty( $instance['widget_class'] ) && !empty( $before_widget ) ){
|
746 |
+
//$before_widget is usually just a DIV start-tag, with an id and a class; if it
|
747 |
+
//gets more complicated than that then this may not work as expected...
|
748 |
+
if( preg_match( '/^<[^>]+?class=["\']/', $before_widget ) > 0 ){
|
749 |
+
//...already has a class attribute : prepend mine...
|
750 |
+
$before_widget = preg_replace( '/(class=["\'])/', '$1' . $instance['widget_class'] . ' ', $before_widget, 1 );
|
751 |
+
}else{
|
752 |
+
//...doesn't currently have a class : add class attribute...
|
753 |
+
$before_widget = preg_replace( '/^(<\w+)(\s|>)/', '$1 class="' . $instance['widget_class'] . '"$2', $before_widget );
|
754 |
+
}
|
755 |
+
}
|
756 |
+
|
757 |
+
if( !empty( $title ) ){
|
758 |
+
$out = $before_title . $title . $after_title . $out;
|
759 |
+
}
|
760 |
+
$out = $before_widget . $out . $after_widget;
|
761 |
+
//allow a filter to modify the entire output...
|
762 |
+
//eg. add_filter( 'custom_menu_wizard_widget_output', [filter_function], 10, 3 ) => $output (HTML string)
|
763 |
+
echo apply_filters( 'custom_menu_wizard_widget_output', $out, $instance, $this->id_base );
|
764 |
+
}
|
765 |
+
}
|
766 |
+
}
|
767 |
+
|
768 |
+
} //end widget()
|
769 |
+
|
770 |
+
/**
|
771 |
+
* outputs an assist anchor
|
772 |
+
*/
|
773 |
+
function cmw_assist_link(){
|
774 |
+
|
775 |
+
//don't really need to worry about the id for non-javascript enabled usage because the css hides the
|
776 |
+
//button, but it doesn't hurt so I've left it in...
|
777 |
+
$hashid = $this->get_field_id( 'cmw' . ++$this->_cmw_hash_ct );
|
778 |
+
?>
|
779 |
+
<a class="widget-<?php echo $this->id_base; ?>-assist button" id="<?php echo $hashid; ?>" href="#<?php echo $hashid; ?>"><?php _e('assist'); ?></a>
|
780 |
+
<?php
|
781 |
+
|
782 |
+
}
|
783 |
+
|
784 |
+
/**
|
785 |
+
* outputs the HTML to close off a collapsible/expandable group of settings
|
786 |
+
*/
|
787 |
+
function cmw_close_a_field_section(){
|
788 |
+
|
789 |
+
?></div><?php
|
790 |
+
|
791 |
+
} //end cmw_close_a_field_section()
|
792 |
+
|
793 |
+
/**
|
794 |
+
* either pushes, pops, or echoes last of, the disabled attributes array
|
795 |
+
* note that if accessibility mode is on, nothing should get disabled!
|
796 |
+
*
|
797 |
+
* @param string $action 'pop' or 'push'
|
798 |
+
* @param boolean $test What to push
|
799 |
+
*/
|
800 |
+
function cmw_disableif( $action = 'echo', $test = false ){
|
801 |
+
if( !isset( $this->_cmw_disableif ) ){
|
802 |
+
$this->_cmw_disableif = array( '' );
|
803 |
+
}
|
804 |
+
if( $action == 'push' ){
|
805 |
+
if( $test && !$this->_cmw_accessibility ){
|
806 |
+
//append disabled attribute...
|
807 |
+
$this->_cmw_disableif[] = 'disabled="disabled"';
|
808 |
+
//and echo disabled class...
|
809 |
+
echo ' cmw-colour-grey';
|
810 |
+
}else{
|
811 |
+
//append a copy of current last element (maintaining status quo)...
|
812 |
+
$e = array_slice( $this->_cmw_disableif, -1 );
|
813 |
+
$this->_cmw_disableif[] = $e[0];
|
814 |
+
}
|
815 |
+
}elseif( $action == 'pop' ){
|
816 |
+
//remove last element (if count is greater than 1, so it is never left totally empty by mistake)...
|
817 |
+
if( count( $this->_cmw_disableif ) > 1 ){
|
818 |
+
array_pop( $this->_cmw_disableif );
|
819 |
+
}
|
820 |
+
}else{
|
821 |
+
//echo last element...
|
822 |
+
$e = array_slice( $this->_cmw_disableif, -1 );
|
823 |
+
echo $e[0];
|
824 |
+
}
|
825 |
+
}
|
826 |
+
|
827 |
+
/**
|
828 |
+
* this gets run (filter: wp_nav_menu_{$menu->slug}_items) if hide_empty is set
|
829 |
+
* if $items is empty then add a wp_nav_menu filter to do the actual return of an empty string
|
830 |
+
* it gets run before the wp_nav_menu filter, but it gets the $items array whereas the wp_nav_menu filter does not
|
831 |
+
* it gets added by $this->widget() before wp_nav_menu() is called, and removed immediately after wp_nav_menu() returns
|
832 |
+
*
|
833 |
+
* v1.1.0 As of WP v3.6 this method becomes superfluous because wp_nav_menu() has had code added to immediately
|
834 |
+
* cop out (return false) if the output from wp_nav_menu_{$menu->slug}_items filter(s) is empty.
|
835 |
+
* However, it stays in so as to cope with versions < 3.6
|
836 |
+
*
|
837 |
+
* @param array $items Menu items
|
838 |
+
* @param object $args
|
839 |
+
* @return array Menu items
|
840 |
+
*/
|
841 |
+
function cmw_filter_check_for_no_items($items, $args){
|
842 |
+
|
843 |
+
if( !empty( $args->_custom_menu_wizard ) && empty( $items ) ){
|
844 |
+
add_filter( 'wp_nav_menu', array( $this, 'cmw_filter_no_output_when_empty' ), 65532, 2 );
|
845 |
+
}
|
846 |
+
return $items;
|
847 |
+
|
848 |
+
} //end cmw_filter_check_for_no_items()
|
849 |
+
|
850 |
+
/**
|
851 |
+
* this (filter: wp_nav_menu) merely removes itself from the filters and returns an empty string
|
852 |
+
* it gets added by the cmw_filter_check_for_no_items method below, and only
|
853 |
+
* ever gets run when hide_empty is set on the widget instance
|
854 |
+
*
|
855 |
+
* v1.1.0 As of WP v3.6 this method becomes superfluous because wp_nav_menu() has had code added to immediately
|
856 |
+
* cop out (return false) if the output from wp_nav_menu_{$menu->slug}_items filter(s) is empty.
|
857 |
+
* However, it stays in so as to cope with versions < 3.6
|
858 |
+
*
|
859 |
+
* @param string $nav_menu HTML for the menu
|
860 |
+
* @param object $args
|
861 |
+
* @return string HTML for the menu
|
862 |
+
*/
|
863 |
+
function cmw_filter_no_output_when_empty($nav_menu, $args){
|
864 |
+
|
865 |
+
remove_filter( 'wp_nav_menu', array( $this, __FUNCTION__ ), 65532, 2 );
|
866 |
+
return empty( $args->_custom_menu_wizard ) ? $nav_menu : '';
|
867 |
+
|
868 |
+
} //end cmw_filter_no_output_when_empty()
|
869 |
+
|
870 |
+
/**
|
871 |
+
* v1.2.1 stores any walker-determined information back into the widget instance
|
872 |
+
* gets run by the walker, on the filtered array of menu items, just before running parent::walk()
|
873 |
+
* only gets run *if* there are menu items found
|
874 |
+
*
|
875 |
+
* @param array $items Filtered menu items
|
876 |
+
* @param object $args
|
877 |
+
* @return array Menu items
|
878 |
+
*/
|
879 |
+
function cmw_filter_walker_items( $items, $args ){
|
880 |
+
|
881 |
+
if( !empty( $args->_custom_menu_wizard['_walker'] ) ){
|
882 |
+
$this->_cmw_walker = $args->_custom_menu_wizard['_walker'];
|
883 |
+
}
|
884 |
+
return $items;
|
885 |
+
|
886 |
+
} //end cmw_filter_walker_items()
|
887 |
+
|
888 |
+
/**
|
889 |
+
* output a checkbox field
|
890 |
+
*
|
891 |
+
* @param array $instance Contains current field value
|
892 |
+
* @param string $field Field name
|
893 |
+
* @param array $params Attribute values
|
894 |
+
*/
|
895 |
+
function cmw_formfield_checkbox( &$instance, $field, $params ){
|
896 |
+
|
897 |
+
$labelClass = empty( $params['lclass'] ) ? '' : $params['lclass'];
|
898 |
+
$fieldClass = empty( $params['fclass'] ) ? '' : $params['fclass'];
|
899 |
+
$disabling = !empty( $labelClass ) && isset( $params['disableif'] );
|
900 |
+
?>
|
901 |
+
<label class="<?php echo $labelClass; if( $disabling ){ $this->cmw_disableif( 'push', $params['disableif'] ); } ?>">
|
902 |
+
<input id="<?php echo $this->get_field_id( $field ); ?>" class="<?php echo $fieldClass; ?>"
|
903 |
+
name="<?php echo $this->get_field_name( $field ); ?>" <?php $this->cmw_disableif(); ?>
|
904 |
+
<?php checked($instance[ $field ]); ?> type="checkbox" value="1"
|
905 |
+
/><?php echo $params['label']; ?></label><?php if( $disabling ){ $this->cmw_disableif( 'pop' ); } ?>
|
906 |
+
<?php
|
907 |
+
if( !empty( $params['desc'] ) ){
|
908 |
+
?>
|
909 |
+
<span class="cmw-small-block"><em class="cmw-colour-grey"><?php echo $params['desc']; ?></em></span>
|
910 |
+
<?php
|
911 |
+
}
|
912 |
+
|
913 |
+
} // end cmw_formfield_checkbox()
|
914 |
+
|
915 |
+
/**
|
916 |
+
* output a text input field
|
917 |
+
*
|
918 |
+
* @param array $instance Contains current field value
|
919 |
+
* @param string $field Field name
|
920 |
+
* @param array $params Attribute values
|
921 |
+
*/
|
922 |
+
function cmw_formfield_textbox( &$instance, $field, $params ){
|
923 |
+
|
924 |
+
$fieldClass = empty( $params['fclass'] ) ? '' : $params['fclass'];
|
925 |
+
|
926 |
+
if( !empty( $params['label'] ) ){
|
927 |
+
?>
|
928 |
+
<label for="<?php echo $this->get_field_id( $field ); ?>"><?php echo $params['label']; ?></label>
|
929 |
+
<?php
|
930 |
+
}
|
931 |
+
?>
|
932 |
+
<input id="<?php echo $this->get_field_id( $field ); ?>" class="<?php echo $fieldClass; ?>"
|
933 |
+
name="<?php echo $this->get_field_name( $field ); ?>" <?php $this->cmw_disableif(); ?>
|
934 |
+
type="text" value="<?php echo $instance[ $field ]; ?>" />
|
935 |
+
<?php
|
936 |
+
if( !empty( $params['desc'] ) ){
|
937 |
+
?>
|
938 |
+
<span class="cmw-small-block"><em class="cmw-colour-grey"><?php echo $params['desc']; ?></em></span>
|
939 |
+
<?php
|
940 |
+
}
|
941 |
+
|
942 |
+
} // end cmw_formfield_textbox()
|
943 |
+
|
944 |
+
/**
|
945 |
+
* gets menus (in name order) and their items, returning empty array if there are none (or if none have items)
|
946 |
+
*
|
947 |
+
* @param integer $selectedMenu (by reference) The instance setting to check against for a menu to be "selected"
|
948 |
+
* @return array
|
949 |
+
*/
|
950 |
+
function cmw_get_custom_menus( &$selectedMenu ){
|
951 |
+
|
952 |
+
$findSM = $selectedMenu > 0;
|
953 |
+
$menus = wp_get_nav_menus( array( 'orderby' => 'name' ) );
|
954 |
+
if( !empty( $menus ) ){
|
955 |
+
foreach( $menus as $i => $menu ){
|
956 |
+
//find the menu's items, then remove any menus that have no items...
|
957 |
+
$menus[ $i ]->_items = wp_get_nav_menu_items( $menu->term_id );
|
958 |
+
if( empty( $menus[ $i ]->_items ) ){
|
959 |
+
unset( $menus[ $i ] );
|
960 |
+
}else{
|
961 |
+
//if the items are all orphans, then remove the menu...
|
962 |
+
$rootItem = false;
|
963 |
+
foreach( $menus[ $i ]->_items as $item ){
|
964 |
+
$rootItem = $rootItem || $item->menu_item_parent == 0;
|
965 |
+
}
|
966 |
+
if( !$rootItem ){
|
967 |
+
unset( $menus[ $i ] );
|
968 |
+
}elseif( $findSM && $selectedMenu == $menu->term_id ){
|
969 |
+
$findSM = false;
|
970 |
+
}
|
971 |
+
}
|
972 |
+
}
|
973 |
+
}
|
974 |
+
//if findSM is TRUE then we were looking for a specific menu and failed to find it (or it had no eligible items)...
|
975 |
+
if( $findSM ){
|
976 |
+
//clear selectedMenu...
|
977 |
+
$selectedMenu = 0;
|
978 |
+
//this would be the place to flag a warning!
|
979 |
+
}
|
980 |
+
|
981 |
+
return empty( $menus ) ? array() : array_values( $menus );
|
982 |
+
|
983 |
+
} // end cmw_get_custom_menus()
|
984 |
+
|
985 |
+
/**
|
986 |
+
* gets the various option, optgroups, max levels, etc, from the available custom menus (if any)
|
987 |
+
*
|
988 |
+
* @param integer $selectedMenu The instance setting to check against for a menu to be "selected"
|
989 |
+
* @param integer $selectedItem The instance setting to check against for an menu item to be "selected"
|
990 |
+
* @return array|boolean
|
991 |
+
*/
|
992 |
+
function cmw_scan_menus( $selectedMenu, $selectedItem ){
|
993 |
+
|
994 |
+
//create the options for the menu select & branch select...
|
995 |
+
// IE is a pita when it comes to SELECTs because it ignores any styling on OPTGROUPs and OPTIONs, so I'm using
|
996 |
+
// a copy from which the javascript can pick the relevant OPTGROUP
|
997 |
+
$rtn = array(
|
998 |
+
'maxlevel' => 1, //maximum number of levels (across all menus)
|
999 |
+
'names' => array(), //HTML of OPTIONs, for selecting a menu (returned as a string)
|
1000 |
+
'optgroups' => array(), //HTML of OPTGROUPs & contained OPTIONs, for selecting an item (returned as a string)
|
1001 |
+
'selectedOptgroup' => array(''), //HTML of currently selected menu's OPTGROUP and its OPTIONs (returned as string)
|
1002 |
+
'selectedBranchName' => __('the Current Item'), //title of currently selected menu item
|
1003 |
+
'selectedLevels' => 1 //number of levels in the currently selected menu
|
1004 |
+
);
|
1005 |
+
|
1006 |
+
//couple of points:
|
1007 |
+
// - if there's no currently selected menu (eg. it's a new, unsaved form) then use the first menu found that has eligible items
|
1008 |
+
// - if there is a currently selected menu, but that menu is no longer available (no longer exists, or now has no eligible items)
|
1009 |
+
// then, again, use the first menu found that does have items. PROBLEM : this means that the widget's instance settings
|
1010 |
+
// won't match what the widget is currently displaying! this situation is not unique to this function because it can
|
1011 |
+
// also occur for things like depth, but it does raise the question of whether the user should be informed that what
|
1012 |
+
// is being presented does not match the current saved settings?
|
1013 |
+
// Note that also applies to selected item (ie. the menu still exists but the currently selected item within that menu does not).
|
1014 |
+
|
1015 |
+
$ct = 0;
|
1016 |
+
$sogCt = 0;
|
1017 |
+
$itemindents = $menu = $item = NULL;
|
1018 |
+
//note that fetching the menus can clear selectedMenu!
|
1019 |
+
foreach( $this->cmw_get_custom_menus( $selectedMenu ) as $i => $menu ){
|
1020 |
+
$maxgrplevel = 1;
|
1021 |
+
$itemindents = array( '0' => 0 );
|
1022 |
+
$menuGrpOpts = '';
|
1023 |
+
//don't need to check for existence of items because if there were none then the menu wouldn't be here!
|
1024 |
+
foreach( $menu->_items as $item ){
|
1025 |
+
//exclude orphans!
|
1026 |
+
if( isset($itemindents[ $item->menu_item_parent ])){
|
1027 |
+
$title = apply_filters( 'the_title', $item->title, $item->ID );
|
1028 |
+
$level = $itemindents[ $item->menu_item_parent ] + 1;
|
1029 |
+
|
1030 |
+
$itemindents[ $item->ID ] = $level;
|
1031 |
+
$rtn['maxlevel'] = max( $rtn['maxlevel'], $level );
|
1032 |
+
$maxgrplevel = max( $maxgrplevel, $level );
|
1033 |
+
|
1034 |
+
//if there is no currently selected menu AND this is the first found item for this menu then
|
1035 |
+
//set this menu as the currently selected menu (being the first one found with an eligible item)...
|
1036 |
+
if( empty( $selectedMenu ) && empty( $menuGrpOpts ) ){
|
1037 |
+
$selectedMenu = $menu->term_id;
|
1038 |
+
}
|
1039 |
+
//only if THIS is the currently selected menu do we determine "selected" for each menu item...
|
1040 |
+
if( $selectedMenu == $menu->term_id ){
|
1041 |
+
$selected = selected( $selectedItem, $item->ID, false );
|
1042 |
+
if( !empty( $selected ) ){
|
1043 |
+
$rtn['selectedBranchName'] = $title;
|
1044 |
+
}
|
1045 |
+
$rtn['selectedOptgroup'][ $sogCt ] .= '<option value="' . $item->ID . '" ' . $selected . ' data-cmw-level="' . $level . '">';
|
1046 |
+
$rtn['selectedOptgroup'][ $sogCt ] .= str_repeat( ' ', ($level - 1) * 3 ) . $title . '</option>';
|
1047 |
+
}
|
1048 |
+
//don't set "selected" on the big list...
|
1049 |
+
$menuGrpOpts .= '<option value="' . $item->ID . '" data-cmw-level="' . $level . '">';
|
1050 |
+
$menuGrpOpts .= str_repeat( ' ', ($level - 1) * 3 ) . $title . '</option>';
|
1051 |
+
}
|
1052 |
+
}
|
1053 |
+
|
1054 |
+
//should never be empty, but check nevertheless...
|
1055 |
+
if( !empty( $menuGrpOpts ) ){
|
1056 |
+
$rtn['names'][ $ct ] = '<option ' . selected( $selectedMenu, $menu->term_id, false ) . ' value="' . $menu->term_id . '">' . $menu->name . '</option>';
|
1057 |
+
$rtn['optgroups'][ $ct ] = '<optgroup label="' . $menu->name . '" data-cmw-optgroup-index="' . $ct . '" data-cmw-max-level="' . $maxgrplevel . '">';
|
1058 |
+
$rtn['optgroups'][ $ct ] .= $menuGrpOpts;
|
1059 |
+
$rtn['optgroups'][ $ct ] .= '</optgroup>';
|
1060 |
+
//if this menu is selected, then store this optgroup as the selected optgroup, and the number of levels it has...
|
1061 |
+
if( $selectedMenu == $menu->term_id ){
|
1062 |
+
$rtn['selectedOptgroup'][ $sogCt ] = '<optgroup label="' . $menu->name . '" data-cmw-optgroup-index="' . $ct . '" data-cmw-max-level="' . $maxgrplevel . '">' . $rtn['selectedOptgroup'][ $sogCt ] . '</optgroup>';
|
1063 |
+
$rtn['selectedOptgroup'][ ++$sogCt ] = '';
|
1064 |
+
$rtn['selectedLevels'] = $maxgrplevel;
|
1065 |
+
}elseif( $this->_cmw_accessibility ){
|
1066 |
+
//if accessibility is on then the selected groups need to contain *all* the groups otherwise, with javascript disabled, the
|
1067 |
+
//user will not be able to select menu items from a switched menu without saving first. if javascript is not disabled, then
|
1068 |
+
//the script should initially remove any optgroups not immediately required...
|
1069 |
+
$rtn['selectedOptgroup'][ $sogCt ] = $rtn['optgroups'][ $ct ];
|
1070 |
+
$rtn['selectedOptgroup'][ ++$sogCt ] = '';
|
1071 |
+
}
|
1072 |
+
$ct++;
|
1073 |
+
}
|
1074 |
+
}
|
1075 |
+
unset( $itemindents, $menu, $item );
|
1076 |
+
|
1077 |
+
if( empty( $rtn['names'] ) ){
|
1078 |
+
$rtn = false;
|
1079 |
+
}else{
|
1080 |
+
$rtn['names'] = implode( '', $rtn['names'] );
|
1081 |
+
$rtn['optgroups'] = implode( '', $rtn['optgroups'] );
|
1082 |
+
$rtn['selectedOptgroup'] = implode( '', $rtn['selectedOptgroup'] );
|
1083 |
+
if( $this->_cmw_accessibility ){
|
1084 |
+
//reset levels of selected optgroup to be the max levels of any group...
|
1085 |
+
$rtn['selectedLevels'] = $rtn['maxlevel'];
|
1086 |
+
}
|
1087 |
+
}
|
1088 |
+
return $rtn;
|
1089 |
+
|
1090 |
+
}
|
1091 |
+
|
1092 |
+
/**
|
1093 |
+
* outputs the HTML to begin a collapsible/expandable group of settings
|
1094 |
+
*
|
1095 |
+
* @param array $instance
|
1096 |
+
* @param string $text Label
|
1097 |
+
* @param string $fname Field name
|
1098 |
+
*/
|
1099 |
+
function cmw_open_a_field_section( &$instance, $text, $fname ){
|
1100 |
+
|
1101 |
+
$hashid = $this->get_field_id( 'cmw' . ++$this->_cmw_hash_ct );
|
1102 |
+
?>
|
1103 |
+
<a class="widget-<?php echo $this->id_base; ?>-fieldset<?php echo $instance[$fname] ? ' cmw-collapsed-fieldset' : ''; ?>"
|
1104 |
+
id="<?php echo $hashid; ?>" href="#<?php echo $hashid; ?>"><?php echo $text; ?></a>
|
1105 |
+
<input id="<?php echo $this->get_field_id($fname); ?>" class="cmw-display-none cmw-fieldset-state"
|
1106 |
+
name="<?php echo $this->get_field_name($fname); ?>"
|
1107 |
+
type="checkbox" value="1" <?php checked( $instance[$fname] ); ?> />
|
1108 |
+
<div class="cmw-fieldset<?php echo $instance[$fname] ? ' cmw-start-fieldset-collapsed' : ''; ?>">
|
1109 |
+
<?php
|
1110 |
+
|
1111 |
+
} //end cmw_open_a_field_section()
|
1112 |
+
|
1113 |
+
/**
|
1114 |
+
* returns true if the version of WP is lower-than or greater-than-or-equal to the one provided
|
1115 |
+
*
|
1116 |
+
* @param string $v Version to test for lower than
|
1117 |
+
* @return boolean
|
1118 |
+
*/
|
1119 |
+
function cmw_wp_version( $v, $gte=false ){
|
1120 |
+
global $wp_version;
|
1121 |
+
|
1122 |
+
$rtn = version_compare( strtolower( $wp_version ), $v . 'a', '<' );
|
1123 |
+
return $gte ? !$rtn : $rtn;
|
1124 |
+
|
1125 |
+
} //end cmw_wp_version()
|
1126 |
+
|
1127 |
+
/**
|
1128 |
+
* sanitizes the widget settings for update(), widget() and form()
|
1129 |
+
*
|
1130 |
+
* @param array $from_instance Widget settings
|
1131 |
+
* @param array $base_instance Old widget settings or an empty array
|
1132 |
+
* @param string Name of the calling method
|
1133 |
+
* @return array Sanitized widget settings
|
1134 |
+
*/
|
1135 |
+
function cmw_settings( $from_instance, $base_instance, $method = 'update' ){
|
1136 |
+
|
1137 |
+
/* old (pre v3) settings...
|
1138 |
+
//switches...
|
1139 |
+
'include_ancestors' => 0 : replaced by ancestors
|
1140 |
+
'include_parent' => 0 : replaced by ancestors
|
1141 |
+
'include_parent_siblings' => 0 : replaced by ancestor_siblings
|
1142 |
+
'title_from_parent' => 0 : replaced by title_from_branch
|
1143 |
+
'fallback_no_ancestor' => 0 : no longer applicable
|
1144 |
+
'fallback_include_parent' => 0 : no longer applicable
|
1145 |
+
'fallback_include_parent_siblings' => 0 : no longer applicable (but "sort of" replicated by fallback_siblings)
|
1146 |
+
'fallback_no_children' => 0 : replaced by fallback
|
1147 |
+
'fallback_nc_include_parent' => 0 : no longer applicable
|
1148 |
+
'fallback_nc_include_parent_siblings' => 0 : no longer applicable
|
1149 |
+
//integers...
|
1150 |
+
'filter_item' => -2 : replaced by branch
|
1151 |
+
'start_level' => 1 : replaced by level & branch_start
|
1152 |
+
*/
|
1153 |
+
|
1154 |
+
$instance = is_array( $base_instance ) ? $base_instance : array();
|
1155 |
+
|
1156 |
+
//switches : values are defaults...
|
1157 |
+
foreach( array(
|
1158 |
+
'allow_all_root' => 0, //v3.0.0
|
1159 |
+
'depth_rel_current' => 0,
|
1160 |
+
'fallback_siblings' => 0, //v3.0.0 sort of replaces fallback_include_parent_siblings
|
1161 |
+
'flat_output' => 0,
|
1162 |
+
'hide_title' => 0,
|
1163 |
+
'siblings' => 0, //v3.0.0 replaces include_parent_siblings
|
1164 |
+
'include_root' => 0, //v3.0.0
|
1165 |
+
'title_from_branch' => 0, //v3.0.0 replaces title_from_parent
|
1166 |
+
'title_from_branch_root' => 0, //v3.0.0 added
|
1167 |
+
'title_from_current' => 0,
|
1168 |
+
'title_from_current_root' => 0, //v3.0.0 added
|
1169 |
+
'ol_root' => 0,
|
1170 |
+
'ol_sub' => 0,
|
1171 |
+
'hide_empty' => 0, //this only has relevance prior to WP v3.6
|
1172 |
+
//field section collapsed toggles...
|
1173 |
+
'fs_filters' => 1, //v3.0.0 replaces fs_filter and now starts out collapsed
|
1174 |
+
'fs_fallbacks' => 1,
|
1175 |
+
'fs_output' => 1,
|
1176 |
+
'fs_container' => 1,
|
1177 |
+
'fs_classes' => 1,
|
1178 |
+
'fs_links' => 1
|
1179 |
+
) as $k => $v ){
|
1180 |
+
|
1181 |
+
if( $method == 'update' ){
|
1182 |
+
//store as 0 or 1...
|
1183 |
+
$instance[ $k ] = empty( $from_instance[ $k ] ) ? 0 : 1;
|
1184 |
+
}else{
|
1185 |
+
//use internally as boolean...
|
1186 |
+
$instance[ $k ] = isset( $from_instance[ $k ] ) ? !empty( $from_instance[ $k ] ) : !empty( $v );
|
1187 |
+
}
|
1188 |
+
}
|
1189 |
+
|
1190 |
+
//integers : values are minimums (defaults are the values maxed against 0)...
|
1191 |
+
foreach( array(
|
1192 |
+
'ancestors' => -9999, //v3.0.0 replaces include_ancestors, but with levels (relative & absolute)
|
1193 |
+
'ancestor_siblings' => -9999, //v3.0.0 also has levels (relative & absolute)
|
1194 |
+
'depth' => 0,
|
1195 |
+
'branch' => 0, //v3.0.0 replaces filter_item, but without current parent|root item
|
1196 |
+
'menu' => 0,
|
1197 |
+
'level' => 1, //v3.0.0 replace start_level (for a level filter)
|
1198 |
+
'fallback_depth' => 0 //v3.0.0 added
|
1199 |
+
) as $k => $v ){
|
1200 |
+
|
1201 |
+
$instance[ $k ] = isset( $from_instance[ $k ]) ? max( $v, intval( $from_instance[ $k ] ) ) : max( $v, 0 );
|
1202 |
+
}
|
1203 |
+
|
1204 |
+
//strings : values are defaults...
|
1205 |
+
foreach( array(
|
1206 |
+
'title' => '',
|
1207 |
+
'filter' => '', //v3.0.0 changed from integer ('', 'branch', 'items'), where empty is equiv. to 'level' (was level=0, branch=1, items=-1)
|
1208 |
+
'branch_start' => '', //v3.0.0 replace start_level (for a branch filter)
|
1209 |
+
'start_mode' => '', //v3.0.0 forces branch_start to use entire level ('', 'level')
|
1210 |
+
'contains_current' => '', //v3.0.0 changed from switch ('', 'menu', 'primary', 'secondary', 'inclusions' or 'output')
|
1211 |
+
'container' => 'div',
|
1212 |
+
'container_id' => '',
|
1213 |
+
'container_class' => '',
|
1214 |
+
'exclude_level' => '', //v3.0.0 (1 or more digits, possibly with an appended '-' or '+')
|
1215 |
+
'fallback' => '', //v3.0.0 replace fallback_no_children ('', 'parent', 'current', 'quit')
|
1216 |
+
'menu_class' => 'menu-widget',
|
1217 |
+
'widget_class' => '',
|
1218 |
+
'cmwv' => ''
|
1219 |
+
) as $k => $v ){
|
1220 |
+
|
1221 |
+
$instance[ $k ] = isset( $from_instance[ $k ] ) ? strip_tags( trim( (string)$from_instance[ $k ] ) ) : $v;
|
1222 |
+
if( $method == 'form' ){
|
1223 |
+
//escape strings...
|
1224 |
+
$instance[ $k ] = esc_attr( trim( $instance[ $k ] ) );
|
1225 |
+
}
|
1226 |
+
}
|
1227 |
+
|
1228 |
+
//html strings : values are defaults...
|
1229 |
+
foreach( array(
|
1230 |
+
'before' => '',
|
1231 |
+
'after' => '',
|
1232 |
+
'link_before' => '',
|
1233 |
+
'link_after' => ''
|
1234 |
+
) as $k => $v ){
|
1235 |
+
|
1236 |
+
$instance[ $k ] = isset( $from_instance[ $k ] ) ? trim( (string)$from_instance[ $k ] ) : $v;
|
1237 |
+
if( $method == 'form' ){
|
1238 |
+
//escape html strings...
|
1239 |
+
$instance[ $k ] = esc_html( trim( $instance[ $k ] ) );
|
1240 |
+
}
|
1241 |
+
}
|
1242 |
+
|
1243 |
+
//csv strings : values are defaults...
|
1244 |
+
foreach( array(
|
1245 |
+
'exclude' => '', //v3.0.0 added
|
1246 |
+
'items' => ''
|
1247 |
+
) as $k => $v ){
|
1248 |
+
|
1249 |
+
$inherits = array();
|
1250 |
+
$instance[ "_$k" ] = array();
|
1251 |
+
$instance[ $k ] = isset( $from_instance[ $k ] ) ? trim( (string)$from_instance[ $k ] ) : $v;
|
1252 |
+
foreach( preg_split('/[,\s]+/', $instance[ $k ], -1, PREG_SPLIT_NO_EMPTY ) as $i ){
|
1253 |
+
//values can be just digits, or digits followed by a '+' (for inheritance)...
|
1254 |
+
if( preg_match( '/^(\d+)(\+?)$/', $i, $m ) > 0 ){
|
1255 |
+
$i = intval( $m[1] );
|
1256 |
+
if( $i > 0 ){
|
1257 |
+
if( !empty( $m[2] ) ){
|
1258 |
+
$inherits[] = $i;
|
1259 |
+
$i = $i . '+';
|
1260 |
+
}
|
1261 |
+
if( !in_array( "$i", $instance[ "_$k" ] ) ){
|
1262 |
+
$instance[ "_$k" ][] = "$i";
|
1263 |
+
}
|
1264 |
+
}
|
1265 |
+
}
|
1266 |
+
}
|
1267 |
+
if( !empty( $inherits ) ){
|
1268 |
+
$instance[ "_$k" ] = array_diff( $instance[ "_$k" ], $inherits );
|
1269 |
+
}
|
1270 |
+
unset( $inherits );
|
1271 |
+
//just store as comma-separated...
|
1272 |
+
$instance[ $k ] = implode( ',', $instance[ "_$k" ] );
|
1273 |
+
//can dump the underbar versions if called from update()...
|
1274 |
+
if( $method == 'update' ){
|
1275 |
+
unset( $instance[ "_$k" ] );
|
1276 |
+
}
|
1277 |
+
}
|
1278 |
+
|
1279 |
+
//holds information determined by the walker...
|
1280 |
+
$this->_cmw_walker = array();
|
1281 |
+
|
1282 |
+
return $instance;
|
1283 |
+
|
1284 |
+
} //end cmw_settings()
|
1285 |
+
|
1286 |
+
/**
|
1287 |
+
* returns the shortcode equivalent of the current settings (not called by legacy code!)
|
1288 |
+
*
|
1289 |
+
* @param array $instance
|
1290 |
+
* @return string
|
1291 |
+
*/
|
1292 |
+
function cmw_shortcode( $instance, $asJSON=false ){
|
1293 |
+
|
1294 |
+
$args = array(
|
1295 |
+
'menu' => $instance['menu']
|
1296 |
+
);
|
1297 |
+
$byBranch = $instance['filter'] == 'branch';
|
1298 |
+
$byItems = $instance['filter'] == 'items';
|
1299 |
+
$byLevel = !$byBranch && !$byItems;
|
1300 |
+
|
1301 |
+
//take notice of the widget's hide_title flag...
|
1302 |
+
if( !empty( $instance['title'] ) && !$instance['hide_title'] ){
|
1303 |
+
$args['title'] = array( $instance['title'] );
|
1304 |
+
}
|
1305 |
+
//byLevel is the default (no branch & no items), as is level=1, so we only *have* to specify level if it's greater than 1...
|
1306 |
+
if( $byLevel && $instance['level'] > 1 ){
|
1307 |
+
$args['level'] = $instance['level'];
|
1308 |
+
}
|
1309 |
+
//specifying branch sets byBranch, overriding byLevel...
|
1310 |
+
if( $byBranch ){
|
1311 |
+
//use the alternative for 0 ("current") because it's more self-explanatory...
|
1312 |
+
$args['branch'] = $instance['branch'] > 0 ? $instance['branch'] : 'current';
|
1313 |
+
//start_at only *has* to be specified if not empty...
|
1314 |
+
if( !empty( $instance['branch_start'] ) ){
|
1315 |
+
$args['start_at'] = array( $instance['branch_start'] );
|
1316 |
+
}
|
1317 |
+
//start_mode may be brought into play by a fallback so always specify it...
|
1318 |
+
if( $instance['start_mode'] == 'level' ){
|
1319 |
+
$args['start_mode'] = 'level';
|
1320 |
+
}
|
1321 |
+
}
|
1322 |
+
//specifying items set byItems, overriding byLevel & byBranch...
|
1323 |
+
if( $byItems ){
|
1324 |
+
$args['items'] = $instance['_items'];
|
1325 |
+
}
|
1326 |
+
//depth if greater than 0...
|
1327 |
+
if( $instance['depth'] > 0 ){
|
1328 |
+
$args['depth'] = $instance['depth'];
|
1329 |
+
}
|
1330 |
+
//depth relative to current item is only applicable if depth is not unlimited...
|
1331 |
+
if( $instance['depth_rel_current'] && $instance['depth'] > 0 ){
|
1332 |
+
$args['depth_rel_current'] = 1;
|
1333 |
+
}
|
1334 |
+
//fallbacks...
|
1335 |
+
//no children : branch = current item...
|
1336 |
+
if( $byBranch && $instance['branch'] == 0 ){
|
1337 |
+
if( !empty( $instance['fallback'] ) ){
|
1338 |
+
$args['fallback'] = array( $instance['fallback'] );
|
1339 |
+
if( $args['fallback'] != 'quit' ){
|
1340 |
+
if( $instance['fallback_siblings'] ){
|
1341 |
+
$args['fallback'][] = '+siblings';
|
1342 |
+
}
|
1343 |
+
if( $instance['fallback_depth'] > 0 ){
|
1344 |
+
$args['fallback'][] = $instance['fallback_depth'];
|
1345 |
+
}
|
1346 |
+
}
|
1347 |
+
}
|
1348 |
+
}
|
1349 |
+
//branch ancestor inclusions...
|
1350 |
+
if( $byBranch && !empty( $instance['ancestors'] ) ){
|
1351 |
+
$args['ancestors'] = $instance['ancestors'];
|
1352 |
+
//only ancestor-siblings if ancestors...
|
1353 |
+
if( !empty( $instance['ancestor_siblings'] ) ){
|
1354 |
+
$args['ancestor_siblings'] = $instance['ancestor_siblings'];
|
1355 |
+
}
|
1356 |
+
}
|
1357 |
+
//exclusions by id...
|
1358 |
+
if( !empty( $instance['_exclude'] ) ){
|
1359 |
+
$args['exclude'] = $instance['_exclude'];
|
1360 |
+
}
|
1361 |
+
//...and by level...
|
1362 |
+
if( !empty( $instance['exclude_level'] ) ){
|
1363 |
+
$args['exclude_level'] = array( $instance['exclude_level'] );
|
1364 |
+
}
|
1365 |
+
//title from...
|
1366 |
+
$n = array();
|
1367 |
+
if( $instance['title_from_current'] ){
|
1368 |
+
$n[] = 'current';
|
1369 |
+
}else if( $instance['title_from_current_root'] ){
|
1370 |
+
$n[] = 'current-root';
|
1371 |
+
}
|
1372 |
+
if( $byBranch && $instance['title_from_branch'] ){
|
1373 |
+
$n[] = 'branch';
|
1374 |
+
}else if( $byBranch && $instance['title_from_branch_root'] ){
|
1375 |
+
$n[] = 'branch-root';
|
1376 |
+
}
|
1377 |
+
if( !empty( $n ) ){
|
1378 |
+
$args['title_from'] = $n;
|
1379 |
+
}
|
1380 |
+
//switches...
|
1381 |
+
foreach( array('allow_all_root', 'siblings', 'include_root', 'flat_output', 'ol_root', 'ol_sub') as $n ){
|
1382 |
+
if( $instance[ $n ] ){
|
1383 |
+
$args[ $n ] = 1;
|
1384 |
+
}
|
1385 |
+
}
|
1386 |
+
//strings...
|
1387 |
+
foreach( array(
|
1388 |
+
'contains_current' => '',
|
1389 |
+
'container' => 'div',
|
1390 |
+
'container_id' => '',
|
1391 |
+
'container_class' => '',
|
1392 |
+
'menu_class' => 'menu-widget',
|
1393 |
+
'widget_class' => ''
|
1394 |
+
) as $n => $v ){
|
1395 |
+
if( $instance[ $n ] != $v ){
|
1396 |
+
$args[ $n ] = array( $instance[ $n ] );
|
1397 |
+
}
|
1398 |
+
}
|
1399 |
+
foreach( array(
|
1400 |
+
'wrap_link' => 'before',
|
1401 |
+
'wrap_link_text' => 'link_before'
|
1402 |
+
) as $n => $v ){
|
1403 |
+
if( preg_match( '/^<(\w+)/', $instance[ $v ], $m ) > 0 ){
|
1404 |
+
$args[ $n ] = array( $m[1] );
|
1405 |
+
}
|
1406 |
+
}
|
1407 |
+
//build the shortcode...
|
1408 |
+
$m = array();
|
1409 |
+
foreach( $args as $n => $v ){
|
1410 |
+
//array indicates join (with comma sep) & surround it in double quotes, otherwise leave 'as-is'...
|
1411 |
+
if( $asJSON ){
|
1412 |
+
$m[ $n ] = is_array( $v ) ? implode( ',', $v ) : $v;
|
1413 |
+
}else{
|
1414 |
+
$m[] = is_array( $v ) ? $n . '="' . implode( ',', $v ) . '"' : $n . '=' . $v;
|
1415 |
+
}
|
1416 |
+
}
|
1417 |
+
unset( $args );
|
1418 |
+
|
1419 |
+
//NB at v3.0.0, the shortcode changed from custom_menu_wizard to cmwizard (the previous version is still supported)
|
1420 |
+
return $asJSON ? json_encode( $m ) : '[cmwizard ' . implode( ' ', $m ) . ']';
|
1421 |
+
|
1422 |
+
} //end cmw_shortcode()
|
1423 |
+
|
1424 |
+
|
1425 |
+
|
1426 |
+
/*======================
|
1427 |
+
* LEGACY CODE (v2.1.0)
|
1428 |
+
*======================*/
|
1429 |
+
|
1430 |
+
/**
|
1431 |
+
* produces the legacy version of the backend admin form(s)
|
1432 |
+
*
|
1433 |
+
* @param array $instance Widget settings
|
1434 |
+
*/
|
1435 |
+
function cmw_legacy_form( $instance ) {
|
1436 |
+
|
1437 |
+
//sanitize $instance...
|
1438 |
+
$instance = $this->cmw_legacy_settings( $instance, array(), 'form' );
|
1439 |
+
|
1440 |
+
//if no populated menus exist, suggest the user go create one...
|
1441 |
+
if( ( $menus = $this->cmw_scan_menus( $instance['menu'], $instance['filter_item'] ) ) === false ){
|
1442 |
+
?>
|
1443 |
+
<p class="widget-<?php echo $this->id_base; ?>-no-menus">
|
1444 |
+
<?php printf( __('No populated menus have been created yet. <a href="%s">Create one</a>.'), admin_url('nav-menus.php') ); ?>
|
1445 |
+
</p>
|
1446 |
+
<?php
|
1447 |
+
return;
|
1448 |
+
}
|
1449 |
+
|
1450 |
+
//set up some simple booleans for use at the disableif___ classes...
|
1451 |
+
$isShowSpecific = $instance['filter'] < 0; // disableif-ss (IS show specific items)
|
1452 |
+
$isNotChildrenOf = $instance['filter'] < 1; // disableif (is NOT Children-of)
|
1453 |
+
$isNotCurrentRootParent = $isNotChildrenOf || $instance['filter_item'] >= 0; // disableifnot-rp (is NOT Children-of Current Root/Parent)
|
1454 |
+
$isNotCurrentItem = $isNotChildrenOf || $instance['filter_item'] != 0; // disableifnot-ci (is NOT Children-of Current Item)
|
1455 |
+
|
1456 |
+
?>
|
1457 |
+
<div id="<?php echo $this->get_field_id('onchange'); ?>"
|
1458 |
+
class="widget-<?php echo $this->id_base; ?>-onchange<?php echo $this->cmw_wp_version('3.8') ? ' cmw-pre-wp-v38' : ''; ?>"
|
1459 |
+
data-cmw-v36plus='<?php echo $this->cmw_wp_version('3.6', true) ? 'true' : 'false'; ?>'
|
1460 |
+
data-cmw-dialog-prompt='<?php _e('Click an item to toggle "Current Menu Item"'); ?>'
|
1461 |
+
data-cmw-dialog-output='<?php _e('Basic Output'); ?>'
|
1462 |
+
data-cmw-dialog-fallback='<?php _e('Fallback invoked'); ?>'
|
1463 |
+
data-cmw-dialog-set-current='<?php _e('Set Current Item?'); ?>'
|
1464 |
+
data-cmw-dialog-shortcodes='<?php _e('Find posts/pages containing a CMW shortcode'); ?>'
|
1465 |
+
data-cmw-dialog-untitled='<?php _e('untitled'); ?>'
|
1466 |
+
data-cmw-dialog-fixed='<?php _e('fixed'); ?>'
|
1467 |
+
data-cmw-dialog-nonce='<?php echo wp_create_nonce( 'cmw-find-shortcodes' ); ?>'
|
1468 |
+
data-cmw-dialog-version='2.1.0'
|
1469 |
+
data-cmw-dialog-id='<?php echo $this->get_field_id('dialog'); ?>'>
|
1470 |
+
<?php
|
1471 |
+
/**
|
1472 |
+
* Legacy warning...
|
1473 |
+
*/
|
1474 |
+
?>
|
1475 |
+
<p class="cmw-legacy-warn">
|
1476 |
+
<a class="widget-<?php echo $this->id_base; ?>-legacy-close cmw-legacy-close" title="<?php _e('Dismiss'); ?>" href="#">X</a>
|
1477 |
+
<em><?php _e('This is an old version of the widget!'); ?>
|
1478 |
+
<?php
|
1479 |
+
if( !$this->_cmw_allow_legacy_update ){
|
1480 |
+
?>
|
1481 |
+
<br /><?php _e('Any changes you make will NOT be Saved!'); ?>
|
1482 |
+
<?php
|
1483 |
+
}
|
1484 |
+
?>
|
1485 |
+
<br /><?php _e('Please consider creating a new instance of the widget to replace this one.'); ?>
|
1486 |
+
<a href="<?php echo $this->_cmw_legacy_warnreadmore; ?>" target="_blank"><?php _e('read more'); ?></a></em>
|
1487 |
+
</p>
|
1488 |
+
<?php
|
1489 |
+
|
1490 |
+
/**
|
1491 |
+
* permanently visible section : Title (with Hide) and Menu
|
1492 |
+
*/
|
1493 |
+
?>
|
1494 |
+
<p>
|
1495 |
+
<label for="<?php echo $this->get_field_id('title'); ?>"><?php _e('Title:') ?></label>
|
1496 |
+
<?php $this->cmw_formfield_checkbox( $instance, 'hide_title',
|
1497 |
+
array(
|
1498 |
+
'label' => __('Hide'),
|
1499 |
+
'lclass' => 'alignright'
|
1500 |
+
) ); ?>
|
1501 |
+
<?php $this->cmw_formfield_textbox( $instance, 'title',
|
1502 |
+
array(
|
1503 |
+
'desc' => __('Title can be set, but need not be displayed'),
|
1504 |
+
'fclass' => 'widefat cmw-widget-title'
|
1505 |
+
) ); ?>
|
1506 |
+
</p>
|
1507 |
+
|
1508 |
+
<p>
|
1509 |
+
<?php $this->cmw_assist_link(); ?>
|
1510 |
+
<label for="<?php echo $this->get_field_id('menu'); ?>"><?php _e('Select Menu:'); ?></label>
|
1511 |
+
<select id="<?php echo $this->get_field_id('menu'); ?>" <?php $this->cmw_disableif(); ?>
|
1512 |
+
class="cmw-select-menu cmw-listen" name="<?php echo $this->get_field_name('menu'); ?>">
|
1513 |
+
<?php echo $menus['names']; ?>
|
1514 |
+
</select>
|
1515 |
+
</p>
|
1516 |
+
|
1517 |
+
<?php
|
1518 |
+
/**
|
1519 |
+
* start collapsible section : 'Filter'
|
1520 |
+
*/
|
1521 |
+
$this->cmw_open_a_field_section( $instance, __('Filter'), 'fs_filter' );
|
1522 |
+
?>
|
1523 |
+
<p>
|
1524 |
+
<?php $this->cmw_assist_link(); ?>
|
1525 |
+
<label>
|
1526 |
+
<input id="<?php echo $this->get_field_id('filter'); ?>_0" class="cmw-showall cmw-listen" <?php $this->cmw_disableif(); ?>
|
1527 |
+
name="<?php echo $this->get_field_name('filter'); ?>" type="radio" value="0" <?php checked( $instance['filter'], 0 ); ?> />
|
1528 |
+
<?php _e('Show all'); ?></label>
|
1529 |
+
<br /><label>
|
1530 |
+
<input id="<?php echo $this->get_field_id('filter'); ?>_1" class="cmw-listen" <?php $this->cmw_disableif(); ?>
|
1531 |
+
name="<?php echo $this->get_field_name('filter'); ?>" type="radio" value="1" <?php checked( $instance['filter'], 1 ); ?> />
|
1532 |
+
<?php _e('Children of:'); ?></label>
|
1533 |
+
<select id="<?php echo $this->get_field_id('filter_item'); ?>" class="cmw-childrenof cmw-assist-items cmw-listen"
|
1534 |
+
name="<?php echo $this->get_field_name('filter_item'); ?>" <?php $this->cmw_disableif(); ?>>
|
1535 |
+
<option value="0" <?php selected( $instance['filter_item'], 0 ); ?>><?php _e('Current Item'); ?></option>
|
1536 |
+
<option value="-2" <?php selected( $instance['filter_item'], -2 ); ?>><?php _e('Current Root Item'); ?></option>
|
1537 |
+
<option value="-1" <?php selected( $instance['filter_item'], -1 ); ?>><?php _e('Current Parent Item'); ?></option>
|
1538 |
+
<?php echo $menus['selectedOptgroup']; ?>
|
1539 |
+
</select>
|
1540 |
+
<br /><label>
|
1541 |
+
<input id="<?php echo $this->get_field_id('filter'); ?>_2" class="cmw-showspecific cmw-listen" <?php $this->cmw_disableif(); ?>
|
1542 |
+
name="<?php echo $this->get_field_name('filter'); ?>" type="radio" value="-1" <?php checked( $instance['filter'], -1 ); ?> />
|
1543 |
+
<?php _e('Items:'); ?></label>
|
1544 |
+
<?php $this->cmw_formfield_textbox( $instance, 'items',
|
1545 |
+
array(
|
1546 |
+
'fclass' => 'cmw-setitems'
|
1547 |
+
) ); ?>
|
1548 |
+
|
1549 |
+
<select id="<?php echo $this->get_field_id('filter_item_ignore'); ?>" disabled="disabled"
|
1550 |
+
class='cmw-off-the-page' name="<?php echo $this->get_field_name('filter_item_ignore'); ?>">
|
1551 |
+
<?php echo $menus['optgroups']; ?>
|
1552 |
+
</select>
|
1553 |
+
</p>
|
1554 |
+
|
1555 |
+
<p class="cmw-disableif-ss<?php $this->cmw_disableif( 'push', $isShowSpecific ); ?>">
|
1556 |
+
<label for="<?php echo $this->get_field_id('start_level'); ?>"><?php _e('Starting Level:'); ?></label>
|
1557 |
+
<select id="<?php echo $this->get_field_id('start_level'); ?>" <?php $this->cmw_disableif(); ?>
|
1558 |
+
class="cmw-start-level" name="<?php echo $this->get_field_name('start_level'); ?>">
|
1559 |
+
<?php for( $i = 1; $i <= $menus['selectedLevels']; $i++ ){ ?>
|
1560 |
+
<option value="<?php echo $i; ?>" <?php selected( $instance['start_level'] > $menus['selectedLevels'] ? 1 : $instance['start_level'], $i ); ?>><?php echo $i; ?></option>
|
1561 |
+
<?php } ?>
|
1562 |
+
</select>
|
1563 |
+
<span class="cmw-small-block"><em><?php _e('Level to start testing items for inclusion'); ?></em></span>
|
1564 |
+
</p><!-- end .cmw-disableif-ss --><?php $this->cmw_disableif( 'pop' ); ?>
|
1565 |
+
|
1566 |
+
<p class="cmw-disableif-ss<?php $this->cmw_disableif( 'push', $isShowSpecific ); ?>">
|
1567 |
+
<label for="<?php echo $this->get_field_id('depth'); ?>"><?php _e('For Depth:'); ?></label>
|
1568 |
+
<select id="<?php echo $this->get_field_id('depth'); ?>" class="cmw-depth" data-cmw-text-levels="<?php _e('levels'); ?>"
|
1569 |
+
name="<?php echo $this->get_field_name('depth'); ?>" <?php $this->cmw_disableif(); ?>>
|
1570 |
+
<option value="0" <?php selected( $instance['depth'] > $menus['selectedLevels'] ? 0 : $instance['depth'], 0 ); ?>><?php _e('unlimited'); ?></option>
|
1571 |
+
<?php
|
1572 |
+
for( $i = 1; $i <= $menus['selectedLevels']; $i++ ){
|
1573 |
+
?>
|
1574 |
+
<option value="<?php echo $i; ?>" <?php selected( $instance['depth'], $i ); ?>><?php echo $i; ?> <?php _e($i > 1 ? 'levels' : 'level'); ?></option>
|
1575 |
+
<?php
|
1576 |
+
}
|
1577 |
+
?>
|
1578 |
+
</select>
|
1579 |
+
<span class="cmw-small-block"><em><?php _e('Relative to first Filter item found, <strong>unless</strong>…'); ?></em></span>
|
1580 |
+
<?php $this->cmw_formfield_checkbox( $instance, 'depth_rel_current',
|
1581 |
+
array(
|
1582 |
+
'label' => sprintf( __('Relative to "Current" Item %1$s(if found)%2$s'), '<small><em>', '</em></small>' )
|
1583 |
+
) ); ?>
|
1584 |
+
</p><!-- end .cmw-disableif-ss --><?php $this->cmw_disableif( 'pop' ); ?>
|
1585 |
+
|
1586 |
+
<?php $this->cmw_close_a_field_section(); ?>
|
1587 |
+
|
1588 |
+
<?php
|
1589 |
+
/**
|
1590 |
+
* v1.2.0 start collapsible section : 'Fallbacks'
|
1591 |
+
*/
|
1592 |
+
$this->cmw_open_a_field_section( $instance, __('Fallbacks'), 'fs_fallbacks' );
|
1593 |
+
?>
|
1594 |
+
<p class="cmw-disableifnot-rp<?php $this->cmw_disableif( 'push', $isNotCurrentRootParent ); ?>">
|
1595 |
+
<?php $this->cmw_assist_link(); ?>
|
1596 |
+
<span class="cmw-small-block"><strong><?php _e( 'If "Children of" is <em>Current Root / Parent Item</em>, and no ancestor exists' ); ?> :</strong></span>
|
1597 |
+
<?php $this->cmw_formfield_checkbox( $instance, 'fallback_no_ancestor',
|
1598 |
+
array(
|
1599 |
+
'label' => __('Switch to Current Item, and')
|
1600 |
+
) ); ?>
|
1601 |
+
<br />
|
1602 |
+
<?php $this->cmw_formfield_checkbox( $instance, 'fallback_include_parent',
|
1603 |
+
array(
|
1604 |
+
'label' => __('Include Parent...')
|
1605 |
+
) ); ?>
|
1606 |
+
<?php $this->cmw_formfield_checkbox( $instance, 'fallback_include_parent_siblings',
|
1607 |
+
array(
|
1608 |
+
'label' => __('with Siblings'),
|
1609 |
+
'lclass' => 'cmw-whitespace-nowrap'
|
1610 |
+
) ); ?>
|
1611 |
+
</p><!-- end .cmw-disableifnot-rp --><?php $this->cmw_disableif( 'pop' ); ?>
|
1612 |
+
|
1613 |
+
<p class="cmw-disableifnot-ci<?php $this->cmw_disableif( 'push', $isNotCurrentItem ); ?>">
|
1614 |
+
<span class="cmw-small-block"><strong><?php _e( 'If "Children of" is <em>Current Item</em>, and current item has no children' ); ?> :</strong></span>
|
1615 |
+
<?php $this->cmw_formfield_checkbox( $instance, 'fallback_no_children',
|
1616 |
+
array(
|
1617 |
+
'label' => __('Switch to Current Parent Item, and')
|
1618 |
+
) ); ?>
|
1619 |
+
<br />
|
1620 |
+
<?php $this->cmw_formfield_checkbox( $instance, 'fallback_nc_include_parent',
|
1621 |
+
array(
|
1622 |
+
'label' => __('Include Parent...')
|
1623 |
+
) ); ?>
|
1624 |
+
<?php $this->cmw_formfield_checkbox( $instance, 'fallback_nc_include_parent_siblings',
|
1625 |
+
array(
|
1626 |
+
'label' => __('with Siblings'),
|
1627 |
+
'lclass' => 'cmw-whitespace-nowrap'
|
1628 |
+
) ); ?>
|
1629 |
+
</p><!-- end .cmw-disableifnot-ci --><?php $this->cmw_disableif( 'pop' ); ?>
|
1630 |
+
|
1631 |
+
<?php $this->cmw_close_a_field_section(); ?>
|
1632 |
+
|
1633 |
+
<?php
|
1634 |
+
/**
|
1635 |
+
* start collapsible section : 'Output'
|
1636 |
+
*/
|
1637 |
+
$this->cmw_open_a_field_section( $instance, __('Output'), 'fs_output' );
|
1638 |
+
?>
|
1639 |
+
<p>
|
1640 |
+
<?php $this->cmw_assist_link(); ?>
|
1641 |
+
<label>
|
1642 |
+
<input id="<?php echo $this->get_field_id('flat_output'); ?>_0" name="<?php echo $this->get_field_name('flat_output'); ?>"
|
1643 |
+
type="radio" value="0" <?php checked(!$instance['flat_output']); ?> <?php $this->cmw_disableif(); ?> />
|
1644 |
+
<?php _e('Hierarchical'); ?></label>
|
1645 |
+
<label class="cmw-whitespace-nowrap">
|
1646 |
+
<input id="<?php echo $this->get_field_id('flat_output'); ?>_1" name="<?php echo $this->get_field_name('flat_output'); ?>"
|
1647 |
+
type="radio" value="1" <?php checked($instance['flat_output']); ?> <?php $this->cmw_disableif(); ?> />
|
1648 |
+
<?php _e('Flat'); ?></label>
|
1649 |
+
</p>
|
1650 |
+
|
1651 |
+
<p>
|
1652 |
+
<?php $this->cmw_formfield_checkbox( $instance, 'contains_current',
|
1653 |
+
array(
|
1654 |
+
'label' => __('Must Contain "Current" Item'),
|
1655 |
+
'desc' => __('Checks both Filtered and Included items')
|
1656 |
+
) ); ?>
|
1657 |
+
</p>
|
1658 |
+
|
1659 |
+
<p class="cmw-disableif<?php $this->cmw_disableif( 'push', $isNotChildrenOf ); ?>">
|
1660 |
+
<?php $this->cmw_formfield_checkbox( $instance, 'include_parent',
|
1661 |
+
array(
|
1662 |
+
'label' => __('Include Parent...')
|
1663 |
+
) ); ?>
|
1664 |
+
<?php $this->cmw_formfield_checkbox( $instance, 'include_parent_siblings',
|
1665 |
+
array(
|
1666 |
+
'label' => __('with Siblings'),
|
1667 |
+
'lclass' => 'cmw-whitespace-nowrap'
|
1668 |
+
) ); ?>
|
1669 |
+
<br />
|
1670 |
+
<?php $this->cmw_formfield_checkbox( $instance, 'include_ancestors',
|
1671 |
+
array(
|
1672 |
+
'label' => __('Include Ancestors')
|
1673 |
+
) ); ?>
|
1674 |
+
<br />
|
1675 |
+
<?php $this->cmw_formfield_checkbox( $instance, 'title_from_parent',
|
1676 |
+
array(
|
1677 |
+
'label' => __('Title from Parent'),
|
1678 |
+
'desc' => __('Only if the "Children of" Filter returns items')
|
1679 |
+
) ); ?>
|
1680 |
+
</p><!-- end .cmw-disableif --><?php $this->cmw_disableif( 'pop' ); ?>
|
1681 |
+
|
1682 |
+
<p>
|
1683 |
+
<?php $this->cmw_formfield_checkbox( $instance, 'title_from_current',
|
1684 |
+
array(
|
1685 |
+
'label' => __('Title from "Current" Item'),
|
1686 |
+
'desc' => __('Lower priority than "Title from Parent"')
|
1687 |
+
) ); ?>
|
1688 |
+
</p>
|
1689 |
+
|
1690 |
+
<p>
|
1691 |
+
<?php _e('Change UL to OL:'); ?>
|
1692 |
+
<br />
|
1693 |
+
<?php $this->cmw_formfield_checkbox( $instance, 'ol_root',
|
1694 |
+
array(
|
1695 |
+
'label' => __('Top Level')
|
1696 |
+
) ); ?>
|
1697 |
+
|
1698 |
+
<?php $this->cmw_formfield_checkbox( $instance, 'ol_sub',
|
1699 |
+
array(
|
1700 |
+
'label' => __('Sub-Levels')
|
1701 |
+
) ); ?>
|
1702 |
+
</p>
|
1703 |
+
|
1704 |
+
<?php
|
1705 |
+
//v1.1.0 As of WP v3.6, wp_nav_menu() automatically cops out (without outputting any HTML) if there are no items,
|
1706 |
+
// so the hide_empty option becomes superfluous; however, I'll keep the previous setting (if there was one)
|
1707 |
+
// in case of reversion to an earlier version of WP...
|
1708 |
+
if( $this->cmw_wp_version('3.6') ){
|
1709 |
+
?>
|
1710 |
+
<p>
|
1711 |
+
<?php $this->cmw_formfield_checkbox( $instance, 'hide_empty',
|
1712 |
+
array(
|
1713 |
+
'label' => __('Hide Widget if Empty'),
|
1714 |
+
'desc' => __('Prevents any output when no items are found')
|
1715 |
+
) ); ?>
|
1716 |
+
</p>
|
1717 |
+
<?php }else{ ?>
|
1718 |
+
<input id="<?php echo $this->get_field_id('hide_empty'); ?>" name="<?php echo $this->get_field_name('hide_empty'); ?>"
|
1719 |
+
type="hidden" value="<?php echo $instance['hide_empty'] ? '1' : ''; ?>" />
|
1720 |
+
<?php } ?>
|
1721 |
+
|
1722 |
+
<?php $this->cmw_close_a_field_section(); ?>
|
1723 |
+
|
1724 |
+
<?php
|
1725 |
+
/**
|
1726 |
+
* start collapsible section : 'Container'
|
1727 |
+
*/
|
1728 |
+
$this->cmw_open_a_field_section( $instance, __('Container'), 'fs_container' );
|
1729 |
+
?>
|
1730 |
+
<p>
|
1731 |
+
<?php $this->cmw_formfield_textbox( $instance, 'container',
|
1732 |
+
array(
|
1733 |
+
'label' => __('Element:'),
|
1734 |
+
'desc' => __('Eg. div or nav; leave empty for no container')
|
1735 |
+
) ); ?>
|
1736 |
+
</p>
|
1737 |
+
<p>
|
1738 |
+
<?php $this->cmw_formfield_textbox( $instance, 'container_id',
|
1739 |
+
array(
|
1740 |
+
'label' => __('Unique ID:'),
|
1741 |
+
'desc' => __('An optional ID for the container')
|
1742 |
+
) ); ?>
|
1743 |
+
</p>
|
1744 |
+
<p>
|
1745 |
+
<?php $this->cmw_formfield_textbox( $instance, 'container_class',
|
1746 |
+
array(
|
1747 |
+
'label' => __('Class:'),
|
1748 |
+
'desc' => __('Extra class for the container')
|
1749 |
+
) ); ?>
|
1750 |
+
</p>
|
1751 |
+
|
1752 |
+
<?php $this->cmw_close_a_field_section(); ?>
|
1753 |
+
|
1754 |
+
<?php
|
1755 |
+
/**
|
1756 |
+
* start collapsible section : 'Classes'
|
1757 |
+
*/
|
1758 |
+
$this->cmw_open_a_field_section( $instance, __('Classes'), 'fs_classes' );
|
1759 |
+
?>
|
1760 |
+
<p>
|
1761 |
+
<?php $this->cmw_formfield_textbox( $instance, 'menu_class',
|
1762 |
+
array(
|
1763 |
+
'label' => __('Menu Class:'),
|
1764 |
+
'desc' => __('Class for the list element forming the menu')
|
1765 |
+
) ); ?>
|
1766 |
+
</p>
|
1767 |
+
<p>
|
1768 |
+
<?php $this->cmw_formfield_textbox( $instance, 'widget_class',
|
1769 |
+
array(
|
1770 |
+
'label' => __('Widget Class:'),
|
1771 |
+
'desc' => __('Extra class for the widget itself')
|
1772 |
+
) ); ?>
|
1773 |
+
</p>
|
1774 |
+
|
1775 |
+
<?php $this->cmw_close_a_field_section(); ?>
|
1776 |
+
|
1777 |
+
<?php
|
1778 |
+
/**
|
1779 |
+
* start collapsible section : 'Links'
|
1780 |
+
*/
|
1781 |
+
$this->cmw_open_a_field_section( $instance, __('Links'), 'fs_links' );
|
1782 |
+
?>
|
1783 |
+
<p>
|
1784 |
+
<?php $this->cmw_formfield_textbox( $instance, 'before',
|
1785 |
+
array(
|
1786 |
+
'label' => __('Before the Link:'),
|
1787 |
+
'desc' => __( htmlspecialchars('Text/HTML to go before the <a> of the link') ),
|
1788 |
+
'fclass' => 'widefat'
|
1789 |
+
) ); ?>
|
1790 |
+
</p>
|
1791 |
+
<p>
|
1792 |
+
<?php $this->cmw_formfield_textbox( $instance, 'after',
|
1793 |
+
array(
|
1794 |
+
'label' => __('After the Link:'),
|
1795 |
+
'desc' => __( htmlspecialchars('Text/HTML to go after the <a> of the link') ),
|
1796 |
+
'fclass' => 'widefat'
|
1797 |
+
) ); ?>
|
1798 |
+
</p>
|
1799 |
+
<p>
|
1800 |
+
<?php $this->cmw_formfield_textbox( $instance, 'link_before',
|
1801 |
+
array(
|
1802 |
+
'label' => __('Before the Link Text:'),
|
1803 |
+
'desc' => __('Text/HTML to go before the link text'),
|
1804 |
+
'fclass' => 'widefat'
|
1805 |
+
) ); ?>
|
1806 |
+
</p>
|
1807 |
+
<p>
|
1808 |
+
<?php $this->cmw_formfield_textbox( $instance, 'link_after',
|
1809 |
+
array(
|
1810 |
+
'label' => __('After the Link Text:'),
|
1811 |
+
'desc' => __('Text/HTML to go after the link text'),
|
1812 |
+
'fclass' => 'widefat'
|
1813 |
+
) ); ?>
|
1814 |
+
</p>
|
1815 |
+
|
1816 |
+
<?php $this->cmw_close_a_field_section(); ?>
|
1817 |
+
|
1818 |
+
</div>
|
1819 |
+
<?php
|
1820 |
+
|
1821 |
+
} //end cmw_legacy_form()
|
1822 |
+
|
1823 |
+
/**
|
1824 |
+
* sanitizes the widget settings for cmw_legacy_update(), cmw_legacy_widget() and cmw_legacy_form()
|
1825 |
+
*
|
1826 |
+
* @param array $from_instance Widget settings
|
1827 |
+
* @param array $base_instance Old widget settings or an empty array
|
1828 |
+
* @param string $method Name suffix of the calling method
|
1829 |
+
* @return array Sanitized widget settings
|
1830 |
+
*/
|
1831 |
+
function cmw_legacy_settings( $from_instance, $base_instance, $method = 'update' ){
|
1832 |
+
|
1833 |
+
$instance = is_array( $base_instance ) ? $base_instance : array();
|
1834 |
+
|
1835 |
+
//switches...
|
1836 |
+
foreach( array(
|
1837 |
+
'hide_title' => 0,
|
1838 |
+
'contains_current' => 0, //v2.0.0 added
|
1839 |
+
'depth_rel_current' => 0, //v2.0.0 added
|
1840 |
+
'fallback_no_ancestor' => 0, //v1.1.0 added
|
1841 |
+
'fallback_include_parent' => 0, //v1.1.0 added
|
1842 |
+
'fallback_include_parent_siblings' => 0, //v1.1.0 added
|
1843 |
+
'fallback_no_children' => 0, //v1.2.0 added
|
1844 |
+
'fallback_nc_include_parent' => 0, //v1.2.0 added
|
1845 |
+
'fallback_nc_include_parent_siblings' => 0, //v1.2.0 added
|
1846 |
+
'flat_output' => 0,
|
1847 |
+
'include_parent' => 0,
|
1848 |
+
'include_parent_siblings' => 0, //v1.1.0 added
|
1849 |
+
'include_ancestors' => 0,
|
1850 |
+
'hide_empty' => 0, //v1.1.0: this now only has relevance prior to WP v3.6
|
1851 |
+
'title_from_parent' => 0,
|
1852 |
+
'title_from_current' => 0, //v1.2.0 added
|
1853 |
+
'ol_root' => 0,
|
1854 |
+
'ol_sub' => 0,
|
1855 |
+
//field section toggles...
|
1856 |
+
'fs_filter' => 0,
|
1857 |
+
'fs_fallbacks' => 1, //v1.2.0 added
|
1858 |
+
'fs_output' => 1,
|
1859 |
+
'fs_container' => 1,
|
1860 |
+
'fs_classes' => 1,
|
1861 |
+
'fs_links' => 1
|
1862 |
+
) as $k => $v ){
|
1863 |
+
|
1864 |
+
if( $method == 'form' ){
|
1865 |
+
$instance[ $k ] = isset( $from_instance[ $k ] ) ? !empty( $from_instance[ $k ] ) : !empty( $v );
|
1866 |
+
}elseif( $method == 'widget' ){
|
1867 |
+
$instance[ $k ] = !empty( $from_instance[ $k ] );
|
1868 |
+
}else{
|
1869 |
+
$instance[ $k ] = empty( $from_instance[ $k ] ) ? 0 : 1;
|
1870 |
+
}
|
1871 |
+
|
1872 |
+
}
|
1873 |
+
|
1874 |
+
//strings...
|
1875 |
+
foreach( array(
|
1876 |
+
'title' => '',
|
1877 |
+
'items' => '', //v2.0.0 added
|
1878 |
+
'container' => 'div',
|
1879 |
+
'container_id' => '',
|
1880 |
+
'container_class' => '',
|
1881 |
+
'menu_class' => 'menu-widget',
|
1882 |
+
'widget_class' => ''
|
1883 |
+
) as $k => $v ){
|
1884 |
+
|
1885 |
+
if( $method == 'form' ){
|
1886 |
+
$instance[ $k ] = isset( $from_instance[ $k ] ) ? esc_attr( trim( $from_instance[ $k ] ) ) : $v;
|
1887 |
+
}elseif( $method == 'widget' ){
|
1888 |
+
$instance[ $k ] = isset( $from_instance[ $k ] ) ? trim( $from_instance[ $k ] ) : $v; //bug in 2.0.2 fixed!
|
1889 |
+
}else{
|
1890 |
+
$instance[ $k ] = isset( $from_instance[ $k ] ) ? strip_tags( trim( $from_instance[ $k ] ) ) : $v;
|
1891 |
+
}
|
1892 |
+
|
1893 |
+
}
|
1894 |
+
|
1895 |
+
//html strings...
|
1896 |
+
foreach( array(
|
1897 |
+
'before' => '',
|
1898 |
+
'after' => '',
|
1899 |
+
'link_before' => '',
|
1900 |
+
'link_after' => ''
|
1901 |
+
) as $k => $v ){
|
1902 |
+
|
1903 |
+
if( $method == 'form' ){
|
1904 |
+
$instance[ $k ] = isset( $from_instance[ $k ] ) ? esc_html( trim( $from_instance[ $k ] ) ) : $v;
|
1905 |
+
}elseif( $method == 'widget' ){
|
1906 |
+
$instance[ $k ] = empty( $from_instance[ $k ] ) ? $v : trim( $from_instance[ $k ] );
|
1907 |
+
}else{
|
1908 |
+
$instance[ $k ] = isset( $from_instance[ $k ] ) ? trim( $from_instance[ $k ] ) : $v;
|
1909 |
+
}
|
1910 |
+
|
1911 |
+
}
|
1912 |
+
|
1913 |
+
//integers...
|
1914 |
+
foreach( array(
|
1915 |
+
'depth' => 0,
|
1916 |
+
'filter' => -1, //v2.0.0 changed from switch
|
1917 |
+
'filter_item' => -2, //v1.1.0 changed from 0
|
1918 |
+
'menu' => 0,
|
1919 |
+
'start_level' => 1
|
1920 |
+
) as $k => $v ){
|
1921 |
+
|
1922 |
+
if( $method == 'form' ){
|
1923 |
+
$instance[ $k ] = isset( $from_instance[ $k ]) ? max( $v, intval( $from_instance[ $k ] ) ) : max($v, 0);
|
1924 |
+
}elseif( $method == 'widget' ){
|
1925 |
+
$instance[ $k ] = max( $v, intval( $from_instance[ $k ] ) );
|
1926 |
+
}else{
|
1927 |
+
$instance[ $k ] = isset( $from_instance[ $k ]) ? max( $v, intval( $from_instance[ $k ] ) ) : $v;
|
1928 |
+
}
|
1929 |
+
|
1930 |
+
}
|
1931 |
+
|
1932 |
+
//items special case...
|
1933 |
+
if( $method == 'update' && !empty( $instance['items'] ) ){
|
1934 |
+
$sep = preg_match( '/(^\d+$|,)/', $instance['items'] ) > 0 ? ',' : ' ';
|
1935 |
+
$a = array();
|
1936 |
+
foreach( preg_split('/[,\s]+/', $instance['items'], -1, PREG_SPLIT_NO_EMPTY ) as $v ){
|
1937 |
+
$i = intval( $v );
|
1938 |
+
if( $i > 0 ){
|
1939 |
+
$a[] = $i;
|
1940 |
+
}
|
1941 |
+
}
|
1942 |
+
$instance['items'] = implode( $sep, $a );
|
1943 |
+
}
|
1944 |
+
|
1945 |
+
//v1.2.1 holds information determined by the walker...
|
1946 |
+
$this->_cmw_walker = array();
|
1947 |
+
|
1948 |
+
return $instance;
|
1949 |
+
|
1950 |
+
} //end cmw_legacy_settings()
|
1951 |
+
|
1952 |
+
/**
|
1953 |
+
* updates the widget settings sent from the legacy backend admin
|
1954 |
+
*
|
1955 |
+
* @param array $new_instance New widget settings
|
1956 |
+
* @param array $old_instance Old widget settings
|
1957 |
+
* @return array Sanitized widget settings
|
1958 |
+
*/
|
1959 |
+
function cmw_legacy_update( $new_instance, $old_instance ){
|
1960 |
+
|
1961 |
+
if( $this->_cmw_allow_legacy_update ){
|
1962 |
+
return $this->cmw_legacy_settings( $new_instance, $old_instance, 'update' );
|
1963 |
+
}else{
|
1964 |
+
//prevent the save!...
|
1965 |
+
return false;
|
1966 |
+
}
|
1967 |
+
|
1968 |
+
} //end cmw_legacy_update()
|
1969 |
+
|
1970 |
+
/**
|
1971 |
+
* produces the legacy widget HTML at the front end
|
1972 |
+
*
|
1973 |
+
* @filters : custom_menu_wizard_nav_params array of params that will be sent to wp_nav_menu(), array of instance settings, id base
|
1974 |
+
* custom_menu_wizard_settings_pre_widget array of instance settings, id base
|
1975 |
+
* custom_menu_wizard_widget_output HTML output string, array of instance settings, id base
|
1976 |
+
*
|
1977 |
+
* @param object $args Widget arguments
|
1978 |
+
* @param array $instance Configuration for this widget instance
|
1979 |
+
*/
|
1980 |
+
function cmw_legacy_widget( $args, $instance ) {
|
1981 |
+
|
1982 |
+
//sanitize $instance...
|
1983 |
+
$instance = $this->cmw_legacy_settings( $instance, array(), 'widget' );
|
1984 |
+
|
1985 |
+
extract( $args, EXTR_SKIP );
|
1986 |
+
|
1987 |
+
//v1.1.0 As of WP v3.6, wp_nav_menu() automatically prevents any HTML output if there are no items...
|
1988 |
+
$instance['hide_empty'] = $instance['hide_empty'] && $this->cmw_wp_version('3.6');
|
1989 |
+
|
1990 |
+
//allow a filter to amend the instance settings prior to producing the widget output...
|
1991 |
+
//eg. add_filter( 'custom_menu_wizard_settings_pre_widget', [filter_function], 10, 2 ) => $instance (array)
|
1992 |
+
$instance = apply_filters( 'custom_menu_wizard_settings_pre_widget', $instance, $this->id_base );
|
1993 |
+
|
1994 |
+
//fetch menu...
|
1995 |
+
if( !empty($instance['menu'] ) ){
|
1996 |
+
$menu = wp_get_nav_menu_object( $instance['menu'] );
|
1997 |
+
|
1998 |
+
//no menu, no output...
|
1999 |
+
if ( !empty( $menu ) ){
|
2000 |
+
|
2001 |
+
if( !empty( $instance['widget_class'] ) ){
|
2002 |
+
//$before_widget is usually just a DIV start-tag, with an id and a class; if it
|
2003 |
+
//gets more complicated than that then this may not work as expected...
|
2004 |
+
if( preg_match( '/^<[^>]+?class=["\']/', $before_widget ) > 0 ){
|
2005 |
+
$before_widget = preg_replace( '/(class=["\'])/', '$1' . $instance['widget_class'] . ' ', $before_widget, 1 );
|
2006 |
+
}else{
|
2007 |
+
$before_widget = preg_replace( '/^(<\w+)(\s|>)/', '$1 class="' . $instance['widget_class'] . '"$2', $before_widget );
|
2008 |
+
}
|
2009 |
+
}
|
2010 |
+
|
2011 |
+
if( !empty( $instance['container_class'] ) ){
|
2012 |
+
$instance['container_class'] = "menu-{$menu->slug}-container {$instance['container_class']}";
|
2013 |
+
}
|
2014 |
+
|
2015 |
+
$instance['menu_class'] = preg_split( '/\s+/', $instance['menu_class'], -1, PREG_SPLIT_NO_EMPTY );
|
2016 |
+
if( $instance['fallback_no_ancestor'] || $instance['fallback_no_children'] ){
|
2017 |
+
//v1.2.1 add a cmw-fellback-maybe class to the menu and we'll remove or replace it later...
|
2018 |
+
$instance['menu_class'][] = 'cmw-fellback-maybe';
|
2019 |
+
}
|
2020 |
+
$instance['menu_class'] = implode( ' ', $instance['menu_class'] );
|
2021 |
+
|
2022 |
+
$walker = new Custom_Menu_Wizard_Walker;
|
2023 |
+
$params = array(
|
2024 |
+
'menu' => $menu,
|
2025 |
+
'container' => empty( $instance['container'] ) ? false : $instance['container'], //bug in 2.0.2 fixed!
|
2026 |
+
'container_id' => $instance['container_id'],
|
2027 |
+
'menu_class' => $instance['menu_class'],
|
2028 |
+
'echo' => false,
|
2029 |
+
'fallback_cb' => false,
|
2030 |
+
'before' => $instance['before'],
|
2031 |
+
'after' => $instance['after'],
|
2032 |
+
'link_before' => $instance['link_before'],
|
2033 |
+
'link_after' => $instance['link_after'],
|
2034 |
+
'depth' => empty( $instance['flat_output'] ) ? $instance['depth'] : -1,
|
2035 |
+
'walker' =>$walker,
|
2036 |
+
//widget specific stuff...
|
2037 |
+
'_custom_menu_wizard' => $instance
|
2038 |
+
);
|
2039 |
+
//for the walker's use...
|
2040 |
+
$params['_custom_menu_wizard']['_walker'] = array();
|
2041 |
+
|
2042 |
+
if( $instance['ol_root'] ){
|
2043 |
+
$params['items_wrap'] = '<ol id="%1$s" class="%2$s">%3$s</ol>';
|
2044 |
+
}
|
2045 |
+
if( !empty( $instance['container_class'] ) ){
|
2046 |
+
$params['container_class'] = $instance['container_class'];
|
2047 |
+
}
|
2048 |
+
|
2049 |
+
add_filter('custom_menu_wizard_walker_items', array( $this, 'cmw_filter_walker_items' ), 10, 2);
|
2050 |
+
if( $instance['hide_empty'] ){
|
2051 |
+
add_filter( "wp_nav_menu_{$menu->slug}_items", array( $this, 'cmw_filter_check_for_no_items' ), 65532, 2 );
|
2052 |
+
}
|
2053 |
+
|
2054 |
+
//allow a filter to amend the wp_nav_menu() params prior to calling it...
|
2055 |
+
//eg. add_filter( 'custom_menu_wizard_nav_params', [filter_function], 10, 3 ) => $params (array)
|
2056 |
+
//NB: wp_nav_menu() is in wp-includes/nav-menu-template.php
|
2057 |
+
$out = wp_nav_menu( apply_filters( 'custom_menu_wizard_nav_params', $params, $instance, $this->id_base ) );
|
2058 |
+
|
2059 |
+
remove_filter('custom_menu_wizard_walker_items', array( $this, 'cmw_filter_walker_items' ), 10, 2);
|
2060 |
+
if( $instance['hide_empty'] ){
|
2061 |
+
remove_filter( "wp_nav_menu_{$menu->slug}_items", array( $this, 'cmw_filter_check_for_no_items' ), 65532, 2 );
|
2062 |
+
}
|
2063 |
+
|
2064 |
+
//only put something out if there is something to put out...
|
2065 |
+
if( !empty( $out ) ){
|
2066 |
+
|
2067 |
+
//title from : 'from parent' has priority over 'from current'...
|
2068 |
+
//note that 'parent' is whatever you are getting the children of and therefore doesn't apply to a ShowAll, whereas
|
2069 |
+
//'current' is the current menu item (as determined by WP); also note that neither parent nor current actually has
|
2070 |
+
//to be present in the results
|
2071 |
+
if( $instance['title_from_parent'] && !empty( $this->_cmw_walker['parent_title'] ) ){
|
2072 |
+
$title = $this->_cmw_walker['parent_title'];
|
2073 |
+
}
|
2074 |
+
if( empty( $title ) && $instance['title_from_current'] && !empty( $this->_cmw_walker['current_title'] ) ){
|
2075 |
+
$title = $this->_cmw_walker['current_title'];
|
2076 |
+
}
|
2077 |
+
if( empty( $title ) ){
|
2078 |
+
$title = $instance['hide_title'] ? '' : $instance['title'];
|
2079 |
+
}
|
2080 |
+
|
2081 |
+
//remove/replace the cmw-fellback-maybe class...
|
2082 |
+
$out = str_replace(
|
2083 |
+
'cmw-fellback-maybe',
|
2084 |
+
empty( $this->_cmw_walker['fellback'] ) ? '' : 'cmw-fellback-' . $this->_cmw_walker['fellback'],
|
2085 |
+
$out );
|
2086 |
+
|
2087 |
+
if ( !empty($title) ){
|
2088 |
+
$out = $before_title . apply_filters('widget_title', $title, $instance, $this->id_base) . $after_title . $out;
|
2089 |
+
}
|
2090 |
+
$out = $before_widget . $out . $after_widget;
|
2091 |
+
//allow a filter to modify the entire output...
|
2092 |
+
//eg. add_filter( 'custom_menu_wizard_widget_output', [filter_function], 10, 3 ) => $output (HTML string)
|
2093 |
+
echo apply_filters( 'custom_menu_wizard_widget_output', $out, $instance, $this->id_base );
|
2094 |
+
}
|
2095 |
+
}
|
2096 |
+
}
|
2097 |
+
|
2098 |
+
} //end cmw_legacy_widget()
|
2099 |
+
|
2100 |
+
} //end of class
|
2101 |
+
?>
|
@@ -1,9 +1,10 @@
|
|
1 |
=== Custom Menu Wizard Widget ===
|
2 |
Contributors: wizzud
|
3 |
-
|
4 |
-
|
5 |
-
|
6 |
-
|
|
|
7 |
License: GPLv2 or Later
|
8 |
|
9 |
Show branches or levels of your menu in a widget, or in content using a shortcode, with full customisation.
|
@@ -11,402 +12,538 @@ Show branches or levels of your menu in a widget, or in content using a shortcod
|
|
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. And there
|
15 |
|
16 |
Features include:
|
17 |
|
18 |
-
* Display
|
19 |
-
* Select a branch based on a specific menu item, or the
|
20 |
-
* Specify a level to start at, and the number of levels to output
|
21 |
-
*
|
22 |
-
*
|
23 |
-
*
|
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 |
-
*
|
31 |
-
*
|
32 |
-
|
33 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
34 |
|
35 |
-
Documentation for
|
36 |
-
[
|
|
|
37 |
|
38 |
-
==
|
|
|
|
|
39 |
|
40 |
There are quite a few options, which makes the widget settings box very long. I have therefore grouped most of the options into
|
41 |
-
logical sections
|
42 |
-
|
|
|
43 |
|
44 |
-
|
|
|
|
|
45 |
|
46 |
Set the title for your widget.
|
47 |
|
48 |
-
* **Hide** *
|
49 |
|
50 |
Prevents the entered `Title` being displayed in the front-end widget output.
|
51 |
-
|
52 |
-
In the Widgets admin page, I find it useful to still be able to see the `Title` in the sidebar when the widget is
|
53 |
don't necessarily want that `Title` to actually be output when the widget is displayed at the front-end. Hence this checkbox.
|
54 |
|
55 |
-
* **Select Menu** *
|
56 |
|
57 |
Choose the appropriate menu from the dropdown list of Custom Menus currently defined in your WordPress application. The
|
58 |
first one available (alphabetically) is already selected for you by default.
|
59 |
|
60 |
-
|
|
|
|
|
|
|
|
|
61 |
|
62 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
63 |
|
64 |
-
|
65 |
-
|
|
|
|
|
66 |
|
67 |
-
|
|
|
|
|
68 |
|
69 |
-
|
70 |
-
and "Current Parent Item" (v1.1.0) option, followed by all the available items from the menu chosen in `Select Menu`.
|
71 |
-
The widget will output the *children* of the selected item, always assuming that they lie within the bounds of any other parameters set.
|
72 |
|
73 |
-
|
74 |
|
75 |
-
|
|
|
|
|
|
|
76 |
|
77 |
-
|
|
|
78 |
|
79 |
-
|
80 |
-
appear in the `Select Menu` then there is going to be no output for any of these options.
|
81 |
-
|
82 |
-
If you change `Select Menu`, the options presented in this dropdown will change accordingly and the selected option will revert to the default.
|
83 |
|
84 |
-
|
|
|
85 |
|
86 |
-
|
87 |
-
for situations that it is not possible to handle using other option settings. The simplest way to determine the menu item ids is
|
88 |
-
to use the "assist" facility.
|
89 |
-
|
90 |
-
Note that the `Starting Level` and `Depth` options (including `Relative to "Current" Item`) have no effect if `Items` is set.
|
91 |
|
92 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
93 |
|
94 |
-
|
95 |
-
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.
|
96 |
-
Note that for a `Children of` filter there is no difference between level 1 and level 2 (because there are no children at level 1).
|
97 |
-
Also note that this option does not apply if `Items` is set.
|
98 |
|
99 |
-
|
100 |
|
101 |
-
|
102 |
-
still applied - as if the output were `Hierarchical` and then flattened at the very last moment.
|
103 |
-
|
104 |
-
You need to be aware that, by default, the
|
105 |
-
`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
|
106 |
-
`Children of` to "Current Item", `Starting Level` to "2", and `For Depth` to "2 levels" : if the current item was found at level 3,
|
107 |
-
then you would get the current item's immediate children (from level 4), plus *their* immediate children (from level 5).
|
108 |
-
Note that this option does not apply if `Items` is set.
|
109 |
|
110 |
-
|
111 |
-
|
112 |
-
This changes the `For Depth` option such that depth is applied relative to the current menu item, instead of relative to the
|
113 |
-
first item found that is to be kept. It only has any effect when `For Depth` is set to something other than "unlimited", and when
|
114 |
-
the current menu item is within the filtered items (before taking `For Depth` into account).
|
115 |
|
116 |
-
* **
|
117 |
|
118 |
-
|
|
|
|
|
119 |
|
120 |
-
|
121 |
|
122 |
-
|
123 |
-
it provides a fallback of effectively switching the filter to "Current Item" if the current menu item
|
124 |
-
(as determined by WordPress) is at Level 1
|
125 |
-
(top level) of the selected menu. For example, say you were to set `Children of` to "Current Parent Item", with `Starting Level`
|
126 |
-
at "1" and `For Depth` at "unlimited" : if the current menu item was found at level 1 (root level of the menu) then ordinarily
|
127 |
-
there would be no output because the current item has no parent! If you were to enable the `Switch to Current Item` fallback then you
|
128 |
-
*would* have some output - the entire branch below the current item.
|
129 |
|
130 |
-
|
|
|
131 |
|
132 |
-
|
133 |
-
temporarily override the equivalent **Output** option to ON. Note that if the **Output** options are already set to include
|
134 |
-
the parent item (with or without siblings), this option has absolutely no effect.
|
135 |
|
136 |
-
|
|
|
137 |
|
138 |
-
|
139 |
-
temporarily override the equivalent **Output** option to ON. Note that if the equivalent **Output** option is already enabled,
|
140 |
-
this option has absolutely no effect.
|
141 |
|
142 |
-
|
|
|
|
|
|
|
|
|
|
|
143 |
|
144 |
-
|
|
|
145 |
|
146 |
-
|
147 |
-
of Current Item and there aren't any. For example, say you were to set `Children of` to "Current Item", with `Starting Level`
|
148 |
-
at "1" and `For Depth` at "unlimited" : if the current menu item has no children then ordinarily
|
149 |
-
there would be no output! If you were to enable the `Switch to Current Item` fallback then you
|
150 |
-
*would* have some output - the current item and its siblings.
|
151 |
-
|
152 |
-
Please note that there is one difference between this fallback and the normal "Current Parent Item" filter : if the current item
|
153 |
-
has no ancestor (as well as no children) then you will always get the current item and its siblings, regardless of any other settings!
|
154 |
|
155 |
-
|
156 |
|
157 |
-
|
158 |
-
temporarily override the equivalent **Output** option to ON. Note that if the **Output** options are already set to include
|
159 |
-
the parent item (with or without siblings), this option has absolutely no effect.
|
160 |
|
161 |
-
|
162 |
|
163 |
-
|
164 |
-
|
165 |
-
|
166 |
|
167 |
-
|
168 |
|
169 |
-
|
|
|
|
|
|
|
|
|
|
|
170 |
|
171 |
-
|
172 |
|
173 |
-
|
174 |
|
175 |
-
|
176 |
-
presented in a `Hierarchical` output.
|
177 |
|
178 |
-
|
179 |
-
|
180 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
181 |
|
182 |
-
|
183 |
|
184 |
-
|
|
|
185 |
|
186 |
-
|
|
|
|
|
|
|
|
|
|
|
187 |
|
188 |
-
|
189 |
|
190 |
-
|
191 |
|
192 |
-
|
193 |
-
|
194 |
|
195 |
-
|
196 |
|
197 |
-
|
198 |
-
|
199 |
-
|
200 |
-
|
|
|
|
|
201 |
|
202 |
-
|
203 |
|
204 |
-
|
205 |
-
|
206 |
-
|
207 |
-
|
208 |
-
|
|
|
|
|
209 |
|
210 |
-
|
211 |
|
212 |
-
|
213 |
-
the ULs out for OLs (ordered lists).
|
214 |
-
|
215 |
-
* **Top Level** *(checkbox)*
|
216 |
|
217 |
-
|
218 |
-
|
219 |
-
* **Sub-Levels** *(checkbox)*
|
220 |
|
221 |
-
|
222 |
|
223 |
-
|
|
|
224 |
|
225 |
-
|
226 |
-
|
227 |
-
Please note that as of WordPress v3.6, this option becomes superfluous and will **not** be presented (the wp_nav_menu() function
|
228 |
-
has been modified to automatically suppress all HTML output if there are no items to be displayed). The widget will retain
|
229 |
-
the setting used on earlier WP versions (in case reversion from WP v3.6 might be required) but *will not present the option
|
230 |
-
for WP v3.6+*.
|
231 |
|
232 |
-
|
|
|
|
|
233 |
|
234 |
-
* **
|
|
|
|
|
|
|
235 |
|
236 |
-
|
237 |
-
tag, or you may clear it out and the container will be completely removed. Please note that WordPress is set by default to only
|
238 |
-
accept "div" or "nav", but that could be changed or extended by any template or plugin.
|
239 |
|
240 |
-
|
|
|
241 |
|
242 |
-
|
|
|
243 |
|
244 |
-
|
245 |
|
246 |
-
|
247 |
|
248 |
-
|
|
|
|
|
|
|
249 |
|
250 |
-
|
251 |
|
252 |
-
|
253 |
-
|
254 |
-
* **Widget Class**
|
255 |
|
256 |
-
|
|
|
|
|
257 |
|
258 |
-
* **
|
259 |
|
260 |
-
|
261 |
|
262 |
-
|
263 |
|
264 |
-
|
265 |
|
266 |
-
|
267 |
|
268 |
-
|
269 |
|
270 |
-
|
271 |
|
272 |
-
|
273 |
|
274 |
-
|
275 |
|
276 |
-
==
|
277 |
|
278 |
-
|
279 |
-
Please note that the `Hide Widget if Empty` option is not available to the shortcode : it is set to enabled, and if there are no menu items found then there will be no output from the shortcode.
|
280 |
|
281 |
-
|
282 |
-
the Inactive Widgets area, so you don't have to add an unwanted instance of the widget to a sidebar.
|
283 |
|
284 |
-
* **
|
285 |
|
286 |
-
|
287 |
|
288 |
-
* **
|
289 |
|
290 |
-
|
291 |
-
that has menu items attached to it, and use that.
|
292 |
|
293 |
-
* **
|
294 |
|
295 |
-
|
296 |
-
filter defaults back to `Show all` (see above). Note that `items`, if supplied, will take precedence over `children_of`.
|
297 |
-
|
298 |
-
* If numeric, it is taken as being the id of a menu item. The widget will look for the `Children of` that menu item (within `menu`).
|
299 |
-
(Hint : In Menus Admin, hover over the item's **Remove** link and note the number after *menu-item=* in the URL)
|
300 |
-
|
301 |
-
* Certain specific strings have the following meanings:
|
302 |
-
|
303 |
-
* *'current'* or *'current-item'* : a `Children of` "Current Item" filter
|
304 |
|
305 |
-
|
306 |
|
307 |
-
|
308 |
|
309 |
-
|
310 |
-
|
311 |
-
|
312 |
-
|
|
|
313 |
|
314 |
-
|
|
|
|
|
|
|
|
|
315 |
|
316 |
-
|
|
|
317 |
|
318 |
-
|
319 |
-
|
|
|
320 |
|
321 |
-
|
322 |
-
|
323 |
-
* *'parent'* : Enables widget's `Include Parent...` **Fallbacks** extension option (in addition to the above)
|
324 |
|
325 |
-
|
|
|
326 |
|
327 |
-
*
|
|
|
|
|
328 |
|
329 |
-
|
330 |
-
|
331 |
|
332 |
-
|
333 |
-
|
334 |
-
|
|
|
|
|
|
|
335 |
|
336 |
-
|
|
|
|
|
|
|
|
|
337 |
|
338 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
339 |
|
340 |
-
|
|
|
|
|
341 |
|
342 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
343 |
|
344 |
-
|
|
|
|
|
345 |
|
346 |
-
|
|
|
|
|
|
|
347 |
|
348 |
-
|
|
|
|
|
|
|
349 |
|
350 |
-
|
|
|
|
|
351 |
|
352 |
-
|
|
|
353 |
|
354 |
-
|
355 |
-
|
356 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
357 |
|
358 |
-
|
|
|
359 |
|
360 |
-
|
|
|
361 |
|
362 |
-
|
|
|
363 |
|
364 |
-
|
|
|
|
|
365 |
|
366 |
-
|
|
|
367 |
|
368 |
-
|
|
|
369 |
|
370 |
-
*
|
|
|
|
|
|
|
371 |
|
372 |
-
|
|
|
373 |
|
374 |
-
|
|
|
375 |
|
376 |
-
|
|
|
377 |
|
378 |
-
|
|
|
379 |
|
380 |
-
|
|
|
381 |
|
382 |
-
|
383 |
-
|
384 |
-
tag name - is much more restrictive than the widget's options, which allow HTML.
|
385 |
|
386 |
-
|
|
|
387 |
|
388 |
-
|
389 |
-
|
390 |
-
|
|
|
391 |
|
392 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
393 |
|
394 |
-
* Show the
|
395 |
|
396 |
`
|
397 |
-
[
|
398 |
`
|
399 |
|
400 |
-
*
|
401 |
|
402 |
`
|
403 |
-
[
|
404 |
`
|
405 |
|
406 |
-
* From the "animals" menu, show
|
407 |
|
408 |
`
|
409 |
-
[
|
410 |
`
|
411 |
|
412 |
== Installation ==
|
@@ -418,32 +555,27 @@ the Inactive Widgets area, so you don't have to add an unwanted instance of the
|
|
418 |
1. Activate the plugin through the 'Plugins' menu in your WP Admin
|
419 |
|
420 |
The widget will now be available in the 'Widgets' admin page.
|
421 |
-
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.
|
422 |
Alternatively, you can use the shortcode in your content.
|
423 |
|
424 |
== Frequently Asked Questions ==
|
|
|
425 |
|
426 |
-
|
427 |
-
|
428 |
-
= Are there any known problems?
|
429 |
-
|
430 |
Yep, 'fraid so :
|
431 |
|
432 |
-
1. The widget will only recognise one "current" item (as of v2.0.2, that's the first one encountered; prior to that it was the last one found). It is perfectly possible to have more than one menu item marked as "current"
|
433 |
-
|
434 |
-
2. The widget does not play well with PolyLang's language-switcher when it has been added to a menu that the widget is filtering.
|
435 |
|
436 |
= Why isn't it working? Why is there no output? =
|
437 |
-
|
438 |
I don't know. With all due respect (and a certain amount of confidence in the widget) I would venture to suggest that it is probably due to
|
439 |
the option settings on the widget/shortcode. The quickest way to resolve any such issues is to use the widget's interactive "assist", and
|
440 |
ensure that you set the current menu item correctly for the page(s) that you are having problems with. However, I am well aware that I not
|
441 |
-
infallible
|
442 |
-
|
443 |
-
a request for more details
|
444 |
|
445 |
= How do I use the "assist"? =
|
446 |
-
|
447 |
The widget's interactive "assist" is specific to each widget instance. It is a javascript-driven *emulator* that uses the widget instance's
|
448 |
option settings - including the menu selected - to build a pictorial representation of the menu and show you, in blue, which menu items will
|
449 |
be output according to the current option settings. It also shows a very basic output list of those menu items, although it will not apply
|
@@ -453,183 +585,208 @@ item to change). The "current menu item" is shaded red, with its parent shaded o
|
|
453 |
"current menu item" and the widget options are immediately reflected by the "assist" (text fields in the widget options simply need to lose
|
454 |
focus).
|
455 |
|
456 |
-
|
457 |
-
|
458 |
-
|
|
|
|
|
459 |
|
460 |
-
|
|
|
461 |
|
462 |
-
|
463 |
-
"assist"
|
|
|
464 |
|
465 |
-
=
|
|
|
|
|
|
|
466 |
|
467 |
-
|
|
|
468 |
attribute, so should be seen when the cursor is moved over the item. A simpler way is to check the `Items` option : the "assist" will
|
469 |
-
then show a checkbox
|
470 |
-
widget's `Items` settings, and also in the shortcode
|
471 |
|
472 |
-
|
473 |
the URL (the link's href) for `menu-item=NNN` ... the NNN is the menu item id.
|
474 |
|
475 |
-
=
|
|
|
|
|
476 |
|
477 |
-
|
478 |
-
|
|
|
479 |
|
480 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
481 |
|
482 |
-
|
|
|
|
|
|
|
483 |
|
484 |
-
|
|
|
|
|
|
|
|
|
485 |
|
486 |
-
|
|
|
|
|
487 |
|
488 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
489 |
|
490 |
== Changelog ==
|
491 |
|
492 |
-
=
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
493 |
|
|
|
494 |
* change : modified determination of current item to cope better with multiple occurences (still first-found, but within prioritised groups)
|
495 |
-
|
496 |
* change : display of the upgrade notice in the plugins list has been replaced with a simple request to read the changelog before upgrading
|
497 |
|
498 |
= 2.0.5 =
|
499 |
-
|
500 |
* bugfix : prevent PHP warnings of Undefined index/offset
|
501 |
|
502 |
= 2.0.4 =
|
503 |
-
|
504 |
* bugfix : clearing the container field failed to remove the container from the output
|
505 |
-
|
506 |
* addition : in the "assist", added automatic selection of the shortcode text when it is clicked
|
507 |
-
|
508 |
* addition : remove WordPress's menu-item-has-children class (introduced in v3.7) when the filtered item no longer has children
|
509 |
-
|
510 |
* change : tweaked styles and javascript in admin for WordPress v3.8
|
511 |
|
512 |
= 2.0.3 =
|
513 |
-
|
514 |
* bugfix : missing global when enqueuing scripts and styles for admin
|
515 |
|
516 |
= 2.0.2 =
|
517 |
-
|
518 |
* bugfix : the Include Ancestors option was not automatically including the Parent
|
519 |
-
|
520 |
* bugfix : the "assist" was incorrectly calculating Depth Relative to Current Item when the current menu item was outside the scope of the Filtered items
|
521 |
-
|
522 |
* behaviour change : only recognise the first "current" item found (used to allow subsequent "current" items to override any already encountered)
|
523 |
|
524 |
= 2.0.1 =
|
525 |
-
|
526 |
* bugfix : an incorrect test for a specific-items filter prevented show-all producing any output
|
527 |
|
528 |
= 2.0.0 =
|
529 |
-
|
530 |
* **! Possible Breaker !** The calculation of `Start Level` has been made consistent across the `Show all` and `Children of` filters : if you previously had a setup where you were filtering for the children of an item at level 2, with start level set to 4, there would have been no output because the immediate children (at level 3) were outside the start level. Now, there *will* be output, starting with the grand-children (at level 4).
|
531 |
-
|
532 |
* **! Possible Breaker !** There is now deemed to be an artificial "root" item above the level 1 items, which mean that a `Children of` filter set to "Current Parent Item" or "Current Root Item" will no longer fail for a top-level "current menu item". If you have the "no ancestor" fallback set then this change will have no impact (but you may now want to consider turning the fallback off?); if you *don't* currently use the "no ancestor" fallback, then where there was previously no output there will now be some!
|
533 |
-
|
534 |
* added new option : Items, a comma- or space-delimited list of menu item ids, as an alternative Filter
|
535 |
-
|
536 |
* added new option : Depth Relative to Current Item to the Filter section (depth_rel_current=1 in the shortcode)
|
537 |
-
|
538 |
* added new option : Must Contain Current Item to the Output section (contains_current=1 in the shortcode)
|
539 |
-
|
540 |
* changed the widget's "demo" facility to "assist" and brought it into WordPress admin, with full interactivity with the widget
|
541 |
-
|
542 |
* refactored code
|
543 |
|
544 |
= 1.2.2 =
|
545 |
-
|
546 |
* bugfix : fallback for Current Item with no children was failing because the parent's children weren't being picked out correctly
|
547 |
|
548 |
= 1.2.1 =
|
549 |
-
|
550 |
* added some extra custom classes, when applicable : cmw-fellback-to-current & cmw-fellback-to-parent (on outer UL/OL) and cmw-the-included-parent, cmw-an-included-parent-sibling & cmw-an-included-ancestor (on relevant LIs)
|
551 |
-
|
552 |
* corrected 'show all from start level 1' processing so that custom classes get applied and 'Title from "Current" Item' works (regardless of filter settings)
|
553 |
-
|
554 |
* changed the defaults for new widgets such that only the Filter section is open by default; all the others are collapsed
|
555 |
-
|
556 |
* in demo.html, added output of the shortcode applicable to the selections made
|
557 |
-
|
558 |
* in demo.html, added a link to the documentation page
|
559 |
-
|
560 |
* corrected 2 of the shortcode examples in the readme.txt, and made emulator (demo) available from the readme
|
561 |
|
562 |
= 1.2.0 =
|
563 |
-
|
564 |
* added custom_menu_wizard shortcode, to run the widget from within content
|
565 |
-
|
566 |
* moved the 'no ancestor' fallback into new Fallback collapsible section, and added a fallback for Current Item with no children
|
567 |
-
|
568 |
* added an option allowing setting of title from current menu item's title
|
569 |
-
|
570 |
* fixed a bug with optgroups/options made available for the 'Children of' selector after the widget has been saved (also affected disabled fields and styling)
|
571 |
-
|
572 |
* don't include menus with no items
|
573 |
-
|
574 |
* updated demo.html
|
575 |
|
576 |
= 1.1.0 =
|
577 |
-
|
578 |
* added 'Current Root Item' and 'Current Parent Item' to the `Children of` filter
|
579 |
-
|
580 |
* added `Fallback to Current Item` option, with subsidiary options for overriding a couple of Output options, as a means to enable Current Root & Current Parent to match a Current Item at root level
|
581 |
-
|
582 |
* added an Output option to include both the parent item **and** the parent's siblings (for a successful `Children of` filter)
|
583 |
-
|
584 |
* added max-width style (100%) to the `Children of` SELECT in the widget options
|
585 |
-
|
586 |
* added widget version to the admin js enqueuer
|
587 |
-
|
588 |
* ignore/disable Hide Empty option for WP >= v3.6 (wp_nav_menu() now does it automatically)
|
589 |
-
|
590 |
* included a stand-alone helper/demo html page
|
591 |
-
|
592 |
* rebuilt the `Children of` SELECT in the widget options to cope with IE's lack of OPTGROUP/OPTION styling
|
593 |
-
|
594 |
* moved the setting of 'disabled' attributes on INPUTs/SELECTs from PHP into javascript
|
595 |
|
596 |
= 1.0.0 =
|
597 |
-
|
598 |
-
Initial release
|
599 |
|
600 |
== Upgrade Notice ==
|
601 |
|
602 |
-
=
|
|
|
|
|
|
|
603 |
|
|
|
604 |
Determination of the current menu item has been slightly modified to cope a bit better with occasions where multiple items have been set as "current".
|
605 |
The display of the upgrade notice in the plugins list has been replaced with a simple request to read the changelog before upgrading.
|
606 |
|
607 |
= 2.0.5 =
|
608 |
-
|
609 |
Fixed a bug to prevent PHP warnings of Undefined index/offset being output.
|
610 |
|
611 |
= 2.0.4 =
|
612 |
-
|
613 |
Fixed a bug that prevented the container field being removed, and added removal of the menu-item-has-children class when the filtered item no longer has children.
|
614 |
The admin widget styling and javascript have been tweaked to accommodate WordPress 3.8.
|
615 |
|
616 |
= 2.0.3 =
|
617 |
-
|
618 |
Fixed a minor bug with a missing global when enqueuing script and style for the admin.
|
619 |
|
620 |
= 2.0.2 =
|
621 |
-
|
622 |
Fixed a bug with the Include Ancestors option, where it was not automatically including the Parent.
|
623 |
Fixed a bug in the "assist", where it was incorrectly calculating Depth Relative to Current Item when the current menu item was outside the scope of the Filtered items.
|
624 |
Changed determination of the "current" item such that only the first one encountered is recognised, rather than allowing subsequent "current" items to override previous ones.
|
625 |
|
626 |
= 2.0.1 =
|
627 |
-
|
628 |
Fixed a bug whereby a test for a specific-items filter prevented show-all from producing any output.
|
629 |
|
630 |
= 2.0.0 =
|
631 |
-
|
632 |
-
**! Possible Breaker !** My apologies if this affects you, but there are 2 possible scenarios where settings that previously resulted in no output *might* now produce output :
|
633 |
+ if you have set a `Children of` filter, **and** you have changed the `Start Level` to a level greater than 2, or
|
634 |
+ if you have set the `Children of` filter to Current Parent/Root Item, and you have **not** set the "no ancestor" fallback.
|
635 |
*__If you think you may be impacted, please check the [Changelog](http://wordpress.org/plugins/custom-menu-wizard/changelog/) for a fuller explanation of what has changed.__*
|
@@ -641,17 +798,14 @@ New options :
|
|
641 |
Rebuilt the "demo" facility as an "assist" wizard for the widget It is now fully interactive with the widget instance, and generates the entire shortcode according to the widget instance settings.
|
642 |
|
643 |
= 1.2.2 =
|
644 |
-
|
645 |
Bugfix : The fallback for Current Item with no children was failing because the parent's children weren't being picked out correctly
|
646 |
|
647 |
= 1.2.1 =
|
648 |
-
|
649 |
Added a few extra custom classes, and changed the defaults for new widgets such that only the Filter section is open by default.
|
650 |
Fixed Show All processing so that custom classes always get applied, and 'Title from "Current" Item' works regardless of filter settings.
|
651 |
Fixed a couple of the shortcode examples in the readme.txt, and added display of the applicable shortcode settings to the demo.html.
|
652 |
|
653 |
= 1.2.0 =
|
654 |
-
|
655 |
Added custom_menu_wizard shortcode, to run the widget from within content.
|
656 |
Added a new fallback for Current Item having no children, and moved all fallbacks into a collapsible Fallbacks section.
|
657 |
Fixed a bug with optgroups/options made available for the 'Children of' selector after the widget has been saved (also affected disabled fields and styling).
|
1 |
=== Custom Menu Wizard Widget ===
|
2 |
Contributors: wizzud
|
3 |
+
Donate link: https://www.paypal.com/cgi-bin/webscr?cmd=_s-xclick&hosted_button_id=KP2LVCBXNCEB4
|
4 |
+
Tags: menu,widget,widgets,navigation,nav,custom menus,custom menu,partial menu,current item,current page,menu level,menu branch,menu shortcode,menu widget,advanced,enhanced
|
5 |
+
Requires at least: 3.6
|
6 |
+
Tested up to: 3.9
|
7 |
+
Stable tag: 3.0.0
|
8 |
License: GPLv2 or Later
|
9 |
|
10 |
Show branches or levels of your menu in a widget, or in content using a shortcode, with full customisation.
|
12 |
== Description ==
|
13 |
|
14 |
This plugin is a boosted version of the WordPress "Custom Menu" widget.
|
15 |
+
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. And there's a shortcode that enables you to include the widget's output in your content.
|
16 |
|
17 |
Features include:
|
18 |
|
19 |
+
* Display an entire menu, just a branch of it, just certain level(s) of it, or even just specific items from it!
|
20 |
+
* Select a branch based on a specific menu item, or the current menu item (currently displayed page)
|
21 |
+
* Specify a relative or absolute level to start at, and the number of levels to output
|
22 |
+
* Include ancestor item(s) in the output, with or without siblings
|
23 |
+
* Exclude certain menu items, or levels of items
|
24 |
+
* Make the output conditional upon the current menu item being found in different stages of the filter selection process
|
|
|
25 |
* Automatically add cmw-level-N and cmw-has-submenu classes to output menu items
|
26 |
+
* Allow the widget title to be entered but not output, or to be set from the current menu item or selected branch item
|
27 |
+
* Select hierarchicial or flat output, both options still abiding by the specified number of levels to output
|
28 |
* Add/specify custom class(es) for the widget block, the menu container, and the menu itself
|
29 |
* Modify the link's output with additional HTML around the link's text and/or the link element itself
|
30 |
* Use Ordered Lists (OL) for the top and/or sub levels instead of Unordered Lists (UL)
|
31 |
+
* Shortcode, `[cmwizard]`, available to run the widget from within content
|
32 |
+
* Interactive "assist" to help with the widget settings and/or shortcode definition
|
33 |
+
* Utility to find posts containing this plugin's shortcode
|
34 |
+
|
35 |
+
Current documentation for the [Widget Options](http://wordpress.org/plugins/custom-menu-wizard/other_notes/#WIDGET-OPTIONS),
|
36 |
+
and the associated [Shortcode Parameters](http://wordpress.org/plugins/custom-menu-wizard/other_notes/#SHORTCODE-PARAMETERS),
|
37 |
+
can be found under [Other Notes](http://wordpress.org/plugins/custom-menu-wizard/other_notes/).
|
38 |
+
|
39 |
+
**Please, do not be put off by the number of options available!** I suspect (and I admit that I'm guessing!) that for the majority of users
|
40 |
+
there are probably a couple of very common scenarios:
|
41 |
+
|
42 |
+
1. Show the current menu item, plus any descendants...
|
43 |
+
* Drag a new Custom Menu Wizard widget into the sidebar, and give it a title (if you want one)
|
44 |
+
* Select the menu you wish to use (if it's not already selected)
|
45 |
+
* Open the FILTERS section :
|
46 |
+
* under Primary Filter, click on the *Branch* radio
|
47 |
+
* Save the widget!
|
48 |
+
* *Equivalent shortcode resembles `[cmwizard menu=N title="Your Title" branch=current]`*
|
49 |
+
|
50 |
+
2. Show just the descendants of the current menu item (if there are any)...
|
51 |
+
* Drag a new Custom Menu Wizard widget into the sidebar, and give it a title (if you want one)
|
52 |
+
* Select the menu you wish to use (if it's not already selected)
|
53 |
+
* Open the FILTERS section :
|
54 |
+
* under Primary Filter, click on the *Branch* radio
|
55 |
+
* under Secondary Filter, set *Starting at* to "+1 (children)"
|
56 |
+
* Save the widget!
|
57 |
+
* *Equivalent shortcode resembles `[cmwizard menu=N title="Your Title" branch=current start_at="+1"]`*
|
58 |
+
|
59 |
+
If you like this widget (or if you don't?), please consider taking a moment or two to give it a
|
60 |
+
[Review](http://wordpress.org/support/view/plugin-reviews/custom-menu-wizard) : it helps others, and gives me valuable feedback.
|
61 |
|
62 |
+
*Documentation for version 2 of the widget
|
63 |
+
can be found [here](http://plugins.svn.wordpress.org/custom-menu-wizard/tags/2.0.6/readme.txt)
|
64 |
+
or [here](http://www.wizzud.com/v210-readme.html).*
|
65 |
|
66 |
+
== WIDGET OPTIONS ==
|
67 |
+
|
68 |
+
*NB. Version 2 documentation is [here](http://plugins.svn.wordpress.org/custom-menu-wizard/tags/3.0.0/v210-readme.html#Widget-Options).*
|
69 |
|
70 |
There are quite a few options, which makes the widget settings box very long. I have therefore grouped most of the options into
|
71 |
+
collapsible logical sections (with remembered state once saved).
|
72 |
+
|
73 |
+
Note that certain options may be enabled/disabled depending on your choice of primary, and possibly secondary, filters.
|
74 |
|
75 |
+
***Always Visible***
|
76 |
+
|
77 |
+
* **Title** *textbox*
|
78 |
|
79 |
Set the title for your widget.
|
80 |
|
81 |
+
* **Hide** *checkbox*
|
82 |
|
83 |
Prevents the entered `Title` being displayed in the front-end widget output.
|
84 |
+
|
85 |
+
In the Widgets admin page, I find it useful to still be able to see the `Title` in the sidebar when the widget is closed, but I
|
86 |
don't necessarily want that `Title` to actually be output when the widget is displayed at the front-end. Hence this checkbox.
|
87 |
|
88 |
+
* **Select Menu** *select*
|
89 |
|
90 |
Choose the appropriate menu from the dropdown list of Custom Menus currently defined in your WordPress application. The
|
91 |
first one available (alphabetically) is already selected for you by default.
|
92 |
|
93 |
+
== Filters Section ==
|
94 |
+
|
95 |
+
Filters are applied in the order they are presented.
|
96 |
+
|
97 |
+
***Primary Filter***
|
98 |
|
99 |
+
* **Level** *radio (default On) & select*
|
100 |
+
|
101 |
+
Filters by level within the selected menu, starting at the level selected here. This is the default setting
|
102 |
+
for a new widget instance, which, if left alone and with all other options at their default, will show the entire selected menu.
|
103 |
+
|
104 |
+
Example : If you wanted to show all the options that were at level 3 or below, you could check this radio and set the select to "3".
|
105 |
+
|
106 |
+
* **Branch** *radio & select*
|
107 |
+
|
108 |
+
Filters by branch, with the head item of the branch being selected from the dropdown. The dropdown presents all the
|
109 |
+
items from the selected menu, plus a "Current Item" option (the default). Selecting "Current Item" means that the head item of the
|
110 |
+
branch is the current menu item (as indicated by WordPress), provided, of course, that the current menu item actually corresponds to
|
111 |
+
a menu item from the currently selected menu!
|
112 |
+
|
113 |
+
* **Items** *radio & textbox*
|
114 |
+
|
115 |
+
Filters by the menu items that you specifically pick (by menu item id, as a comma-separated list). The simplest way
|
116 |
+
to get your list of ids is to use the "assist", and [un]check the green tick box at the right hand side of each depicted menu item that
|
117 |
+
you want. Alternatively, just type your list of ids into the box.
|
118 |
|
119 |
+
If the id is appended with a '+', eg. '23+', then all the item's descendants will also be included.
|
120 |
+
|
121 |
+
Example : If you only wanted to show, say, 5 of your many available menu items, and those 5 items are not in one handy branch of the menu,
|
122 |
+
then you might want to use this option.
|
123 |
|
124 |
+
Example : If your menu has 6 root branches - "A" thru to "F" - and you were only interested in branches "B" (id of, say, 11) and
|
125 |
+
"E" (id of, say, 19), you could set `Items` to be "11+,19+", which would include "B" with all its descendants, and "E" with all its
|
126 |
+
descendants.
|
127 |
|
128 |
+
***Secondary Filter*** *(not applicable to an `Items` filter)*
|
|
|
|
|
129 |
|
130 |
+
* **Starting at** *select*
|
131 |
|
132 |
+
This is only applicable to a `Branch` filter and it allows you to shift the starting point of your output within the confines
|
133 |
+
of the selected branch. By default it is set to the selected branch item itself, but it can be changed to a relative of the branch item (eg.
|
134 |
+
parent, grandparent, children, etc) or to an absolute, fixed level within the branch containing the selected branch item (eg. the root
|
135 |
+
level item for the branch, or one level below the branch's root item, etc).
|
136 |
|
137 |
+
Example : If you wanted the entire "current" branch then, with `Branch` set to "Current Item", you might set `Starting at` to "1 (root)".
|
138 |
+
Alternatively, if you wanted the children of the current menu item then `Starting at` could be set to "+1 (children)".
|
139 |
|
140 |
+
* **Item, if possible** *radio (default On)*
|
|
|
|
|
|
|
141 |
|
142 |
+
This is the default filter mechanism whereby, if `Starting at` can only result in a single item (ie. it is the branch item itself, or
|
143 |
+
an ancestor thereof) then only that item and its descendants are considered for filtering.
|
144 |
|
145 |
+
* **Level** *radio*
|
|
|
|
|
|
|
|
|
146 |
|
147 |
+
Changes the default filter mechanism such that if `Starting at` results in the selection of the branch item or one of its ancestors,
|
148 |
+
then all siblings of that resultant item are also included in the secondary filtering process.
|
149 |
+
|
150 |
+
Example : If Joe and Fred are siblings (ie. they have a common parent) and Joe is the selected branch item - with `Starting at` set
|
151 |
+
to Joe - then the secondary filter would normally only consider Joe and its descendants. However, if `Level` was enabled instead of
|
152 |
+
`Item`, then both Joe and Fred, *and all their descendants*, would be considered for filtering.
|
153 |
+
|
154 |
+
Note that there is one exception, and that is that if `Starting at` results in a root-level item, then `Allow all Root Items` must
|
155 |
+
be enabled in order to allow the other sibling root items to be added into the filter process.
|
156 |
|
157 |
+
* **Allow all Root Items** *checkbox*
|
|
|
|
|
|
|
158 |
|
159 |
+
In the right conditions - see `Level` above - this allows sibling root items to be considered for secondary filtering.
|
160 |
|
161 |
+
* **For Depth** *select*
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
162 |
|
163 |
+
This the number of levels of the menu structure that will be considered for inclusion in the final output.
|
|
|
|
|
|
|
|
|
164 |
|
165 |
+
* **Relative to Current Item** *checkbox*
|
166 |
|
167 |
+
By default, `For Depth` (above) is relative to the first item found, but this may be overridden to be relative to the
|
168 |
+
current menu item ***if*** `For Depth` is not unlimited **and** the current menu item can found within the selected menu.
|
169 |
+
If the current menu item is not within the selected menu then it falls back to being relative to the first item found.
|
170 |
|
171 |
+
***Inclusions***
|
172 |
|
173 |
+
These allow certain other items to be added to the output from the secondary filters.
|
|
|
|
|
|
|
|
|
|
|
|
|
174 |
|
175 |
+
The first 3 are only applicable to a `Branch` filter. Please note that they only come into effect when the `Branch` filter item is at
|
176 |
+
or below the `Starting at` level, and do not include any items that would break the depth limit set in the Secondary Filter options.
|
177 |
|
178 |
+
* **Branch Ancestors** *select*
|
|
|
|
|
179 |
|
180 |
+
Include any ancestors (parent, grandparent, etc) of the items selected as the `Branch` filter.
|
181 |
+
Ancestors can be set to go up to an absolute level, or to go up a certain number of levels relative to the `Branch` filter item.
|
182 |
|
183 |
+
* **... with Siblings** *select*
|
|
|
|
|
184 |
|
185 |
+
In conjunction with `Branch Ancestors`, also include all siblings of those ancestors.
|
186 |
+
As with Ancestors, their siblings can be set to go up to an absolute level, or to go up a certain number of levels relative
|
187 |
+
to the `Branch` filter item. Note that while it is possibe to set a larger range for siblings than ancestors, the final output
|
188 |
+
is limited by `Branch Ancestors` setting.
|
189 |
+
|
190 |
+
* **Branch Siblings** *checkbox*
|
191 |
|
192 |
+
Include any siblings of the item selected as the `Branch` filter (ie. any items at the same level and within
|
193 |
+
the same branch as the `Branch` item).
|
194 |
|
195 |
+
* **All Root Items** *checkbox*
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
196 |
|
197 |
+
This is not restricted by other previous filter settings, and simply adds all the top level menu items into the mix.
|
198 |
|
199 |
+
***Exclusions***
|
|
|
|
|
200 |
|
201 |
+
* **Item Ids** *textbox*
|
202 |
|
203 |
+
This is a comma-separated list of the ids of menu items that you do *not* want to appear in the final output.
|
204 |
+
The simplest way to get your list of ids is to use the "assist", and [un]check
|
205 |
+
the red cross box at the left hand side of each depicted menu item. Alternatively, just type your list of ids into the box.
|
206 |
|
207 |
+
If the id is appended with a '+', eg. '23+', then all the item's descendants will also be excluded.
|
208 |
|
209 |
+
Example : If you wanted to show the entire "A" branch, with the sole exception of one grandchild of "A", say "ABC", then you could
|
210 |
+
set `Branch` to "A", and `Exclusions` to the id of the "ABC" item.
|
211 |
+
|
212 |
+
Example : If you have a menu with 4 root items - "A", "B", "C" & "D" - and you wanted to show all items, with descendants, for all bar
|
213 |
+
the "C" branch, then you could set `Level` to "1 (root)" and `Exclusions` to, say, "12+", where "12" is the menu item id for "C" and
|
214 |
+
the "+" indicates that all the descendants of "C" should also be excluded.
|
215 |
|
216 |
+
* **By Level** *select*
|
217 |
|
218 |
+
This allows an entire level of items to be excluded, optionally also excluding all levels either above or below it.
|
219 |
|
220 |
+
***Qualifier***
|
|
|
221 |
|
222 |
+
* **Current Item is in** *select*
|
223 |
+
|
224 |
+
This allows you to specify that there only be any output shown when/if the current menu item is one of the menu items selected
|
225 |
+
for output at a particular stage in the filter proccessing.
|
226 |
+
|
227 |
+
* *"Menu"* : the current menu item has to be somewhere within the selected menu.
|
228 |
+
* *"Primary Filter"* : the current menu item has to be within the scope of the selected primary filter. So if you selected, say, a child
|
229 |
+
of "A" as the `Branch` item, then if "A" was the current menu item there would be no output with this qualifier.
|
230 |
+
* *"Secondary Filter"* : the current menu item has to be within the items as restricted by the secondary filters. So if you
|
231 |
+
selected `Branch` as "A", with `Starting at` set to "+1 (children)", then if "A" was the current menu item there would be no output with this qualifier.
|
232 |
+
* *"Inclusions"* : the current menu item has to be in within the items as set by the primary and secondary filters, and the inclusions.
|
233 |
+
* *"Final Output"* : the current menu item has to be in the final output.
|
234 |
|
235 |
+
== Fallbacks Section ==
|
236 |
|
237 |
+
Fallbacks get applied at the Secondary Filter stage, and their eligibility and application are therefore determined and
|
238 |
+
governed by the other Secondary Filter settings.
|
239 |
|
240 |
+
There is one fallback, and it only comes into play (possibly) when a `Branch` filter
|
241 |
+
is set as "Current Item", and the `Starting at` and `For Depth` settings are such that the output should start at or below the current item,
|
242 |
+
and would normally include some of the current item's descendants (eg. `Starting at` "the Branch", `For Depth` "1 level" does *not* invoke
|
243 |
+
the fallback).
|
244 |
+
The fallback allows for the occasion when the current menu item
|
245 |
+
*does not have* any immediate children, and provides the ability to then switch the following options:
|
246 |
|
247 |
+
* **Starting at** *select*
|
248 |
|
249 |
+
Enable the fallback, and change the `Starting at` from "+1 (children)" to either
|
250 |
|
251 |
+
* *"-1 (parent)"* : the immediate parent of the current menu item.
|
252 |
+
* *"the Current Item"* : the current menu item itself.
|
253 |
|
254 |
+
* **...and Include its Siblings** *checkbox*
|
255 |
|
256 |
+
This will add in the siblings of the item selected above.
|
257 |
+
|
258 |
+
Note : This *only* adds the siblings, not the siblings' descendants! However, if the `Level` radio (in Secondary Filter stage above) is
|
259 |
+
set, then all the item's siblings *and their descendants* will automatically be included, and [un]setting this option will have no effect.
|
260 |
+
Also note that if the fallback results in a root-level item being selected as the new `Starting at` item, then the inclusion of siblings
|
261 |
+
outside the current branch depends on the setting of the `Allow all Root Items` checkbox.
|
262 |
|
263 |
+
* **For Depth** *select*
|
264 |
|
265 |
+
Override the current `For Depth` setting. Note that any depth value set here will be relative to the current item, regardless
|
266 |
+
of the current setting of `...Relative to`!
|
267 |
+
|
268 |
+
As an example, this option may be useful in the following scenario : item A has 2 children, B and C; B is the current menu item but has
|
269 |
+
no children, whereas C has loads of children/grandchildren. If you fallback to B's parent - A - with Unlimited depth set, then you will
|
270 |
+
get A, B, C, and *all* C's dependents! You may well want to override depth to limit the output to, say, just A, B and C, by setting this
|
271 |
+
fallback option to "1"? Or maybe A, B, C, and C's immediate children, by setting "2"?
|
272 |
|
273 |
+
== Output Section ==
|
274 |
|
275 |
+
* **Hierarchical** *radio (default On)*
|
|
|
|
|
|
|
276 |
|
277 |
+
Output in the standard nested list format. The alternative is `Flat`.
|
|
|
|
|
278 |
|
279 |
+
* **Flat** *radio*
|
280 |
|
281 |
+
Output in a single list format, ignoring any parent-child relationship other than to maintain the same physical order as would be
|
282 |
+
presented in a `Hierarchical` output (which is the alternative and default).
|
283 |
|
284 |
+
* **Set Title from** *checkboxes*
|
|
|
|
|
|
|
|
|
|
|
285 |
|
286 |
+
These allow you to set the `Title` option from a menu item, and, if brought into play, the `Hide` flag is ignored.
|
287 |
+
Note that the item providing the `Title` only has to be within the selected menu; it does not have to be present in the final output!
|
288 |
+
Note also that priority is the order presented (first found, first used).
|
289 |
|
290 |
+
* **Current Item** : sets `Title` from the current menu item (if current menu item is in the selected menu).
|
291 |
+
* **...or its Root** : sets `Title` from the root menu item of the branch containing the current menu item (if current menu item is in the selected menu).
|
292 |
+
* **Branch** : only applicable to a `Branch` filter, and sets `Title` from the `Branch` item.
|
293 |
+
* **...or its Root** : only applicable to a `Branch` filter, and sets `Title` from the branch's root menu item.
|
294 |
|
295 |
+
* **Change UL to OL** *checkboxes*
|
|
|
|
|
296 |
|
297 |
+
The standard for menus is to use UL (unordered list) elements to display the output. These settings give you the option to
|
298 |
+
swap the ULs out for OLs (ordered lists).
|
299 |
|
300 |
+
* **Top Level** : swap the outermost UL for an OL.
|
301 |
+
* **Sub-Levels** : swap any nested (ie. not the outermost) ULs for an OLs.
|
302 |
|
303 |
+
* **Hide Widget if Empty** *checkbox*
|
304 |
|
305 |
+
If checked, the widget will not output *any* HTML unless it finds at least one menu item that matches the Filter settings.
|
306 |
|
307 |
+
Please note that as of WordPress v3.6, this option becomes superfluous and will **not** be presented (the wp_nav_menu() function
|
308 |
+
has been modified to automatically suppress all HTML output if there are no items to be displayed). The widget will retain
|
309 |
+
the setting used on earlier WP versions (in case reversion from WP v3.6 might be required) but *will not present the option
|
310 |
+
for WP v3.6+*.
|
311 |
|
312 |
+
== Container Section ==
|
313 |
|
314 |
+
* **Element** *textbox (default "div")*
|
|
|
|
|
315 |
|
316 |
+
The menu list is usually wrapped in a "container" element, and this is the tag for that element.
|
317 |
+
You may change it for another tag, or you may clear it out and the container will be completely removed. Please note that
|
318 |
+
WordPress is set by default to only accept "div" or "nav", but that could be changed or extended by any theme or plugin.
|
319 |
|
320 |
+
* **Unique ID** *textbox*
|
321 |
|
322 |
+
This allows you to specify your own id (which should be unique) for the container.
|
323 |
|
324 |
+
* **Class** *textbox*
|
325 |
|
326 |
+
This allows you to add your own class to the container element.
|
327 |
|
328 |
+
== Classes Section ==
|
329 |
|
330 |
+
* **Menu Class** *textbox (default "menu-widget")*
|
331 |
|
332 |
+
This is the class that will be applied to the list element that holds the entire menu.
|
333 |
|
334 |
+
* **Widget Class** *textbox*
|
335 |
|
336 |
+
This allows you to add your own class to the outermost element of the widget, the one that wraps the entire widget output.
|
337 |
|
338 |
+
== Links Section ==
|
339 |
|
340 |
+
* **Before the Link** *textbox*
|
|
|
341 |
|
342 |
+
Text or HTML that will be placed immediately before each menu item's link.
|
|
|
343 |
|
344 |
+
* **After the Link** *textbox*
|
345 |
|
346 |
+
Text or HTML that will be placed immediately after each menu item's link.
|
347 |
|
348 |
+
* **Before the Link Text** *textbox*
|
349 |
|
350 |
+
Text or HTML that will be placed immediately before each menu item's link text.
|
|
|
351 |
|
352 |
+
* **After the Link Text** *textbox*
|
353 |
|
354 |
+
Text or HTML that will be placed immediately after each menu item's link text.
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
355 |
|
356 |
+
== SHORTCODE PARAMETERS ==
|
357 |
|
358 |
+
*NB. Version 2 documentation is [here](http://plugins.svn.wordpress.org/custom-menu-wizard/tags/3.0.0/v210-readme.html#Shortcode-Parameters).*
|
359 |
|
360 |
+
The shortcode is **`[cmwizard]`** (prior to v3, shortcode was *`[custom_menu_wizard]`*, and it is still supported but with a slightly
|
361 |
+
different parameter set).
|
362 |
+
Most of the attributes reflect the options available to the widget, but some have been simplified for easier use in the shortcode format.
|
363 |
+
Please note that the `Hide Widget if Empty` option is not available to the shortcode : it is set to enabled, and if there are no menu items
|
364 |
+
found then there will be no output from the shortcode.
|
365 |
|
366 |
+
The simplest way to build a shortcode is to use a widget : as you set options, the equivalent shortcode is displayed at the base of
|
367 |
+
the widget (v3+) and the base of the "assist". The widget itself need not be assigned to a widget area, so you can construct your
|
368 |
+
shortcode using a widget in the Inactive Widgets area if you have no need for an active one. Please remember that any options you play
|
369 |
+
with while constructing your shortcode ***do not have to be Saved*** to the widget itself! Just copy-paste the shortcode when
|
370 |
+
you are happy with it.
|
371 |
|
372 |
+
= title =
|
373 |
+
*string* : The output's `Title`, which may be overridden by **title_from**. Note that there is no shortcode equivalent of the widget's `Hide` option for the title.
|
374 |
|
375 |
+
= menu =
|
376 |
+
*string or integer* : Accepts a menu name or id. If not provided, the shortcode will attempt to find the first menu (alphabetically)
|
377 |
+
that has menu items attached to it, and use that.
|
378 |
|
379 |
+
= level =
|
380 |
+
*integer* : Sets the `Level` filter to the specified (greater than zero) value. Defaults to 1, and is ignored if either **branch** or **items** is specified.
|
|
|
381 |
|
382 |
+
= branch =
|
383 |
+
*string or integer* : If not empty then `Branch` is set as the primary filter, with the branch item being set from the assigned value:
|
384 |
|
385 |
+
* If numeric, it is taken as being the id of a menu item.
|
386 |
+
* If set to either *"current"* or *"current-item"* then the `Branch` item is set to "Current Item".
|
387 |
+
* If any other string, it is taken to be the title of a menu item (within the selected menu). The widget will look for the first *caseless* title match, so specifying `branch="my menu item"` will match against a menu item with the title "My Menu Item".
|
388 |
|
389 |
+
= items =
|
390 |
+
*string* : Comma-separated list of meu item ids, where an id can optionally be followed by a '+' to include all its descendants (eg. "23+"). Takes priority over **branch**.
|
391 |
|
392 |
+
= start_at =
|
393 |
+
*string* : This is only relevant to a `Branch` filter, and consists of a signed or unsigned integer that indicates either a relative
|
394 |
+
(to the selected branch item) or absolute level to start your output at (ref. the widget's `Starting at` option under *Secondary Filter*,
|
395 |
+
[Filters Section](http://wordpress.org/plugins/custom-menu-wizard/other_notes/#Filters-Section) above).
|
396 |
+
By default the starting level for output is the branch item's level. A relative level is indicated by a signed (ie. preceded by
|
397 |
+
a "+" or "-") integer, eg. `start_at="+1"`, while an absolute level is unsigned, eg. `start_at="1"`. Some examples :
|
398 |
|
399 |
+
* `start_at="+1"` : (relative) start at the branch item's level + 1 (also accepts `start_at="children"`)
|
400 |
+
* `start_at="-1"` : (relative) start at the branch item's level - 1 (also accepts `start_at="parent"`)
|
401 |
+
* `start_at="-2"` : (relative) would be the "grandparent" level
|
402 |
+
* `start_at="1"` : (absolute) start at the root item of the selected branch (also accepts `start_at="root"`)
|
403 |
+
* `start_at="2"` : (absolute) start at one level below root (still within the selected branch)
|
404 |
|
405 |
+
= start_mode =
|
406 |
+
*string* : This has only one accepted value - "level" - and is only applicable for a `Branch` filter whose **start_at** setting returns
|
407 |
+
in an item is at or above the selected branch item (relatively or absolutely).
|
408 |
+
Setting `start_mode="level"` forces the widget to use not only the resultant starting item
|
409 |
+
and its relevant descendants, but also all that item's siblings *and their descendants*
|
410 |
+
(ref. the widget's `Level` radio option under *Secondary Filter*,
|
411 |
+
[Filters Section](http://wordpress.org/plugins/custom-menu-wizard/other_notes/#Filters-Section) above).
|
412 |
|
413 |
+
= allow_all_root =
|
414 |
+
*switch, off by default, 1 to enable* : See widget's `Allow all Root Items` option, under *Secondary Filter*,
|
415 |
+
[Filters Section](http://wordpress.org/plugins/custom-menu-wizard/other_notes/#Filters-Section) above.
|
416 |
|
417 |
+
= depth =
|
418 |
+
*integer, default 0 (unlimited)* : See widget's `For Depth` option, under *Secondary Filter*,
|
419 |
+
[Filters Section](http://wordpress.org/plugins/custom-menu-wizard/other_notes/#Filters-Section) above.
|
420 |
+
|
421 |
+
= depth_rel_current =
|
422 |
+
*switch, off by default, 1 to enable* : See widget's `Relative to Current Item` option, under *Secondary Filter*,
|
423 |
+
[Filters Section](http://wordpress.org/plugins/custom-menu-wizard/other_notes/#Filters-Section) above.
|
424 |
|
425 |
+
= include_root =
|
426 |
+
*switch, off by default, 1 to enable* : Sets the widget's Include `All Root Items` option. See widget's `All Root Items`
|
427 |
+
option, under *Inclusions*, [Filters Section](http://wordpress.org/plugins/custom-menu-wizard/other_notes/#Filters-Section) above.
|
428 |
|
429 |
+
= ancestors =
|
430 |
+
*integer, default 0 (off)* : Sets an absolute level (positive integer), or a relative number of levels (negative integer), for which
|
431 |
+
the ancestors of the `Branch` filter item should be included. See widget's `Branch Ancestors` option, under *Inclusions*,
|
432 |
+
[Filters Section](http://wordpress.org/plugins/custom-menu-wizard/other_notes/#Filters-Section) above. (only relevant to a `Branch` filter)
|
433 |
|
434 |
+
= ancestor_siblings =
|
435 |
+
*integer, default 0 (off)* : Sets an absolute level (positive integer), or a relative number of levels (negative integer), for which
|
436 |
+
the siblings of ancestors of the `Branch` filter item should be included. See widget's `... with Siblings` option, under *Inclusions*,
|
437 |
+
[Filters Section](http://wordpress.org/plugins/custom-menu-wizard/other_notes/#Filters-Section) above. (only relevant to a `Branch` filter)
|
438 |
|
439 |
+
= siblings =
|
440 |
+
*switch, off by default, 1 to enable* : See widget's `Branch Siblings` option, under *Inclusions*,
|
441 |
+
[Filters Section](http://wordpress.org/plugins/custom-menu-wizard/other_notes/#Filters-Section) above. (only relevant to a `Branch` filter)
|
442 |
|
443 |
+
= exclude =
|
444 |
+
*string* : Comma-separated list of meu item ids, where an id can optionally be followed by a '+' to include all its descendants (eg. "23+").
|
445 |
|
446 |
+
= exclude_level =
|
447 |
+
*string* : A level (1, 2, 3, etc), optionally followed by a "+" or "-" to include all subsequent (lower) or prior (higher)
|
448 |
+
levels respectively. For example, "2" will exclude all items at level 2, whereas "2-" would exclude all level 1 **and** level 2 items,
|
449 |
+
and "2+" would exlude all items at level 2 or greater.
|
450 |
+
|
451 |
+
= contains_current =
|
452 |
+
*string* : Accepted values : "menu", "primary", "secondary", "inclusions", or "output". See widget's *Qualifier* options,
|
453 |
+
under [Filters Section](http://wordpress.org/plugins/custom-menu-wizard/other_notes/#Filters-Section) above,
|
454 |
+
for an explanation of the respective settings.
|
455 |
|
456 |
+
= fallback =
|
457 |
+
*string* : There are 2 main options for fallback (ref. [Fallbacks Section](http://wordpress.org/plugins/custom-menu-wizard/other_notes/#Fallbacks-Section) above)...
|
458 |
|
459 |
+
* *"parent"* : Sets the widget's `Starting at` Fallback option to "-1 (parent)"
|
460 |
+
* *"current"* : Sets the widget's `Starting at` Fallback option to "the Current Item"
|
461 |
|
462 |
+
Either of these 2 values can be further qualified by appending a comma and a digit, eg. `fallback="current,1"` or `fallback="parent,2"`, which
|
463 |
+
will also set the widget's `For Depth` fallback option to the value of the digit(s).
|
464 |
|
465 |
+
Optionally, "+siblings" can also be used (comma-separated, with or without a depth digit) to indicate that siblings of the "parent" or
|
466 |
+
"current" fallback item should also be included. The order of the comma-separated values is not important, so "current,+siblings,1" is the
|
467 |
+
same as "current,1,+siblings", and "2,parent" is the same as "parent,2", etc.
|
468 |
|
469 |
+
= flat_output =
|
470 |
+
*switch, off by default, 1 to enable* : See widget's `Flat` option, under [Output Section](http://wordpress.org/plugins/custom-menu-wizard/other_notes/#Output-Section) above.
|
471 |
|
472 |
+
= title_from =
|
473 |
+
*string* : Supply one or more (by separating them with a comma, eg. `title_from="branch,current"`) of the following (ref. the widget's `Set Title from` options, under [Output Section](http://wordpress.org/plugins/custom-menu-wizard/other_notes/#Output-Section) above)...
|
474 |
|
475 |
+
* *"current"* : enables the widget's *Current Item* `Set Title from` option
|
476 |
+
* *"current-root"* : enables the widget's *...or its Root* option that relates to the `Current Item` `Set Title from` option
|
477 |
+
* *"branch"* : enables the widget's *Branch* `Set Title from` option
|
478 |
+
* *"branch-root"* : enables the widget's *...or its Root* option that relates to the `Branch` `Set Title from` option
|
479 |
|
480 |
+
= ol_root =
|
481 |
+
*switch, off by default, 1 to enable* : See widget's `Top Level` option, under *Change UL to OL* in the [Output Section](http://wordpress.org/plugins/custom-menu-wizard/other_notes/#Output-Section) above.
|
482 |
|
483 |
+
= ol_sub =
|
484 |
+
*switch, off by default, 1 to enable* : See widget's `Sub-Levels` option, under *Change UL to OL* in the [Output Section](http://wordpress.org/plugins/custom-menu-wizard/other_notes/#Output-Section) above.
|
485 |
|
486 |
+
= container =
|
487 |
+
*string* : See widget's `Element` option, under [Container Section](http://wordpress.org/plugins/custom-menu-wizard/other_notes/#Container-Section) above.
|
488 |
|
489 |
+
= container_id =
|
490 |
+
*string* : See widget's `Unique ID` option, under [Container Section](http://wordpress.org/plugins/custom-menu-wizard/other_notes/#Container-Section) above.
|
491 |
|
492 |
+
= container_class =
|
493 |
+
*string* : See widget's `Class` option, under [Container Section](http://wordpress.org/plugins/custom-menu-wizard/other_notes/#Container-Section) above.
|
494 |
|
495 |
+
= menu_class =
|
496 |
+
*string* : See widget's `Menu Class` option, under [Classes Section](http://wordpress.org/plugins/custom-menu-wizard/other_notes/#Classes-Section) above.
|
|
|
497 |
|
498 |
+
= widget_class =
|
499 |
+
*string* : See widget's `Widget Class` option, under [Classes Section](http://wordpress.org/plugins/custom-menu-wizard/other_notes/#Classes-Section) above.
|
500 |
|
501 |
+
= wrap_link =
|
502 |
+
*string* : This is an optional tag name (eg. "div", "p", "span") that, if provided, will be made into HTML start/end tags
|
503 |
+
and sent through to the widget as its `Before the Link` and `After the Link` options (ref. [Links Section](http://wordpress.org/plugins/custom-menu-wizard/other_notes/#Links-Section)).
|
504 |
+
Please note that the shortcode usage - a simple tag name - is much more restrictive than the widget's options, which allow HTML.
|
505 |
|
506 |
+
= wrap_link_text =
|
507 |
+
*string* : This is an optional tag name (eg. "span", "em", "strong") that, if provided, will be made into HTML start/end tags
|
508 |
+
and sent through to the widget as its `Before the Link Text` and `After the Link Text` options (ref. [Links Section](http://wordpress.org/plugins/custom-menu-wizard/other_notes/#Links-Section)).
|
509 |
+
Please note that the shortcode usage - a simple tag name - is much more restrictive than the widget's options, which allow HTML.
|
510 |
+
|
511 |
+
= title_tag =
|
512 |
+
*string* : An optional tag name (eg. "h1", "h3", etc) to replace the default "h2" used to enclose the widget title.
|
513 |
+
Please note that this option has no equivalent in the widget options, because it *only* applies when a widget is instantiated via a shortcode.
|
514 |
+
|
515 |
+
= findme =
|
516 |
+
*switch, off by default, 1 to enable* : This is a utility intended for editors only, and output is restricted to those with edit_pages capability.
|
517 |
+
If enabled it will return a list of posts that contain a CMW shortcode. If `findme` is set, the only other option that is taken any
|
518 |
+
notice of is `title`, which will be output (if supplied) as an H3 in front of the list. The information provided by this utility is also available
|
519 |
+
from any widget's "assist".
|
520 |
+
|
521 |
+
Example : `[cmwizard findme=1 title="Posts containing a CMW shortcode..."]`
|
522 |
+
|
523 |
+
== Shortcode Examples ==
|
524 |
+
|
525 |
+
* Show the entire "main" menu
|
526 |
+
|
527 |
+
`
|
528 |
+
[cmwizard menu=main]
|
529 |
+
`
|
530 |
|
531 |
+
* Show the children of the current menu item within the "main" menu, for unlimited depth, setting the widget title from the current menu item
|
532 |
|
533 |
`
|
534 |
+
[cmwizard menu=main branch=current start_at=children title_from=current]
|
535 |
`
|
536 |
|
537 |
+
* From the "animals" menu, show all the items *immediately* below "Small Dogs", plus "Small Dogs" and its sibling items, as ordered lists
|
538 |
|
539 |
`
|
540 |
+
[cmwizard menu="animals" branch="small dogs" depth=2 include="siblings" ol_root=1 ol_sub=1]
|
541 |
`
|
542 |
|
543 |
+
* From the "animals" menu, show the entire "Small Animals" branch, with the sole exception of the "Small Animals" item itself, whenever "Small Animals" or one of its descendants is the current menu item
|
544 |
|
545 |
`
|
546 |
+
[cmwizard menu="animals" branch="small animals" start_at=children contains_current=primary]
|
547 |
`
|
548 |
|
549 |
== Installation ==
|
555 |
1. Activate the plugin through the 'Plugins' menu in your WP Admin
|
556 |
|
557 |
The widget will now be available in the 'Widgets' admin page.
|
558 |
+
As long as you already have at least one Custom Menu defined, you can add the new widget to a sidebar and configure it however you want.
|
559 |
Alternatively, you can use the shortcode in your content.
|
560 |
|
561 |
== Frequently Asked Questions ==
|
562 |
+
If you have a question or problem that is not covered here, please use the [integrated Support forum](http://wordpress.org/support/plugin/custom-menu-wizard).
|
563 |
|
564 |
+
= Are there any known problems/restrictions? =
|
|
|
|
|
|
|
565 |
Yep, 'fraid so :
|
566 |
|
567 |
+
1. The widget will only recognise one "current" item (as of v2.0.2, that's the first one encountered; prior to that it was the last one found). It is perfectly possible to have more than one menu item marked as "current", but if CMW has been configured to filter on anything related to a "current menu item" it can only choose one. The simplest example of multiple "current" items is if you add the same page to a menu more than once, but any other plugin that adds and/or manipulates menu items could potentially cause problems for CMW.
|
568 |
+
2. The widget's "assist" uses jQuery UI's Dialog, which unfortunately (in versions 1.10.3/4) has a *really* annoying bug in its handling of a draggable (ie. when you drag the Dialog's title bar to reposition it on the page) when the page has been scrolled. It is due to be fixed in UI v1.11.0, but meantime I have defaulted the Dialog to fixed position, with an option to toggle back to absolute : it's not perfect but it's the best compromise I can come up with to maintain some sort of useability.
|
|
|
569 |
|
570 |
= Why isn't it working? Why is there no output? =
|
|
|
571 |
I don't know. With all due respect (and a certain amount of confidence in the widget) I would venture to suggest that it is probably due to
|
572 |
the option settings on the widget/shortcode. The quickest way to resolve any such issues is to use the widget's interactive "assist", and
|
573 |
ensure that you set the current menu item correctly for the page(s) that you are having problems with. However, I am well aware that I not
|
574 |
+
infallible (and it's been proven a fair few times!), so if you still have problems then please let me have as much information as possible
|
575 |
+
(the shortcode for your settings is a good start?) and I will endeavour to help. Please note that simply reporting "It doesn't work" is not
|
576 |
+
the most useful of feedbacks, and is unlikely to get a response other than, possibly, a request for more details.
|
577 |
|
578 |
= How do I use the "assist"? =
|
|
|
579 |
The widget's interactive "assist" is specific to each widget instance. It is a javascript-driven *emulator* that uses the widget instance's
|
580 |
option settings - including the menu selected - to build a pictorial representation of the menu and show you, in blue, which menu items will
|
581 |
be output according to the current option settings. It also shows a very basic output list of those menu items, although it will not apply
|
585 |
"current menu item" and the widget options are immediately reflected by the "assist" (text fields in the widget options simply need to lose
|
586 |
focus).
|
587 |
|
588 |
+
The red cross to the left of each menu item toggles the Exclusions setting for the item and/or its descendants. The button has 3 settings :
|
589 |
+
|
590 |
+
* Off (dimmed)
|
591 |
+
* Just this item (white on red)
|
592 |
+
* This item *plus* all its descendants (white on red, with a small yellow plus sign)
|
593 |
|
594 |
+
Just click through the toggle states. When the Primary Filter is set to "Items", the green tick buttons to the right of each menu item
|
595 |
+
work in the same way.
|
596 |
|
597 |
+
Once you are happy with the results, having tested all possible settings of "current menu item" (if it applies), then simply Save the widget.
|
598 |
+
Alternatively, copy-paste the shortcode text - at the base of either the "assist" or the widget form - straight into your post (you do **not** need to Save the widget!).
|
599 |
+
The widget does not have to Saved to *test* any of the options.
|
600 |
|
601 |
+
= Is there an easy way to construct the shortcode? =
|
602 |
+
Yes, use a widget form. The shortcode for all the selected/specified options is show at the base of the widget (v3+) and the base of the
|
603 |
+
"assist". The widget does not have to be placed within a widget area, it can also be used from the Inactive Widgets area. And
|
604 |
+
you do **not** need to Save the widget just to get a shortcode!
|
605 |
|
606 |
+
= How do I get the menu item ids for the 'Items' option? =
|
607 |
+
Use the widget's interactive "assist" (see above). Within the representative menu structure, each menu item's id is set in its title
|
608 |
attribute, so should be seen when the cursor is moved over the item. A simpler way is to check the `Items` option : the "assist" will
|
609 |
+
then show a green tick "checkbox" to the right of each menu item and you simply [un]check the items as required. Each selection will be reflected back into the
|
610 |
+
widget's `Items` settings, and also in the shortcode texts.
|
611 |
|
612 |
+
The more painstaking way is to go to Appearance, Menus and select the relevant menu; hover over the *edit*, *Remove*, or *Cancel* link for an item and look in
|
613 |
the URL (the link's href) for `menu-item=NNN` ... the NNN is the menu item id.
|
614 |
|
615 |
+
= How do I get the menu item ids for the 'Exclude Ids' option? =
|
616 |
+
The "assist" shows a red cross "checkbox" to the left of each menu item, and [un]checking the items will refelect back into the options and
|
617 |
+
shortcode texts. Otherwise, it's the same principle as outlined above for `Items` ids.
|
618 |
|
619 |
+
= What's the difference between including Branch Siblings (or Branch Ancestors + Siblings), and switching to 'Level' instead of 'Item' in the Secondary Filter section? =
|
620 |
+
If you elect to include Branch [Ancestor] Siblings, you will *only* get the siblings, **not** their descendants (assuming they have any).
|
621 |
+
On the other hand, if you make `Starting at` use 'Level' instead of 'Item' then siblings *and their descendants* will be added to the filter.
|
622 |
|
623 |
+
For example, let's say that Bravo and Charlie are sibling items immediately below Alpha, and that Bravo is the selected Branch Item,
|
624 |
+
with `Starting at` set to "the Branch" (ie. Bravo). If you switch from "Item" to "Level" then both Bravo, Charlie, *and all their descendants*,
|
625 |
+
will become eligible for filtering. If you left "Item" enabled, and switched on the inclusion of Branch Siblings, then Bravo and Charlie
|
626 |
+
would both still be eligible, but only *Bravo's descendants* would be; not Charlie's!
|
627 |
+
|
628 |
+
= Where is the styling of the output coming from, and how do I change it? =
|
629 |
+
The widget does not supply any ouput styling (at all!). This is because I have absolutely no idea where you are going to place either the
|
630 |
+
widget (sidebar, footer, header, ad-hoc, etc?) or the shortcode (page content, post content, widget content, custom field, etc?) and everyone's
|
631 |
+
requirements for styling are likely to be different ... possibly even within the same web page's output. So all styling is down to your theme,
|
632 |
+
and if you wish to modify it you will need to add to your theme's stylesheet.
|
633 |
|
634 |
+
The safest way to do this is via a child theme, so that any changes you make will not be lost if/when the main theme gets updated. The best
|
635 |
+
way to test your changes is by utilising the developer capabilities that are available in most modern browsers (personally, I could not
|
636 |
+
do without Firefox and the Firebug extension!) and dynamically applying/modifying styles, possibly utilising the custom classes that the
|
637 |
+
widget applies to its output, or the Container options for a user-defined id or class.
|
638 |
|
639 |
+
= How can I find all my posts/pages that have a CMW shortcode so that I can upgrade them? =
|
640 |
+
There is a button on the widget's "assist" - `[...]` - that will provide a list of posts/pages whose content, or meta data (custom fields),
|
641 |
+
contains any CMW shortcode. Each entry is a link that opens the item in a new tab/window. The link's title gives a bit more information :
|
642 |
+
post type, id, whether the shortcode(s) are in content and/or meta data, and the shortcode(s) concerned.
|
643 |
+
This utility does not check things like text widgets, plugin-specific tables, theme-provided textareas, etc.
|
644 |
|
645 |
+
There is also an extension to the shortcode - `[cmwizard findme=1]` - that will output the same information, should you not be able to use
|
646 |
+
the "assist" (for some unknown reason). You may optionally provide a title attribute; any other attributes are ignored.
|
647 |
+
Note that output from this shortcode extension is restricted to users with edit_pages capability.
|
648 |
|
649 |
+
|
650 |
+
== Screenshots ==
|
651 |
+
1. Widget (all sections collapsed)
|
652 |
+
2. Filters Section
|
653 |
+
3. Fallbacks Section
|
654 |
+
4. Output Section
|
655 |
+
5. Container Section
|
656 |
+
6. Classes Section
|
657 |
+
7. Links Section
|
658 |
+
8. Widget's "assist"
|
659 |
|
660 |
== Changelog ==
|
661 |
|
662 |
+
= 3.0.0 =
|
663 |
+
* **! Rewrite, and Change of Approach !** The widget has had a major rewrite! The `Children of` filter has been replaced with a `Branch` filter, with a subsequent shift in focus for the secondary filter parameters, from the children's level (0, 1 or more items) up to the branch level (a single item!). This should provide a more intuitive interface, and is definitely easier to code for. **However**, it only affects *new instances* of the widget; v2 instances are still ***fully supported***.
|
664 |
+
|
665 |
+
Please also note that the shortcode tag for v3 has changed to **`[cmwizard]`**, with a revised set of parameters. The old shortcode tag is still supported, but only with the v2 parameter set, and only providing v2 functionality, ie. it is the shortcode tag that determines which widget version to use, and the appropriate parameter set for that version.
|
666 |
+
|
667 |
+
There is no automatic upgrade of widget settings from v2 to v3! I suggest bringing up the "assist" for the existing v2 widget, running it side-by-side with the "assist" of a new instance of the widget, and using them to the compare the desired outputs. I would also strongly recommend that you put your old widgets into the inactive area until you are completely happy with their new replacements. If you are upgrading from version 2, and you would like a bit more information, [this article](http://www.wizzud.com/2014/06/16/custom-menu-wizard-wordpress-plugin-version-3/) might help.
|
668 |
+
* change : **the minmum requirement for WordPress is v3.6**
|
669 |
+
* addition : more options for requiring that the "current" menu item be present at some point in the filter process
|
670 |
+
* addition : Branch filter levels can be either relative (to the selected Branch item) or absolute (within the menu structure)
|
671 |
+
* addition : menu items can now be excluded from the final output, either explicitly by id (optionally including descendants), or by level
|
672 |
+
* addition : the ids of Items can be set to include all descendants
|
673 |
+
* addition : the inclusion of branch ancestors, and optionally their siblings, can be set by absolute level or relative number of levels
|
674 |
+
* addition : the widget title can now be automatically set from the root level item of the Branch item or current menu item
|
675 |
+
* addition : the shortcode for a widget's current settings is now also displayed at the base of the widget (as well as at the base of the "assist")
|
676 |
+
* addition : "title_tag" has been added to the shortcode options, enabling the default H2 to be changed without having to resort to coding a filter
|
677 |
+
* addition : as an alternative to using the "assist", "findme" has been addded to the shortcode options to aid editors with the location of posts containing a CMW shortcode ([cmwizard findme=1])
|
678 |
+
* This release includes an upgrade to v2.1.0 for all existing version 2 widgets/shortcodes - please read the v2.1.0 changes below.
|
679 |
+
|
680 |
+
= 2.1.0 (incorporated into v3.0.0 release) =
|
681 |
+
* change : **the minmum requirement for WordPress is v3.6**
|
682 |
+
* bugfix : handle duplicate menu item ids which were causing elements to be ignored
|
683 |
+
* bugfix : fix IE8 levels indentation in the "assist"
|
684 |
+
* bugfix : the "assist" is now "fixed" position (toggle-able back to absolute), mainly to get around a bug in jQuery UI draggable
|
685 |
+
* remove : take out the automatic selection of shortcode text (inconsistent cross-browser, so just triple click as usual; paste-as-text if possible!)
|
686 |
+
* addition : in the "assist", provide collapsible options for those larger menus
|
687 |
+
* addition : added utility to the "assist" enabling posts containing a CMW shortcode to be located
|
688 |
+
* change : in the "assist", swap the menu Items checkboxes for clickable Ticks
|
689 |
+
* change : in the "assist", tweak styling and make more responsive to re-sizing
|
690 |
+
* change : made compatible with Widget Customizer
|
691 |
+
* Note : there is no separate release available for this version!
|
692 |
|
693 |
+
= 2.0.6 =
|
694 |
* change : modified determination of current item to cope better with multiple occurences (still first-found, but within prioritised groups)
|
|
|
695 |
* change : display of the upgrade notice in the plugins list has been replaced with a simple request to read the changelog before upgrading
|
696 |
|
697 |
= 2.0.5 =
|
|
|
698 |
* bugfix : prevent PHP warnings of Undefined index/offset
|
699 |
|
700 |
= 2.0.4 =
|
|
|
701 |
* bugfix : clearing the container field failed to remove the container from the output
|
|
|
702 |
* addition : in the "assist", added automatic selection of the shortcode text when it is clicked
|
|
|
703 |
* addition : remove WordPress's menu-item-has-children class (introduced in v3.7) when the filtered item no longer has children
|
|
|
704 |
* change : tweaked styles and javascript in admin for WordPress v3.8
|
705 |
|
706 |
= 2.0.3 =
|
|
|
707 |
* bugfix : missing global when enqueuing scripts and styles for admin
|
708 |
|
709 |
= 2.0.2 =
|
|
|
710 |
* bugfix : the Include Ancestors option was not automatically including the Parent
|
|
|
711 |
* bugfix : the "assist" was incorrectly calculating Depth Relative to Current Item when the current menu item was outside the scope of the Filtered items
|
|
|
712 |
* behaviour change : only recognise the first "current" item found (used to allow subsequent "current" items to override any already encountered)
|
713 |
|
714 |
= 2.0.1 =
|
|
|
715 |
* bugfix : an incorrect test for a specific-items filter prevented show-all producing any output
|
716 |
|
717 |
= 2.0.0 =
|
|
|
718 |
* **! Possible Breaker !** The calculation of `Start Level` has been made consistent across the `Show all` and `Children of` filters : if you previously had a setup where you were filtering for the children of an item at level 2, with start level set to 4, there would have been no output because the immediate children (at level 3) were outside the start level. Now, there *will* be output, starting with the grand-children (at level 4).
|
|
|
719 |
* **! Possible Breaker !** There is now deemed to be an artificial "root" item above the level 1 items, which mean that a `Children of` filter set to "Current Parent Item" or "Current Root Item" will no longer fail for a top-level "current menu item". If you have the "no ancestor" fallback set then this change will have no impact (but you may now want to consider turning the fallback off?); if you *don't* currently use the "no ancestor" fallback, then where there was previously no output there will now be some!
|
|
|
720 |
* added new option : Items, a comma- or space-delimited list of menu item ids, as an alternative Filter
|
|
|
721 |
* added new option : Depth Relative to Current Item to the Filter section (depth_rel_current=1 in the shortcode)
|
|
|
722 |
* added new option : Must Contain Current Item to the Output section (contains_current=1 in the shortcode)
|
|
|
723 |
* changed the widget's "demo" facility to "assist" and brought it into WordPress admin, with full interactivity with the widget
|
|
|
724 |
* refactored code
|
725 |
|
726 |
= 1.2.2 =
|
|
|
727 |
* bugfix : fallback for Current Item with no children was failing because the parent's children weren't being picked out correctly
|
728 |
|
729 |
= 1.2.1 =
|
|
|
730 |
* added some extra custom classes, when applicable : cmw-fellback-to-current & cmw-fellback-to-parent (on outer UL/OL) and cmw-the-included-parent, cmw-an-included-parent-sibling & cmw-an-included-ancestor (on relevant LIs)
|
|
|
731 |
* corrected 'show all from start level 1' processing so that custom classes get applied and 'Title from "Current" Item' works (regardless of filter settings)
|
|
|
732 |
* changed the defaults for new widgets such that only the Filter section is open by default; all the others are collapsed
|
|
|
733 |
* in demo.html, added output of the shortcode applicable to the selections made
|
|
|
734 |
* in demo.html, added a link to the documentation page
|
|
|
735 |
* corrected 2 of the shortcode examples in the readme.txt, and made emulator (demo) available from the readme
|
736 |
|
737 |
= 1.2.0 =
|
|
|
738 |
* added custom_menu_wizard shortcode, to run the widget from within content
|
|
|
739 |
* moved the 'no ancestor' fallback into new Fallback collapsible section, and added a fallback for Current Item with no children
|
|
|
740 |
* added an option allowing setting of title from current menu item's title
|
|
|
741 |
* fixed a bug with optgroups/options made available for the 'Children of' selector after the widget has been saved (also affected disabled fields and styling)
|
|
|
742 |
* don't include menus with no items
|
|
|
743 |
* updated demo.html
|
744 |
|
745 |
= 1.1.0 =
|
|
|
746 |
* added 'Current Root Item' and 'Current Parent Item' to the `Children of` filter
|
|
|
747 |
* added `Fallback to Current Item` option, with subsidiary options for overriding a couple of Output options, as a means to enable Current Root & Current Parent to match a Current Item at root level
|
|
|
748 |
* added an Output option to include both the parent item **and** the parent's siblings (for a successful `Children of` filter)
|
|
|
749 |
* added max-width style (100%) to the `Children of` SELECT in the widget options
|
|
|
750 |
* added widget version to the admin js enqueuer
|
|
|
751 |
* ignore/disable Hide Empty option for WP >= v3.6 (wp_nav_menu() now does it automatically)
|
|
|
752 |
* included a stand-alone helper/demo html page
|
|
|
753 |
* rebuilt the `Children of` SELECT in the widget options to cope with IE's lack of OPTGROUP/OPTION styling
|
|
|
754 |
* moved the setting of 'disabled' attributes on INPUTs/SELECTs from PHP into javascript
|
755 |
|
756 |
= 1.0.0 =
|
757 |
+
* Initial release
|
|
|
758 |
|
759 |
== Upgrade Notice ==
|
760 |
|
761 |
+
= 3.0.0 =
|
762 |
+
**Rewrite, and change of approach** : __! Important !__ : existing (version 2) widgets and shortcodes *__are fully supported__*. Please [read the Changelog](http://wordpress.org/plugins/custom-menu-wizard/changelog/) *before* upgrading!
|
763 |
+
Version 3 swaps the *Children-Of* filter for a *Branch* filter, with secondary filters to then refine the branch items. It has better filter capabilities - relative and absolute start level, presence of a current menu item at different stages - and adds exclusion of items by id and/or level. A new shortcode - *[cmwizard]* - has been added to support the v3 functionality.
|
764 |
+
Changes that also apply to version 2 widgets include : **Minimum requirement for WordPress now v3.6!**; handling of duplicate menu ids, improved compatibility with Widget Customizer (required due to its incorporation into WordPress v3.9 core), and tweaks to the "assist".
|
765 |
|
766 |
+
= 2.0.6 =
|
767 |
Determination of the current menu item has been slightly modified to cope a bit better with occasions where multiple items have been set as "current".
|
768 |
The display of the upgrade notice in the plugins list has been replaced with a simple request to read the changelog before upgrading.
|
769 |
|
770 |
= 2.0.5 =
|
|
|
771 |
Fixed a bug to prevent PHP warnings of Undefined index/offset being output.
|
772 |
|
773 |
= 2.0.4 =
|
|
|
774 |
Fixed a bug that prevented the container field being removed, and added removal of the menu-item-has-children class when the filtered item no longer has children.
|
775 |
The admin widget styling and javascript have been tweaked to accommodate WordPress 3.8.
|
776 |
|
777 |
= 2.0.3 =
|
|
|
778 |
Fixed a minor bug with a missing global when enqueuing script and style for the admin.
|
779 |
|
780 |
= 2.0.2 =
|
|
|
781 |
Fixed a bug with the Include Ancestors option, where it was not automatically including the Parent.
|
782 |
Fixed a bug in the "assist", where it was incorrectly calculating Depth Relative to Current Item when the current menu item was outside the scope of the Filtered items.
|
783 |
Changed determination of the "current" item such that only the first one encountered is recognised, rather than allowing subsequent "current" items to override previous ones.
|
784 |
|
785 |
= 2.0.1 =
|
|
|
786 |
Fixed a bug whereby a test for a specific-items filter prevented show-all from producing any output.
|
787 |
|
788 |
= 2.0.0 =
|
789 |
+
**! Possible Breaker! !** My apologies if this affects you, but there are 2 possible scenarios where settings that previously resulted in no output *might* now produce output :
|
|
|
790 |
+ if you have set a `Children of` filter, **and** you have changed the `Start Level` to a level greater than 2, or
|
791 |
+ if you have set the `Children of` filter to Current Parent/Root Item, and you have **not** set the "no ancestor" fallback.
|
792 |
*__If you think you may be impacted, please check the [Changelog](http://wordpress.org/plugins/custom-menu-wizard/changelog/) for a fuller explanation of what has changed.__*
|
798 |
Rebuilt the "demo" facility as an "assist" wizard for the widget It is now fully interactive with the widget instance, and generates the entire shortcode according to the widget instance settings.
|
799 |
|
800 |
= 1.2.2 =
|
|
|
801 |
Bugfix : The fallback for Current Item with no children was failing because the parent's children weren't being picked out correctly
|
802 |
|
803 |
= 1.2.1 =
|
|
|
804 |
Added a few extra custom classes, and changed the defaults for new widgets such that only the Filter section is open by default.
|
805 |
Fixed Show All processing so that custom classes always get applied, and 'Title from "Current" Item' works regardless of filter settings.
|
806 |
Fixed a couple of the shortcode examples in the readme.txt, and added display of the applicable shortcode settings to the demo.html.
|
807 |
|
808 |
= 1.2.0 =
|
|
|
809 |
Added custom_menu_wizard shortcode, to run the widget from within content.
|
810 |
Added a new fallback for Current Item having no children, and moved all fallbacks into a collapsible Fallbacks section.
|
811 |
Fixed a bug with optgroups/options made available for the 'Children of' selector after the widget has been saved (also affected disabled fields and styling).
|
@@ -0,0 +1,626 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
<!DOCTYPE html>
|
2 |
+
<html>
|
3 |
+
<head>
|
4 |
+
<title>Custom Menu Wizard WP Plugin, v2.1.0 Readme</title>
|
5 |
+
<style type="text/css">
|
6 |
+
body {font-family: "Lucida Grande", Verdana, sans-serif;}
|
7 |
+
code {font-size: 1.3em;}
|
8 |
+
div.success {background: #0f0; width: 50%; margin: 0 auto; padding: 1px 10px; border: 3px solid #0d0;}
|
9 |
+
div.error {padding: 1px 10px; margin: 30px auto;}
|
10 |
+
div.error p {font-weight: bold;}
|
11 |
+
div.error ul {list-style: square;}
|
12 |
+
div.fatal {background: #faa; border: 3px solid #d00;}
|
13 |
+
div.warning {background: #f60; border: 3px solid #e40;}
|
14 |
+
div.note {background: #5cf; border: 3px solid #3ad;}
|
15 |
+
</style>
|
16 |
+
</head>
|
17 |
+
<body>
|
18 |
+
<hr />
|
19 |
+
|
20 |
+
<h1>Custom Menu Wizard Widget</h1>
|
21 |
+
|
22 |
+
<p><em>Show branches or levels of your menu in a widget, or in content using a shortcode, with full customisation.</em></p>
|
23 |
+
|
24 |
+
<hr />
|
25 |
+
|
26 |
+
<p>
|
27 |
+
<strong>Contributors:</strong> wizzud<br />
|
28 |
+
<strong>Donate link:</strong> <br />
|
29 |
+
<strong>Tags:</strong> menu, widget, widgets, navigation, nav, custom menus, custom menu, partial menu, menu level, menu branch<br />
|
30 |
+
<strong>Requires at least:</strong> 3.6<br />
|
31 |
+
<strong>Tested up to:</strong> 3.9<br />
|
32 |
+
<strong>Stable tag:</strong> 2.1.0<br/>
|
33 |
+
<strong>License:</strong> GPLv2 or Later </p>
|
34 |
+
|
35 |
+
<hr />
|
36 |
+
|
37 |
+
<h3>Description</h3>
|
38 |
+
<p>This plugin is a boosted version of the WordPress "Custom Menu" widget.
|
39 |
+
It provides full control over most of the parameters available when calling WP's <a href="http://codex.wordpress.org/Function_Reference/wp_nav_menu">wp_nav_menu()</a> 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. And there is now (v1.2.0) a shortcode that enables you to include the widget's output in your content.</p>
|
40 |
+
|
41 |
+
<p>Features include:</p>
|
42 |
+
|
43 |
+
<ul>
|
44 |
+
<li>Display the entire menu, just a branch of it, or even just a specific level of it</li>
|
45 |
+
<li>Select a branch based on a specific menu item, or the "current" item (currently displayed page)</li>
|
46 |
+
<li>Specify a level to start at, and the number of levels to output</li>
|
47 |
+
<li>Select hierarchicial or flat output, both options still abiding by the specified number of levels to output</li>
|
48 |
+
<li>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</li>
|
49 |
+
<li>Optionally disable widget output completely if there are no matching menu items found (WordPress < v3.6)</li>
|
50 |
+
<li>Include a sub-branch's parent and/or ancestor item(s) in the output, over and above any start level setting</li>
|
51 |
+
<li>Automatically add cmw-level-N and cmw-has-submenu classes to output menu items</li>
|
52 |
+
<li>Add/specify custom class(es) for the widget block, the menu container, and the menu itself</li>
|
53 |
+
<li>Modify the link's output with additional HTML around the link's text and/or the link element itself</li>
|
54 |
+
<li>Use Ordered Lists (OL) for the top and/or sub levels instead of Unordered Lists (UL)</li>
|
55 |
+
<li>Select a branch based on the ultimate ancestor (root level) of the "current" item</li>
|
56 |
+
<li>Shortcode, [custom_menu_wizard], available to run the widget from within content</li>
|
57 |
+
<li>Make the output conditional upon the "current" item appearing in the selected/included items</li>
|
58 |
+
<li>Specify specific menu items</li>
|
59 |
+
<li>Use the widget's interactive "assist" to help with the widget settings or shortcode definition </li>
|
60 |
+
</ul>
|
61 |
+
|
62 |
+
<p>Documentation for the <a href='#Widget-Options'>Widget Options</a>, and the associated
|
63 |
+
<a href='#Shortcode-Parameters'>Shortcode Parameters</a>, can be found under Other Notes.</p> <hr />
|
64 |
+
<h3>Installation</h3>
|
65 |
+
<ol>
|
66 |
+
<li><p>EITHER Upload the zip package via 'Plugins > Add New > Upload' in your WP Admin</p>
|
67 |
+
|
68 |
+
<p>OR Extract the zip package and upload <code>custom-menu-wizard</code> folder to the <code>/wp-content/plugins/</code> directory</p></li>
|
69 |
+
<li><p>Activate the plugin through the 'Plugins' menu in your WP Admin</p></li>
|
70 |
+
</ol>
|
71 |
+
|
72 |
+
<p>The widget will now be available in the 'Widgets' admin page.
|
73 |
+
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.
|
74 |
+
Alternatively, you can use the shortcode in your content.</p> <hr />
|
75 |
+
<h3>Frequently Asked Questions</h3>
|
76 |
+
<p>If you have a question or problem that is not covered here, please use the integrated Support forum.</p>
|
77 |
+
|
78 |
+
<h4>Are there any known problems?</h4>
|
79 |
+
|
80 |
+
<p>Yep, 'fraid so :</p>
|
81 |
+
|
82 |
+
<ol>
|
83 |
+
<li>The widget will only recognise one "current" item (as of v2.0.2, that's the first one encountered; prior to that it was the last one found). It is perfectly possible to have more than one menu item marked as "current", but if CMW has been configured to filter on anything related to a "current menu item" it can only choose one. The simplest example of multiple "current" items is if you add the same page to a menu more than once, but any plugin that adds and/or manipulates menu items, could potentially cause problems for the widget.</li>
|
84 |
+
</ol>
|
85 |
+
|
86 |
+
<h4>Why isn't it working? Why is there no output?</h4>
|
87 |
+
|
88 |
+
<p>I don't know. With all due respect (and a certain amount of confidence in the widget) I would venture to suggest that it is probably due to
|
89 |
+
the option settings on the widget/shortcode. The quickest way to resolve any such issues is to use the widget's interactive "assist", and
|
90 |
+
ensure that you set the current menu item correctly for the page(s) that you are having problems with. However, I am well aware that I not
|
91 |
+
infallible, and if you still have problems then please let me have as much information as possible and I will endeavour to help. (Please
|
92 |
+
note that simply reporting "It doesn't work" is not the most useful of feedbacks, and is unlikely to get a response other than, possibly,
|
93 |
+
a request for more details).</p>
|
94 |
+
|
95 |
+
<h4>How do I use the "assist"?</h4>
|
96 |
+
|
97 |
+
<p>The widget's interactive "assist" is specific to each widget instance. It is a javascript-driven <em>emulator</em> that uses the widget instance's
|
98 |
+
option settings - including the menu selected - to build a pictorial representation of the menu and show you, in blue, which menu items will
|
99 |
+
be output according to the current option settings. It also shows a very basic output list of those menu items, although it will not apply
|
100 |
+
some of the more advanced HTML-modifying options such as can be found under the Container, Classes or Links sections.
|
101 |
+
Any of the displayed menu items can be designated as the "current menu item" simply by clicking on it (click again to deselect, or another
|
102 |
+
item to change). The "current menu item" is shaded red, with its parent shaded orange and ancestors shaded yellow. All changes in the
|
103 |
+
"current menu item" and the widget options are immediately reflected by the "assist" (text fields in the widget options simply need to lose
|
104 |
+
focus).</p>
|
105 |
+
|
106 |
+
<p>Once you are happy with the results, having tested all possible settings of "current menu item" (if it applies), then simply Save the widget.
|
107 |
+
Alternatively, simply copy-paste the shortcode code produced by the "assist" straight into your post (you do not need to Save the widget!).
|
108 |
+
The widget does not have to Saved to <em>test</em> any of the options.</p>
|
109 |
+
|
110 |
+
<h4>Is there an easy way to construct the shortcode to get the results that I want?</h4>
|
111 |
+
|
112 |
+
<p>Yes. Use the widget's interactive "assist" capability (see above). Note that you do not need to have the widget in a sidebar : the
|
113 |
+
"assist" also works off a widget that is in the Inactive Widgets area of the widget admin page.</p>
|
114 |
+
|
115 |
+
<h4>How do I get the menu item ids for the `Items` option?</h4>
|
116 |
+
|
117 |
+
<p>Use the widget's interactive "assist" (see above). Within the representation menu structure, each menu item's id is set in its title
|
118 |
+
attribute, so should be seen when the cursor is moved over the item. A simpler way is to check the <code>Items</code> option : the "assist" will
|
119 |
+
then show a green tick "checkbox" beside each menu item and you simply [un]check the items as required. Each selection will be reflected back into the
|
120 |
+
widget's <code>Items</code> settings, and also in the shortcode code.</p>
|
121 |
+
|
122 |
+
<p>Alternatively, go to Appearance, Menus and select the relevant menu; hover over the edit, Remove, or Cancel link for an item and look in
|
123 |
+
the URL (the link's href) for <code>menu-item=NNN</code> ... the NNN is the menu item id.</p>
|
124 |
+
|
125 |
+
<h4>How can I find all my posts/pages that have a CMW shortcode so that I can upgrade them?</h4>
|
126 |
+
|
127 |
+
<p>There is a button on the widget's "assist" - <code>[...]</code> - that will provide a list of posts that contain any CMW shortcode.
|
128 |
+
Each entry is a link that opens the item in a new tab/window. The link's title gives a bit more information : post type, id, and
|
129 |
+
shortcode(s) concerned. This utility *only* looks at post content; it does not check custom fields, widgets, etc.</p> <hr />
|
130 |
+
|
131 |
+
<h3>Changelog</h3>
|
132 |
+
<h4>2.1.0</h4>
|
133 |
+
|
134 |
+
<ul>
|
135 |
+
<li><p>change : <strong>the minmum requirement for WordPress is v3.6</strong></p></li>
|
136 |
+
<li><p>bugfix : handle duplicate menu item ids which were causing elements to be ignored</p></li>
|
137 |
+
<li><p>bugfix : fix IE8 levels indentation in the "assist"</p></li>
|
138 |
+
<li><p>bugfix : the "assist" is now "fixed" position (toggle-able back to absolute), mainly to get around a bug in jQuery UI draggable</p></li>
|
139 |
+
<li><p>remove : take out the automatic selection of shortcode text (inconsistent cross-browser, so just triple click as usual; paste-as-text if possible!)</p></li>
|
140 |
+
<li><p>addition : in the "assist", provide collapsible options for those larger menus</p></li>
|
141 |
+
<li><p>addition : added utility to the "assist" enabling posts containing a CMW shortcode to be located</p></li>
|
142 |
+
<li><p>change : in the "assist", swap the menu Items checkboxes for clickable Ticks</p></li>
|
143 |
+
<li><p>change : in the "assist", tweak styling and make more responsive to re-sizing</p></li>
|
144 |
+
<li><p>change : made compatible with Widget Customizer</p></li>
|
145 |
+
<li><p>change : display of the upgrade notice in the plugins list has been replaced with a simple request to read the changelog before upgrading</p></li>
|
146 |
+
<li><p>Note : there is no separate release available for this version!</p></li>
|
147 |
+
</ul>
|
148 |
+
|
149 |
+
<h4>2.0.6</h4>
|
150 |
+
|
151 |
+
<ul>
|
152 |
+
<li><p>change : modified determination of current item to cope better with multiple occurences (still first-found, but within prioritised groups)</p></li>
|
153 |
+
<li><p>change : display of the upgrade notice in the plugins list has been replaced with a simple request to read the changelog before upgrading</p></li>
|
154 |
+
</ul>
|
155 |
+
|
156 |
+
<h4>2.0.5</h4>
|
157 |
+
|
158 |
+
<ul>
|
159 |
+
<li>bugfix : prevent PHP warnings of Undefined index/offset</li>
|
160 |
+
</ul>
|
161 |
+
|
162 |
+
<h4>2.0.4</h4>
|
163 |
+
|
164 |
+
<ul>
|
165 |
+
<li><p>bugfix : clearing the container field failed to remove the container from the output</p></li>
|
166 |
+
<li><p>addition : in the "assist", added automatic selection of the shortcode text when it is clicked</p></li>
|
167 |
+
<li><p>addition : remove WordPress's menu-item-has-children class (introduced in v3.7) when the filtered item no longer has children</p></li>
|
168 |
+
<li><p>change : tweaked styles and javascript in admin for WordPress v3.8</p></li>
|
169 |
+
</ul>
|
170 |
+
|
171 |
+
<h4>2.0.3</h4>
|
172 |
+
|
173 |
+
<ul>
|
174 |
+
<li>bugfix : missing global when enqueuing scripts and styles for admin</li>
|
175 |
+
</ul>
|
176 |
+
|
177 |
+
<h4>2.0.2</h4>
|
178 |
+
|
179 |
+
<ul>
|
180 |
+
<li><p>bugfix : the Include Ancestors option was not automatically including the Parent</p></li>
|
181 |
+
<li><p>bugfix : the "assist" was incorrectly calculating Depth Relative to Current Item when the current menu item was outside the scope of the Filtered items</p></li>
|
182 |
+
<li><p>behaviour change : only recognise the first "current" item found (used to allow subsequent "current" items to override any already encountered)</p></li>
|
183 |
+
</ul>
|
184 |
+
|
185 |
+
<h4>2.0.1</h4>
|
186 |
+
|
187 |
+
<ul>
|
188 |
+
<li>bugfix : an incorrect test for a specific-items filter prevented show-all producing any output</li>
|
189 |
+
</ul>
|
190 |
+
|
191 |
+
<h4>2.0.0</h4>
|
192 |
+
|
193 |
+
<ul>
|
194 |
+
<li><p><strong>! Possible Breaker !</strong> The calculation of <code>Start Level</code> has been made consistent across the <code>Show all</code> and <code>Children of</code> filters : if you previously had a setup where you were filtering for the children of an item at level 2, with start level set to 4, there would have been no output because the immediate children (at level 3) were outside the start level. Now, there <em>will</em> be output, starting with the grand-children (at level 4).</p></li>
|
195 |
+
<li><p><strong>! Possible Breaker !</strong> There is now deemed to be an artificial "root" item above the level 1 items, which mean that a <code>Children of</code> filter set to "Current Parent Item" or "Current Root Item" will no longer fail for a top-level "current menu item". If you have the "no ancestor" fallback set then this change will have no impact (but you may now want to consider turning the fallback off?); if you <em>don't</em> currently use the "no ancestor" fallback, then where there was previously no output there will now be some!</p></li>
|
196 |
+
<li><p>added new option : Items, a comma- or space-delimited list of menu item ids, as an alternative Filter</p></li>
|
197 |
+
<li><p>added new option : Depth Relative to Current Item to the Filter section (depth_rel_current=1 in the shortcode)</p></li>
|
198 |
+
<li><p>added new option : Must Contain Current Item to the Output section (contains_current=1 in the shortcode)</p></li>
|
199 |
+
<li><p>changed the widget's "demo" facility to "assist" and brought it into WordPress admin, with full interactivity with the widget</p></li>
|
200 |
+
<li><p>refactored code</p></li>
|
201 |
+
</ul>
|
202 |
+
|
203 |
+
<h4>1.2.2</h4>
|
204 |
+
|
205 |
+
<ul>
|
206 |
+
<li>bugfix : fallback for Current Item with no children was failing because the parent's children weren't being picked out correctly</li>
|
207 |
+
</ul>
|
208 |
+
|
209 |
+
<h4>1.2.1</h4>
|
210 |
+
|
211 |
+
<ul>
|
212 |
+
<li><p>added some extra custom classes, when applicable : cmw-fellback-to-current & cmw-fellback-to-parent (on outer UL/OL) and cmw-the-included-parent, cmw-an-included-parent-sibling & cmw-an-included-ancestor (on relevant LIs)</p></li>
|
213 |
+
<li><p>corrected 'show all from start level 1' processing so that custom classes get applied and 'Title from "Current" Item' works (regardless of filter settings)</p></li>
|
214 |
+
<li><p>changed the defaults for new widgets such that only the Filter section is open by default; all the others are collapsed</p></li>
|
215 |
+
<li><p>in demo.html, added output of the shortcode applicable to the selections made</p></li>
|
216 |
+
<li><p>in demo.html, added a link to the documentation page</p></li>
|
217 |
+
<li><p>corrected 2 of the shortcode examples in the readme.txt, and made emulator (demo) available from the readme</p></li>
|
218 |
+
</ul>
|
219 |
+
|
220 |
+
<h4>1.2.0</h4>
|
221 |
+
|
222 |
+
<ul>
|
223 |
+
<li><p>added custom_menu_wizard shortcode, to run the widget from within content</p></li>
|
224 |
+
<li><p>moved the 'no ancestor' fallback into new Fallback collapsible section, and added a fallback for Current Item with no children</p></li>
|
225 |
+
<li><p>added an option allowing setting of title from current menu item's title</p></li>
|
226 |
+
<li><p>fixed a bug with optgroups/options made available for the 'Children of' selector after the widget has been saved (also affected disabled fields and styling)</p></li>
|
227 |
+
<li><p>don't include menus with no items</p></li>
|
228 |
+
<li><p>updated demo.html</p></li>
|
229 |
+
</ul>
|
230 |
+
|
231 |
+
<h4>1.1.0</h4>
|
232 |
+
|
233 |
+
<ul>
|
234 |
+
<li><p>added 'Current Root Item' and 'Current Parent Item' to the <code>Children of</code> filter</p></li>
|
235 |
+
<li><p>added <code>Fallback to Current Item</code> option, with subsidiary options for overriding a couple of Output options, as a means to enable Current Root & Current Parent to match a Current Item at root level</p></li>
|
236 |
+
<li><p>added an Output option to include both the parent item <strong>and</strong> the parent's siblings (for a successful <code>Children of</code> filter)</p></li>
|
237 |
+
<li><p>added max-width style (100%) to the <code>Children of</code> SELECT in the widget options</p></li>
|
238 |
+
<li><p>added widget version to the admin js enqueuer</p></li>
|
239 |
+
<li><p>ignore/disable Hide Empty option for WP >= v3.6 (wp_nav_menu() now does it automatically)</p></li>
|
240 |
+
<li><p>included a stand-alone helper/demo html page</p></li>
|
241 |
+
<li><p>rebuilt the <code>Children of</code> SELECT in the widget options to cope with IE's lack of OPTGROUP/OPTION styling</p></li>
|
242 |
+
<li><p>moved the setting of 'disabled' attributes on INPUTs/SELECTs from PHP into javascript</p></li>
|
243 |
+
</ul>
|
244 |
+
|
245 |
+
<h4>1.0.0</h4>
|
246 |
+
|
247 |
+
<p>Initial release</p> <hr />
|
248 |
+
|
249 |
+
<h3>Upgrade Notice</h3>
|
250 |
+
<dl>
|
251 |
+
<dt>2.1.0 (incorporated into v3.0.0 release)</dt>
|
252 |
+
<dd>Minimum requirement for WordPress is now v3.6! Added the ability to handle duplicate menu ids, and made the widget compatible with Widget Customizer. Tweaked some styling in the "assist".
|
253 |
+
Please note that there is no separate release package for v2.1.0!</dd>
|
254 |
+
<dt>2.0.5</dt>
|
255 |
+
<dd>Fixed a bug to prevent PHP warnings of Undefined index/offset being output.</dd>
|
256 |
+
<dt>2.0.4</dt>
|
257 |
+
<dd>Fixed a bug that prevented the container field being removed, and added removal of the menu-item-has-children class when the filtered item no longer has children.
|
258 |
+
The admin widget styling and javascript have been tweaked to accommodate WordPress 3.8.</dd>
|
259 |
+
<dt>2.0.3</dt>
|
260 |
+
<dd>Fixed a minor bug with a missing global when enqueuing script and style for the admin.</dd>
|
261 |
+
<dt>2.0.2</dt>
|
262 |
+
<dd>Fixed a bug with the Include Ancestors option, where it was not automatically including the Parent.
|
263 |
+
Fixed a bug in the "assist", where it was incorrectly calculating Depth Relative to Current Item when the current menu item was outside the scope of the Filtered items.
|
264 |
+
Changed determination</dd>
|
265 |
+
<dt>2.0.1</dt>
|
266 |
+
<dd>Fixed a bug whereby a test for a specific-items filter prevented show-all from producing any output.</dd>
|
267 |
+
<dt>2.0.0</dt>
|
268 |
+
<dd>! Possible Breaker ! My apologies if this affects you, but there are 2 possible scenarios where settings that previously resulted in no output might now produce output :
|
269 |
+
+ if you have set a Children of filter, and you have changed the Start Level to a level greater than 2, or
|
270 |
+
+ if you have set the </dd>
|
271 |
+
<dt>1.2.2</dt>
|
272 |
+
<dd>Bugfix : The fallback for Current Item with no children was failing because the parent's children weren't being picked out correctly</dd>
|
273 |
+
<dt>1.2.1</dt>
|
274 |
+
<dd>Added a few extra custom classes, and changed the defaults for new widgets such that only the Filter section is open by default.
|
275 |
+
Fixed Show All processing so that custom classes always get applied, and 'Title from "Current" Item' works regardless of filter settings.
|
276 |
+
Fixed a cou</dd>
|
277 |
+
<dt>1.2.0</dt>
|
278 |
+
<dd>Added custom_menu_wizard shortcode, to run the widget from within content.
|
279 |
+
Added a new fallback for Current Item having no children, and moved all fallbacks into a collapsible Fallbacks section.
|
280 |
+
Fixed a bug with optgroups/options made available for the 'Children of' selector after the widg</dd>
|
281 |
+
</dl>
|
282 |
+
<hr />
|
283 |
+
|
284 |
+
<h3 id='Widget-Options'>Widget Options</h3>
|
285 |
+
<p>There are quite a few options, which makes the widget settings box very long. I have therefore grouped most of the options into
|
286 |
+
logical sections and made each section collapsible (with remembered state once saved). As of v1.2.1, only the Filter section is
|
287 |
+
open by default; all sections below that start off collapsed.</p>
|
288 |
+
|
289 |
+
<ul>
|
290 |
+
<li><p><strong>Title</strong></p>
|
291 |
+
|
292 |
+
<p>Set the title for your widget.</p></li>
|
293 |
+
<li><p><strong>Hide</strong> <em>(checkbox)</em></p>
|
294 |
+
|
295 |
+
<p>Prevents the entered <code>Title</code> being displayed in the front-end widget output.</p>
|
296 |
+
|
297 |
+
<p>In the Widgets admin page, I find it useful to still be able to see the <code>Title</code> in the sidebar when the widget is collapsed, but I
|
298 |
+
don't necessarily want that <code>Title</code> to actually be output when the widget is displayed at the front-end. Hence this checkbox.</p></li>
|
299 |
+
<li><p><strong>Select Menu</strong> <em>(select)</em></p>
|
300 |
+
|
301 |
+
<p>Choose the appropriate menu from the dropdown list of Custom Menus currently defined in your WordPress application. The
|
302 |
+
first one available (alphabetically) is already selected for you by default.</p></li>
|
303 |
+
<li><p><strong>Filter</strong></p>
|
304 |
+
|
305 |
+
<ul>
|
306 |
+
<li><p><strong>Show all</strong> <em>(radio, default)</em></p>
|
307 |
+
|
308 |
+
<p>Don't apply the <code>Children of</code> filter. If you check this option, the <code>Children of</code> select will be disabled, as will the <code>Include Parent</code>,
|
309 |
+
<code>Include Ancestors</code> and <code>Title from Parent Item</code> checkboxes, as they are only applicable to a <code>Children of</code> filter.</p></li>
|
310 |
+
<li><p><strong>Children of</strong> <em>(radio & select)</em></p>
|
311 |
+
|
312 |
+
<p>The dropdown list will present a "Current Item" option (default), a "Current Root Item" (v1.1.0)
|
313 |
+
and "Current Parent Item" (v1.1.0) option, followed by all the available items from the menu chosen in <code>Select Menu</code>.
|
314 |
+
The widget will output the <em>children</em> of the selected item, always assuming that they lie within the bounds of any other parameters set.</p>
|
315 |
+
|
316 |
+
<ul>
|
317 |
+
<li><p>"Current Item" is the menu item that WordPress recognises as being currently on display (current menu item)</p></li>
|
318 |
+
<li><p>"Current Parent Item" (v1.1.0) is the <em>immediate</em> ancestor (within <code>Select Menu</code>) of the current menu item</p></li>
|
319 |
+
<li><p>"Current Root Item" (v1.1.0) is the <em>ultimate</em> ancestor (within <code>Select Menu</code>) of the current menu item.</p></li>
|
320 |
+
</ul>
|
321 |
+
|
322 |
+
<p>Obviously, if the current menu item (as determined by WordPress) does not
|
323 |
+
appear in the <code>Select Menu</code> then there is going to be no output for any of these options.</p>
|
324 |
+
|
325 |
+
<p>If you change <code>Select Menu</code>, the options presented in this dropdown will change accordingly and the selected option will revert to the default.</p></li>
|
326 |
+
<li><p><strong>Items</strong> (radio & text input)* as of v2.0.0</p>
|
327 |
+
|
328 |
+
<p>Takes a comma- or space-delimited list of menu item ids, specifiying the specific menu items that are required. This is intended
|
329 |
+
for situations that it is not possible to handle using other option settings. The simplest way to determine the menu item ids is
|
330 |
+
to use the "assist" facility.</p>
|
331 |
+
|
332 |
+
<p>Note that the <code>Starting Level</code> and <code>Depth</code> options (including <code>Relative to "Current" Item</code>) have no effect if <code>Items</code> is set.</p></li>
|
333 |
+
<li><p><strong>Starting Level</strong> <em>(select, default: "1")</em></p>
|
334 |
+
|
335 |
+
<p>This is the level within the chosen menu (from <code>Select Menu</code>) that the widget will start looking for items to keep. Obviously, level 1
|
336 |
+
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.
|
337 |
+
Note that for a <code>Children of</code> filter there is no difference between level 1 and level 2 (because there are no children at level 1).
|
338 |
+
Also note that this option does not apply if <code>Items</code> is set.</p></li>
|
339 |
+
<li><p><strong>For Depth</strong> <em>(select, default: "unlimited")</em></p>
|
340 |
+
|
341 |
+
<p>This is the maximum depth of the eventual output structure after filtering, and in the case of <code>Flat</code> output being requested it is
|
342 |
+
still applied - as if the output were <code>Hierarchical</code> and then flattened at the very last moment.</p>
|
343 |
+
|
344 |
+
<p>You need to be aware that, by default, the
|
345 |
+
<code>For Depth</code> setting is applied relative to the level at which the first item to be kept is found. For example, say you were to set
|
346 |
+
<code>Children of</code> to "Current Item", <code>Starting Level</code> to "2", and <code>For Depth</code> to "2 levels" : if the current item was found at level 3,
|
347 |
+
then you would get the current item's immediate children (from level 4), plus <em>their</em> immediate children (from level 5).
|
348 |
+
Note that this option does not apply if <code>Items</code> is set.</p></li>
|
349 |
+
<li><p><strong>Relative to "Current" Item</strong> <em>(checkbox)</em> as of v2.0.0</p>
|
350 |
+
|
351 |
+
<p>This changes the <code>For Depth</code> option such that depth is applied relative to the current menu item, instead of relative to the
|
352 |
+
first item found that is to be kept. It only has any effect when <code>For Depth</code> is set to something other than "unlimited", and when
|
353 |
+
the current menu item is within the filtered items (before taking <code>For Depth</code> into account).</p></li>
|
354 |
+
</ul></li>
|
355 |
+
<li><p><strong>Fallbacks</strong></p>
|
356 |
+
|
357 |
+
<p>Fallback for <code>Children of</code> being set to either <em>Current Root Item</em> or <em>Current Parent Item</em>, and current item not having an ancestor:</p>
|
358 |
+
|
359 |
+
<ul>
|
360 |
+
<li><p><strong>Switch to Current Item</strong> <em>(checkbox)</em> as of v1.1.0</p>
|
361 |
+
|
362 |
+
<p>If enabled,
|
363 |
+
it provides a fallback of effectively switching the filter to "Current Item" if the current menu item
|
364 |
+
(as determined by WordPress) is at Level 1
|
365 |
+
(top level) of the selected menu. For example, say you were to set <code>Children of</code> to "Current Parent Item", with <code>Starting Level</code>
|
366 |
+
at "1" and <code>For Depth</code> at "unlimited" : if the current menu item was found at level 1 (root level of the menu) then ordinarily
|
367 |
+
there would be no output because the current item has no parent! If you were to enable the <code>Switch to Current Item</code> fallback then you
|
368 |
+
<em>would</em> have some output - the entire branch below the current item.</p>
|
369 |
+
|
370 |
+
<ul>
|
371 |
+
<li><p><strong>Include Parent...</strong> <em>(checkbox)</em> as of v1.1.0</p>
|
372 |
+
|
373 |
+
<p>This option extends the <code>Switch to Current Item</code> option (above). If the enabled fallback is actually used, this option can
|
374 |
+
temporarily override the equivalent <strong>Output</strong> option to ON. Note that if the <strong>Output</strong> options are already set to include
|
375 |
+
the parent item (with or without siblings), this option has absolutely no effect.</p></li>
|
376 |
+
<li><p><strong>& its Siblings</strong> <em>(checkbox)</em> as of v1.1.0</p>
|
377 |
+
|
378 |
+
<p>This option extends the <code>Switch to Current Item</code> option (above). If the enabled fallback is actually used, this option can
|
379 |
+
temporarily override the equivalent <strong>Output</strong> option to ON. Note that if the equivalent <strong>Output</strong> option is already enabled,
|
380 |
+
this option has absolutely no effect.</p></li>
|
381 |
+
</ul></li>
|
382 |
+
</ul>
|
383 |
+
|
384 |
+
<p>Fallback for <code>Children of</code> being set to <em>Current Item</em>, and current item not having any children:</p>
|
385 |
+
|
386 |
+
<ul>
|
387 |
+
<li><p><strong>Switch to Current Parent Item</strong> <em>(checkbox)</em> as of v1.2.0</p>
|
388 |
+
|
389 |
+
<p>If enabled, it provides a fallback of effectively switching the filter to "Current Parent Item" if looking for children
|
390 |
+
of Current Item and there aren't any. For example, say you were to set <code>Children of</code> to "Current Item", with <code>Starting Level</code>
|
391 |
+
at "1" and <code>For Depth</code> at "unlimited" : if the current menu item has no children then ordinarily
|
392 |
+
there would be no output! If you were to enable the <code>Switch to Current Item</code> fallback then you
|
393 |
+
<em>would</em> have some output - the current item and its siblings.</p>
|
394 |
+
|
395 |
+
<p>Please note that there is one difference between this fallback and the normal "Current Parent Item" filter : if the current item
|
396 |
+
has no ancestor (as well as no children) then you will always get the current item and its siblings, regardless of any other settings!</p>
|
397 |
+
|
398 |
+
<ul>
|
399 |
+
<li><p><strong>Include Parent...</strong> <em>(checkbox)</em> as of v1.2.0</p>
|
400 |
+
|
401 |
+
<p>This option extends the <code>Switch to Current Parent Item</code> option (above). If the enabled fallback is actually used, this option can
|
402 |
+
temporarily override the equivalent <strong>Output</strong> option to ON. Note that if the <strong>Output</strong> options are already set to include
|
403 |
+
the parent item (with or without siblings), this option has absolutely no effect.</p></li>
|
404 |
+
<li><p><strong>& its Siblings</strong> <em>(checkbox)</em> as of v1.2.0</p>
|
405 |
+
|
406 |
+
<p>This option extends the <code>Switch to Current Parent Item</code> option (above). If the enabled fallback is actually used, this option can
|
407 |
+
temporarily override the equivalent <strong>Output</strong> option to ON. Note that if the equivalent <strong>Output</strong> option is already enabled,
|
408 |
+
this option has absolutely no effect.</p></li>
|
409 |
+
</ul></li>
|
410 |
+
</ul></li>
|
411 |
+
<li><p><strong>Output</strong></p>
|
412 |
+
|
413 |
+
<ul>
|
414 |
+
<li><p><strong>Hierarchical</strong> <em>(radio, default)</em></p>
|
415 |
+
|
416 |
+
<p>Output in the standard nested list format.</p></li>
|
417 |
+
<li><p><strong>Flat</strong> <em>(radio)</em></p>
|
418 |
+
|
419 |
+
<p>Output in a single list format, ignoring any parent-child relationship other than to maintain the same physical order as would be
|
420 |
+
presented in a <code>Hierarchical</code> output.</p></li>
|
421 |
+
<li><p><strong>Must Contain "Current" Item</strong> <em>(checkbox)</em> as of v2.0.0</p>
|
422 |
+
|
423 |
+
<p>If checked, the widget will not list any menu items unless the current menu item appears somewhere in the list.</p></li>
|
424 |
+
<li><p><strong>Include Parent...</strong> <em>(checkbox)</em></p>
|
425 |
+
|
426 |
+
<p>If checked, include the parent item in the output. Only applies to a successful <code>Children of</code> filter.</p></li>
|
427 |
+
<li><p><strong>& its Siblings</strong> <em>(checkbox)</em> as of v1.1.0</p>
|
428 |
+
|
429 |
+
<p>If checked, include the parent item <strong>and</strong> its siblings in the output. Only applies to a successful <code>Children of</code> filter.</p></li>
|
430 |
+
<li><p><strong>Include Ancestors</strong> <em>(checkbox)</em></p>
|
431 |
+
|
432 |
+
<p>Same as <code>Include Parent</code> except that all ancestors, right back to root level, are included. Only applies to a successful
|
433 |
+
<code>Children of</code> filter.</p></li>
|
434 |
+
<li><p><strong>Title from Parent</strong> <em>(checkbox)</em></p>
|
435 |
+
|
436 |
+
<p>Again, this only applies to a successful <code>Children of</code> filter. If checked, use the title of the parent item as the widget's
|
437 |
+
title when displaying the output. This will override (ie. ignore) the <code>Hide</code> checkbox setting!</p>
|
438 |
+
|
439 |
+
<p>Please note that this is <strong>not</strong> the same as asking for the title from "the parent of the current menu item"!</p></li>
|
440 |
+
<li><p><strong>Title from "Current" Item</strong> <em>(checkbox)</em></p>
|
441 |
+
|
442 |
+
<p>If checked, use the title of the current menu item (as determined by WordPress) as the widget's
|
443 |
+
title when displaying the output. This will override (ie. ignore) the <code>Hide</code> checkbox setting!</p>
|
444 |
+
|
445 |
+
<p>Note that the current menu item is not required to be within the resultant output, merely within the <code>Select Menu</code>.
|
446 |
+
Also, <code>Title from Parent</code> (if applicable, and if available) takes priority over this option.</p></li>
|
447 |
+
<li><p><strong>Change UL to OL</strong></p>
|
448 |
+
|
449 |
+
<p>The standard for menus is to use UL (unordered list) elements to display the output. These settings give you the option to swap
|
450 |
+
the ULs out for OLs (ordered lists).</p>
|
451 |
+
|
452 |
+
<ul>
|
453 |
+
<li><p><strong>Top Level</strong> <em>(checkbox)</em></p>
|
454 |
+
|
455 |
+
<p>If checked, swap the outermost UL for an OL.</p></li>
|
456 |
+
<li><p><strong>Sub-Levels</strong> <em>(checkbox)</em></p>
|
457 |
+
|
458 |
+
<p>If checked, swap any nested (ie. not the outermost) ULs for an OLs.</p></li>
|
459 |
+
</ul></li>
|
460 |
+
<li><p><strong>Hide Widget if Empty</strong> <em>(checkbox)</em></p>
|
461 |
+
|
462 |
+
<p>If checked, the widget will not output <em>any</em> HTML unless it finds at least one menu item that matches the Filter settings.</p>
|
463 |
+
|
464 |
+
<p>Please note that as of WordPress v3.6, this option becomes superfluous and will <strong>not</strong> be presented (the wp_nav_menu() function
|
465 |
+
has been modified to automatically suppress all HTML output if there are no items to be displayed). The widget will retain
|
466 |
+
the setting used on earlier WP versions (in case reversion from WP v3.6 might be required) but <em>will not present the option
|
467 |
+
for WP v3.6+</em>.</p></li>
|
468 |
+
</ul></li>
|
469 |
+
<li><p><strong>Container</strong></p>
|
470 |
+
|
471 |
+
<ul>
|
472 |
+
<li><p><strong>Element</strong> <em>(default: "div")</em></p>
|
473 |
+
|
474 |
+
<p>This menu list is usually wrapped in a "container" element, and this is the tag for that element. You may change it for another
|
475 |
+
tag, or you may clear it out and the container will be completely removed. Please note that WordPress is set by default to only
|
476 |
+
accept "div" or "nav", but that could be changed or extended by any template or plugin.</p></li>
|
477 |
+
<li><p><strong>Unique ID</strong></p>
|
478 |
+
|
479 |
+
<p>This allows you to specify your own id (which should be unique) for the container.</p></li>
|
480 |
+
<li><p><strong>Class</strong></p>
|
481 |
+
|
482 |
+
<p>This allows you to add your own class to the container element.</p></li>
|
483 |
+
</ul></li>
|
484 |
+
<li><p><strong>Classes</strong></p>
|
485 |
+
|
486 |
+
<ul>
|
487 |
+
<li><p><strong>Menu Class</strong> <em>(default: "menu-widget")</em></p>
|
488 |
+
|
489 |
+
<p>This is the class that will be applied to the list element that holds the entire menu.</p></li>
|
490 |
+
<li><p><strong>Widget Class</strong></p>
|
491 |
+
|
492 |
+
<p>This allows you to add your own class to the outermost element of the widget, the one that wraps the entire widget output.</p></li>
|
493 |
+
</ul></li>
|
494 |
+
<li><p><strong>Links</strong></p>
|
495 |
+
|
496 |
+
<ul>
|
497 |
+
<li><p><strong>Before the Link</strong></p>
|
498 |
+
|
499 |
+
<p>Text or HTML that will be placed immediately before each menu item's link.</p></li>
|
500 |
+
<li><p><strong>After the Link</strong></p>
|
501 |
+
|
502 |
+
<p>Text or HTML that will be placed immediately after each menu item's link.</p></li>
|
503 |
+
<li><p><strong>Before the Link Text</strong></p>
|
504 |
+
|
505 |
+
<p>Text or HTML that will be placed immediately before each menu item's link text.</p></li>
|
506 |
+
<li><p><strong>After the Link Text</strong></p>
|
507 |
+
|
508 |
+
<p>Text or HTML that will be placed immediately after each menu item's link text.</p></li>
|
509 |
+
</ul></li>
|
510 |
+
</ul>
|
511 |
+
<hr />
|
512 |
+
|
513 |
+
<h3 id='Shortcode-Parameters'>Shortcode Parameters</h3>
|
514 |
+
<p>The shortcode is <strong><code>[custom_menu_wizard]</code></strong>. Most of the attributes reflect the options available to the widget, but some have been simplified for easier use in the shortcode format.
|
515 |
+
Please note that the <code>Hide Widget if Empty</code> option is not available to the shortcode : it is set to enabled, and if there are no menu items found then there will be no output from the shortcode.</p>
|
516 |
+
|
517 |
+
<p>The simplest way to build a shortcode is to use the widget's "assist" facility (new in v2.0.0). The facilty is available even when the widget is in
|
518 |
+
the Inactive Widgets area, so you don't have to add an unwanted instance of the widget to a sidebar.</p>
|
519 |
+
|
520 |
+
<ul>
|
521 |
+
<li><p><strong>title</strong> <em>(string)</em></p>
|
522 |
+
|
523 |
+
<p>The output's <code>Title</code>, which may be overridden by <code>title_from</code>. Note that there is no shortcode equivalent of the widget's <code>Hide</code> option for the title.</p></li>
|
524 |
+
<li><p><strong>menu</strong> <em>(string | integer)</em></p>
|
525 |
+
|
526 |
+
<p>Accepts a menu name (most likely usage) or id. If not provided, the shortcode will attempt to find the first menu (ordered by name)
|
527 |
+
that has menu items attached to it, and use that.</p></li>
|
528 |
+
<li><p><strong>children_of</strong> <em>(string | integer)</em></p>
|
529 |
+
|
530 |
+
<p>If not empty then it specifies a <code>Children of</code> filter. If neither <code>children_of</code> nor <code>items</code> are supplied (or are empty) then the
|
531 |
+
filter defaults back to <code>Show all</code> (see above). Note that <code>items</code>, if supplied, will take precedence over <code>children_of</code>.</p>
|
532 |
+
|
533 |
+
<ul>
|
534 |
+
<li><p>If numeric, it is taken as being the id of a menu item. The widget will look for the <code>Children of</code> that menu item (within <code>menu</code>).
|
535 |
+
(Hint : In Menus Admin, hover over the item's <strong>Remove</strong> link and note the number after <em>menu-item=</em> in the URL)</p></li>
|
536 |
+
<li><p>Certain specific strings have the following meanings:</p>
|
537 |
+
|
538 |
+
<ul>
|
539 |
+
<li><p><em>'current'</em> or <em>'current-item'</em> : a <code>Children of</code> "Current Item" filter</p></li>
|
540 |
+
<li><p><em>'parent'</em> or <em>'current-parent'</em> : a <code>Children of</code> "Current Parent Item" filter</p></li>
|
541 |
+
<li><p><em>'root'</em> or <em>'current-ancestor'</em> : a <code>Children of</code> "Current Root Item" filter</p></li>
|
542 |
+
</ul></li>
|
543 |
+
<li><p>If any other string, it is taken to be the title of a menu item. The widget will look for the <code>Children of</code> that menu item
|
544 |
+
(within <code>menu</code>). Please note that the code looks for a <em>caseless</em> title match, so specifying <code>children_of="my menu item"</code> will
|
545 |
+
match against a menu item with the title "My Menu Item". Also note that the first match found (hierarchically) is the one that
|
546 |
+
gets used (it is quite possible to have same-named items within a menu structure).</p></li>
|
547 |
+
</ul></li>
|
548 |
+
<li><p><strong>items</strong> <em>(string)</em> See widget's <code>Items</code> option, under <strong>Filter</strong> above.</p></li>
|
549 |
+
<li><p><strong>fallback_parent</strong> <em>(string | integer)</em></p>
|
550 |
+
|
551 |
+
<p>This is the fallback option for when <code>Children of</code> is set to either <em>Current Root Item</em> or <em>Current Parent Item</em>, and
|
552 |
+
the current item has no ancestors (see <code>Switch to Current Item</code> under <strong>Fallbacks</strong> above).</p>
|
553 |
+
|
554 |
+
<ul>
|
555 |
+
<li><p>Any "truthy" value (eg. 1, <em>'true'</em>, <em>'on'</em>, <em>'parent'</em>, <em>'siblings'</em>) : Enables widget's <code>Switch to Current Item</code> <strong>Fallbacks</strong> option</p></li>
|
556 |
+
<li><p><em>'parent'</em> : Enables widget's <code>Include Parent...</code> <strong>Fallbacks</strong> extension option (in addition to the above)</p></li>
|
557 |
+
<li><p><em>'siblings'</em> : Enables widget's <code>& its Siblings</code> <strong>Fallbacks</strong> extension option (in addition to the above)</p></li>
|
558 |
+
</ul></li>
|
559 |
+
<li><p><strong>fallback_current</strong> <em>(string | integer)</em></p>
|
560 |
+
|
561 |
+
<p>This is the fallback option for when <code>Children of</code> is set to <em>Current Item</em>, and
|
562 |
+
the current item has no children (see <code>Switch to Current Parent Item</code> under <strong>Fallbacks</strong> above).</p>
|
563 |
+
|
564 |
+
<ul>
|
565 |
+
<li><p>Any "truthy" value (eg. 1, <em>'true'</em>, <em>'on'</em>, <em>'parent'</em>, <em>'siblings'</em>) : Enables widget's <code>Switch to Current Parent Item</code> <strong>Fallbacks</strong> option</p></li>
|
566 |
+
<li><p><em>'parent'</em> : Enables widget's <code>Include Parent...</code> <strong>Fallbacks</strong> extension option (in addition to the above)</p></li>
|
567 |
+
<li><p><em>'siblings'</em> : Enables widget's <code>& its Siblings</code> <strong>Fallbacks</strong> extension option (in addition to the above)</p></li>
|
568 |
+
</ul></li>
|
569 |
+
<li><p><strong>start_level</strong> <em>(integer, default 1)</em> See widget's <code>Starting Level</code> option, under <strong>Filter</strong> above.</p></li>
|
570 |
+
<li><p><strong>depth</strong> <em>(integer, default 0)</em> See widget's <code>For Depth</code> option, under <strong>Filter</strong> above.</p></li>
|
571 |
+
<li><p><strong>depth_rel_current</strong> <em>(switch, off by default, 1 to enable)</em> See widget's <code>Relative to "Currrent" Item</code> option, under <strong>Filter</strong> above.</p></li>
|
572 |
+
<li><p><strong>flat_output</strong> <em>(switch, off by default, 1 to enable)</em> See widget's <code>Flat</code> option, under <strong>Output</strong> above.</p></li>
|
573 |
+
<li><p><strong>contains_current</strong> <em>(switch, off by default, 1 to enable)</em> See widget's <code>Must Contain "Current" Item</code> option, under <strong>Output</strong> above.</p></li>
|
574 |
+
<li><p><strong>include</strong> <em>(string)</em></p>
|
575 |
+
|
576 |
+
<ul>
|
577 |
+
<li><p><em>'parent'</em> : Enables widget's <code>Include Parent...</code> <strong>Output</strong> option</p></li>
|
578 |
+
<li><p><em>'siblings'</em> : Enables widget's <code>& its Siblings</code> <strong>Output</strong> option</p></li>
|
579 |
+
<li><p><em>'ancestors'</em> : Enables widget's <code>Include Ancestors</code> <strong>Output</strong> option</p></li>
|
580 |
+
</ul>
|
581 |
+
|
582 |
+
<p>Supply more than one by separating them with a comma, space or hyphen, eg. <code>include="siblings ancestors"</code>.</p></li>
|
583 |
+
<li><p><strong>title_from</strong> <em>(string)</em></p>
|
584 |
+
|
585 |
+
<ul>
|
586 |
+
<li><p><em>'parent'</em> : Enables widget's <code>Title from Parent</code> <strong>Output</strong> option</p></li>
|
587 |
+
<li><p><em>'current'</em> : Enables widget's <code>Title from "Current" Item</code> <strong>Output</strong> option</p></li>
|
588 |
+
</ul>
|
589 |
+
|
590 |
+
<p>Supply more than one by separating them with a comma, space or hyphen, eg. <code>title_from="parent,current"</code>.</p></li>
|
591 |
+
<li><p><strong>ol_root</strong> <em>(switch, off by default, 1 to enable)</em> See widget's <code>Top Level</code> option, under <strong>Output</strong> above.</p></li>
|
592 |
+
<li><p><strong>ol_sub</strong> <em>(switch, off by default, 1 to enable)</em> See widget's <code>Sub-Levels</code> option, under <strong>Output</strong> above.</p></li>
|
593 |
+
<li><p><strong>container</strong> <em>(string)</em> See widget's <code>Element</code> option, under <strong>Container</strong> above.</p></li>
|
594 |
+
<li><p><strong>container_id</strong> <em>(string)</em> See widget's <code>Unique ID</code> option, under <strong>Container</strong> above.</p></li>
|
595 |
+
<li><p><strong>container_class</strong> <em>(string)</em> See widget's <code>Class</code> option, under <strong>Container</strong> above.</p></li>
|
596 |
+
<li><p><strong>menu_class</strong> <em>(string)</em> See widget's <code>Menu Class</code> option, under <strong>Classes</strong> above.</p></li>
|
597 |
+
<li><p><strong>widget_class</strong> <em>(string)</em> See widget's <code>Widget Class</code> option, under <strong>Classes</strong> above.</p></li>
|
598 |
+
<li><p><strong>wrap_link</strong> <em>(string)</em></p>
|
599 |
+
|
600 |
+
<p>This is an optional tag name (eg. <em>'div'</em>, <em>'p'</em>, <em>'span'</em>) that, if provided, will be made into HTML start/end tags
|
601 |
+
and sent through to the widget as its <code>Before the Link</code> and <code>After the Link</code> options. Please note that the shortcode usage - a simple
|
602 |
+
tag name - is much more restrictive than the widget's options, which allow HTML.</p></li>
|
603 |
+
<li><p><strong>wrap_link_text</strong> <em>(string)</em></p>
|
604 |
+
|
605 |
+
<p>This is an optional tag name (eg. <em>'span'</em>, <em>'em'</em>, <em>'strong'</em>) that, if provided, will be made into HTML start/end tags
|
606 |
+
and sent through to the widget as its <code>Before the Link Text</code> and <code>After the Link Text</code> options. Please note that the shortcode usage - a
|
607 |
+
simple tag name - is much more restrictive than the widget's options, which allow HTML.</p></li>
|
608 |
+
</ul>
|
609 |
+
|
610 |
+
<p><strong>Shortcode Examples</strong></p>
|
611 |
+
|
612 |
+
<ul>
|
613 |
+
<li><p>Show the entire "main" menu :</p>
|
614 |
+
|
615 |
+
<p><code>[custom_menu_wizard menu=main]</code></p></li>
|
616 |
+
<li><p>Show the children of the Current Item within the "main" menu, for unlimited depth, and include the Current Item's parent :</p>
|
617 |
+
|
618 |
+
<p><code>[custom_menu_wizard menu=main children_of=current include=parent]</code></p></li>
|
619 |
+
<li><p>From the "animals" menu, show all the items <em>immediately</em> below (depth=1) "Small Dogs", plus "Small Dogs" and its sibling items, as ordered lists :</p>
|
620 |
+
|
621 |
+
<p><code>[custom_menu_wizard menu="animals" children_of="small dogs" depth=1 include="siblings" ol_root=1 ol_sub=1]</code></p></li>
|
622 |
+
</ul>
|
623 |
+
<hr />
|
624 |
+
|
625 |
+
</body>
|
626 |
+
</html>
|