Custom Menu Wizard Widget - Version 3.1.0

Version Description

  • addition : new Alternative section which takes a cmwizard shortcode and conditionally applies it as an entirely new widget configuration
  • addition : new fallback switch which enables an item marked as current_item_parent to be used as current item when no other current item is found
  • bugfix : updated the determination of current item so that a paged (?paged=2, etc) Home page still shows Home page as being current
  • bugfix : fixed code introduced in v3.0.4 that prevented CMW script loading on the customizer page - when the Widget Customizer plugin is loaded - for WordPress v3.8 and below
  • bugfix : stop disabling selected fields based on other settings, because this caused the customizer to wipe values that may have been still required
Download this release

Release Info

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

Code changes from version 3.0.4 to 3.1.0

custom-menu-wizard.css CHANGED
@@ -11,10 +11,15 @@
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:after {content:""; display:inline-block; width:1em;}
@@ -113,6 +118,8 @@ a.widget-custom-menu-wizard-fieldset.cmw-collapsed-fieldset:active {background-p
113
  .widget-custom-menu-wizard-dialog .cmw-has-tick > a.cmw-tick:hover,
114
  .widget-custom-menu-wizard-dialog .cmw-has-tick.cmw-inherit-tick a.cmw-tick:hover {background-position:0 -300px;}
115
  .widget-custom-menu-wizard-dialog .cmw-has-tick.cmw-inherit-tick > a.cmw-tick:hover {background-position:0 -380px;}
 
 
116
  /*...expanders...*/
117
  .widget-custom-menu-wizard-dialog .widget-custom-menu-wizard-colexp {position:absolute; top:0.5em; -webkit-transition-duration:0s; transition-duration:0s;}
118
  .widget-custom-menu-wizard-dialog .widget-custom-menu-wizard-colexp.ui-icon-triangle-1-e {opacity:0.2;}
@@ -143,20 +150,23 @@ a.widget-custom-menu-wizard-fieldset.cmw-collapsed-fieldset:active {background-p
143
  .widget-custom-menu-wizard-dialog .cmw-demo-inclusions,
144
  .widget-custom-menu-wizard-dialog .cmw-demo-exclusions,
145
  .widget-custom-menu-wizard-dialog .cmw-demo-setcurrent,
 
146
  .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;}
147
  .widget-custom-menu-wizard-dialog .cmw-demo-setcurrent {border-color:#DD3D36; border-left:4px solid #DD3D36; margin:2px 0 0;}
 
148
  .widget-custom-menu-wizard-dialog .cmw-demo-setcurrent.error,
149
  .widget-custom-menu-wizard-dialog .cmw-demo-inclusions.updated,
150
  .widget-custom-menu-wizard-dialog .cmw-demo-exclusions.updated,
 
151
  .widget-custom-menu-wizard-dialog .cmw-demo-fallback.updated {display:block;}
 
152
  /*...find shortcodes...*/
153
  .widget-custom-menu-wizard-find-shortcodes {overflow:hidden; text-align:center; width:50px;}
154
  .widget-custom-menu-wizard-find-shortcodes span {display:block;}
155
- .widget-custom-menu-wizard-find-shortcodes span.spinner {display:none; float:none;}
156
  .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%;}
157
  .widget-custom-menu-wizard-dialog .cmw-find-shortcodes {position:absolute; right:0; top:-3em; z-index:10;}
158
  .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;}
159
- .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;}
160
  .widget-custom-menu-wizard-dialog .cmw-ajax-showing .cmw-demo-found-shortcodes {opacity:1;}
161
  .widget-custom-menu-wizard-dialog .cmw-ajax-showing .cmw-demo-found-shortcodes,
162
  .widget-custom-menu-wizard-dialog .cmw-ajax-fetching .cmw-demo-found-shortcodes {right:60px; top:-4em;}
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 textarea,
15
  .widget-custom-menu-wizard-onchange input[type="text"] {max-width:100%;}
16
+ .widget-custom-menu-wizard-onchange textarea {height:5em;}
17
  .widget-custom-menu-wizard-onchange optgroup option {padding-left:0.75em;}
18
+ .widget-custom-menu-wizard-onchange .cmw-border-top {border-top:1px solid #e5e5e5;}
19
  .widget-custom-menu-wizard-onchange .cmw-colour-grey,
20
+ .widget-custom-menu-wizard-onchange .cmw-colour-grey input,
21
+ .widget-custom-menu-wizard-onchange .cmw-colour-grey select,
22
+ .widget-custom-menu-wizard-onchange .cmw-colour-grey textarea {color:#7F7F7F}
23
  .widget-custom-menu-wizard-onchange small.cmw-colour-grey {vertical-align:top;}
24
  .widget-custom-menu-wizard-onchange .cmw-display-none {display:none;}
25
  .widget-custom-menu-wizard-onchange .cmw-followed-by:after {content:""; display:inline-block; width:1em;}
118
  .widget-custom-menu-wizard-dialog .cmw-has-tick > a.cmw-tick:hover,
119
  .widget-custom-menu-wizard-dialog .cmw-has-tick.cmw-inherit-tick a.cmw-tick:hover {background-position:0 -300px;}
120
  .widget-custom-menu-wizard-dialog .cmw-has-tick.cmw-inherit-tick > a.cmw-tick:hover {background-position:0 -380px;}
121
+ .widget-custom-menu-wizard-dialog .cmw-using-alternative .cmw-tick,
122
+ .widget-custom-menu-wizard-dialog .cmw-using-alternative .cmw-cross {opacity:0.5;}
123
  /*...expanders...*/
124
  .widget-custom-menu-wizard-dialog .widget-custom-menu-wizard-colexp {position:absolute; top:0.5em; -webkit-transition-duration:0s; transition-duration:0s;}
125
  .widget-custom-menu-wizard-dialog .widget-custom-menu-wizard-colexp.ui-icon-triangle-1-e {opacity:0.2;}
150
  .widget-custom-menu-wizard-dialog .cmw-demo-inclusions,
151
  .widget-custom-menu-wizard-dialog .cmw-demo-exclusions,
152
  .widget-custom-menu-wizard-dialog .cmw-demo-setcurrent,
153
+ .widget-custom-menu-wizard-dialog .cmw-demo-alternative,
154
  .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;}
155
  .widget-custom-menu-wizard-dialog .cmw-demo-setcurrent {border-color:#DD3D36; border-left:4px solid #DD3D36; margin:2px 0 0;}
156
+ .widget-custom-menu-wizard-dialog .cmw-demo-alternative.error {border-color:#DD3D36; border-left:4px solid #DD3D36;}
157
  .widget-custom-menu-wizard-dialog .cmw-demo-setcurrent.error,
158
  .widget-custom-menu-wizard-dialog .cmw-demo-inclusions.updated,
159
  .widget-custom-menu-wizard-dialog .cmw-demo-exclusions.updated,
160
+ .widget-custom-menu-wizard-dialog .cmw-demo-alternative.updated,
161
  .widget-custom-menu-wizard-dialog .cmw-demo-fallback.updated {display:block;}
162
+ .widget-custom-menu-wizard-dialog span.spinner {display:none; float:none;}
163
  /*...find shortcodes...*/
164
  .widget-custom-menu-wizard-find-shortcodes {overflow:hidden; text-align:center; width:50px;}
165
  .widget-custom-menu-wizard-find-shortcodes span {display:block;}
 
166
  .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%;}
167
  .widget-custom-menu-wizard-dialog .cmw-find-shortcodes {position:absolute; right:0; top:-3em; z-index:10;}
168
  .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;}
169
+ .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; -moz-transition:opacity 1s linear 0s, right 0s linear 1s, top 0s linear 1s; -o-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;}
170
  .widget-custom-menu-wizard-dialog .cmw-ajax-showing .cmw-demo-found-shortcodes {opacity:1;}
171
  .widget-custom-menu-wizard-dialog .cmw-ajax-showing .cmw-demo-found-shortcodes,
172
  .widget-custom-menu-wizard-dialog .cmw-ajax-fetching .cmw-demo-found-shortcodes {right:60px; top:-4em;}
custom-menu-wizard.js CHANGED
@@ -7,6 +7,11 @@
7
  jQuery(function($){
8
  'use strict';
9
  var cmwAssist,
 
 
 
 
 
10
  widgetCustomMenuWizardClass = function(suffix, dot){
11
  return (!dot ? '' : '.') + 'widget-custom-menu-wizard-' + suffix;
12
  },
@@ -25,6 +30,260 @@ jQuery(function($){
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
@@ -94,34 +353,6 @@ jQuery(function($){
94
  }
95
  return rtn.join(',');
96
  },
97
- /**
98
- * gets the widget's field values
99
- * @param {object} oc jQuery of the widget's onchange wrapper
100
- * @return {object} key=>value pairs of the field element values
101
- */
102
- getSettings = function(oc){
103
- var settings = {},
104
- legacyVersion = oc.data('cmwDialogVersion') === '2.1.0',
105
- csv = {items:1, exclude:1},
106
- keepAsString = $.extend({branch_start:1, exclude_level:1, include_level:1}, csv);
107
- $.each(oc.find(':input').serializeArray(), function(i, v){
108
- var name = v.name.replace(/.*\[([^\]]+)\]$/, '$1'),
109
- val = !keepAsString[name] && /^-?\d+$/.test(v.value) ? parseInt(v.value, 10) : v.value;
110
- settings[name] = val;
111
- if(name === 'hide_empty'){
112
- settings[name] = !!oc.data().cmwV36plus || val;
113
- }else if(csv[name]){
114
- settings['_' + name + '_sep'] = !val || /(^\d+\+?$|,)/.test($.trim(val)) ? ',' : ' ';
115
- val = $.map(val.split(/[,\s]+/), function(x){
116
- var inherit = !legacyVersion && /\+$/.test(x);
117
- x = x ? parseInt(x, 10) : 0;
118
- return isNaN(x) || x < 1 ? null : (inherit ? x + '+' : x);
119
- });
120
- settings['_' + name] = val.join(settings['_' + name + '_sep']);
121
- }
122
- });
123
- return settings;
124
- }, //end getSettings()
125
  /**
126
  * produces the final output
127
  * @param {object} dialog jQuery of target dialog
@@ -250,7 +481,7 @@ jQuery(function($){
250
  }else{
251
  //fetch results via ajax, showing spinner while doing so...
252
  grandad.addClass('cmw-ajax-fetching');
253
- $.post(
254
  ajaxurl,
255
  { 'action': 'cmw-find-shortcodes', '_wpnonce': self.data().nonce }
256
  ).done(function(response){
@@ -369,7 +600,9 @@ jQuery(function($){
369
  widgetField = $( item.closest('.ui-dialog-content').data().cmwOnchange )
370
  .find(tickOrCross === 'tick' ? '.cmw-setitems' : '.cmw-exclusions'),
371
  sampleSet;
372
- if(widgetField.length){ //should never not find it!
 
 
373
  //A. if this item hasInheritTickCross then this click will remove tickCross entirely and all inheritance will be lost
374
  //B. else* if this item hasTickCross then this click will either
375
  // B1. if the item has no descendants, or we're running legacy version, remove the tickCross
@@ -454,7 +687,7 @@ jQuery(function($){
454
  },
455
  dialogClass: 'cmw-assistance-dialog cmw-assistance-dialog-fixed'
456
  },
457
- msgs = $.map(['SetCurrent', 'Inclusions', 'Exclusions', 'Fallback'], function(v){
458
  return '<div class="cmw-demo-' + v.toLowerCase() + ' cmw-demo-small">' + (data['cmwDialog' + v] || '') + '</div>';
459
  }),
460
  dialog = $('<div/>', {id:data.cmwDialogId}).addClass(widgetCustomMenuWizardClass('dialog'))
@@ -498,7 +731,7 @@ jQuery(function($){
498
  */
499
  setDialogTitle = function(dialog, oc){
500
  dialog.dialog('option', 'title', 'CMW : ' + ( oc.find('.cmw-widget-title').val() || dialog.data().cmwUntitled ) + ' [' + oc.find('.cmw-select-menu').find('option:selected').text() + ']' );
501
- },
502
  /**
503
  * creates a new list of menu items and inserts it into the dialog content in place of any previous one
504
  * @param {object} dialog jQuery object of the dialog
@@ -749,10 +982,13 @@ jQuery(function($){
749
  '-ud' : byItems || oc.find('.cmw-depth').val() < 1, //...is Unlimited Depth
750
  'not-br' : notByBranch, //...is NOT Branch
751
  'not-br-ci' : notByBranch || !!selectedItem, //...is NOT Branch:Current Item
752
- 'not-fb-pc' : notByBranch || !!selectedItem || (fallback !== 'parent' && fallback !== 'current') //...is NOT fallback to parent or current
 
753
  },
754
  function(k, v){
755
- oc.find('.cmw-disableif' + k).toggleClass('cmw-colour-grey', v).find('input,select').prop('disabled', v);
 
 
756
  });
757
  }, //end cmwAssist.setFields()
758
  /**
@@ -767,7 +1003,7 @@ jQuery(function($){
767
  byBranch = settings.filter === 'branch',
768
  byItems = settings.filter === 'items',
769
  byLevel = !byBranch && !byItems,
770
- v, m, n;
771
  //take notice of the widget's hide_title flag...
772
  if(settings.title && !settings.hide_title){
773
  args.title = [settings.title];
@@ -853,7 +1089,7 @@ jQuery(function($){
853
  args.title_from = n;
854
  }
855
  //switches...
856
- for(n in {allow_all_root:1, siblings:1, flat_output:1, ol_root:1, ol_sub:1}){
857
  if(settings[n]){
858
  args[n] = 1;
859
  }
@@ -872,6 +1108,13 @@ jQuery(function($){
872
  args[n] = [m[1]];
873
  }
874
  }
 
 
 
 
 
 
 
875
  //build the shortcode...
876
  v = [];
877
  for(n in args){
@@ -879,324 +1122,398 @@ jQuery(function($){
879
  v.push( $.isArray(args[n]) ? n + '="' + args[n].join(',') + '"' : n + '=' + args[n] );
880
  }
881
  //NB at v3.0.0, the shortcode changed from custom_menu_wizard to cmwizard (the previous version is still supported)
882
- return '[cmwizard ' + v.join(' ') + '/]';
883
  }, //end cmwAssist.shortcode()
884
  /**
885
- * updates the graphic menu structure from the widget data
886
- * @param {element} el Element responsible for being here
 
 
 
 
 
887
  */
888
- update : function(el){
889
- var target = $(el),
890
- oc = findOnchange(0, target),
891
- dialog = $('#' + oc.data().cmwDialogId),
892
- tobLevel = -1,
893
  lastVisibleLevel = 9999,
894
  hasIncl = 0,
895
  hasExcl = 0,
896
  fallback = '',
897
- byLevel, byBranch, byItems, theBranchItem,
898
- ciBranch, maxLevel, settings,
899
- topOfMenu, items, exclusions,
900
- local_depth, local_depth_rel_current,
901
- currentItemLI, currentItemLevel, topOfBranch, i, j, k, x, y;
 
 
 
 
 
 
 
 
 
 
 
 
902
 
903
- if(target.hasClass('cmw-listen')){
904
- //the widget field that changed is likely to have an effect on other widget fields...
905
- this.setFields(target, oc);
 
 
 
 
 
 
 
 
906
  }
907
- settings = getSettings(oc);
908
-
909
- //dialog specific...
910
- if(dialog.length && dialog.dialog('isOpen')){
911
 
912
- dialog.dialog('moveToTop');
 
 
 
 
913
 
914
- //if selected menu has changed, modify assist's structure...
915
- if(target.hasClass('cmw-select-menu')){
916
- createMenu(dialog);
 
 
 
 
 
 
 
917
  }
918
- byBranch = settings.filter === 'branch';
919
- byItems = settings.filter === 'items';
920
- byLevel = !byBranch && !byItems;
921
- ciBranch = byBranch && !settings.branch;
922
- topOfMenu = dialog.find('.cmw-demo-themenu-ul');
923
- maxLevel = topOfMenu.data().maxLevel;
924
- currentItemLI = topOfMenu.find('.current-menu-item').closest('li');
925
- currentItemLevel = currentItemLI.length ? currentItemLI.data().level : -1;
926
- items = topOfMenu.find('li').removeData('included').removeClass('title-from-item');
927
-
928
- //don't want to alter settings at all (affects shortcode output), so create some local copies for use within this function...
929
- local_depth = settings.depth;
930
- local_depth_rel_current = settings.depth_rel_current;
931
-
932
- //ticks and crosses (need to be run against the full set of items)...
933
- exclusions = filterTickCross(items, settings, 'cross');
934
 
935
- //primary filter : items...
936
- if(byItems){
937
- items = filterTickCross(items, settings, 'tick');
 
938
  }
 
 
939
 
940
- //primary filter : branch...
941
- if(byBranch && items.length){
942
- topOfBranch = ciBranch ? currentItemLI : items.filter('[data-itemid=' + settings.branch + ']');
943
- if(topOfBranch.length){
944
- tobLevel = topOfBranch.data().level || 0;
945
- items = topOfBranch.add( topOfBranch.find('li') );
946
- //since topOfBranch can change later on...
947
- theBranchItem = topOfBranch;
948
- }else{
949
- items = $([]);
950
- }
951
  }
 
952
 
953
- //primary filter : level...
954
- if(byLevel && items.length && settings.level > 1){
955
- for(i = 1, j = []; i < settings.level; i++){
 
 
 
 
 
 
 
 
 
956
  j.push('.level-' + i);
957
  }
 
958
  items = items.not( j.join(',') );
959
  }
 
960
 
961
- //check for current item in menu...
962
- //NB: this used to be done (pre 3.0.4) in front of the branch primary filter, but that filter setup may now
963
- // be needed, so this check has moved down so that all primary filters are done before checking
964
- if(settings.contains_current === 'menu' && items.length && !currentItemLI.length){
965
- items = $([]);
966
- }
967
-
968
- //check for current item after primary...
969
- if(settings.contains_current === 'primary' && items.length && !currentItemLI.is(items)){
970
- items = $([]);
971
- }
972
 
973
- //secondary filter : level...
974
- if(byLevel && items.length && local_depth){
975
- i = local_depth_rel_current && currentItemLevel >= settings.level
976
- //if the limited depth is relative to current item, and current item can be found at or below the start level...
977
- ? currentItemLevel
978
- //set relative to start level...
979
- : settings.level;
980
- i += local_depth;
981
- //note that i has been set to the first level *not* wanted!
982
- if(i <= maxLevel){
983
- for(j = []; i <= maxLevel; i++){
984
- j.push('.level-' + i);
 
 
 
 
 
985
  }
986
- //filter to remove...
987
- items = items.not( j.join(',') );
988
  }
989
  }
990
 
991
- //secondary filter : branch...
992
- if(byBranch && items.length){
993
- //convert start level to integer...
994
- j = parseInt(settings.branch_start, 10);
995
- //convert relative to absolute (max'd against 1)...
996
- j = isNaN(j) || !j ? tobLevel : (settings.branch_start.match(/^(\+|-)/) ? Math.max(1, tobLevel + j) : j);
997
-
998
- //in order to be eligible for a no-kids fallback:
999
- // - branch must be current item
1000
- // - fallback must be set
1001
- // - current item has no kids
1002
- if(ciBranch && settings.fallback && !currentItemLI.find('li').length){
1003
- //yes, we have a fallback situation...
1004
- fallback = 'cmw-fellback-to-' + settings.fallback;
1005
- if(settings.fallback === 'quit'){
1006
- //copout : just set secondary start level beyond maxLevel...
1007
- j = maxLevel + 1;
1008
- }else{
1009
- //for current, fall back to tob; for parent, fall back to tob - 1, ensuring that we don't fall back further than root...
1010
- j = settings.fallback === 'current' || tobLevel < 2 ? tobLevel : tobLevel - 1;
1011
- //if fallback depth is specified, override depth and set to relative-to-current...
1012
- if(settings.fallback_depth){
1013
- local_depth = settings.fallback_depth;
1014
- local_depth_rel_current = 1;
1015
- }
1016
- }
1017
  }
1018
-
1019
- //j is the secondary start level, tobLevel is the primary level
1020
- //easy result : if j > maxLevel then there are no matches...
1021
- if(j > maxLevel){
1022
- items = $([]);
1023
- }else{
1024
- //if secondary start is higher up the structure than primary start, reset the tob...
1025
- if(j < tobLevel){
1026
- topOfBranch = topOfBranch.parentsUntil(topOfMenu, 'li.level-' + j);
1027
- }
1028
- //do we want (and need) to force starting with the entire level...
1029
- // - only relevant if secondary start is at or above primary start
1030
- // - and if secondary level is root then allow_all_root must be set
1031
- if(settings.start_mode === 'level' && j <= tobLevel && (j > 1 || settings.allow_all_root)){
1032
- //...reset items to eveything at tob's level, plus all their descendants...
1033
- items = topOfBranch.parent().find('li');
1034
- }else if(j < tobLevel){
1035
- //tob has changed so reset items (to just tob and descendants)...
1036
- items = topOfBranch.add( topOfBranch.find('li') );
1037
- }
1038
- //if falling back and siblings are required, add them in...
1039
- //note that root level sibling inclusion is still governed by allow_all_root!
1040
- if(!!fallback && settings.fallback_siblings && items.length && (j > 1 || settings.allow_all_root)){
1041
- items = items.add( topOfBranch.siblings('li.level-' + j) );
1042
- }
1043
  }
1044
- //may have a tob but might not have any items!...
1045
- if(items.length){
1046
- //reset tob level (regardless of whether tob has changed)...
1047
- tobLevel = j;
1048
- //is depth unlimited?...
1049
- k = 9999;
1050
- if(local_depth){
1051
- //is (limited) depth relative to current item, and is there an eligible current item to measure against?...
1052
- k = local_depth_rel_current && currentItemLevel >= tobLevel && items.filter(currentItemLI).length
1053
- ? currentItemLevel
1054
- : tobLevel;
1055
- k += local_depth;
1056
- lastVisibleLevel = k - 1;
1057
- }
1058
- //note that k has been set to the first level (after those wanted) that is *not* wanted!
1059
- for(i = 1, j = []; i <= maxLevel; i++){
1060
- if(i >= tobLevel && i < k){
1061
- j.push('.level-' + i);
1062
- }
 
 
 
 
 
1063
  }
1064
- //filter to keep...
1065
- items = items.filter( j.join(',') );
1066
  }
 
 
1067
  }
 
1068
 
1069
- //check for current item after secondary...
1070
- if(settings.contains_current === 'secondary' && items.length && !currentItemLI.is(items)){
1071
- items = $([]);
 
 
 
 
 
 
 
1072
  }
 
1073
 
1074
- //branch inclusions...
1075
- //NB: only applicable if there are already items
1076
- if(byBranch && items.length){
1077
- //branch ancestors, possibly with their siblings : but only if the original branch item is either
1078
- //in items or is below lastVisibleLevel; ALSO, do not show ancestors below lastVisibleLevel!
1079
- j = theBranchItem.data().level;
1080
- if(settings.ancestors && (theBranchItem.is(items) || j > lastVisibleLevel)){
1081
- x = settings.ancestors;
1082
- //convert a relative level to an absolute one...
1083
- if(x < 0){
1084
- x = Math.max(1, j + x);
1085
- }
1086
- //ancestor siblings?...
1087
- y = settings.ancestor_siblings;
1088
- //convert a relative level to an absolute one...
1089
- if(y < 0){
1090
- y = Math.max(1, j + y);
1091
- }
1092
- //get the level classes for ancestors and siblings that need to be included...
1093
- for(i = x, j = [], k = []; i <= maxLevel; i++){
1094
- if(i <= lastVisibleLevel){
1095
- //ancestors...
1096
- j.push('.level-' + i);
1097
- if(y > 0 && i >= y){
1098
- //siblings...
1099
- k.push('.level-' + i);
1100
- }
1101
  }
1102
  }
1103
- //store current length of items...
1104
- x = items.length;
1105
- //find the ancestors...
1106
- j = theBranchItem.parentsUntil(topOfMenu, j.join(','));
1107
- //add new ones into items...
1108
- items = items.add( j.not(items).data('included', ' cmw-an-included-ancestor') );
1109
- //got ancestors, now what about their siblings?...
1110
- if(k.length){
1111
- //filter ancestors for those we want siblings of, and add new siblings into items...
1112
- items = items.add( j.filter( k.join(',') ).siblings('li').not(items).data('included', ' cmw-an-included-ancestor-sibling') );
1113
- }
1114
- //note how many have been added to items as a result of the includes...
1115
- hasIncl += items.length - x;
1116
  }
1117
- //branch siblings : only if the original branch item is currently in items...
1118
- if(settings.siblings && theBranchItem.is(items)){
1119
- j = items.length;
1120
- items = items.add( theBranchItem.siblings('li').data('included', ' cmw-an-included-sibling') );
1121
- hasIncl += items.length - j;
 
 
 
 
 
1122
  }
 
 
1123
  }
1124
- //other inclusions...
1125
- if(items.length && !!settings.include_level){
1126
- k = getLevelClasses(settings.include_level, maxLevel);
1127
- if(k){
1128
- //find and add...
1129
- j = items.length;
1130
- items = items.add( topOfMenu.find(k) );
1131
- hasIncl += items.length - j;
1132
- }
1133
  }
 
 
 
 
 
 
 
 
 
 
 
1134
 
1135
- //check for current item after inclusions...
1136
- if(settings.contains_current === 'inclusions' && items.length && !currentItemLI.is(items)){
1137
- items = $([]);
 
 
 
 
 
 
 
1138
  }
 
1139
 
1140
- //exclusions...
1141
- if(items.length && exclusions.length){
 
 
 
 
 
 
 
 
 
1142
  //filter to remove...
1143
  j = items.length;
1144
- items = items.not(exclusions);
1145
  hasExcl += j - items.length;
1146
  }
1147
- if(items.length && !!settings.exclude_level){
1148
- k = getLevelClasses(settings.exclude_level, maxLevel);
1149
- if(k){
1150
- //filter to remove...
1151
- j = items.length;
1152
- items = items.not(k);
1153
- hasExcl += j - items.length;
1154
- }
 
 
 
 
1155
  }
 
1156
 
1157
- //final check for current item in output...
1158
- if(settings.contains_current === 'output' && items.length && !currentItemLI.is(items)){
1159
- items = $([]);
 
 
 
 
 
 
 
 
 
1160
  }
 
1161
 
1162
- //title from...
1163
- //...check current then current root...
1164
- if(settings.title_from_current && currentItemLI.length){
1165
- currentItemLI.addClass('title-from-item');
1166
- }else if(settings.title_from_current_root && currentItemLI.length){
1167
- currentItemLI.closest('.level-1').addClass('title-from-item');
1168
- }else if(byBranch && theBranchItem){
1169
- //...then branch, then branch root...
1170
- if(settings.title_from_branch){
1171
- theBranchItem.addClass('title-from-item');
1172
- }else if(settings.title_from_branch_root){
1173
- theBranchItem.closest('.level-1').addClass('title-from-item');
1174
- }
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1175
  }
1176
 
1177
- //show/hide the fall back message...
1178
- dialog.find('.cmw-demo-fallback').data('fellback', fallback).toggleClass('updated', !!fallback);
1179
- //show/hide the 'select current item' prompt...
1180
- dialog.find('.cmw-demo-setcurrent').toggleClass('error', !currentItemLI.length && (!!settings.contains_current || ciBranch));
1181
- //...and the inclusions/exclusions messages...
1182
- i = {inclusions:hasIncl, exclusions:hasExcl};
1183
- for(j in i){
1184
- k = dialog.find('.cmw-demo-' + j);
1185
- k.text( k.text().replace(/\d+$/, i[j]) ).toggleClass('updated', i[j] > 0);
1186
  }
1187
 
1188
- //toggle ticks and 'pick' the remaining items...
1189
- topOfMenu.toggleClass('cmw-demo-filteritems', byItems)
1190
- .find('.picked').not( items.addClass('picked') ).removeClass('picked');
1191
  //produce output...
1192
  setDialogTitle(dialog, oc);
1193
- showOutput(dialog, settings);
1194
-
 
1195
  } //end dialog specific
1196
 
 
1197
  oc.add(dialog).find('code').text( this.shortcode( settings ) );
1198
 
1199
  } //end cmwAssist.update()
 
1200
  }; //end cmwAssist
1201
 
1202
  /**
7
  jQuery(function($){
8
  'use strict';
9
  var cmwAssist,
10
+ //only test for : key="value", key='value' and key=value...
11
+ parseSwitchTo = /(\w+)\s*=\s*"([^"]*)"(?:\s|$)|(\w+)\s*=\s*\'([^\']*)\'(?:\s|$)|(\w+)\s*=\s*([^\s\'"]+)(?:\s|$)/g,
12
+ isNumeric = function(x){
13
+ return (/^[+\-]?\d+$/).test(x.toString());
14
+ },
15
  widgetCustomMenuWizardClass = function(suffix, dot){
16
  return (!dot ? '' : '.') + 'widget-custom-menu-wizard-' + suffix;
17
  },
30
  cmwAssist.update(e ? e.target : this);
31
  }
32
  }, //end assistance()
33
+ /**
34
+ * gets the widget's field values, or their equivalents from an alternative set
35
+ * @param {object|boolean} oc jQuery of the widget's onchange wrapper (false if alts are supplied)
36
+ * @param {object} alts Optional parsed set of alternative field settings
37
+ * @return {object} key=>value pairs of the field element values
38
+ */
39
+ getSettings = function(oc, altFields){
40
+ var useAlternative = oc === false,
41
+ ocd = useAlternative ? {} : oc.data(),
42
+ settings = {},
43
+ legacyVersion = !useAlternative && ocd.cmwDialogVersion === '2.1.0',
44
+ csv = {items:1, exclude:1},
45
+ keepAsString = $.extend({branch_start:1, exclude_level:1, include_level:1}, csv);
46
+ $.each(useAlternative ? altFields : oc.find(':input').serializeArray(), function(i, v){
47
+ var name = v.name.replace(/.*\[([^\]]+)\]$/, '$1'),
48
+ val = !keepAsString[name] && /^-?\d+$/.test(v.value) ? parseInt(v.value, 10) : v.value;
49
+ settings[name] = val;
50
+ if(name === 'hide_empty'){
51
+ settings[name] = useAlternative || !!ocd.cmwV36plus || val;
52
+ }else if(csv[name]){
53
+ settings['_' + name + '_sep'] = !val || /(^\d+\+?$|,)/.test($.trim(val)) ? ',' : ' ';
54
+ val = $.map(val.split(/[,\s]+/), function(x){
55
+ var inherit = !legacyVersion && /\+$/.test(x);
56
+ x = x ? parseInt(x, 10) : 0;
57
+ return isNaN(x) || x < 1 ? null : (inherit ? x + '+' : x);
58
+ });
59
+ settings['_' + name] = val.join(settings['_' + name + '_sep']);
60
+ }
61
+ });
62
+ return settings;
63
+ }, //end getSettings()
64
+ /**
65
+ * checks for switching to the alternative settings (v3.1.0)
66
+ * @param {string} at Processing stage
67
+ * @param {boolean} hasCurrent Current Item is in items
68
+ * @param {integer} itemsLength Items length
69
+ * @param {array} settings Current settings
70
+ * @return {boolean} True if should switch to alternative settings
71
+ */
72
+ alternativeCheckFor = function(at, hasCurrent, itemsLength, settings){
73
+ var switchIf = settings.switch_if;
74
+ return (settings.switch_at === at && (
75
+ ( switchIf === 'current' && hasCurrent ) ||
76
+ ( switchIf === 'no-current' && !hasCurrent ) ||
77
+ ( switchIf === 'no-output' && !itemsLength )
78
+ ) );
79
+ }, //end alternativeCheckFor()
80
+ /**
81
+ * takes a switch_to setting, parses it, and returns settings (equiv. Custom_Menu_Wizard_Plugin->shortcode_instance())
82
+ * @param {string} switchTo switch_to value
83
+ * @param {object} themenu jQuery of demo menu structure (.cmw-demo-themenu-ul)
84
+ * @return {object} Settings, or False if can't be determined
85
+ */
86
+ alternativeParse = function(switchTo, themenu){
87
+ switchTo = $.trim(switchTo || '');
88
+ var alts = {
89
+ 'title' : '',
90
+ 'level' : 1, //default setting
91
+ 'branch' : 0,
92
+ 'items' : '',
93
+ 'depth' : 0,
94
+ 'depth_rel_current' : 0,
95
+ 'start_at' : '',
96
+ 'start_mode' : '',
97
+ 'allow_all_root' : 0,
98
+ 'ancestors' : 0,
99
+ 'ancestor_siblings' : 0,
100
+ 'include_root' : 0,
101
+ 'include_level' : '',
102
+ 'siblings' : 0,
103
+ 'exclude' : '',
104
+ 'exclude_level' : '',
105
+ 'contains_current' : '',
106
+ 'fallback' : '',
107
+ 'flat_output' : 0,
108
+ 'title_from' : '',
109
+ 'ol_root' : 0,
110
+ 'ol_sub' : 0
111
+ },
112
+ attribute = parseSwitchTo.exec(switchTo),
113
+ attr = {},
114
+ i = 0,
115
+ byItems, byBranch, byLevel, n;
116
+ while(attribute){
117
+ i++;
118
+ // key = "value" [1] [2] ...
119
+ if(attribute[1]){
120
+ attr[ attribute[1] ] = attribute[2];
121
+ // key = 'value' [3] [4] ...
122
+ }else if(attribute[3]){
123
+ attr[ attribute[3] ] = attribute[4];
124
+ // key = value [5] [6] ...
125
+ }else if(attribute[5]){
126
+ attr[ attribute[5] ] = attribute[6];
127
+ }else{
128
+ i--;
129
+ }
130
+ attribute = parseSwitchTo.exec(switchTo);
131
+ }
132
+ if(i){
133
+ for(n in attr){
134
+ if(alts.hasOwnProperty(n)){
135
+ alts[n] = attr[n];
136
+ }
137
+ }
138
+ }
139
+
140
+ //in order of priority...
141
+ byItems = !!alts.items;
142
+ byBranch = !byItems && !!alts.branch;
143
+ byLevel = !byItems && !byBranch;
144
+
145
+ if(byItems){
146
+ alts.filter = 'items';
147
+ }
148
+ if(byBranch){
149
+ alts.filter = 'branch';
150
+ n = alts.start_at.toString();
151
+ //default...
152
+ alts.branch_start = n;
153
+ //override...
154
+ if(n === '0' || n === 'branch'){
155
+ alts.branch_start = '';
156
+ }
157
+ if(n === 'root'){
158
+ alts.branch_start = '1';
159
+ }
160
+ if(n === 'children'){
161
+ alts.branch_start = '+1';
162
+ }
163
+ if(n === 'parent'){
164
+ alts.branch_start = '-1';
165
+ }
166
+ if(alts.branch === 'current' || alts.branch === 'current-item'){
167
+ alts.branch = 0;
168
+ }else if( !isNumeric( alts.branch ) ){
169
+ //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...
170
+ //NB : if branch *is* numeric, but the item id is not within this menu, then ... tough! Basically, this assist mimics what
171
+ // the widget does, and the widget doesn't check numeric branch values until it gets into the walker - at which point
172
+ // it either produces the relevant output or doesn't. only if branch is non-numeric and possibly an item title does
173
+ // the widget pre-check for it being in the menu (because the walker requires an item id) : so this does the same.
174
+ alts.branch = alts.branch.toLowerCase();
175
+ n = themenu.find('a.cmw-item').filter(function(){
176
+ return $(this).text().toLowerCase() === alts.branch;
177
+ });
178
+ if(n.length){
179
+ alts.branch = n.parent().data('itemid');
180
+ }else{
181
+ //COP OUT!
182
+ return false;
183
+ }
184
+ }
185
+ }
186
+ if(byLevel){
187
+ alts.filter = '';
188
+ alts.level = Math.max(1, parseInt(alts.level, 10));
189
+ }
190
+ alts.start_at = null;
191
+
192
+ //include_level, and the deprecated include_root switch...
193
+ //if level is empty but root is set, set include_level to '1'...
194
+ if( !alts.include_level && alts.include_root === '1' ){
195
+ alts.include_level = '1';
196
+ }
197
+ alts.include_root = null;
198
+ //fallback => fallback and fallback_siblings and fallback_depth...
199
+ //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)
200
+ //but "quit", "current" or "parent" must be present (others are optional)
201
+ if(byBranch && !alts.branch && alts.fallback ){
202
+ attr = alts.fallback.toLowerCase().split(/[\s,]+/);
203
+ n = ' ' + attr.join(' ') + ' ';
204
+ alts.fallback = '';
205
+ if(n.indexOf(' quit ') >= 0){
206
+ alts.fallback = 'quit';
207
+ }else if(n.indexOf(' parent ') >= 0){
208
+ alts.fallback = 'parent';
209
+ }else if(n.indexOf(' current ') >= 0){
210
+ alts.fallback = 'current';
211
+ }
212
+ if(alts.fallback !== '' && alts.fallback !== 'quit'){
213
+ if( n.indexOf(' +siblings ') >= 0){
214
+ alts.fallback_siblings = 1;
215
+ }
216
+ for(i = 0; i < attr.length; i++){
217
+ if(/^\d+$/.test(attr[i])){
218
+ n = parseInt(attr[i], 10);
219
+ if(n > 0){
220
+ alts.fallback_depth = n;
221
+ break;
222
+ }
223
+ }
224
+ }
225
+ }
226
+ }
227
+ //title_from => title_from_...
228
+ if(alts.title_from){
229
+ attr = alts.title_from.toLowerCase().split(/[\s,]+/);
230
+ for(i = 0; i < attr.length; i++){
231
+ if(attr[i] === 'branch' || attr[i] === 'current'){
232
+ alts['title_from_' + attr[i]] = 1;
233
+ }else if(attr[i] === 'branch-root' || attr[i] === 'current-root'){
234
+ alts['title_from_' + attr[i].replace('-', '_')] = 1;
235
+ }
236
+ }
237
+ }
238
+ alts.title_from = null;
239
+ alts.hide_empty = 1;
240
+
241
+ return getSettings( false, $.map(alts, function(v, k){ return v === null ? v : {name:k, value:v}; }) );
242
+ }, //end alternativeParse()
243
+ /**
244
+ * strips an alternative settings shortcode down to its bare essentials (v3.1.0)
245
+ * @param {string} x The alternative
246
+ * @return {string}
247
+ */
248
+ alternativeStripDown = function(x){
249
+ var rtn = '';
250
+ if(!!x){
251
+ //remove tabs, CRLFs, containing square brackets, self-terminator and spaces, then split on square bracket, taking first element...
252
+ rtn = x.replace(/[\r\n\t]+/g, ' ').replace(/^[\[\s]+/, '').replace(/[\s\/\]]+$/, '').split(/[\[\]]/)[0];
253
+ //trim trailing slash, surrounding spaces, and append a space...
254
+ rtn = $.trim(rtn.replace(/\/+$/, '')) + ' ';
255
+ //remove leading cmwizard, any occurrence of menu=something, and any occurrence of alternative="something" (optional quotes)...
256
+ rtn = $.trim( (' ' + rtn.replace(/^cmwizard\s/, '') + ' ').replace(/\smenu=[^\s]*\s/, ' ').replace(/\salternative=("[^"]*"|[^\s]*)\s/, ' ') );
257
+ //remove multiple spaces...
258
+ rtn = rtn.replace(/\s\s+/g, ' ');
259
+ }
260
+ return rtn;
261
+ },
262
+ /**
263
+ * retrieves alternative settings
264
+ * @param {array} settings Current settings
265
+ * @param {object} dialog jQuery of dialog
266
+ * @return {boolean|array} Alternative settings
267
+ */
268
+ alternativeUse = function(settings, dialog){
269
+ //alt settings are cached in the data of the menu display (which gets reconstructed when menu id changes)
270
+ var themenu = dialog.find('.cmw-demo-themenu-ul'),
271
+ dataStore = themenu.data(),
272
+ altCode = alternativeStripDown( settings.switch_to );
273
+ altCode = 'cmwizard menu=' + settings.menu + (altCode === '' ? altCode : ' ' + altCode);
274
+
275
+ //if don't have cached code, or the code has changed, get new set...
276
+ if(!dataStore.altCode || dataStore.altCode !== altCode){
277
+ dataStore.altCode = altCode;
278
+ dataStore.altSettings = alternativeParse(altCode, themenu);
279
+ }
280
+ //show that we are - or should be - using the alternative settings...
281
+ dialog.find('.cmw-demo-alternative').addClass('updated')
282
+ //...but if they're bad settings (from a bad switch_to code?) then show as an error...
283
+ .toggleClass('error', dataStore.altSettings === false);
284
+
285
+ return dataStore.altSettings === false ? false : $.extend({}, dataStore.altSettings);
286
+ }, //end alternativeUse()
287
  /**
288
  * sets the tick or cross classes and returns a filtered set of the items that *are* ticked/crossed
289
  * @param {object} items jQuery of elements to filter
353
  }
354
  return rtn.join(',');
355
  },
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
356
  /**
357
  * produces the final output
358
  * @param {object} dialog jQuery of target dialog
481
  }else{
482
  //fetch results via ajax, showing spinner while doing so...
483
  grandad.addClass('cmw-ajax-fetching');
484
+ $.get(
485
  ajaxurl,
486
  { 'action': 'cmw-find-shortcodes', '_wpnonce': self.data().nonce }
487
  ).done(function(response){
600
  widgetField = $( item.closest('.ui-dialog-content').data().cmwOnchange )
601
  .find(tickOrCross === 'tick' ? '.cmw-setitems' : '.cmw-exclusions'),
602
  sampleSet;
603
+ //if we're using the alternative settings, then click a tick/cross is disabled because they are set according to the
604
+ //alternative settings, which are not modifiable via this instance of the assist!
605
+ if(!topOfMenu.hasClass('cmw-using-alternative') && widgetField.length){ //should never not find it!
606
  //A. if this item hasInheritTickCross then this click will remove tickCross entirely and all inheritance will be lost
607
  //B. else* if this item hasTickCross then this click will either
608
  // B1. if the item has no descendants, or we're running legacy version, remove the tickCross
687
  },
688
  dialogClass: 'cmw-assistance-dialog cmw-assistance-dialog-fixed'
689
  },
690
+ msgs = $.map(['SetCurrent', 'Inclusions', 'Exclusions', 'Fallback', 'Alternative'], function(v){
691
  return '<div class="cmw-demo-' + v.toLowerCase() + ' cmw-demo-small">' + (data['cmwDialog' + v] || '') + '</div>';
692
  }),
693
  dialog = $('<div/>', {id:data.cmwDialogId}).addClass(widgetCustomMenuWizardClass('dialog'))
731
  */
732
  setDialogTitle = function(dialog, oc){
733
  dialog.dialog('option', 'title', 'CMW : ' + ( oc.find('.cmw-widget-title').val() || dialog.data().cmwUntitled ) + ' [' + oc.find('.cmw-select-menu').find('option:selected').text() + ']' );
734
+ }, //end setDialogTitle()
735
  /**
736
  * creates a new list of menu items and inserts it into the dialog content in place of any previous one
737
  * @param {object} dialog jQuery object of the dialog
982
  '-ud' : byItems || oc.find('.cmw-depth').val() < 1, //...is Unlimited Depth
983
  'not-br' : notByBranch, //...is NOT Branch
984
  'not-br-ci' : notByBranch || !!selectedItem, //...is NOT Branch:Current Item
985
+ 'not-fb-pc' : notByBranch || !!selectedItem || (fallback !== 'parent' && fallback !== 'current'), //...is NOT fallback to parent or current
986
+ 'not-sw' : !!oc.find('.cmw-switchable').filter(function(){ return !$(this).val(); }).length //...is NOT switchable (missing rither condition or stage)
987
  },
988
  function(k, v){
989
+ //as of v3.1.0, the input fields (+ selects, etc) are no longer disabled, because the customizer "pseudo-saves" the
990
+ //form which wipes out values that you may not have wanted to lose!
991
+ oc.find('.cmw-disableif' + k).toggleClass('cmw-colour-grey', v);
992
  });
993
  }, //end cmwAssist.setFields()
994
  /**
1003
  byBranch = settings.filter === 'branch',
1004
  byItems = settings.filter === 'items',
1005
  byLevel = !byBranch && !byItems,
1006
+ v, m, n, c;
1007
  //take notice of the widget's hide_title flag...
1008
  if(settings.title && !settings.hide_title){
1009
  args.title = [settings.title];
1089
  args.title_from = n;
1090
  }
1091
  //switches...
1092
+ for(n in {allow_all_root:1, siblings:1, flat_output:1, ol_root:1, ol_sub:1, fallback_ci_parent:1}){
1093
  if(settings[n]){
1094
  args[n] = 1;
1095
  }
1108
  args[n] = [m[1]];
1109
  }
1110
  }
1111
+ //alternative...
1112
+ if(settings.switch_if){
1113
+ if(settings.switch_at){
1114
+ args.alternative = [settings.switch_if, settings.switch_at];
1115
+ c = alternativeStripDown(settings.switch_to);
1116
+ }
1117
+ }
1118
  //build the shortcode...
1119
  v = [];
1120
  for(n in args){
1122
  v.push( $.isArray(args[n]) ? n + '="' + args[n].join(',') + '"' : n + '=' + args[n] );
1123
  }
1124
  //NB at v3.0.0, the shortcode changed from custom_menu_wizard to cmwizard (the previous version is still supported)
1125
+ return '[cmwizard ' + v.join(' ') + (!c ? '/]' : ']' + c + '[/cmwizard]');
1126
  }, //end cmwAssist.shortcode()
1127
  /**
1128
+ * performs the filtering and update of the menu structure
1129
+ * note to self : this function must not alter whatever settings are passed into it, otherwise subsequent update
1130
+ * actions, such as shortcode output, will be screwed!
1131
+ * @param {object} dialog jQuery of dialog
1132
+ * @param {array} settings Widget config
1133
+ * @param {integer} usingAlts Indicates whether alternative settings are being used or not
1134
+ * @return {boolean|array} False if completed, or the alternative settings if they should be applied
1135
  */
1136
+ structureUpdate : function(dialog, settings, usingAlts){
1137
+
1138
+ var tobLevel = -1,
 
 
1139
  lastVisibleLevel = 9999,
1140
  hasIncl = 0,
1141
  hasExcl = 0,
1142
  fallback = '',
1143
+ altSettings = null,
1144
+ theBranchItem, hasCurrent, topOfBranch, i, j, k, x, y,
1145
+ stage = 'menu',
1146
+ byBranch = settings.filter === 'branch',
1147
+ byItems = settings.filter === 'items',
1148
+ byLevel = !byBranch && !byItems,
1149
+ ciBranch = byBranch && !settings.branch,
1150
+ canSwitch = !usingAlts && !!settings.switch_if && !!settings.switch_at,
1151
+ topOfMenu = dialog.find('.cmw-demo-themenu-ul'),
1152
+ maxLevel = topOfMenu.data().maxLevel,
1153
+ currentItemLI = topOfMenu.find('.current-menu-item').closest('li'),
1154
+ currentItemLevel = currentItemLI.length ? currentItemLI.data().level : -1,
1155
+ items = topOfMenu.find('li').removeData('included').removeClass('title-from-item'),
1156
+ local_depth = settings.depth,
1157
+ local_depth_rel_current = settings.depth_rel_current,
1158
+ //ticks and crosses (need to be run against the full set of items)...
1159
+ exclusions = filterTickCross(items, settings, 'cross');
1160
 
1161
+ //check for current item and switch...
1162
+ hasCurrent = items.length && currentItemLI.is(items);
1163
+ if(settings.contains_current === stage && !hasCurrent){
1164
+ items = $([]);
1165
+ }
1166
+ if(canSwitch && alternativeCheckFor(stage, hasCurrent, items.length, settings) ){
1167
+ altSettings = alternativeUse(settings, dialog);
1168
+ if(altSettings !== false){
1169
+ //cop out with alternative settings!...
1170
+ return altSettings;
1171
+ }
1172
  }
 
 
 
 
1173
 
1174
+ stage = 'primary';
1175
+ //primary filter : items...
1176
+ if(byItems && items.length){
1177
+ items = filterTickCross(items, settings, 'tick');
1178
+ }
1179
 
1180
+ //primary filter : branch...
1181
+ if(byBranch && items.length){
1182
+ topOfBranch = ciBranch ? currentItemLI : items.filter('[data-itemid=' + settings.branch + ']');
1183
+ if(topOfBranch.length){
1184
+ tobLevel = topOfBranch.data().level || 0;
1185
+ items = topOfBranch.add( topOfBranch.find('li') );
1186
+ //since topOfBranch can change later on...
1187
+ theBranchItem = topOfBranch;
1188
+ }else{
1189
+ items = $([]);
1190
  }
1191
+ }
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1192
 
1193
+ //primary filter : level...
1194
+ if(byLevel && items.length && settings.level > 1){
1195
+ for(i = 1, j = []; i < settings.level; i++){
1196
+ j.push('.level-' + i);
1197
  }
1198
+ items = items.not( j.join(',') );
1199
+ }
1200
 
1201
+ //check for current item and switch...
1202
+ hasCurrent = items.length && currentItemLI.is(items);
1203
+ if(settings.contains_current === stage && !hasCurrent){
1204
+ items = $([]);
1205
+ }
1206
+ if(canSwitch && alternativeCheckFor(stage, hasCurrent, items.length, settings) ){
1207
+ altSettings = alternativeUse(settings, dialog);
1208
+ if(altSettings !== false){
1209
+ //cop out with alternative settings!...
1210
+ return altSettings;
 
1211
  }
1212
+ }
1213
 
1214
+ stage = 'secondary';
1215
+ //secondary filter : level...
1216
+ if(byLevel && items.length && local_depth){
1217
+ i = local_depth_rel_current && currentItemLevel >= settings.level
1218
+ //if the limited depth is relative to current item, and current item can be found at or below the start level...
1219
+ ? currentItemLevel
1220
+ //set relative to start level...
1221
+ : settings.level;
1222
+ i += local_depth;
1223
+ //note that i has been set to the first level *not* wanted!
1224
+ if(i <= maxLevel){
1225
+ for(j = []; i <= maxLevel; i++){
1226
  j.push('.level-' + i);
1227
  }
1228
+ //filter to remove...
1229
  items = items.not( j.join(',') );
1230
  }
1231
+ }
1232
 
1233
+ //secondary filter : branch...
1234
+ if(byBranch && items.length){
1235
+ //convert start level to integer...
1236
+ j = parseInt(settings.branch_start, 10);
1237
+ //convert relative to absolute (max'd against 1)...
1238
+ j = isNaN(j) || !j ? tobLevel : (settings.branch_start.match(/^(\+|-)/) ? Math.max(1, tobLevel + j) : j);
 
 
 
 
 
1239
 
1240
+ //in order to be eligible for a no-kids fallback:
1241
+ // - branch must be current item
1242
+ // - fallback must be set
1243
+ // - current item has no kids
1244
+ if(ciBranch && settings.fallback && !currentItemLI.find('li').length){
1245
+ //yes, we have a fallback situation...
1246
+ fallback = 'cmw-fellback-to-' + settings.fallback;
1247
+ if(settings.fallback === 'quit'){
1248
+ //copout : just set secondary start level beyond maxLevel...
1249
+ j = maxLevel + 1;
1250
+ }else{
1251
+ //for current, fall back to tob; for parent, fall back to tob - 1, ensuring that we don't fall back further than root...
1252
+ j = settings.fallback === 'current' || tobLevel < 2 ? tobLevel : tobLevel - 1;
1253
+ //if fallback depth is specified, override depth and set to relative-to-current...
1254
+ if(settings.fallback_depth){
1255
+ local_depth = settings.fallback_depth;
1256
+ local_depth_rel_current = 1;
1257
  }
 
 
1258
  }
1259
  }
1260
 
1261
+ //j is the secondary start level, tobLevel is the primary level
1262
+ //easy result : if j > maxLevel then there are no matches...
1263
+ if(j > maxLevel){
1264
+ items = $([]);
1265
+ }else{
1266
+ //if secondary start is higher up the structure than primary start, reset the tob...
1267
+ if(j < tobLevel){
1268
+ topOfBranch = topOfBranch.parentsUntil(topOfMenu, 'li.level-' + j);
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1269
  }
1270
+ //do we want (and need) to force starting with the entire level...
1271
+ // - only relevant if secondary start is at or above primary start
1272
+ // - and if secondary level is root then allow_all_root must be set
1273
+ if(settings.start_mode === 'level' && j <= tobLevel && (j > 1 || settings.allow_all_root)){
1274
+ //...reset items to eveything at tob's level, plus all their descendants...
1275
+ items = topOfBranch.parent().find('li');
1276
+ }else if(j < tobLevel){
1277
+ //tob has changed so reset items (to just tob and descendants)...
1278
+ items = topOfBranch.add( topOfBranch.find('li') );
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1279
  }
1280
+ //if falling back and siblings are required, add them in...
1281
+ //note that root level sibling inclusion is still governed by allow_all_root!
1282
+ if(!!fallback && settings.fallback_siblings && items.length && (j > 1 || settings.allow_all_root)){
1283
+ items = items.add( topOfBranch.siblings('li.level-' + j) );
1284
+ }
1285
+ }
1286
+ //may have a tob but might not have any items!...
1287
+ if(items.length){
1288
+ //reset tob level (regardless of whether tob has changed)...
1289
+ tobLevel = j;
1290
+ //is depth unlimited?...
1291
+ k = 9999;
1292
+ if(local_depth){
1293
+ //is (limited) depth relative to current item, and is there an eligible current item to measure against?...
1294
+ k = local_depth_rel_current && currentItemLevel >= tobLevel && items.filter(currentItemLI).length
1295
+ ? currentItemLevel
1296
+ : tobLevel;
1297
+ k += local_depth;
1298
+ lastVisibleLevel = k - 1;
1299
+ }
1300
+ //note that k has been set to the first level (after those wanted) that is *not* wanted!
1301
+ for(i = 1, j = []; i <= maxLevel; i++){
1302
+ if(i >= tobLevel && i < k){
1303
+ j.push('.level-' + i);
1304
  }
 
 
1305
  }
1306
+ //filter to keep...
1307
+ items = items.filter( j.join(',') );
1308
  }
1309
+ }
1310
 
1311
+ //check for current item and switch...
1312
+ hasCurrent = items.length && currentItemLI.is(items);
1313
+ if(settings.contains_current === stage && !hasCurrent){
1314
+ items = $([]);
1315
+ }
1316
+ if(canSwitch && alternativeCheckFor(stage, hasCurrent, items.length, settings) ){
1317
+ altSettings = alternativeUse(settings, dialog);
1318
+ if(altSettings !== false){
1319
+ //cop out with alternative settings!...
1320
+ return altSettings;
1321
  }
1322
+ }
1323
 
1324
+ stage = 'inclusions';
1325
+ //branch inclusions...
1326
+ //NB: only applicable if there are already items
1327
+ if(byBranch && items.length){
1328
+ //branch ancestors, possibly with their siblings : but only if the original branch item is either
1329
+ //in items or is below lastVisibleLevel; ALSO, do not show ancestors below lastVisibleLevel!
1330
+ j = theBranchItem.data().level;
1331
+ if(settings.ancestors && (theBranchItem.is(items) || j > lastVisibleLevel)){
1332
+ x = settings.ancestors;
1333
+ //convert a relative level to an absolute one...
1334
+ if(x < 0){
1335
+ x = Math.max(1, j + x);
1336
+ }
1337
+ //ancestor siblings?...
1338
+ y = settings.ancestor_siblings;
1339
+ //convert a relative level to an absolute one...
1340
+ if(y < 0){
1341
+ y = Math.max(1, j + y);
1342
+ }
1343
+ //get the level classes for ancestors and siblings that need to be included...
1344
+ for(i = x, j = [], k = []; i <= maxLevel; i++){
1345
+ if(i <= lastVisibleLevel){
1346
+ //ancestors...
1347
+ j.push('.level-' + i);
1348
+ if(y > 0 && i >= y){
1349
+ //siblings...
1350
+ k.push('.level-' + i);
1351
  }
1352
  }
 
 
 
 
 
 
 
 
 
 
 
 
 
1353
  }
1354
+ //store current length of items...
1355
+ x = items.length;
1356
+ //find the ancestors...
1357
+ j = theBranchItem.parentsUntil(topOfMenu, j.join(','));
1358
+ //add new ones into items...
1359
+ items = items.add( j.not(items).data('included', ' cmw-an-included-ancestor') );
1360
+ //got ancestors, now what about their siblings?...
1361
+ if(k.length){
1362
+ //filter ancestors for those we want siblings of, and add new siblings into items...
1363
+ items = items.add( j.filter( k.join(',') ).siblings('li').not(items).data('included', ' cmw-an-included-ancestor-sibling') );
1364
  }
1365
+ //note how many have been added to items as a result of the includes...
1366
+ hasIncl += items.length - x;
1367
  }
1368
+ //branch siblings : only if the original branch item is currently in items...
1369
+ if(settings.siblings && theBranchItem.is(items)){
1370
+ j = items.length;
1371
+ items = items.add( theBranchItem.siblings('li').data('included', ' cmw-an-included-sibling') );
1372
+ hasIncl += items.length - j;
 
 
 
 
1373
  }
1374
+ }
1375
+ //other inclusions...
1376
+ if(items.length && !!settings.include_level){
1377
+ k = getLevelClasses(settings.include_level, maxLevel);
1378
+ if(k){
1379
+ //find and add...
1380
+ j = items.length;
1381
+ items = items.add( topOfMenu.find(k) );
1382
+ hasIncl += items.length - j;
1383
+ }
1384
+ }
1385
 
1386
+ //check for current item and switch...
1387
+ hasCurrent = items.length && currentItemLI.is(items);
1388
+ if(settings.contains_current === stage && !hasCurrent){
1389
+ items = $([]);
1390
+ }
1391
+ if(canSwitch && alternativeCheckFor(stage, hasCurrent, items.length, settings) ){
1392
+ altSettings = alternativeUse(settings, dialog);
1393
+ if(altSettings !== false){
1394
+ //cop out with alternative settings!...
1395
+ return altSettings;
1396
  }
1397
+ }
1398
 
1399
+ stage = 'output';
1400
+ //exclusions...
1401
+ if(items.length && exclusions.length){
1402
+ //filter to remove...
1403
+ j = items.length;
1404
+ items = items.not(exclusions);
1405
+ hasExcl += j - items.length;
1406
+ }
1407
+ if(items.length && !!settings.exclude_level){
1408
+ k = getLevelClasses(settings.exclude_level, maxLevel);
1409
+ if(k){
1410
  //filter to remove...
1411
  j = items.length;
1412
+ items = items.not(k);
1413
  hasExcl += j - items.length;
1414
  }
1415
+ }
1416
+
1417
+ //check for current item and switch...
1418
+ hasCurrent = items.length && currentItemLI.is(items);
1419
+ if(settings.contains_current === stage && !hasCurrent){
1420
+ items = $([]);
1421
+ }
1422
+ if(canSwitch && alternativeCheckFor(stage, hasCurrent, items.length, settings) ){
1423
+ altSettings = alternativeUse(settings, dialog);
1424
+ if(altSettings !== false){
1425
+ //cop out with alternative settings!...
1426
+ return altSettings;
1427
  }
1428
+ }
1429
 
1430
+ //title from...
1431
+ //...check current then current root...
1432
+ if(settings.title_from_current && currentItemLI.length){
1433
+ currentItemLI.addClass('title-from-item');
1434
+ }else if(settings.title_from_current_root && currentItemLI.length){
1435
+ currentItemLI.closest('.level-1').addClass('title-from-item');
1436
+ }else if(byBranch && theBranchItem){
1437
+ //...then branch, then branch root...
1438
+ if(settings.title_from_branch){
1439
+ theBranchItem.addClass('title-from-item');
1440
+ }else if(settings.title_from_branch_root){
1441
+ theBranchItem.closest('.level-1').addClass('title-from-item');
1442
  }
1443
+ }
1444
 
1445
+ //show/hide the fall back message...
1446
+ dialog.find('.cmw-demo-fallback').data('fellback', fallback).toggleClass('updated', !!fallback);
1447
+ //show/hide the 'select current item' prompt...
1448
+ dialog.find('.cmw-demo-setcurrent').toggleClass('error', !currentItemLI.length && (!!settings.contains_current || ciBranch));
1449
+ //hide the alternative message if not using - and haven't tried to use! - alternative settings...
1450
+ if(!usingAlts && altSettings === null){
1451
+ dialog.find('.cmw-demo-alternative').removeClass('error updated');
1452
+ }
1453
+ //...and toggle the demo menu structure's class (eg. applies an opacity to the ticks/crosses if alternative settings
1454
+ // are being used, and prevents them being clicked on - because they can't be updated back into the current settings)...
1455
+ dialog.find('.cmw-demo-themenu-ul').toggleClass('cmw-using-alternative', !!usingAlts);
1456
+ //show/hide the inclusions/exclusions messages...
1457
+ i = {inclusions:hasIncl, exclusions:hasExcl};
1458
+ for(j in i){
1459
+ k = dialog.find('.cmw-demo-' + j);
1460
+ k.text( k.text().replace(/\d+$/, i[j]) ).toggleClass('updated', i[j] > 0);
1461
+ }
1462
+
1463
+ //toggle ticks and 'pick' the remaining items...
1464
+ topOfMenu.toggleClass('cmw-demo-filteritems', byItems)
1465
+ .find('.picked').not( items.addClass('picked') ).removeClass('picked');
1466
+
1467
+ //returning false means we're done!...
1468
+ return false;
1469
+
1470
+ }, //end cmwAssist.structureUpdate()
1471
+ /**
1472
+ * updates the graphic menu structure from the widget data
1473
+ * @param {element} el Element responsible for being here
1474
+ */
1475
+ update : function(el){
1476
+ var target = $(el),
1477
+ oc = findOnchange(0, target),
1478
+ dialog = $('#' + oc.data().cmwDialogId),
1479
+ settings, altSettings;
1480
+
1481
+ if(target.hasClass('cmw-listen')){
1482
+ //the widget field that changed is likely to have an effect on other widget fields...
1483
+ this.setFields(target, oc);
1484
+ }
1485
+ settings = getSettings(oc);
1486
+
1487
+ //dialog specific...
1488
+ if(dialog.length && dialog.dialog('isOpen')){
1489
+ dialog.dialog('moveToTop');
1490
+ //if selected menu has changed, modify assist's structure...
1491
+ if(target.hasClass('cmw-select-menu')){
1492
+ createMenu(dialog);
1493
  }
1494
 
1495
+ //if it's determined that altSettings should be used then they are intially returned and the structure update
1496
+ //is re-run with those settings (and an indicator to say that alts are bing used). otherwise, the structure
1497
+ //update simply returns false to say that the original settings should be used (either because alts don't apply,
1498
+ //or because the alts that we've got are not valid and can't be used)
1499
+ altSettings = this.structureUpdate(dialog, settings);
1500
+ if(altSettings !== false){
1501
+ //don't care what this returns (should only be false!) because we're not going to run it again...
1502
+ this.structureUpdate(dialog, altSettings, true);
 
1503
  }
1504
 
 
 
 
1505
  //produce output...
1506
  setDialogTitle(dialog, oc);
1507
+ //show output with whichever settings we ended up using...
1508
+ showOutput(dialog, altSettings || settings);
1509
+ altSettings = null;
1510
  } //end dialog specific
1511
 
1512
+ //always use original settings to update the shortcode displays...
1513
  oc.add(dialog).find('code').text( this.shortcode( settings ) );
1514
 
1515
  } //end cmwAssist.update()
1516
+
1517
  }; //end cmwAssist
1518
 
1519
  /**
custom-menu-wizard.min.js CHANGED
@@ -1,52 +1,59 @@
1
  /*Source: custom-menu-wizard.js
2
- *Compiled: 2014-08-29, Google Closure Compiler...
3
  *STATISTICS
4
- * - originalSize: 62564
5
- * - originalGzipSize: 15695
6
- * - compressedSize: 22446
7
- * - compressedGzipSize: 7165
8
  */
9
- jQuery(function(g){var z,y=function(a,b){return(b?".":"")+"widget-custom-menu-wizard-"+a},D=function(a){var b=g(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,f=[],l="tick"===d?"_items":"_exclude",l=b[l]?g.grep(b[l].split(c),function(b){return/\+$/.test(b)?(f.push(parseInt(b,10)),!b):!!b}):[],l=c+l.join(c)+c,f=c+f.join(c)+c;a=a.each(function(){var b=
10
- g(this),a=b.data(),q=-1<f.indexOf(c+a.itemid+c),a=q||-1<l.indexOf(c+a.itemid+c);b.toggleClass("cmw-has-"+d,a).toggleClass("cmw-inherit-"+d,q)});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,b){var d=[],c=a.match(/^(\d+)(\+|-)?$/),f,c=c?[parseInt(c[1],10),c[2]||""]:[];if(0<c[0])for(f=1;f<=b;f++)(f===c[0]||"-"===c[1]&&f<c[0]||"+"===c[1]&&f>c[0])&&
11
- d.push(".level-"+f);return d.join(",")},I=function(a){var b={},d="2.1.0"===a.data("cmwDialogVersion"),c={items:1,exclude:1},f=g.extend({branch_start:1,exclude_level:1,include_level:1},c);g.each(a.find(":input").serializeArray(),function(l,e){var k=e.name.replace(/.*\[([^\]]+)\]$/,"$1"),q=!f[k]&&/^-?\d+$/.test(e.value)?parseInt(e.value,10):e.value;b[k]=q;"hide_empty"===k?b[k]=!!a.data().cmwV36plus||q:c[k]&&(b["_"+k+"_sep"]=!q||/(^\d+\+?$|,)/.test(g.trim(q))?",":" ",q=g.map(q.split(/[,\s]+/),function(b){var a=
12
- !d&&/\+$/.test(b);b=b?parseInt(b,10):0;return isNaN(b)||1>b?null:a?b+"+":b}),b["_"+k]=q.join(b["_"+k+"_sep"]))});return b},J=function(a,b){var d=a.find(".cmw-demo-themenu-ul"),c=d.find(".picked"),f="",l=b.hide_title?"":b.title,e=0,k=a.find(".cmw-demo-theoutput-wrap").empty(),q=["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=g(this),d=c.data(),k=d.trace?d.trace.toString().split(","):
13
- [];a=d.itemid.toString();var l=1,c=c.children(".cmw-item");if(!b.flat_output)for(u[a]=1,a=0;a<k.length;a++)u[k[a]]&&l++;if(e)if(l>e)f+=b.ol_sub?"<ol>":"<ul>";else{for(;e>l;)--e,f+="</li>"+(b.ol_sub?"</ol>":"</ul>");f+="</li>"}f+='<li class="cmw-level-'+l+(d.included||"")+'"><a href="#'+c.data("indx")+'">'+c.text()+"</a>";e=l});1<e;)--e,f+="</li>"+(b.ol_sub?"</ol>":"</ul>");f+="</li>";q.push(a.find(".cmw-demo-fallback").data("fellback"));f=(b.ol_root?"<ol":"<ul")+' class="'+g.trim(q.join(" "))+'">'+
14
- f+(b.ol_root?"</ol>":"</ul>");k.html(f);k.find("li").filter(function(){return!!g(this).children("ul, ol").length}).addClass("cmw-has-submenu")}k.length&&l&&(c.length||!b.hide_empty)&&k.prepend("<h3>"+l+"</h3>")},K=function(a,b,d){var c;a.find("optgroup").filter(function(){var b=g(this).data().cmwOptgroupIndex===d;b||g(this).remove();return b}).length||(c=g("#"+a.attr("id")+"_ignore").find("optgroup").eq(d).clone(),c.length&&(0<b&&(b=0),a.append(c).val(b)));return b},L=function(a){a=g(this);var b=
15
- a.data(),d=!b.cmwAbsolute,c=a.closest(".ui-dialog"),f=c.find(".ui-dialog-content"),l=parseInt(c.css("top"),10)+(d?1:-1)*g(document).scrollTop();b.cmwAbsolute=d;b.cmwMaxHeight||(b.cmwMaxHeight=f.dialog("option","maxHeight"));a.button("option","icons",{primary:d?"ui-icon-circle-close":"ui-icon-circle-check"});c.toggleClass("cmw-assistance-dialog-fixed",!d);f.dialog("option",{maxHeight:d?!d:b.cmwMaxHeight});c.css("top",l);return!1},M=function(a){var b=g(this);a=["current-menu-item","current-menu-parent",
16
- "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"),f,l=function(){this.title=this.title+" "+f.replace(" "," & ").replace(/-/g," ")};c.find("."+a.join(",.")).removeClass(a.join(" ")).each(function(){this.title=this.title.replace(/\s.*$/,"")});for(c=0;c<b.length;c++)f=1===c?a.join(" "):a[0],b.eq(c).children(".cmw-item").find("span").addClass(f).each(l),1<a.length&&a.shift();D.call(g(d.data().cmwOnchange).get(0));
17
- return!1},N=function(a){g(this).closest(".ui-dialog-content").find(".cmw-item").eq(this.href.split("#")[1]).not(":has(.current-menu-item)").trigger("click");this.blur();return!1},O=function(a){a=g(this);var b=a.hasClass("cmw-tick")?"tick":"cross",d=a.parent();a=d.closest(".cmw-demo-themenu-ul");var c=d.hasClass("cmw-inherit-"+b),f=c||d.hasClass("cmw-has-"+b),l=f?g([]):d.parentsUntil(a,".cmw-inherit-"+b),e=g(d.closest(".ui-dialog-content").data().cmwOnchange).find("tick"===b?".cmw-setitems":".cmw-exclusions"),
18
- k;e.length&&(k=a.find(".cmw-has-"+b)[c||l.length?"not":"add"](d),!f||d.children("ul").length&&!a.parent().hasClass("cmw-version-210")?f&&!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=this===d[0]||this===l.get(0)?f:g(this).hasClass("cmw-inherit-"+b);return g(this).data().itemid+(a?"+":"")}).get().join(/(,|^\d+\+?$)/.test(g.trim(e.val())||",")?",":" "),e.val(k).trigger("change"));this.blur();return!1},P=function(a){var b={autoOpen:!1,width:Math.min(.9*
19
- g(window).width(),600),maxHeight:g(window).height()-40,modal:!1,containment:"window",create:function(){var b=g(this).closest(".ui-dialog");if(b.hasClass("cmw-assistance-dialog-fixed"))g("<button/>").addClass("cmw-dialog-fixed-absolute").button({label:a.cmwDialogFixed,icons:{primary:"ui-icon-circle-check"}}).appendTo(b.find(".ui-dialog-titlebar")).on("click",L)},dialogClass:"cmw-assistance-dialog cmw-assistance-dialog-fixed"},d=g.map(["SetCurrent","Inclusions","Exclusions","Fallback"],function(b){return'<div class="cmw-demo-'+
20
- b.toLowerCase()+' cmw-demo-small">'+(a["cmwDialog"+b]||"")+"</div>"}),d=g("<div/>",{id:a.cmwDialogId}).addClass(y("dialog")).append(g("<div/>").addClass("cmw-demo-themenu cmw-version-"+a.cmwDialogVersion.replace(/\./g,"")).html('<em class="cmw-demo-small">'+a.cmwDialogPrompt+"</em>")).append(g("<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>'+
21
- d.join(""))).append(g("<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="'+(a.cmwDialogNonce||"")+'" title="'+a.cmwDialogShortcodes+'"><span class="spinner"></span><span>[&hellip;]</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",O).on("click",
22
- ".cmw-item",M);d.find(".cmw-demo-theoutput").on("click","a",N);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()+"]")},G=function(a){var b=g(a.data().cmwOnchange),d=parseInt(b.find(".cmw-select-menu").val(),10),c=a.find(".cmw-demo-themenu-ul"),f=[],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*
23
- (b-2)+2)+'em;">&nbsp;</a>':""};if(!c.length||c.data("menuid")!==d){for(b.find(".cmw-assist-items optgroup").find("option").each(function(b){for(var a=g(this),c=a.data().cmwLevel;c<f.length;)e+="</li></ul>"+k(f.length),f.pop();c>f.length?e+="<ul>":(e+="</li>",f.pop());e+='<li class="level-'+c+'" data-itemid="'+this.value+'" data-level="'+c+'" data-trace="'+f.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="#'+
24
- this.value+'">'+g.trim(a.text());e+='</span></a><a href="#" class="cmw-tick ui-corner-all"></a>';f.push(this.value);c>l&&(l=c)});f.length;)e+="</li></ul>"+k(f.length),f.pop();c.remove();a.find(".cmw-demo-themenu").append(g(e).addClass("cmw-demo-themenu-ul").data({maxLevel:l,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=g(this),d=c.find("option"),k=d.length,q=c.data();if(a)for(d.slice(b).remove();k<b;)++k,c.append(g("<option/>",
25
- {value:k}).text(k));else for(k=(k+1)/2,k>b&&d.each(function(a,c){Math.abs(c.value)>=b&&g(c).remove()});k<b;)c.prepend(g("<option/>",{value:-k}).text(-k+(1<k?"":" ("+q.cmwTextParent+")"))).append(g("<option/>",{value:"+"+k}).text("+"+k+(1<k?"":" ("+q.cmwTextChildren+")"))),++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=g(this),c=(a.find("option").length+1)/2,d=a.val(),k=Math.max(2,b);Math.abs(d)>=b&&a.val(0>
26
- d?1-b:b-1);c!==k&&a.find("optgroup").each(function(b,a){var d=g(a),f=d.data().cmwTextForOption,e;c>k&&d.find("option").slice(k-c).remove();for(e=c;e<k;e++)d.append(g("<option/>",{value:b?e:-e}).text(f.replace("%d",b?e:-e)))})});a.find(".cmw-include-level,.cmw-exclude-level").each(function(){var a=g(this),c=a.find("option"),d=(c.length-1)/3,k=a.val(),q=c.eq(2).text(),u=c.eq(3).text();for(c.slice(3*b+1).remove();d<b;)++d,a.append(g("<option/>",{value:d}).text(d)).append(g("<option/>",{value:d+"-"}).text(q.replace(/\d+/,
27
- d))).append(g("<option/>",{value:d+"+"}).text(u.replace(/\d+/,d)));parseInt(k,10)>b&&a.val("")});a.find(".cmw-set-levels").each(function(){var a=g(this),c=a.data(),d=c.cmwTextLevels||"",c=c.cmwSetLevels||0,k=a.find("option"),q=k.length-c;a.val()>b&&a.val(k.eq(0).val());for(a.find("option").slice(c+b).remove();q<b;)++q,a.append(g("<option/>",{value:q}).text(q+d))})}},setFields:function(a,b){var d=b.find(".cmw-bybranch"),c=b.find(".cmw-byitems").prop("checked"),f=c||!d.prop("checked"),l=b.find(".cmw-assist-items"),
28
- e=parseInt(l.val(),10);a.hasClass("cmw-select-menu")?(e=K(l,e,a[0].selectedIndex),this.setLevels(b,(l.find("optgroup").data()||{}).cmwMaxLevel)):a.hasClass("cmw-level")?(f=!0,c=!f,b.find(".cmw-bylevel").prop("checked",f)):a.is(l)?(f=c=!1,d.prop("checked",!f)):a.hasClass("cmw-setitems")?(f=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()&&
29
- b.find(".cmw-ancestors").val(a.val());d=b.find(".cmw-fallback").val();g.each({"-ss":c,"-ud":c||1>b.find(".cmw-depth").val(),"not-br":f,"not-br-ci":f||!!e,"not-fb-pc":f||!!e||"parent"!==d&&"current"!==d},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,f;a.title&&!a.hide_title&&(b.title=[a.title]);!d&&!c&&1<a.level&&(b.level=a.level);d&&(b.branch=
30
- 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]);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));
31
- a.include_level&&(b.include_level=[a.include_level]);a._exclude&&(b.exclude=[a._exclude]);a.exclude_level&&(b.exclude_level=[a.exclude_level]);c=[];a.title_from_current?c.push("current"):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,flat_output:1,ol_root:1,ol_sub:1})a[c]&&(b[c]=1);d={contains_current:"",container:"div",container_id:"",container_class:"",
32
- 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)(f=a[d[c]].toString().match(/^<(\w+)/))&&f[1]&&(b[c]=[f[1]]);d=[];for(c in b)d.push(g.isArray(b[c])?c+'="'+b[c].join(",")+'"':c+"="+b[c]);return"[cmwizard "+d.join(" ")+"/]"},update:function(a){var b=g(a);a=B(0,b);var d=g("#"+a.data().cmwDialogId),c=-1,f=9999,l=0,e=0,k="",q,u,p,v,w,m,s,h,y,A,z,x,C,t,r,n;b.hasClass("cmw-listen")&&this.setFields(b,a);m=I(a);
33
- if(d.length&&d.dialog("isOpen")){d.dialog("moveToTop");b.hasClass("cmw-select-menu")&&G(d);b="branch"===m.filter;u="items"===m.filter;q=!b&&!u;v=b&&!m.branch;s=d.find(".cmw-demo-themenu-ul");w=s.data().maxLevel;x=s.find(".current-menu-item").closest("li");C=x.length?x.data().level:-1;h=s.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"));b&&h.length&&(t=v?x:h.filter("[data-itemid="+m.branch+"]"),t.length?(c=t.data().level||
34
- 0,h=t.add(t.find("li")),p=t):h=g([]));if(q&&h.length&&1<m.level){r=1;for(n=[];r<m.level;r++)n.push(".level-"+r);h=h.not(n.join(","))}"menu"===m.contains_current&&h.length&&!x.length&&(h=g([]));"primary"===m.contains_current&&h.length&&!x.is(h)&&(h=g([]));if(q&&h.length&&A&&(r=z&&C>=m.level?C:m.level,r+=A,r<=w)){for(n=[];r<=w;r++)n.push(".level-"+r);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&&
35
- !x.find("li").length&&(k="cmw-fellback-to-"+m.fallback,"quit"===m.fallback?n=w+1:(n="current"===m.fallback||2>c?c:c-1,m.fallback_depth&&(A=m.fallback_depth,z=1))),n>w?h=g([]):(n<c&&(t=t.parentsUntil(s,"li.level-"+n)),"level"===m.start_mode&&n<=c&&(1<n||m.allow_all_root)?h=t.parent().find("li"):n<c&&(h=t.add(t.find("li"))),k&&m.fallback_siblings&&h.length&&(1<n||m.allow_all_root)&&(h=h.add(t.siblings("li.level-"+n)))),h.length)){c=n;t=9999;A&&(t=z&&C>=c&&h.filter(x).length?C:c,t+=A,f=t-1);r=1;for(n=
36
- [];r<=w;r++)r>=c&&r<t&&n.push(".level-"+r);h=h.filter(n.join(","))}"secondary"===m.contains_current&&h.length&&!x.is(h)&&(h=g([]));if(b&&h.length){n=p.data().level;if(m.ancestors&&(p.is(h)||n>f)){r=m.ancestors;0>r&&(r=Math.max(1,n+r));c=m.ancestor_siblings;0>c&&(c=Math.max(1,n+c));n=[];for(t=[];r<=w;r++)r<=f&&(n.push(".level-"+r),0<c&&r>=c&&t.push(".level-"+r));r=h.length;n=p.parentsUntil(s,n.join(","));h=h.add(n.not(h).data("included"," cmw-an-included-ancestor"));t.length&&(h=h.add(n.filter(t.join(",")).siblings("li").not(h).data("included",
37
- " cmw-an-included-ancestor-sibling")));l+=h.length-r}m.siblings&&p.is(h)&&(n=h.length,h=h.add(p.siblings("li").data("included"," cmw-an-included-sibling")),l+=h.length-n)}h.length&&m.include_level&&(t=H(m.include_level,w))&&(n=h.length,h=h.add(s.find(t)),l+=h.length-n);"inclusions"===m.contains_current&&h.length&&!x.is(h)&&(h=g([]));h.length&&y.length&&(n=h.length,h=h.not(y),e+=n-h.length);h.length&&m.exclude_level&&(t=H(m.exclude_level,w))&&(n=h.length,h=h.not(t),e+=n-h.length);"output"===m.contains_current&&
38
- h.length&&!x.is(h)&&(h=g([]));m.title_from_current&&x.length?x.addClass("title-from-item"):m.title_from_current_root&&x.length?x.closest(".level-1").addClass("title-from-item"):b&&p&&(m.title_from_branch?p.addClass("title-from-item"):m.title_from_branch_root&&p.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",!x.length&&(!!m.contains_current||v));r={inclusions:l,exclusions:e};
39
- for(n in r)t=d.find(".cmw-demo-"+n),t.text(t.text().replace(/\d+$/,r[n])).toggleClass("updated",0<r[n]);s.toggleClass("cmw-demo-filteritems",u).find(".picked").not(h.addClass("picked")).removeClass("picked");F(d,a);J(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(),f=d.find("option").length,l;c>b&&d.val(1);for(d.find("option").slice(b).remove();f<b;)++f,d.append(g("<option/>",{value:f}).text(f));d=a.find(".cmw-depth");c=d.val();
40
- f=d.find("option").length;l=d.data().cmwTextLevels;c>b&&d.val(0);for(d.find("option").slice(b+1).remove();f<=b;)d.append(g("<option/>",{value:f}).text(f+l)),++f},setFields:function(a,b){var d=b.find(".cmw-showall").prop("checked"),c=b.find(".cmw-showspecific").prop("checked"),f=b.find(".cmw-assist-items"),l=parseInt(f.val(),10);a.hasClass("cmw-select-menu")&&(l=K(f,l,a[0].selectedIndex),this.setLevels(b,(f.find("optgroup").data()||{}).cmwMaxLevel));g.each({"":d||c,"-ss":c,"not-rp":d||c||0<=l,"not-ci":d||
41
- 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,f;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=a.fallback_include_parent_siblings?
42
- ["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"),c.length&&(b.include=c));c=[];
43
- 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)(f=a[d[c]].toString().match(/^<(\w+)/))&&f[1]&&(b[c]=[f[1]]);d=[];for(c in b)d.push(g.isArray(b[c])?c+'="'+b[c].join(" ")+
44
- '"':c+"="+b[c]);return"[custom_menu_wizard "+d.join(" ")+"]"},update:function(a){var b=g(a);a=B(0,b);var d=g("#"+a.data().cmwDialogId),c,f,l,e,k,q,u,p,v,w,m,s,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=I(a);c=!e.filter;b=0<e.filter;f=!c&&!b;k=e.include_parent;q=e.include_parent_siblings;u=d.find(".cmw-demo-themenu-ul");l=u.data().maxLevel;v=u.find(".current-menu-item").closest("li");w=v.length?v.data().level:
45
- -1;p=u.find("li").removeData("included").removeClass("title-from-item");f&&(p=E(p,e,"tick"));p.length&&!v.length&&(e.contains_current||b&&1>e.filter_item)&&(p=g([]));p.length&&b&&(0<e.filter_item?s=p.filter("[data-itemid="+e.filter_item+"]"):e.filter_item?1===w&&e.fallback_no_ancestor?(s=v,k=k||e.fallback_include_parent,q=q||e.fallback_include_parent_siblings,m="cmw-fellback-to-current"):s=1===w?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?s=v:e.fallback_no_children&&(s=u.find(".current-menu-parent").closest("li"),s.length||(s=u),k=k||e.fallback_nc_include_parent,q=q||e.fallback_nc_include_parent_siblings,m="cmw-fellback-to-parent"));if(p.length)if(c)for(h=e.depth_rel_current&&e.depth&&v.length&&w>=e.start_level?w+e.depth-1:e.depth?e.start_level+e.depth-1:9999,c=1;c<=l;c++){if(c<e.start_level||c>h)p=p.not(".level-"+c)}else s&&s.length?(h=e.depth_rel_current&&e.depth&&v.length&&s.has(v[0]).length?w-1+e.depth:e.depth?
47
- Math.max((s.data().level||0)+e.depth,e.start_level+e.depth-1):9999,p=s.find("li").filter(function(){var a=g(this).data().level;return a>=e.start_level&&a<=h})):b&&(p=g([]));p.length&&b&&s&&s.is("li")&&(q&&(p=p.add(s.siblings("li").data("included"," cmw-an-included-parent-sibling")),k=!0),e.include_ancestors&&(p=p.add(s.parentsUntil(u,"li").data("included"," cmw-an-included-ancestor")),k=!0),k&&(p=p.add(s.data("included"," cmw-the-included-parent"))));!p.length||!e.contains_current||v.length&&p.filter(v).length||
48
- (p=g([]));e.title_from_parent&&p.length&&s&&s.is("li")?s.addClass("title-from-item"):e.title_from_current&&p.length&&v.addClass("title-from-item");m=p.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",f).find(".picked").not(p.addClass("picked")).removeClass("picked");F(d,a);J(d,e);d.find("code").text(this.shortcode(e))}}}};
49
- g(document).on("change",y("onchange",1),D).on("click",y("assist",1),function(a){a=g(this);a=B(0,a);var b=a.data(),d=g("#"+b.cmwDialogId);d.length||(d=P(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=g(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=g(this).closest("div.widget");var b=a.parent();b.hasClass("customize-control-widget_form")&&!b.hasClass("expanded")||B(a).each(function(){var a=g("#"+g(this).data().cmwDialogId);a.length&&a.dialog("isOpen")&&a.dialog("close")})}).on("click",".widget-control-remove",function(a){B(g(this).closest("div.widget")).each(function(){var a=g("#"+g(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";g(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=g(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"),g.post(ajaxurl,{action:"cmw-find-shortcodes",_wpnonce:a.data().nonce}).done(function(a){a&&
52
- "0"!==a&&(b.find(".cmw-demo-found-shortcodes").html(g(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(){g(this).parent().remove();return!1});window.Custom_Menu_Wizard_Widget&&g(window.Custom_Menu_Wizard_Widget.trigger||[]).trigger("change")});
 
 
 
 
 
 
 
1
  /*Source: custom-menu-wizard.js
2
+ *Compiled: 2014-10-03, Google Closure Compiler...
3
  *STATISTICS
4
+ * - originalSize: 75713
5
+ * - originalGzipSize: 19173
6
+ * - compressedSize: 26151
7
+ * - compressedGzipSize: 8390
8
  */
9
+ jQuery(function(g){var w,K=/(\w+)\s*=\s*"([^"]*)"(?:\s|$)|(\w+)\s*=\s*\'([^\']*)\'(?:\s|$)|(\w+)\s*=\s*([^\s\'"]+)(?:\s|$)/g,u=function(b,a){return(a?".":"")+"widget-custom-menu-wizard-"+b},z=function(b){var a=g(this).data().cmwDialogVersion.replace(/\./g,""),a=/^\d+$/.test(a)?"v"+a:a;w[a]?w[a].update(b?b.target:this):w.update(b?b.target:this)},B=function(b,a){var c=!1===b,d=c?{}:b.data(),e={},l=!c&&"2.1.0"===d.cmwDialogVersion,f={items:1,exclude:1},m=g.extend({branch_start:1,exclude_level:1,include_level:1},
10
+ f);g.each(c?a:b.find(":input").serializeArray(),function(a,b){var h=b.name.replace(/.*\[([^\]]+)\]$/,"$1"),p=!m[h]&&/^-?\d+$/.test(b.value)?parseInt(b.value,10):b.value;e[h]=p;"hide_empty"===h?e[h]=c||!!d.cmwV36plus||p:f[h]&&(e["_"+h+"_sep"]=!p||/(^\d+\+?$|,)/.test(g.trim(p))?",":" ",p=g.map(p.split(/[,\s]+/),function(a){var b=!l&&/\+$/.test(a);a=a?parseInt(a,10):0;return isNaN(a)||1>a?null:b?a+"+":a}),e["_"+h]=p.join(e["_"+h+"_sep"]))});return e},C=function(b,a,c,d){var e=d.switch_if;return d.switch_at===
11
+ b&&("current"===e&&a||"no-current"===e&&!a||"no-output"===e&&!c)},P=function(b,a){b=g.trim(b||"");for(var c={title:"",level:1,branch:0,items:"",depth:0,depth_rel_current:0,start_at:"",start_mode:"",allow_all_root:0,ancestors:0,ancestor_siblings:0,include_root:0,include_level:"",siblings:0,exclude:"",exclude_level:"",contains_current:"",fallback:"",flat_output:0,title_from:"",ol_root:0,ol_sub:0},d=K.exec(b),e={},l=0,f;d;)l++,d[1]?e[d[1]]=d[2]:d[3]?e[d[3]]=d[4]:d[5]?e[d[5]]=d[6]:l--,d=K.exec(b);if(l)for(f in e)c.hasOwnProperty(f)&&
12
+ (c[f]=e[f]);f=!!c.items;d=!f&&!!c.branch;e=!f&&!d;f&&(c.filter="items");if(d){c.filter="branch";f=c.start_at.toString();c.branch_start=f;if("0"===f||"branch"===f)c.branch_start="";"root"===f&&(c.branch_start="1");"children"===f&&(c.branch_start="+1");"parent"===f&&(c.branch_start="-1");if("current"===c.branch||"current-item"===c.branch)c.branch=0;else if(!/^[+\-]?\d+$/.test(c.branch.toString()))if(c.branch=c.branch.toLowerCase(),f=a.find("a.cmw-item").filter(function(){return g(this).text().toLowerCase()===
13
+ c.branch}),f.length)c.branch=f.parent().data("itemid");else return!1}e&&(c.filter="",c.level=Math.max(1,parseInt(c.level,10)));c.start_at=null;c.include_level||"1"!==c.include_root||(c.include_level="1");c.include_root=null;if(d&&!c.branch&&c.fallback&&(e=c.fallback.toLowerCase().split(/[\s,]+/),f=" "+e.join(" ")+" ",c.fallback="",0<=f.indexOf(" quit ")?c.fallback="quit":0<=f.indexOf(" parent ")?c.fallback="parent":0<=f.indexOf(" current ")&&(c.fallback="current"),""!==c.fallback&&"quit"!==c.fallback))for(0<=
14
+ f.indexOf(" +siblings ")&&(c.fallback_siblings=1),l=0;l<e.length;l++)if(/^\d+$/.test(e[l])&&(f=parseInt(e[l],10),0<f)){c.fallback_depth=f;break}if(c.title_from)for(e=c.title_from.toLowerCase().split(/[\s,]+/),l=0;l<e.length;l++)if("branch"===e[l]||"current"===e[l])c["title_from_"+e[l]]=1;else if("branch-root"===e[l]||"current-root"===e[l])c["title_from_"+e[l].replace("-","_")]=1;c.title_from=null;c.hide_empty=1;return B(!1,g.map(c,function(a,b){return null===a?a:{name:b,value:a}}))},L=function(b){var a=
15
+ "";b&&(a=b.replace(/[\r\n\t]+/g," ").replace(/^[\[\s]+/,"").replace(/[\s\/\]]+$/,"").split(/[\[\]]/)[0],a=g.trim(a.replace(/\/+$/,""))+" ",a=g.trim((" "+a.replace(/^cmwizard\s/,"")+" ").replace(/\smenu=[^\s]*\s/," ").replace(/\salternative=("[^"]*"|[^\s]*)\s/," ")),a=a.replace(/\s\s+/g," "));return a},D=function(b,a){var c=a.find(".cmw-demo-themenu-ul"),d=c.data(),e=L(b.switch_to),e="cmwizard menu="+b.menu+(""===e?e:" "+e);d.altCode&&d.altCode===e||(d.altCode=e,d.altSettings=P(e,c));a.find(".cmw-demo-alternative").addClass("updated").toggleClass("error",
16
+ !1===d.altSettings);return!1===d.altSettings?!1:g.extend({},d.altSettings)},H=function(b,a,c){var d="tick"===c?a._items_sep:a._exclude_sep,e=[],l="tick"===c?"_items":"_exclude",l=a[l]?g.grep(a[l].split(d),function(a){return/\+$/.test(a)?(e.push(parseInt(a,10)),!a):!!a}):[],l=d+l.join(d)+d,e=d+e.join(d)+d;b=b.each(function(){var a=g(this),b=a.data(),q=-1<e.indexOf(d+b.itemid+d),b=q||-1<l.indexOf(d+b.itemid+d);a.toggleClass("cmw-has-"+c,b).toggleClass("cmw-inherit-"+c,q)});return b.filter(".cmw-inherit-"+
17
+ c).find("li").removeClass("cmw-has-"+c+" cmw-inherit-"+c).add(b.filter(".cmw-has-"+c))},x=function(b,a){return(b?b:a)[b?"find":"closest"](u("onchange",1))},M=function(b,a){var c=[],d=b.match(/^(\d+)(\+|-)?$/),e,d=d?[parseInt(d[1],10),d[2]||""]:[];if(0<d[0])for(e=1;e<=a;e++)(e===d[0]||"-"===d[1]&&e<d[0]||"+"===d[1]&&e>d[0])&&c.push(".level-"+e);return c.join(",")},N=function(b,a){var c=b.find(".cmw-demo-themenu-ul"),d=c.find(".picked"),e="",l=a.hide_title?"":a.title,f=0,m=b.find(".cmw-demo-theoutput-wrap").empty(),
18
+ q=["menu-widget"],s={};if(d.length&&m.length){(l=c.find(".title-from-item").children(".cmw-item").text()||"")||a.hide_title||(l=a.title||"");for(d.each(function(b){var c=g(this),d=c.data(),l=d.trace?d.trace.toString().split(","):[];b=d.itemid.toString();var m=1,c=c.children(".cmw-item");if(!a.flat_output)for(s[b]=1,b=0;b<l.length;b++)s[l[b]]&&m++;if(f)if(m>f)e+=a.ol_sub?"<ol>":"<ul>";else{for(;f>m;)--f,e+="</li>"+(a.ol_sub?"</ol>":"</ul>");e+="</li>"}e+='<li class="cmw-level-'+m+(d.included||"")+
19
+ '"><a href="#'+c.data("indx")+'">'+c.text()+"</a>";f=m});1<f;)--f,e+="</li>"+(a.ol_sub?"</ol>":"</ul>");e+="</li>";q.push(b.find(".cmw-demo-fallback").data("fellback"));e=(a.ol_root?"<ol":"<ul")+' class="'+g.trim(q.join(" "))+'">'+e+(a.ol_root?"</ol>":"</ul>");m.html(e);m.find("li").filter(function(){return!!g(this).children("ul, ol").length}).addClass("cmw-has-submenu")}m.length&&l&&(d.length||!a.hide_empty)&&m.prepend("<h3>"+l+"</h3>")},O=function(b,a,c){var d;b.find("optgroup").filter(function(){var a=
20
+ g(this).data().cmwOptgroupIndex===c;a||g(this).remove();return a}).length||(d=g("#"+b.attr("id")+"_ignore").find("optgroup").eq(c).clone(),d.length&&(0<a&&(a=0),b.append(d).val(a)));return a},Q=function(b){b=g(this);var a=b.data(),c=!a.cmwAbsolute,d=b.closest(".ui-dialog"),e=d.find(".ui-dialog-content"),l=parseInt(d.css("top"),10)+(c?1:-1)*g(document).scrollTop();a.cmwAbsolute=c;a.cmwMaxHeight||(a.cmwMaxHeight=e.dialog("option","maxHeight"));b.button("option","icons",{primary:c?"ui-icon-circle-close":
21
+ "ui-icon-circle-check"});d.toggleClass("cmw-assistance-dialog-fixed",!c);e.dialog("option",{maxHeight:c?!c:a.cmwMaxHeight});d.css("top",l);return!1},R=function(b){var a=g(this);b=["current-menu-item","current-menu-parent","current-menu-ancestor"];var c=a.closest(".ui-dialog-content"),d=c.find(".cmw-demo-themenu-ul"),a=a.find("span").not("."+b[0]).parentsUntil(d,"li"),e,l=function(){this.title=this.title+" "+e.replace(" "," & ").replace(/-/g," ")};d.find("."+b.join(",.")).removeClass(b.join(" ")).each(function(){this.title=
22
+ this.title.replace(/\s.*$/,"")});for(d=0;d<a.length;d++)e=1===d?b.join(" "):b[0],a.eq(d).children(".cmw-item").find("span").addClass(e).each(l),1<b.length&&b.shift();z.call(g(c.data().cmwOnchange).get(0));return!1},S=function(b){g(this).closest(".ui-dialog-content").find(".cmw-item").eq(this.href.split("#")[1]).not(":has(.current-menu-item)").trigger("click");this.blur();return!1},T=function(b){b=g(this);var a=b.hasClass("cmw-tick")?"tick":"cross",c=b.parent();b=c.closest(".cmw-demo-themenu-ul");
23
+ var d=c.hasClass("cmw-inherit-"+a),e=d||c.hasClass("cmw-has-"+a),l=e?g([]):c.parentsUntil(b,".cmw-inherit-"+a),f=g(c.closest(".ui-dialog-content").data().cmwOnchange).find("tick"===a?".cmw-setitems":".cmw-exclusions"),m;!b.hasClass("cmw-using-alternative")&&f.length&&(m=b.find(".cmw-has-"+a)[d||l.length?"not":"add"](c),!e||c.children("ul").length&&!b.parent().hasClass("cmw-version-210")?e&&!d&&(m=m.not(c.find(".cmw-has-"+a))):m=m.not(c),m=m.add(l.find("li").not(c)),m=m.map(function(){var b=this===
24
+ c[0]||this===l.get(0)?e:g(this).hasClass("cmw-inherit-"+a);return g(this).data().itemid+(b?"+":"")}).get().join(/(,|^\d+\+?$)/.test(g.trim(f.val())||",")?",":" "),f.val(m).trigger("change"));this.blur();return!1},U=function(b){var a={autoOpen:!1,width:Math.min(.9*g(window).width(),600),maxHeight:g(window).height()-40,modal:!1,containment:"window",create:function(){var a=g(this).closest(".ui-dialog");if(a.hasClass("cmw-assistance-dialog-fixed"))g("<button/>").addClass("cmw-dialog-fixed-absolute").button({label:b.cmwDialogFixed,
25
+ icons:{primary:"ui-icon-circle-check"}}).appendTo(a.find(".ui-dialog-titlebar")).on("click",Q)},dialogClass:"cmw-assistance-dialog cmw-assistance-dialog-fixed"},c=g.map(["SetCurrent","Inclusions","Exclusions","Fallback","Alternative"],function(a){return'<div class="cmw-demo-'+a.toLowerCase()+' cmw-demo-small">'+(b["cmwDialog"+a]||"")+"</div>"}),c=g("<div/>",{id:b.cmwDialogId}).addClass(u("dialog")).append(g("<div/>").addClass("cmw-demo-themenu cmw-version-"+b.cmwDialogVersion.replace(/\./g,"")).html('<em class="cmw-demo-small">'+
26
+ b.cmwDialogPrompt+"</em>")).append(g("<div/>").addClass("cmw-demo-theoutput").html('<em class="cmw-demo-small">'+b.cmwDialogOutput+'</em><em class="cmw-demo-plugin-version cmw-demo-small">v'+b.cmwDialogVersion+"</em>"+c.shift()+'<div class="cmw-demo-theoutput-wrap ui-corner-all"></div>'+c.join(""))).append(g("<div/>").addClass("cmw-demo-theshortcode").html('<code class="ui-corner-all"></code><div class="cmw-find-shortcodes"><a href="#" class="button-secondary '+u("find-shortcodes")+'" data-nonce="'+
27
+ (b.cmwDialogNonce||"")+'" title="'+b.cmwDialogShortcodes+'"><span class="spinner"></span><span>[&hellip;]</span></a></div><div class="cmw-demo-found-shortcodes cmw-demo-small ui-corner-all"></div>'));c.dialog(a);c.find(".cmw-demo-themenu").on("click",".cmw-tick,.cmw-cross",T).on("click",".cmw-item",R);c.find(".cmw-demo-theoutput").on("click","a",S);return c},I=function(b,a){b.dialog("option","title","CMW : "+(a.find(".cmw-widget-title").val()||b.data().cmwUntitled)+" ["+a.find(".cmw-select-menu").find("option:selected").text()+
28
+ "]")},J=function(b){var a=g(b.data().cmwOnchange),c=parseInt(a.find(".cmw-select-menu").val(),10),d=b.find(".cmw-demo-themenu-ul"),e=[],l=0,f="",m=function(a){return 1<a?'<a href="#" class="'+u("colexp")+' ui-icon ui-icon-triangle-1-e" style="left:-'+(2.4*(a-2)+2)+'em;">&nbsp;</a>':""};if(!d.length||d.data("menuid")!==c){for(a.find(".cmw-assist-items optgroup").find("option").each(function(a){for(var b=g(this),c=b.data().cmwLevel;c<e.length;)f+="</li></ul>"+m(e.length),e.pop();c>e.length?f+="<ul>":
29
+ (f+="</li>",e.pop());f+='<li class="level-'+c+'" data-itemid="'+this.value+'" data-level="'+c+'" data-trace="'+e.join(",")+'">';f+='<a href="#" class="cmw-cross ui-corner-all"></a>';f+='<a class="cmw-item ui-corner-all" href="#" data-indx="'+a+'"><span class="ui-corner-all" title="#'+this.value+'">'+g.trim(b.text());f+='</span></a><a href="#" class="cmw-tick ui-corner-all"></a>';e.push(this.value);c>l&&(l=c)});e.length;)f+="</li></ul>"+m(e.length),e.pop();d.remove();b.find(".cmw-demo-themenu").append(g(f).addClass("cmw-demo-themenu-ul").data({maxLevel:l,
30
+ menuid:c}))}};w={setLevels:function(b,a){if(a){var c=b.find(".cmw-branch-start"),d=c.val();c.find("optgroup").each(function(b){var c=g(this),d=c.find("option"),m=d.length,q=c.data();if(b)for(d.slice(a).remove();m<a;)++m,c.append(g("<option/>",{value:m}).text(m));else for(m=(m+1)/2,m>a&&d.each(function(b,c){Math.abs(c.value)>=a&&g(c).remove()});m<a;)c.prepend(g("<option/>",{value:-m}).text(-m+(1<m?"":" ("+q.cmwTextParent+")"))).append(g("<option/>",{value:"+"+m}).text("+"+m+(1<m?"":" ("+q.cmwTextChildren+
31
+ ")"))),++m});/^\d+$/.test(d)?d>a&&c.val("1"):""!==d&&Math.abs(d)>=a&&c.val("");b.find(".cmw-ancestors,.cmw-ancestor-siblings").each(function(){var b=g(this),c=(b.find("option").length+1)/2,d=b.val(),m=Math.max(2,a);Math.abs(d)>=a&&b.val(0>d?1-a:a-1);c!==m&&b.find("optgroup").each(function(a,b){var d=g(b),e=d.data().cmwTextForOption,f;c>m&&d.find("option").slice(m-c).remove();for(f=c;f<m;f++)d.append(g("<option/>",{value:a?f:-f}).text(e.replace("%d",a?f:-f)))})});b.find(".cmw-include-level,.cmw-exclude-level").each(function(){var b=
32
+ g(this),c=b.find("option"),d=(c.length-1)/3,m=b.val(),q=c.eq(2).text(),s=c.eq(3).text();for(c.slice(3*a+1).remove();d<a;)++d,b.append(g("<option/>",{value:d}).text(d)).append(g("<option/>",{value:d+"-"}).text(q.replace(/\d+/,d))).append(g("<option/>",{value:d+"+"}).text(s.replace(/\d+/,d)));parseInt(m,10)>a&&b.val("")});b.find(".cmw-set-levels").each(function(){var b=g(this),c=b.data(),d=c.cmwTextLevels||"",c=c.cmwSetLevels||0,m=b.find("option"),q=m.length-c;b.val()>a&&b.val(m.eq(0).val());for(b.find("option").slice(c+
33
+ a).remove();q<a;)++q,b.append(g("<option/>",{value:q}).text(q+d))})}},setFields:function(b,a){var c=a.find(".cmw-bybranch"),d=a.find(".cmw-byitems").prop("checked"),e=d||!c.prop("checked"),l=a.find(".cmw-assist-items"),f=parseInt(l.val(),10);b.hasClass("cmw-select-menu")?(f=O(l,f,b[0].selectedIndex),this.setLevels(a,(l.find("optgroup").data()||{}).cmwMaxLevel)):b.hasClass("cmw-level")?(e=!0,d=!e,a.find(".cmw-bylevel").prop("checked",e)):b.is(l)?(e=d=!1,c.prop("checked",!e)):b.hasClass("cmw-setitems")?
34
+ (e=d=!0,a.find(".cmw-byitems").prop("checked",d)):b.hasClass("cmw-ancestors")&&"0"===b.val()?a.find(".cmw-ancestor-siblings").val("0"):b.hasClass("cmw-ancestor-siblings")&&"0"!==b.val()&&"0"===a.find(".cmw-ancestors").val()&&a.find(".cmw-ancestors").val(b.val());c=a.find(".cmw-fallback").val();g.each({"-ss":d,"-ud":d||1>a.find(".cmw-depth").val(),"not-br":e,"not-br-ci":e||!!f,"not-fb-pc":e||!!f||"parent"!==c&&"current"!==c,"not-sw":!!a.find(".cmw-switchable").filter(function(){return!g(this).val()}).length},
35
+ function(b,c){a.find(".cmw-disableif"+b).toggleClass("cmw-colour-grey",c)})},shortcode:function(b){var a={menu:b.menu},c="branch"===b.filter,d="items"===b.filter,e,l;b.title&&!b.hide_title&&(a.title=[b.title]);!c&&!d&&1<b.level&&(a.level=b.level);c&&(a.branch=b.branch||"current",b.branch_start&&(a.start_at=[b.branch_start]),"level"===b.start_mode&&(a.start_mode="level"));d&&(a.items=[b._items]);0<b.depth&&(a.depth=b.depth);b.depth_rel_current&&0<b.depth&&(a.depth_rel_current=1);c&&!b.branch&&b.fallback&&
36
+ (a.fallback=[b.fallback],"quit"!==b.fallback&&(b.fallback_siblings&&a.fallback.push("+siblings"),b.fallback_depth&&a.fallback.push(b.fallback_depth)));c&&b.ancestors&&(a.ancestors=b.ancestors,b.ancestor_siblings&&(a.ancestor_siblings=b.ancestor_siblings));b.include_level&&(a.include_level=[b.include_level]);b._exclude&&(a.exclude=[b._exclude]);b.exclude_level&&(a.exclude_level=[b.exclude_level]);d=[];b.title_from_current?d.push("current"):b.title_from_current_root&&d.push("current-root");c&&b.title_from_branch?
37
+ d.push("branch"):c&&b.title_from_branch_root&&d.push("branch-root");d.length&&(a.title_from=d);for(d in{allow_all_root:1,siblings:1,flat_output:1,ol_root:1,ol_sub:1,fallback_ci_parent:1})b[d]&&(a[d]=1);c={contains_current:"",container:"div",container_id:"",container_class:"",menu_class:"menu-widget",widget_class:""};for(d in c)b[d]!==c[d]&&(a[d]=[b[d]]);c={wrap_link:"before",wrap_link_text:"link_before"};for(d in c)(e=b[c[d]].toString().match(/^<(\w+)/))&&e[1]&&(a[d]=[e[1]]);b.switch_if&&b.switch_at&&
38
+ (a.alternative=[b.switch_if,b.switch_at],l=L(b.switch_to));c=[];for(d in a)c.push(g.isArray(a[d])?d+'="'+a[d].join(",")+'"':d+"="+a[d]);return"[cmwizard "+c.join(" ")+(l?"]"+l+"[/cmwizard]":"/]")},structureUpdate:function(b,a,c){var d=-1,e=9999,l=0,f=0,m="",q=null,s,h,p,n,t="menu",r="branch"===a.filter,u="items"===a.filter,x=!r&&!u,w=r&&!a.branch,E=!c&&!!a.switch_if&&!!a.switch_at,A=b.find(".cmw-demo-themenu-ul"),y=A.data().maxLevel,v=A.find(".current-menu-item").closest("li"),G=v.length?v.data().level:
39
+ -1,k=A.find("li").removeData("included").removeClass("title-from-item"),F=a.depth,z=a.depth_rel_current,B=H(k,a,"cross");h=k.length&&v.is(k);a.contains_current!==t||h||(k=g([]));if(E&&C(t,h,k.length,a)&&(q=D(a,b),!1!==q))return q;t="primary";u&&k.length&&(k=H(k,a,"tick"));r&&k.length&&(p=w?v:k.filter("[data-itemid="+a.branch+"]"),p.length?(d=p.data().level||0,k=p.add(p.find("li")),s=p):k=g([]));if(x&&k.length&&1<a.level){h=1;for(n=[];h<a.level;h++)n.push(".level-"+h);k=k.not(n.join(","))}h=k.length&&
40
+ v.is(k);a.contains_current!==t||h||(k=g([]));if(E&&C(t,h,k.length,a)&&(q=D(a,b),!1!==q))return q;t="secondary";if(x&&k.length&&F&&(h=z&&G>=a.level?G:a.level,h+=F,h<=y)){for(n=[];h<=y;h++)n.push(".level-"+h);k=k.not(n.join(","))}if(r&&k.length&&(n=parseInt(a.branch_start,10),n=isNaN(n)||!n?d:a.branch_start.match(/^(\+|-)/)?Math.max(1,d+n):n,w&&a.fallback&&!v.find("li").length&&(m="cmw-fellback-to-"+a.fallback,"quit"===a.fallback?n=y+1:(n="current"===a.fallback||2>d?d:d-1,a.fallback_depth&&(F=a.fallback_depth,
41
+ z=1))),n>y?k=g([]):(n<d&&(p=p.parentsUntil(A,"li.level-"+n)),"level"===a.start_mode&&n<=d&&(1<n||a.allow_all_root)?k=p.parent().find("li"):n<d&&(k=p.add(p.find("li"))),m&&a.fallback_siblings&&k.length&&(1<n||a.allow_all_root)&&(k=k.add(p.siblings("li.level-"+n)))),k.length)){d=n;p=9999;F&&(p=z&&G>=d&&k.filter(v).length?G:d,p+=F,e=p-1);h=1;for(n=[];h<=y;h++)h>=d&&h<p&&n.push(".level-"+h);k=k.filter(n.join(","))}h=k.length&&v.is(k);a.contains_current!==t||h||(k=g([]));if(E&&C(t,h,k.length,a)&&(q=D(a,
42
+ b),!1!==q))return q;t="inclusions";if(r&&k.length){n=s.data().level;if(a.ancestors&&(s.is(k)||n>e)){h=a.ancestors;0>h&&(h=Math.max(1,n+h));d=a.ancestor_siblings;0>d&&(d=Math.max(1,n+d));n=[];for(p=[];h<=y;h++)h<=e&&(n.push(".level-"+h),0<d&&h>=d&&p.push(".level-"+h));h=k.length;n=s.parentsUntil(A,n.join(","));k=k.add(n.not(k).data("included"," cmw-an-included-ancestor"));p.length&&(k=k.add(n.filter(p.join(",")).siblings("li").not(k).data("included"," cmw-an-included-ancestor-sibling")));l+=k.length-
43
+ h}a.siblings&&s.is(k)&&(n=k.length,k=k.add(s.siblings("li").data("included"," cmw-an-included-sibling")),l+=k.length-n)}k.length&&a.include_level&&(p=M(a.include_level,y))&&(n=k.length,k=k.add(A.find(p)),l+=k.length-n);h=k.length&&v.is(k);a.contains_current!==t||h||(k=g([]));if(E&&C(t,h,k.length,a)&&(q=D(a,b),!1!==q))return q;t="output";k.length&&B.length&&(n=k.length,k=k.not(B),f+=n-k.length);k.length&&a.exclude_level&&(p=M(a.exclude_level,y))&&(n=k.length,k=k.not(p),f+=n-k.length);h=k.length&&v.is(k);
44
+ a.contains_current!==t||h||(k=g([]));if(E&&C(t,h,k.length,a)&&(q=D(a,b),!1!==q))return q;a.title_from_current&&v.length?v.addClass("title-from-item"):a.title_from_current_root&&v.length?v.closest(".level-1").addClass("title-from-item"):r&&s&&(a.title_from_branch?s.addClass("title-from-item"):a.title_from_branch_root&&s.closest(".level-1").addClass("title-from-item"));b.find(".cmw-demo-fallback").data("fellback",m).toggleClass("updated",!!m);b.find(".cmw-demo-setcurrent").toggleClass("error",!v.length&&
45
+ (!!a.contains_current||w));c||null!==q||b.find(".cmw-demo-alternative").removeClass("error updated");b.find(".cmw-demo-themenu-ul").toggleClass("cmw-using-alternative",!!c);h={inclusions:l,exclusions:f};for(n in h)p=b.find(".cmw-demo-"+n),p.text(p.text().replace(/\d+$/,h[n])).toggleClass("updated",0<h[n]);A.toggleClass("cmw-demo-filteritems",u).find(".picked").not(k.addClass("picked")).removeClass("picked");return!1},update:function(b){var a=g(b);b=x(0,a);var c=g("#"+b.data().cmwDialogId),d;a.hasClass("cmw-listen")&&
46
+ this.setFields(a,b);d=B(b);c.length&&c.dialog("isOpen")&&(c.dialog("moveToTop"),a.hasClass("cmw-select-menu")&&J(c),a=this.structureUpdate(c,d),!1!==a&&this.structureUpdate(c,a,!0),I(c,b),N(c,a||d));b.add(c).find("code").text(this.shortcode(d))},v210:{setLevels:function(b,a){var c=b.find(".cmw-start-level"),d=c.val(),e=c.find("option").length,l;d>a&&c.val(1);for(c.find("option").slice(a).remove();e<a;)++e,c.append(g("<option/>",{value:e}).text(e));c=b.find(".cmw-depth");d=c.val();e=c.find("option").length;
47
+ l=c.data().cmwTextLevels;d>a&&c.val(0);for(c.find("option").slice(a+1).remove();e<=a;)c.append(g("<option/>",{value:e}).text(e+l)),++e},setFields:function(b,a){var c=a.find(".cmw-showall").prop("checked"),d=a.find(".cmw-showspecific").prop("checked"),e=a.find(".cmw-assist-items"),l=parseInt(e.val(),10);b.hasClass("cmw-select-menu")&&(l=O(e,l,b[0].selectedIndex),this.setLevels(a,(e.find("optgroup").data()||{}).cmwMaxLevel));g.each({"":c||d,"-ss":d,"not-rp":c||d||0<=l,"not-ci":c||d||!!l},function(b,
48
+ c){a.find(".cmw-disableif"+b).toggleClass("cmw-colour-grey",c).find("input,select").prop("disabled",c)})},shortcode:function(b){var a={menu:b.menu},c=0<b.filter,d=!!b.filter&&!c,e;b.title&&(a.title=[b.title]);if(c)switch(b.filter_item){case 0:a.children_of=["current"];break;case -1:a.children_of=["parent"];break;case -2:a.children_of=["root"];break;default:a.children_of=b.filter_item}d&&(a.items=[b._items]);c&&0>b.filter_item&&b.fallback_no_ancestor&&(a.fallback_parent=b.fallback_include_parent_siblings?
49
+ ["siblings"]:b.fallback_include_parent?["parent"]:1);c&&!b.filter_item&&b.fallback_no_children&&(a.fallback_current=b.fallback_nc_include_parent_siblings?["siblings"]:b.fallback_nc_include_parent?["parent"]:1);1<b.start_level&&(a.start_level=b.start_level);0<b.depth&&(a.depth=b.depth);b.depth_rel_current&&0<b.depth&&(a.depth_rel_current=1);d=[];c&&(b.include_parent_siblings?d.push("siblings"):b.include_parent&&d.push("parent"),b.include_ancestors&&d.push("ancestors"),d.length&&(a.include=d));d=[];
50
+ c&&b.title_from_parent&&d.push("parent");b.title_from_current&&d.push("current");d.length&&(a.title_from=d);for(d in{flat_output:1,contains_current:1,ol_root:1,ol_sub:1})b[d]&&(a[d]=1);c={container:"div",container_id:"",container_class:"",menu_class:"menu-widget",widget_class:""};for(d in c)b[d]!==c[d]&&(a[d]=[b[d]]);c={wrap_link:"before",wrap_link_text:"link_before"};for(d in c)(e=b[c[d]].toString().match(/^<(\w+)/))&&e[1]&&(a[d]=[e[1]]);c=[];for(d in a)c.push(g.isArray(a[d])?d+'="'+a[d].join(" ")+
51
+ '"':d+"="+a[d]);return"[custom_menu_wizard "+c.join(" ")+"]"},update:function(b){var a=g(b);b=x(0,a);var c=g("#"+b.data().cmwDialogId),d,e,l,f,m,q,s,h,p,n,t,r,u;a.hasClass("cmw-listen")&&this.setFields(a,b);if(c.length&&c.dialog("isOpen")){c.dialog("moveToTop");a.hasClass("cmw-select-menu")&&J(c);f=B(b);d=!f.filter;a=0<f.filter;e=!d&&!a;m=f.include_parent;q=f.include_parent_siblings;s=c.find(".cmw-demo-themenu-ul");l=s.data().maxLevel;p=s.find(".current-menu-item").closest("li");n=p.length?p.data().level:
52
+ -1;h=s.find("li").removeData("included").removeClass("title-from-item");e&&(h=H(h,f,"tick"));h.length&&!p.length&&(f.contains_current||a&&1>f.filter_item)&&(h=g([]));h.length&&a&&(0<f.filter_item?r=h.filter("[data-itemid="+f.filter_item+"]"):f.filter_item?1===n&&f.fallback_no_ancestor?(r=p,m=m||f.fallback_include_parent,q=q||f.fallback_include_parent_siblings,t="cmw-fellback-to-current"):r=1===n?s:-1>f.filter_item?s.find(".current-menu-ancestor").eq(0).closest("li"):s.find(".current-menu-parent").closest("li"):
53
+ p.find("li").length?r=p:f.fallback_no_children&&(r=s.find(".current-menu-parent").closest("li"),r.length||(r=s),m=m||f.fallback_nc_include_parent,q=q||f.fallback_nc_include_parent_siblings,t="cmw-fellback-to-parent"));if(h.length)if(d)for(u=f.depth_rel_current&&f.depth&&p.length&&n>=f.start_level?n+f.depth-1:f.depth?f.start_level+f.depth-1:9999,d=1;d<=l;d++){if(d<f.start_level||d>u)h=h.not(".level-"+d)}else r&&r.length?(u=f.depth_rel_current&&f.depth&&p.length&&r.has(p[0]).length?n-1+f.depth:f.depth?
54
+ Math.max((r.data().level||0)+f.depth,f.start_level+f.depth-1):9999,h=r.find("li").filter(function(){var a=g(this).data().level;return a>=f.start_level&&a<=u})):a&&(h=g([]));h.length&&a&&r&&r.is("li")&&(q&&(h=h.add(r.siblings("li").data("included"," cmw-an-included-parent-sibling")),m=!0),f.include_ancestors&&(h=h.add(r.parentsUntil(s,"li").data("included"," cmw-an-included-ancestor")),m=!0),m&&(h=h.add(r.data("included"," cmw-the-included-parent"))));!h.length||!f.contains_current||p.length&&h.filter(p).length||
55
+ (h=g([]));f.title_from_parent&&h.length&&r&&r.is("li")?r.addClass("title-from-item"):f.title_from_current&&h.length&&p.addClass("title-from-item");t=h.length?t:"";c.find(".cmw-demo-fallback").data("fellback",t).toggleClass("updated",!!t);c.find(".cmw-demo-setcurrent").toggleClass("error",!p.length&&(f.contains_current||a&&1>f.filter_item));s.toggleClass("cmw-demo-filteritems",e).find(".picked").not(h.addClass("picked")).removeClass("picked");I(c,b);N(c,f);c.find("code").text(this.shortcode(f))}}}};
56
+ g(document).on("change",u("onchange",1),z).on("click",u("assist",1),function(b){b=g(this);b=x(0,b);var a=b.data(),c=g("#"+a.cmwDialogId);c.length||(c=U(a).data({cmwOnchange:"#"+b.attr("id"),cmwUntitled:"["+a.cmwDialogUntitled+"]"}));c.dialog("isOpen")?c.dialog("close"):(J(c),I(c,b),c.dialog("open"),z.call(b[0]));this.blur();return!1}).on("click",u("fieldset",1),function(b){b=g(this);var a=b.next(".cmw-fieldset-state"),c=!a.prop("checked");a.length&&(a.prop("checked",c),b.toggleClass("cmw-collapsed-fieldset",
57
+ c),a.next("div")[c?"slideUp":"slideDown"]());this.blur();return!1}).on("click",".widget-action,.widget-control-close",function(b){b=g(this).closest("div.widget");var a=b.parent();a.hasClass("customize-control-widget_form")&&!a.hasClass("expanded")||x(b).each(function(){var a=g("#"+g(this).data().cmwDialogId);a.length&&a.dialog("isOpen")&&a.dialog("close")})}).on("click",".widget-control-remove",function(b){x(g(this).closest("div.widget")).each(function(){var a=g("#"+g(this).data().cmwDialogId);a.length&&
58
+ (a.dialog("destroy"),a.remove())})}).on("click",u("colexp",1),function(b){b=/1-e/.test(this.className)?"slideUp":"slideDown";g(this).toggleClass("ui-icon-triangle-1-s ui-icon-triangle-1-e").prev("ul")[b]();return!1}).on("click",u("find-shortcodes",1),function(b){b=g(this);var a=b.parent().parent();ajaxurl&&!a.hasClass("cmw-ajax-fetching")&&(a.hasClass("cmw-ajax-showing")?a.removeClass("cmw-ajax-showing"):(a.addClass("cmw-ajax-fetching"),g.get(ajaxurl,{action:"cmw-find-shortcodes",_wpnonce:b.data().nonce}).done(function(b){b&&
59
+ "0"!==b&&(a.find(".cmw-demo-found-shortcodes").html(g(b).find("response_data").text()),a.addClass("cmw-ajax-showing"))}).always(function(b){a.removeClass("cmw-ajax-fetching")})));this.blur();return!1}).on("click",u("legacy-close",1),function(){g(this).parent().remove();return!1});window.Custom_Menu_Wizard_Widget&&g(window.Custom_Menu_Wizard_Widget.trigger||[]).trigger("change")});
custom-menu-wizard.php CHANGED
@@ -3,13 +3,20 @@
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.4
7
  * Author: Roger Barrett
8
  * Author URI: http://www.wizzud.com/
9
  * License: GPL2+
10
  */
11
  defined( 'ABSPATH' ) or exit();
12
  /*
 
 
 
 
 
 
 
13
  * v3.0.4 change log
14
  * - fixed bug in the display of the "No Current Item!" warning in the "assist"
15
  * - corrected the enabling/disabling of a couple of fields in the widget form, and tweaked the indentation for better responsiveness
@@ -132,7 +139,7 @@ if( !class_exists( 'Custom_Menu_Wizard_Plugin' ) ){
132
  //declare the main plugin class...
133
  class Custom_Menu_Wizard_Plugin {
134
 
135
- public static $version = '3.0.4';
136
  public static $script_handle = 'custom-menu-wizard-plugin-script';
137
  protected static $instance;
138
 
@@ -150,7 +157,12 @@ if( !class_exists( 'Custom_Menu_Wizard_Plugin' ) ){
150
  //add customizer support...
151
  add_action( 'customize_controls_enqueue_scripts', array( &$this, 'enqueue_styles' ) );
152
  add_action( 'customize_controls_enqueue_scripts', array( &$this, 'enqueue_scripts' ) );
153
-
 
 
 
 
 
154
  } //end __construct()
155
 
156
  /**
@@ -178,6 +190,11 @@ if( !class_exists( 'Custom_Menu_Wizard_Plugin' ) ){
178
  public function enqueue_scripts(){
179
 
180
  //script is pre-registered - see this->register_scripts() - so that it can be localized if need be (like for accessibility mode)
 
 
 
 
 
181
  wp_enqueue_script( self::$script_handle );
182
 
183
  } //end enqueue_scripts()
@@ -244,7 +261,7 @@ if( !class_exists( 'Custom_Menu_Wizard_Plugin' ) ){
244
  } //end update_message()
245
 
246
  /**
247
- * hooked into wp_ajax_cmw-find-shortcodes action : handle ajax request to find posts containing CMW shortcodes
248
  */
249
  public function ajax_find_shortcodes(){
250
 
@@ -395,6 +412,32 @@ if( !class_exists( 'Custom_Menu_Wizard_Plugin' ) ){
395
 
396
  } //end widget_and_shortcode()
397
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
398
  /**
399
  * shortcode processing for [cmwizard option="" option="" ...] (as of v3.0.0)
400
  *
@@ -434,6 +477,85 @@ if( !class_exists( 'Custom_Menu_Wizard_Plugin' ) ){
434
  public function shortcode($atts, $content, $tag){
435
 
436
  $html = '';
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
437
  $ok = false;
438
 
439
  // NB csv = comma or space separated list...
@@ -460,7 +582,7 @@ if( !class_exists( 'Custom_Menu_Wizard_Plugin' ) ){
460
  //exclusions...
461
  'exclude' => '', // csv of menu item ids (an id may have a '+' appended, for inheritance, eg. '23+')
462
  'exclude_level' => '', // digit, possibly appended with a '+' or '-', eg. '2', '2+', or '2-'
463
- 'contains_current' => '', // menu|primary|secondary|output
464
  //determines fallback (current|parent|quit) and, optionally, fallback_siblings and/or fallback_depth...
465
  'fallback' => '', //eg. 'quit', or 'current' or 'current+siblings' or 'parent+siblings,2' or 'parent,1'
466
  //switches...
@@ -475,6 +597,8 @@ if( !class_exists( 'Custom_Menu_Wizard_Plugin' ) ){
475
  'container_class' => '',
476
  'menu_class' => 'menu-widget',
477
  'widget_class' => '',
 
 
478
  //determines before & after...
479
  'wrap_link' => '', // a tag name (eg. div, p, span, etc)
480
  //determines link_before & link_after...
@@ -484,15 +608,25 @@ if( !class_exists( 'Custom_Menu_Wizard_Plugin' ) ){
484
  //utility : doesn't run widget! instead, lists all posts/pages that contain a CMW shortcode...
485
  'findme' => 0
486
  ),
487
- apply_filters(
488
- 'custom_menu_wizard_shortcode_attributes',
489
- array_merge( (array)$atts, array('cmwv' => self::$version) )
490
- ),
491
- $tag // since WP3.6 this allows use of shortcode_atts_cmwizard filter, applied by shortcode_atts()
 
 
 
 
492
  );
493
 
 
 
 
 
 
 
494
  if( !empty( $instance['findme'] ) ){
495
- return $this->find_shortcodes( $instance );
496
  }
497
 
498
  //in order of priority...
@@ -625,64 +759,54 @@ if( !class_exists( 'Custom_Menu_Wizard_Plugin' ) ){
625
  }
626
  unset( $instance['wrap_link_text'] );
627
 
628
- //handle widget_class here because we have full control over $before_widget...
629
- $before_widget_class = array(
630
- 'widget_custom_menu_wizard',
631
- 'shortcode_custom_menu_wizard'
632
- );
633
- $instance['widget_class'] = empty( $instance['widget_class'] ) ? '' : esc_attr( trim ( $instance['widget_class'] ) );
634
- if( !empty( $instance['widget_class'] ) ){
635
- foreach( explode(' ', $instance['widget_class'] ) as $i ){
636
- if( !empty( $i ) && !in_array( $i, $before_widget_class ) ){
637
- $before_widget_class[] = $i;
638
  }
639
- }
 
 
 
 
 
 
640
  }
641
- unset( $instance['widget_class'] );
642
 
643
  //turn on hide_empty...
644
  $instance['hide_empty'] = 1;
645
  }
646
 
647
- if( $ok ){
648
- //not used by the plugin, but could be used in the widget code to tell whether it was being
649
- //run as a result of a widget or a shortcode?...
650
- $instance['shortcode'] = true;
651
- //allow the element that wraps the widget title to be changed from an h2 (the WP default) to another tag...
652
- //note : does not allow for changing the class, or for removing the wrapping element
653
- // for a class override, add CSS rule for
654
- // .shortcode_custom_menu_wizard .widgettitle { ..... }
655
- // can also be overriden using the 'custom_menu_wizard_shortcode_widget_args' filter (applied below)
656
- $instance['title_tag'] = esc_attr( trim( $instance['title_tag'] ) );
657
- if( empty( $instance['title_tag'] ) ){
658
- //default to H2...
659
- $instance['title_tag'] = 'h2';
660
- }
661
- //apart from before_widget, these are lifted from the_widget() (wp-includes/widgets.php)...
662
- $sidebar_args = array(
663
- 'before_widget' => '<div class="' . implode( ' ', $before_widget_class ) . '">',
664
- 'after_widget' => '</div>',
665
- 'before_title' => '<' . $instance['title_tag'] . ' class="widgettitle">',
666
- 'after_title' => '</' . $instance['title_tag'] . '>'
667
- );
668
- unset( $instance['title_tag'] );
669
 
670
- ob_start();
671
- the_widget(
672
- 'Custom_Menu_Wizard_Widget',
673
- apply_filters(
674
- 'custom_menu_wizard_shortcode_settings',
675
- array_merge( $instance, array('cmwv' => self::$version) )
676
- ),
677
- apply_filters(
678
- 'custom_menu_wizard_shortcode_widget_args',
679
- array_merge( $sidebar_args, array('cmwv' => self::$version) )
680
- ) );
681
- $html = ob_get_clean();
 
 
 
 
 
 
 
 
682
  }
683
- return empty($html) ? '' : $html;
684
 
685
- } //end shortcode()
686
 
687
  /**
688
  * shortcode processing for [custom_menu_wizard option="" option="" ...] (as of v2.1.0)
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.1.0
7
  * Author: Roger Barrett
8
  * Author URI: http://www.wizzud.com/
9
  * License: GPL2+
10
  */
11
  defined( 'ABSPATH' ) or exit();
12
  /*
13
+ * v3.1.0 change log
14
+ * - added an Alternative section which takes a cmwizard shortcode and conditionally applies it as an entirely new widget configuration
15
+ * - added fallback determination (has to be enabled) for no current item found as using items marked as current_item_parent (first found)
16
+ * - fixed bug in determination of home page pagination pages (?paged=2, etc) as home page still being current item
17
+ * - fixed bug introduced in v3.0.4 that prevented CMW script loading on the customizer page - when the Widget Customizer plugin is loaded - for WordPress v3.8 and below
18
+ * - fixed bug : stop disabling selected fields based on other settings, because this caused the customizer to wipe values that may have been still required
19
+ *
20
  * v3.0.4 change log
21
  * - fixed bug in the display of the "No Current Item!" warning in the "assist"
22
  * - corrected the enabling/disabling of a couple of fields in the widget form, and tweaked the indentation for better responsiveness
139
  //declare the main plugin class...
140
  class Custom_Menu_Wizard_Plugin {
141
 
142
+ public static $version = '3.1.0';
143
  public static $script_handle = 'custom-menu-wizard-plugin-script';
144
  protected static $instance;
145
 
157
  //add customizer support...
158
  add_action( 'customize_controls_enqueue_scripts', array( &$this, 'enqueue_styles' ) );
159
  add_action( 'customize_controls_enqueue_scripts', array( &$this, 'enqueue_scripts' ) );
160
+
161
+ //add filter for encoding a cmwizard shortcode into instance settings...
162
+ add_filter( 'custom_menu_wizard_encode_shortcode', array( $this, 'encode_shortcode' ), 10, 1 );
163
+ //add filter for sanitizing an alternative shortcode setting...
164
+ add_filter( 'custom_menu_wizard_sanitize_alternative', array( $this, 'sanitize_alternative' ), 10, 1 );
165
+
166
  } //end __construct()
167
 
168
  /**
190
  public function enqueue_scripts(){
191
 
192
  //script is pre-registered - see this->register_scripts() - so that it can be localized if need be (like for accessibility mode)
193
+ //BUT on customize screens pre WPv3.9 the script does not get the chance to pre-register before it is
194
+ //asked to enqueue, so this has to check that it is actually registered!...
195
+ if( !wp_script_is( self::$script_handle, 'registered' ) ){
196
+ $this->register_scripts();
197
+ }
198
  wp_enqueue_script( self::$script_handle );
199
 
200
  } //end enqueue_scripts()
261
  } //end update_message()
262
 
263
  /**
264
+ * hooked into wp_ajax_cmw-find-shortcodes action : handle ajax request to find posts containing CMW shortcodes, returning XML
265
  */
266
  public function ajax_find_shortcodes(){
267
 
412
 
413
  } //end widget_and_shortcode()
414
 
415
+ /**
416
+ * hooked into custom_menu_wizard_sanitize_alternative filter : sanitizes an alternative shortcode setting
417
+ * used by this->shortcode_instance, and the widget class
418
+ *
419
+ * @param string $alt Alternative (switch_to setting)
420
+ * @return string
421
+ */
422
+ public function sanitize_alternative( $alt = '' ){
423
+
424
+ if( empty( $alt ) || !is_string( $alt ) ){
425
+ return '';
426
+ }
427
+
428
+ //kill containing square brackets, self-terminators and spaces, then split on square bracket...
429
+ $alt = preg_split( '/[\[\]]/', trim( $alt, ' []/' ) );
430
+ //use the first element, kill tabs, CRLFs and multiple spaces, and retrim for self-terminators and spaces...
431
+ $alt = trim( preg_replace( array( '/[\r\n\t]+/', '/\s\s+/' ), ' ', $alt[0] ), ' /' );
432
+ //remove leading 'cmwizard' tag...
433
+ $alt = preg_replace( '/^cmwizard\s/', '', $alt . ' ' );
434
+ //remove any occurrences of 'menu=whatever' and 'alternative="whatever"' (optional double quotes), and trim spaces...
435
+ $alt = trim( preg_replace( array('/\smenu=[^\s]*\s/', '/\salternative=("[^"]*"|[^\s]*)\s/' ), ' ', ' ' . $alt . ' ' ) );
436
+
437
+ return $alt;
438
+
439
+ } //end sanitize_alternative()
440
+
441
  /**
442
  * shortcode processing for [cmwizard option="" option="" ...] (as of v3.0.0)
443
  *
477
  public function shortcode($atts, $content, $tag){
478
 
479
  $html = '';
480
+ $instance = $this->shortcode_instance( $atts, $tag, $content, true );
481
+ $ok = !empty( $instance );
482
+
483
+ if( $ok && !empty( $instance['findme'] ) ){
484
+ //return the findme output...
485
+ return $this->find_shortcodes( $instance );
486
+ }
487
+
488
+ if( $ok ){
489
+ //handle widget_class here because we have full control over $before_widget...
490
+ $before_widget_class = array(
491
+ 'widget_custom_menu_wizard',
492
+ 'shortcode_custom_menu_wizard'
493
+ );
494
+ $instance['widget_class'] = empty( $instance['widget_class'] ) ? '' : esc_attr( trim ( $instance['widget_class'] ) );
495
+ if( !empty( $instance['widget_class'] ) ){
496
+ foreach( explode(' ', $instance['widget_class'] ) as $i ){
497
+ if( !empty( $i ) && !in_array( $i, $before_widget_class ) ){
498
+ $before_widget_class[] = $i;
499
+ }
500
+ }
501
+ }
502
+ unset( $instance['widget_class'] );
503
+ }
504
+
505
+ if( $ok ){
506
+ //not used by the plugin, but could be used in the widget code to tell whether it was being
507
+ //run as a result of a widget or a shortcode?...
508
+ $instance['shortcode'] = true;
509
+ //allow the element that wraps the widget title to be changed from an h2 (the WP default) to another tag...
510
+ //note : does not allow for changing the class, or for removing the wrapping element
511
+ // for a class override, add CSS rule for
512
+ // .shortcode_custom_menu_wizard .widgettitle { ..... }
513
+ // can also be overriden using the 'custom_menu_wizard_shortcode_widget_args' filter (applied below)
514
+ $instance['title_tag'] = esc_attr( trim( $instance['title_tag'] ) );
515
+ if( empty( $instance['title_tag'] ) ){
516
+ //default to H2...
517
+ $instance['title_tag'] = 'h2';
518
+ }
519
+ //apart from before_widget, these are lifted from the_widget() (wp-includes/widgets.php)...
520
+ $sidebar_args = array(
521
+ 'before_widget' => '<div class="' . implode( ' ', $before_widget_class ) . '">',
522
+ 'after_widget' => '</div>',
523
+ 'before_title' => '<' . $instance['title_tag'] . ' class="widgettitle">',
524
+ 'after_title' => '</' . $instance['title_tag'] . '>'
525
+ );
526
+ unset( $instance['title_tag'] );
527
+
528
+ ob_start();
529
+ the_widget(
530
+ 'Custom_Menu_Wizard_Widget',
531
+ apply_filters(
532
+ 'custom_menu_wizard_shortcode_settings',
533
+ array_merge( $instance, array('cmwv' => self::$version) )
534
+ ),
535
+ apply_filters(
536
+ 'custom_menu_wizard_shortcode_widget_args',
537
+ array_merge( $sidebar_args, array('cmwv' => self::$version) )
538
+ ) );
539
+ $html = ob_get_clean();
540
+ }
541
+
542
+ return empty( $html ) ? '' : $html;
543
+
544
+ } //end shortcode()
545
+
546
+ /**
547
+ * does most of the attribute processing/checking for the cmwizard (only) shortcode
548
+ * is called from shortcode() method *AND* encode_shortcode() method, which is run from a filter enabling
549
+ * settings to be changed at start (after determination of current item) of the widget's walker process.
550
+ *
551
+ * @param array $atts options supplied to the shortcode
552
+ * @param string $tag Shortcode tag
553
+ * @param string $content Within start-end shortcode tags
554
+ * @param boolean $doShortcode True if called from shortcode(), false otherwise
555
+ * @return array|boolean A set of widget instance settings, or false if shortcode is invalid
556
+ */
557
+ public function shortcode_instance( $atts, $tag, $content = '', $doShortcode = false ){
558
+
559
  $ok = false;
560
 
561
  // NB csv = comma or space separated list...
582
  //exclusions...
583
  'exclude' => '', // csv of menu item ids (an id may have a '+' appended, for inheritance, eg. '23+')
584
  'exclude_level' => '', // digit, possibly appended with a '+' or '-', eg. '2', '2+', or '2-'
585
+ 'contains_current' => '', // menu|primary|secondary|inclusions|output
586
  //determines fallback (current|parent|quit) and, optionally, fallback_siblings and/or fallback_depth...
587
  'fallback' => '', //eg. 'quit', or 'current' or 'current+siblings' or 'parent+siblings,2' or 'parent,1'
588
  //switches...
597
  'container_class' => '',
598
  'menu_class' => 'menu-widget',
599
  'widget_class' => '',
600
+ //determines switch_if, switch_at & switch_to (depending on $content)...
601
+ 'alternative' => '', //csv of current|no-current|no-output and menu|primary|secondary|inclusions|output, eg. 'current,menu'
602
  //determines before & after...
603
  'wrap_link' => '', // a tag name (eg. div, p, span, etc)
604
  //determines link_before & link_after...
608
  //utility : doesn't run widget! instead, lists all posts/pages that contain a CMW shortcode...
609
  'findme' => 0
610
  ),
611
+ $doShortcode
612
+ ? apply_filters(
613
+ 'custom_menu_wizard_shortcode_attributes',
614
+ array_merge( (array)$atts, array('cmwv' => self::$version) )
615
+ )
616
+ : (array)$atts,
617
+ $doShortcode
618
+ ? $tag // since WP3.6 this allows use of shortcode_atts_cmwizard filter, applied by shortcode_atts()
619
+ : ''
620
  );
621
 
622
+ //if not decoding a main shortcode then we're looking at an alternative, and alternatives can't be
623
+ //nested, not can they run findme or change the title's tag element...
624
+ if( !$doShortcode ){
625
+ unset( $instance['findme'], $instance['title_tag'], $instance['alternative'] );
626
+ }
627
+
628
  if( !empty( $instance['findme'] ) ){
629
+ return $instance;
630
  }
631
 
632
  //in order of priority...
759
  }
760
  unset( $instance['wrap_link_text'] );
761
 
762
+ //alternative => switch_if, switch_at & switch_to...
763
+ if( !empty( $instance['alternative'] ) ){
764
+ $i = preg_split( '/[\s,]+/', strtolower( $instance['alternative'] ), -1, PREG_SPLIT_NO_EMPTY );
765
+ foreach( $i as $j ){
766
+ if( in_array( $j, array('current', 'no-current', 'no-output' ) ) ){
767
+ $instance['switch_if'] = $j;
768
+ }elseif( in_array( $j, array('menu', 'primary', 'secondary', 'inclusions', 'output') ) ){
769
+ $instance['switch_at'] = $j;
 
 
770
  }
771
+ }
772
+ if( !empty( $instance['switch_if'] ) && !empty( $instance['switch_at'] ) ){
773
+ $instance['switch_to'] = apply_filters( 'custom_menu_wizard_sanitize_alternative', $instance['switch_to'] );
774
+ }else{
775
+ $instance['switch_if'] = $instance['switch_at'] = $instance['switch_to'] = '';
776
+ }
777
+ unset( $instance['alternative'] );
778
  }
 
779
 
780
  //turn on hide_empty...
781
  $instance['hide_empty'] = 1;
782
  }
783
 
784
+ return $ok ? $instance : false;
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
785
 
786
+ } //end shortcode_instance()
787
+
788
+ /**
789
+ * hooked into custom_menu_wizard_encode_shortcode filter : converts a cmwizard shortcode into instance settings fit for
790
+ * the widget() method of Custom_Menu_Wizard_Widget
791
+ *
792
+ * it's important to note that a shortcode processed this way does *NOT* hit the filters that a cmwizard shortcode would
793
+ * normally hit, namely custom_menu_wizard_shortcode_attributes & shortcode_atts_cmwizard
794
+ *
795
+ * @param string $shortcode A full [cmwizard .../] shortcode
796
+ * @return array|boolean Instance settings, or false if error
797
+ */
798
+ public function encode_shortcode( $shortcode = '' ){
799
+
800
+ if( preg_match( '/^cmwizard\s?(.*)$/', rtrim( ltrim( $shortcode, '[ ' ), '] /' ), $m ) > 0 ){
801
+ $instance = $this->shortcode_instance( shortcode_parse_atts( trim( $m[1] ) ), 'cmwizard' );
802
+ if( !empty( $instance ) ){
803
+ $instance['cmwv'] = self::$version;
804
+ $instance = Custom_Menu_Wizard_Widget::cmw_settings( $instance, false, 'widget' );
805
+ }
806
  }
807
+ return empty( $instance ) ? false : $instance;
808
 
809
+ } //end encode_shortcode()
810
 
811
  /**
812
  * shortcode processing for [custom_menu_wizard option="" option="" ...] (as of v2.1.0)
include/class.walker.php CHANGED
@@ -68,6 +68,10 @@ class Custom_Menu_Wizard_Walker extends Walker_Nav_Menu {
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
@@ -141,25 +145,45 @@ class Custom_Menu_Wizard_Walker extends Walker_Nav_Menu {
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
@@ -167,8 +191,25 @@ class Custom_Menu_Wizard_Walker extends Walker_Nav_Menu {
167
  // - 3rd found : just current = a003
168
  // - 4th found : 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
 
@@ -416,6 +457,55 @@ class Custom_Menu_Wizard_Walker extends Walker_Nav_Menu {
416
 
417
  } //end _cmw_set_keep_recursive()
418
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
419
  /**
420
  * legacy : recursively set the keep flag if within specified level/depth
421
  * runs through kids of item passed in : if kid is eligible, sets kid to kept; if grandkids might be eligible, recurse with kid
@@ -443,20 +533,55 @@ class Custom_Menu_Wizard_Walker extends Walker_Nav_Menu {
443
  /**
444
  * pre-filters elements
445
  *
 
 
 
 
 
446
  * @param {object} $args Params supplied to wp_nav_menu()
447
  * @param {array} $elements Menu items
448
  * @return {array} Modified menu items
449
  */
450
  private function _cmw_walk( &$args, $elements ){
451
 
452
- $id_field = $this->db_fields['id']; //eg. = 'db_id'
453
- $parent_field = $this->db_fields['parent']; //eg. = 'menu_item_parent'
 
 
 
 
 
 
 
454
 
455
- $unlimited = 65532;
456
  $topOfBranch = -1;
457
  $continue = true;
458
 
459
- $cmw =& $args->_custom_menu_wizard;
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
460
 
461
  $cmw['_walker']['fellback'] = false;
462
 
@@ -465,14 +590,27 @@ class Custom_Menu_Wizard_Walker extends Walker_Nav_Menu {
465
  $find_level = !$find_items && !$find_branch;
466
  $find_current = $find_branch && empty( $cmw['branch'] );
467
 
468
- //find the current menu item while creating the tree and levels arrays...
469
- $currentItem = $this->_cmw_find_current_item( $elements, $cmw );
470
-
471
  //measuring depth relative to the current item only applies if depth is *not* unlimited...
472
  $depth = intval( $cmw['depth'] );
473
- $depth_rel_current = $cmw['depth_rel_current'] && $depth > 0 && !empty( $currentItem ); //v2.0.0
474
  //no-kids fallback?...
475
  $canFallback = $find_current && in_array( $cmw['fallback'], array('current', 'parent', 'quit') );
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
476
 
477
  //PRIMARY FILTERS...
478
  if( $continue ){
@@ -488,33 +626,28 @@ class Custom_Menu_Wizard_Walker extends Walker_Nav_Menu {
488
  if( $find_branch ){
489
  //topOfBranch gets set to -1 if it can't be determined...
490
  $topOfBranch = $find_current
491
- ? ( empty( $currentItem ) ? -1 : $currentItem )
492
  : ( isset( $this->_cmw_tree[ $cmw['branch'] ] ) ? $cmw['branch'] : -1 );
493
  $theBranchItem = $topOfBranch;
494
  $continue = $topOfBranch > 0;
495
  }
496
  } //end PRIMARIES
497
 
498
- //check for current item...
499
- //v3.0.4 : do this here (rather than above the primary filters) because I might need
500
- // $theBranchItem later on
501
- //NB: check is for *any* requirement for current item, not just 'menu', because I don't want to have to
502
- // continually check for $currentItem being non-empty ($find_current is already coped with in the primaries)
503
- if( $continue && !empty( $cmw['contains_current'] ) ){
504
- $continue = !empty( $currentItem );
 
 
505
  }
506
-
507
- //check for current item...
508
  if( $continue && $cmw['contains_current'] == 'primary' ){
509
- if( $find_level ){
510
- $continue = $this->_cmw_tree[ $currentItem ]['level'] >= $cmw['level'];
511
- }
512
- if( $find_items ){
513
- $continue = in_array( $currentItem, $cmw['__items'] );
514
- }
515
- if( $find_branch ){
516
- $continue = $topOfBranch == $currentItem || in_array( $topOfBranch, $this->_cmw_tree[ $currentItem ]['ancestors'] );
517
- }
518
  }
519
 
520
  //SECONDARY FILTERS...
@@ -629,9 +762,13 @@ class Custom_Menu_Wizard_Walker extends Walker_Nav_Menu {
629
  $continue = $this->_cmw_tree[0]['keepCount'] > 0;
630
  } //end SECONDARIES
631
 
632
- //check for current item...
 
633
  if( $continue && $cmw['contains_current'] == 'secondary' ){
634
- $continue = $this->_cmw_tree[ $currentItem ]['keep'];
 
 
 
635
  }
636
 
637
  //INCLUSIONS...
@@ -686,9 +823,13 @@ class Custom_Menu_Wizard_Walker extends Walker_Nav_Menu {
686
  }
687
  } //end INCLUSIONS
688
 
689
- //check for current item...
 
690
  if( $continue && $cmw['contains_current'] == 'inclusions' ){
691
- $continue = $this->_cmw_tree[ $currentItem ]['keep'];
 
 
 
692
  }
693
 
694
  //EXCLUSIONS...
@@ -696,9 +837,13 @@ class Custom_Menu_Wizard_Walker extends Walker_Nav_Menu {
696
  $continue = $this->_cmw_run_exclusions( $cmw );
697
  } //end EXCLUSIONS
698
 
699
- //check for current item...
 
700
  if( $continue && $cmw['contains_current'] == 'output' ){
701
- $continue = $this->_cmw_tree[ $currentItem ]['keep'];
 
 
 
702
  }
703
 
704
  //check for title_from...
@@ -715,7 +860,7 @@ class Custom_Menu_Wizard_Walker extends Walker_Nav_Menu {
715
  }
716
  }
717
  //might we want the current item's, or root item's, title as the widget title?...
718
- if( !empty( $currentItem ) ){
719
  $cmw['_walker']['current_title'] = $elements[ $this->_cmw_tree[ $currentItem ]['element'][0] ]->title;
720
  if( $this->_cmw_tree[ $currentItem ]['level'] > 1 ){
721
  $topOfBranch = array_slice( $this->_cmw_tree[ $currentItem ]['ancestors'], 1, 1 );
@@ -795,6 +940,11 @@ class Custom_Menu_Wizard_Walker extends Walker_Nav_Menu {
795
  }
796
  unset( $substructure );
797
 
 
 
 
 
 
798
  return $elements;
799
 
800
  } //end _cmw_walk()
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
+ }else{
72
+ //for v3.1.0 we now need to specifically reset max_depth in case we're using the alternative and it has changed
73
+ //from hierarchic output to flat output...
74
+ $max_depth = -1;
75
  }
76
 
77
  } //ends the check for bad max depth, empty elements, or empty cmw args
145
  // If orphans are required, use WordPress's own Custom Menu widget.
146
  if( isset( $this->_cmw_tree[ $parentID ] ) ){
147
  //check for current item (as a menu item ID, ie. a key into the tree)...
148
+ if( $item->current ||
149
+ ( isset( $inheritItems ) && ( $hasCurrentClass = in_array( 'current-menu-item', (array)$item->classes ) ) === true ) ||
150
+ ( isset( $inheritItems ) && !empty( $cmw['fallback_ci_parent'] ) && $item->current_item_parent )
151
+ ){
152
  //should(!) never get either parent and/or ancestor on an item marked as "current", but unfortunately it does occur (grrr!).
153
  //so this has to cope, not only with more than 1 "current" item, but also with "current" items that are incorrectly marked
154
  //as (their own?!) parent and/or ancestor.
 
 
 
155
  //
156
+ //v3.1.0 : there are also occasions when the item is given a class of current-menu-item but the 'current' property is not set
157
+ //on the item - one such occasion being when the home page is set to latest posts (the default 'blogging' setting for Front
158
+ //page displays, see Settings/Reading page) and you navigate to the second (or subsequent) page of listed posts. A menu item
159
+ //that has the "Home Page" url (it's a "custom" menu item type) will fail to match any sort of current url (.../page/2/
160
+ //or .../?paged=2) but does get recognised as being a "front page" url, so gets the class but no property! ON BY DEFAULT!
161
+ //v3.1.0 : also occasions where $item->current_item_parent is set without there being any item with $item->current!
162
+ //eg. open a post, and if there is a Category menu item available (the post has that category) then Category menu item
163
+ //gets marked as current_item_parent. HAS TO BE ENABLED!
164
+ //
165
+ //we're going to look for correctly (solely) marked "current" items and take the first one found
166
+ //failing that, look for a "current" item that is also marked as parent, and, again, use the first one found
167
+ //failing that, look for a "current" item that is also marked as an ancestor, and, again, use the first one found
168
+ //failing that, look for an item classed as "current-menu-item", again using the first one found
169
+ //finally, if enabled, look for an item marked as parent (if it gets used then there's no current!), using first one found
170
+ //
171
+ //array keys, priority order :
172
+ // just current -> parent, not ancestor -> parent and ancestor -> ancestor -> "current-menu-item" -> parent
173
  // first found...
174
  // - a001 : just current
175
  // - b001 : current & parent (not ancestor)
176
  // - c001 : current & parent & ancestor
177
  // - d001 : current & ancestor (not parent)
178
+ // - e001 : "current-menu-item"
179
+ // - f001 : parent (not current)
180
  // next found...
181
  // - a002 : just current
182
  // - b002 : current & parent (not ancestor)
183
  // - c002 : current & parent & ancestor
184
  // - d002 : current & ancestor (not parent)
185
+ // - e002 : "current-menu-item"
186
+ // - f002 : parent (not current)
187
  // etc
188
  //example :
189
  // - 1st found : current & ancestor = d001
191
  // - 3rd found : just current = a003
192
  // - 4th found : current & parent = b004
193
  // - 5th found : just current = a005
194
+ //reverse sort keys alphabetically and a003 comes out on bottom, so third found gets used! (copes with 999 "current"
195
+ //items; should be enough!)
196
+ if( $item->current ){
197
+ if( $item->current_item_ancestor ){
198
+ if( $item->current_item_parent ){
199
+ $j = 'c';
200
+ }else{
201
+ $j = 'd';
202
+ }
203
+ }elseif( $item->current_item_parent ){
204
+ $j = 'b';
205
+ }else{
206
+ $j = 'a';
207
+ }
208
+ }elseif( $hasCurrentClass ){
209
+ $j = 'e';
210
+ }else{
211
+ $j = 'f';
212
+ }
213
  $currentItem[ $j . sprintf( '%03d' , count( $currentItem ) + 1 ) ] = $itemID;
214
  }
215
 
457
 
458
  } //end _cmw_set_keep_recursive()
459
 
460
+ /**
461
+ * switch the current settings for those indicated by a cmwizard shortcode
462
+ *
463
+ * @param object $args The args passed into walk()
464
+ * @param string $at The current processing stage
465
+ * @param boolean $hasCurrent Whether or not current item is in this stage
466
+ * @param boolean $hasOutput Whether or not there will be any output (as best we know so far)
467
+ * @return boolean True if we can use alternative settings
468
+ */
469
+ private function _cmw_switch_settings( &$args, $at = '', $hasCurrent = false, $hasOutput = false ){
470
+
471
+ if( $args->_custom_menu_wizard['switch_at'] == $at && (
472
+ ( $args->_custom_menu_wizard['switch_if'] == 'current' && $hasCurrent ) ||
473
+ ( $args->_custom_menu_wizard['switch_if'] == 'no-current' && !$hasCurrent ) ||
474
+ ( $args->_custom_menu_wizard['switch_if'] == 'no-output' && !$hasOutput )
475
+ ) ){
476
+
477
+ $plugin = Custom_Menu_Wizard_Plugin::init();
478
+
479
+ //if switch_to is empty, it gets defaulted to a minimum
480
+ //trim off square brackets, self-terminators, and spaces...
481
+ $switchTo = trim( $args->_custom_menu_wizard['switch_to'], ' ][/' );
482
+ //if it doesn't start with our shortcode, prepend it...
483
+ if( substr( $switchTo . ' ', 0, 9 ) != 'cmwizard ' ){
484
+ $switchTo = 'cmwizard ' . $switchTo;
485
+ }
486
+ //append our current menu so that it will be used when the shortcode atts are parsed...
487
+ $switchTo = trim( $switchTo ) . ' menu=' . $args->_custom_menu_wizard['menu'];
488
+
489
+ if( ( $new_cmw = $plugin->encode_shortcode( $switchTo ) ) !== false ){
490
+ //store old...
491
+ $old_cmw = array_merge( array(), $args->_custom_menu_wizard );
492
+ //merge new into old, overriding _walker...
493
+ $new_cmw = array_merge( $old_cmw, (array)$new_cmw, array('_walker' => array('alternative' => true)) );
494
+ //overwrite current with new...
495
+ $args->_custom_menu_wizard = $new_cmw;
496
+ //put new and old into the current _walker, so that they become available to the widget
497
+ //instance (as long as there's some output!)...
498
+ $args->_custom_menu_wizard['_walker']['instances'] = array( 'old' => $old_cmw, 'new' => $new_cmw );
499
+ unset( $old_cmw );
500
+
501
+ return true;
502
+ }
503
+ }
504
+
505
+ return false;
506
+
507
+ } //end _cmw_switch_settings()
508
+
509
  /**
510
  * legacy : recursively set the keep flag if within specified level/depth
511
  * runs through kids of item passed in : if kid is eligible, sets kid to kept; if grandkids might be eligible, recurse with kid
533
  /**
534
  * pre-filters elements
535
  *
536
+ * @filters : custom_menu_wizard_walker_change_settings array of current CMW settings; id of current menu item; array of original menu elements
537
+ * gets applied immediately after determination of the current item, and can be used to provide an alternate set of CMW settings
538
+ * based, maybe, on the value (presence/absence?) of a current menu item, or some other specific value in the current settings.
539
+ * if the returned settings don't exactly match those currently in use, then the new ones are used and current item is re-determined.
540
+ *
541
  * @param {object} $args Params supplied to wp_nav_menu()
542
  * @param {array} $elements Menu items
543
  * @return {array} Modified menu items
544
  */
545
  private function _cmw_walk( &$args, $elements ){
546
 
547
+ $id_field = $this->db_fields['id']; //eg. = 'db_id'
548
+ $parent_field = $this->db_fields['parent']; //eg. = 'menu_item_parent'
549
+ $unlimited = 65532;
550
+ //max number of run-throughs is 2!...
551
+ $runCount = 2;
552
+
553
+ $cmw =& $args->_custom_menu_wizard;
554
+
555
+ while( $runCount > 0 ){
556
 
557
+ $runCount--;
558
  $topOfBranch = -1;
559
  $continue = true;
560
 
561
+ //find the current menu item (ID of the menu item) while creating the tree and levels arrays...
562
+ $currentItem = $this->_cmw_find_current_item( $elements, $cmw );
563
+
564
+ //allow (once only!) a filter to change the cmw settings based on the presence (or absence) of a current item...
565
+ //note that not all changes to settings will have any influence; if the walker doesn't use them, and
566
+ //the widget processing subsequent to the wp_nav_menu() call doesn't use them, then they will have no effect!
567
+ //also note that utilising this filter will prevent any subsequent switchable from being actioned (because of the runCount).
568
+ //BE AWARE : indiscriminate changes to the cmw settings have the potential to totally screw up the output!
569
+ $new_cmw = $runCount > 0 ? apply_filters( 'custom_menu_wizard_walker_change_settings', $cmw, $currentItem, $elements ) : false;
570
+ if( $new_cmw !== false && $new_cmw !== $cmw ){
571
+ //store old...
572
+ $old_cmw = array_merge( array(), $cmw );
573
+ //merge new into old, and don't allow modification of _walker...
574
+ $new_cmw = array_merge( $old_cmw, (array)$new_cmw, array('_walker' => array()) );
575
+ //overwrite current with new...
576
+ $args->_custom_menu_wizard = $new_cmw;
577
+ //put new and old into the current _walker, so that they become available to the widget
578
+ //instance (as long as there's some output!)...
579
+ $cmw['_walker']['instances'] = array( 'old' => $old_cmw, 'new' => $new_cmw );
580
+ unset( $old_cmw );
581
+ //back to top of while loop...
582
+ continue;
583
+ }
584
+ unset( $new_cmw );
585
 
586
  $cmw['_walker']['fellback'] = false;
587
 
590
  $find_level = !$find_items && !$find_branch;
591
  $find_current = $find_branch && empty( $cmw['branch'] );
592
 
 
 
 
593
  //measuring depth relative to the current item only applies if depth is *not* unlimited...
594
  $depth = intval( $cmw['depth'] );
595
+ $depth_rel_current = $cmw['depth_rel_current'] && $depth > 0 && $currentItem !== false; //v2.0.0
596
  //no-kids fallback?...
597
  $canFallback = $find_current && in_array( $cmw['fallback'], array('current', 'parent', 'quit') );
598
+ //switchable?...
599
+ //note that switchable does not require switch_to to contain a value!
600
+ $canSwitch = $runCount > 0 && !empty( $cmw['switch_if'] ) && !empty( $cmw['switch_at'] );
601
+
602
+ //check for current item and switch...
603
+ $hasCurrent = $currentItem !== false;
604
+ //no current item means that a current branch filter CAN'T produce output...
605
+ if( $find_current ){
606
+ $continue = $hasCurrent;
607
+ }
608
+ if( $continue && $cmw['contains_current'] == 'menu' ){
609
+ $continue = $hasCurrent;
610
+ }
611
+ if( $canSwitch && $this->_cmw_switch_settings( $args, 'menu', $hasCurrent, $continue ) ){
612
+ continue;
613
+ }
614
 
615
  //PRIMARY FILTERS...
616
  if( $continue ){
626
  if( $find_branch ){
627
  //topOfBranch gets set to -1 if it can't be determined...
628
  $topOfBranch = $find_current
629
+ ? ( $currentItem === false ? -1 : $currentItem )
630
  : ( isset( $this->_cmw_tree[ $cmw['branch'] ] ) ? $cmw['branch'] : -1 );
631
  $theBranchItem = $topOfBranch;
632
  $continue = $topOfBranch > 0;
633
  }
634
  } //end PRIMARIES
635
 
636
+ //check for current item and switch...
637
+ $hasCurrent = $currentItem !== false;
638
+ if( $hasCurrent ){
639
+ if( ( $find_level && $this->_cmw_tree[ $currentItem ]['level'] < $cmw['level'] ) ||
640
+ ( $find_items && !in_array( $currentItem, $cmw['__items'] ) ) ||
641
+ ( $find_branch && $topOfBranch !== $currentItem && !in_array( $topOfBranch, $this->_cmw_tree[ $currentItem ]['ancestors'] ) )
642
+ ){
643
+ $hasCurrent = false;
644
+ }
645
  }
 
 
646
  if( $continue && $cmw['contains_current'] == 'primary' ){
647
+ $continue = $hasCurrent;
648
+ }
649
+ if( $canSwitch && $this->_cmw_switch_settings( $args, 'primary', $hasCurrent, $continue ) ){
650
+ continue;
 
 
 
 
 
651
  }
652
 
653
  //SECONDARY FILTERS...
762
  $continue = $this->_cmw_tree[0]['keepCount'] > 0;
763
  } //end SECONDARIES
764
 
765
+ //check for current item and switch...
766
+ $hasCurrent = $currentItem !== false && $this->_cmw_tree[ $currentItem ]['keep'];
767
  if( $continue && $cmw['contains_current'] == 'secondary' ){
768
+ $continue = $hasCurrent;
769
+ }
770
+ if( $canSwitch && $this->_cmw_switch_settings( $args, 'secondary', $hasCurrent, $continue ) ){
771
+ continue;
772
  }
773
 
774
  //INCLUSIONS...
823
  }
824
  } //end INCLUSIONS
825
 
826
+ //check for current item and switch...
827
+ $hasCurrent = $currentItem !== false && $this->_cmw_tree[ $currentItem ]['keep'];
828
  if( $continue && $cmw['contains_current'] == 'inclusions' ){
829
+ $continue = $hasCurrent;
830
+ }
831
+ if( $canSwitch && $this->_cmw_switch_settings( $args, 'inclusions', $hasCurrent, $continue ) ){
832
+ continue;
833
  }
834
 
835
  //EXCLUSIONS...
837
  $continue = $this->_cmw_run_exclusions( $cmw );
838
  } //end EXCLUSIONS
839
 
840
+ //check for current item and switch...
841
+ $hasCurrent = $currentItem !== false && $this->_cmw_tree[ $currentItem ]['keep'];
842
  if( $continue && $cmw['contains_current'] == 'output' ){
843
+ $continue = $hasCurrent;
844
+ }
845
+ if( $canSwitch && $this->_cmw_switch_settings( $args, 'output', $hasCurrent, $continue ) ){
846
+ continue;
847
  }
848
 
849
  //check for title_from...
860
  }
861
  }
862
  //might we want the current item's, or root item's, title as the widget title?...
863
+ if( $currentItem !== false ){
864
  $cmw['_walker']['current_title'] = $elements[ $this->_cmw_tree[ $currentItem ]['element'][0] ]->title;
865
  if( $this->_cmw_tree[ $currentItem ]['level'] > 1 ){
866
  $topOfBranch = array_slice( $this->_cmw_tree[ $currentItem ]['ancestors'], 1, 1 );
940
  }
941
  unset( $substructure );
942
 
943
+ //kill the run count...
944
+ $runCount--;
945
+
946
+ } //end while
947
+
948
  return $elements;
949
 
950
  } //end _cmw_walk()
include/class.widget.php CHANGED
@@ -59,7 +59,7 @@ class Custom_Menu_Wizard_Widget extends WP_Widget {
59
  }
60
 
61
  //sanitize $instance...
62
- $instance = $this->cmw_settings( $instance, array(), __FUNCTION__ );
63
 
64
  //if no populated menus exist, suggest the user go create one...
65
  if( ( $menus = $this->cmw_scan_menus( $instance['menu'], $instance['branch'] ) ) === false ){
@@ -128,6 +128,7 @@ class Custom_Menu_Wizard_Widget extends WP_Widget {
128
  $isNotByBranch = $instance['filter'] != 'branch'; // disableifnot-br (is NOT Branch filter)
129
  $isNotBranchCurrentItem = $isNotByBranch || !empty( $instance['branch'] ); // disableifnot-br-ci (is NOT "Branch:Current Item")
130
  $isNotFallbackParentCurrent = $isNotBranchCurrentItem || !in_array( $instance['fallback'], array('parent', 'current') ); //disableifnot-fb-pc (is NOT set to fall back to parent or current)
 
131
 
132
  //NB the 'onchange' wrapper holds any text required by the "assist"
133
  ?>
@@ -136,6 +137,7 @@ class Custom_Menu_Wizard_Widget extends WP_Widget {
136
  data-cmw-v36plus='<?php echo $this->cmw_wp_version('3.6', true) ? 'true' : 'false'; ?>'
137
  data-cmw-dialog-prompt='<?php _e('Click an item to toggle &quot;Current Menu Item&quot;'); ?>'
138
  data-cmw-dialog-output='<?php _e('Basic Output'); ?>'
 
139
  data-cmw-dialog-fallback='<?php _e('Fallback invoked'); ?>'
140
  data-cmw-dialog-inclusions='<?php _e('Inclusions : 0'); ?>'
141
  data-cmw-dialog-exclusions='<?php _e('Exclusions : 0'); ?>'
@@ -449,6 +451,17 @@ class Custom_Menu_Wizard_Widget extends WP_Widget {
449
 
450
  </div><!-- end .cmw-disableifnot-br-ci --><?php $this->cmw_disableif( 'pop' ); ?>
451
 
 
 
 
 
 
 
 
 
 
 
 
452
  <?php $this->cmw_close_a_field_section(); ?>
453
 
454
  <?php
@@ -472,7 +485,7 @@ class Custom_Menu_Wizard_Widget extends WP_Widget {
472
  </div>
473
 
474
  <div>
475
- Set Title from:
476
 
477
  <div class="cmw-indented">
478
  <?php $this->cmw_formfield_checkbox( $instance, 'title_from_current',
@@ -503,7 +516,7 @@ class Custom_Menu_Wizard_Widget extends WP_Widget {
503
  </div>
504
 
505
  <div>
506
- Change UL to OL:
507
  <br />
508
  <?php $this->cmw_formfield_checkbox( $instance, 'ol_root',
509
  array(
@@ -631,9 +644,51 @@ class Custom_Menu_Wizard_Widget extends WP_Widget {
631
 
632
  <?php $this->cmw_close_a_field_section(); ?>
633
 
634
- <div class="cmw-shortcode-nojs cmw-small-block"><?php _e('With Javascript disabled, the shortcode below is only guaranteed to be accurate when you <em>initially enter</em> Edit mode!'); ?></div>
635
- <div class="cmw-shortcode-wrap"><code class="widget-<?php echo $this->id_base; ?>-shortcode ui-corner-all"
636
- title="<?php _e('shortcode'); ?>"><?php echo $this->cmw_shortcode( array_merge( $instance, array( 'menu' => $menus['selectedMenu'] ) ) ); ?></code></div>
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
637
 
638
  </div>
639
  <?php
@@ -660,7 +715,7 @@ class Custom_Menu_Wizard_Widget extends WP_Widget {
660
  return $this->cmw_legacy_update( $new_instance, $old_instance );
661
  }
662
 
663
- return $this->cmw_settings(
664
  $new_instance,
665
  //allow a filter to return true, whereby any previous settings (now possibly unused) will be wiped instead of being allowed to remain...
666
  //eg. add_filter( 'custom_menu_wizard_wipe_on_update', [filter_function], 10, 1 ) => true
@@ -688,8 +743,10 @@ class Custom_Menu_Wizard_Widget extends WP_Widget {
688
  }
689
 
690
  //sanitize $instance...
691
- $instance = $this->cmw_settings( $instance, array(), __FUNCTION__ );
692
-
 
 
693
  //v1.1.0 As of WP v3.6, wp_nav_menu() automatically prevents any HTML output if there are no items...
694
  $instance['hide_empty'] = $instance['hide_empty'] && $this->cmw_wp_version('3.6');
695
 
@@ -704,6 +761,12 @@ class Custom_Menu_Wizard_Widget extends WP_Widget {
704
  //no menu, no output...
705
  if ( !empty( $menu ) ){
706
 
 
 
 
 
 
 
707
  if( !empty( $instance['container_class'] ) ){
708
  //the menu-[menu->slug]-container class gets applied by WP UNLESS an alternative
709
  //container class is supplied in the params - I'm going to set the param such that
@@ -713,10 +776,9 @@ class Custom_Menu_Wizard_Widget extends WP_Widget {
713
  }
714
 
715
  $instance['menu_class'] = preg_split( '/\s+/', $instance['menu_class'], -1, PREG_SPLIT_NO_EMPTY );
716
- if( $instance['fallback'] ){
717
- //add a cmw-fellback-maybe class to the menu and we'll remove or replace it later...
718
- $instance['menu_class'][] = 'cmw-fellback-maybe';
719
- }
720
  $instance['menu_class'] = implode( ' ', $instance['menu_class'] );
721
 
722
  $walker = new Custom_Menu_Wizard_Walker;
@@ -738,11 +800,6 @@ class Custom_Menu_Wizard_Widget extends WP_Widget {
738
  );
739
  //for the walker's use...
740
  $params['_custom_menu_wizard']['_walker'] = array();
741
- //unless told not to, put the shortcode equiv. into a data item...
742
- //NB: to turn this off (example):
743
- // add_filter( 'custom_menu_wizard_settings_pre_widget', 'cmw_no_cmws', 10, 2 );
744
- // function cmw_no_cmws( $instance, $id_base ){ $instance['cmws_off'] = true; return $instance; }
745
- $dataCMWS = empty( $instance['cmws_off'] ) ? " data-cmws='" . esc_attr( $this->cmw_shortcode( $instance, true ) ) . "'" : '';
746
  //set wrapper to UL or OL...
747
  if( $instance['ol_root'] ){
748
  $params['items_wrap'] = '<ol id="%1$s" class="%2$s" data-cmwv="' . $instance['cmwv'] . '"' . $dataCMWS . '>%3$s</ol>';
@@ -774,6 +831,12 @@ class Custom_Menu_Wizard_Widget extends WP_Widget {
774
  //only put something out if there is something to put out...
775
  if( !empty( $out ) ){
776
 
 
 
 
 
 
 
777
  //title from : priority is current -> current root -> branch -> branch root...
778
  //note that none actually have to be present in the results
779
  foreach( array('current', 'current_root', 'branch', 'branch_root') as $v){
@@ -790,8 +853,14 @@ class Custom_Menu_Wizard_Widget extends WP_Widget {
790
 
791
  //remove/replace the cmw-fellback-maybe class...
792
  $out = str_replace(
793
- 'cmw-fellback-maybe',
794
- empty( $this->_cmw_walker['fellback'] ) ? '' : 'cmw-fellback-' . $this->_cmw_walker['fellback'],
 
 
 
 
 
 
795
  $out );
796
 
797
  //try to add widget_class (if specified) to before_widget...
@@ -847,6 +916,7 @@ class Custom_Menu_Wizard_Widget extends WP_Widget {
847
  /**
848
  * either pushes, pops, or echoes last of, the disabled attributes array
849
  * note that if accessibility mode is on, nothing should get disabled!
 
850
  *
851
  * @param string $action 'pop' or 'push'
852
  * @param boolean $test What to push
@@ -859,7 +929,9 @@ class Custom_Menu_Wizard_Widget extends WP_Widget {
859
  if( $action == 'push' ){
860
  if( $test && !$this->_cmw_accessibility ){
861
  //append disabled attribute...
862
- $this->_cmw_disableif[] = 'disabled="disabled"';
 
 
863
  //and echo disabled class...
864
  echo ' cmw-colour-grey';
865
  }else{
@@ -1191,7 +1263,7 @@ class Custom_Menu_Wizard_Widget extends WP_Widget {
1191
  * @param string Name of the calling method
1192
  * @return array Sanitized widget settings
1193
  */
1194
- public function cmw_settings( $from_instance, $base_instance, $method = 'update' ){
1195
 
1196
  /* old (pre v3) settings...
1197
  //switches...
@@ -1216,6 +1288,7 @@ class Custom_Menu_Wizard_Widget extends WP_Widget {
1216
  foreach( array(
1217
  'allow_all_root' => 0, //v3.0.0
1218
  'depth_rel_current' => 0,
 
1219
  'fallback_siblings' => 0, //v3.0.0 sort of replaces fallback_include_parent_siblings
1220
  'flat_output' => 0,
1221
  'hide_title' => 0,
@@ -1234,7 +1307,8 @@ class Custom_Menu_Wizard_Widget extends WP_Widget {
1234
  'fs_output' => 1,
1235
  'fs_container' => 1,
1236
  'fs_classes' => 1,
1237
- 'fs_links' => 1
 
1238
  ) as $k => $v ){
1239
 
1240
  if( $method == 'update' ){
@@ -1273,6 +1347,9 @@ class Custom_Menu_Wizard_Widget extends WP_Widget {
1273
  'exclude_level' => '', //v3.0.0 (1 or more digits, possibly with an appended '-' or '+')
1274
  'fallback' => '', //v3.0.0 replace fallback_no_children ('', 'parent', 'current', 'quit')
1275
  'include_level' => '', //v3.0.4 (1 or more digits, possibly with an appended '-' or '+')
 
 
 
1276
  'menu_class' => 'menu-widget',
1277
  'widget_class' => '',
1278
  'cmwv' => ''
@@ -1284,6 +1361,9 @@ class Custom_Menu_Wizard_Widget extends WP_Widget {
1284
  $instance[ $k ] = esc_attr( trim( $instance[ $k ] ) );
1285
  }
1286
  }
 
 
 
1287
 
1288
  //html strings : values are defaults...
1289
  foreach( array(
@@ -1343,9 +1423,6 @@ class Custom_Menu_Wizard_Widget extends WP_Widget {
1343
  }
1344
  unset( $instance['include_root'] );
1345
 
1346
- //holds information determined by the walker...
1347
- $this->_cmw_walker = array();
1348
-
1349
  return $instance;
1350
 
1351
  } //end cmw_settings()
@@ -1449,7 +1526,7 @@ class Custom_Menu_Wizard_Widget extends WP_Widget {
1449
  $args['title_from'] = $n;
1450
  }
1451
  //switches...
1452
- foreach( array('allow_all_root', 'siblings', 'flat_output', 'ol_root', 'ol_sub') as $n ){
1453
  if( $instance[ $n ] ){
1454
  $args[ $n ] = 1;
1455
  }
@@ -1475,6 +1552,11 @@ class Custom_Menu_Wizard_Widget extends WP_Widget {
1475
  $args[ $n ] = array( $m[1] );
1476
  }
1477
  }
 
 
 
 
 
1478
  //build the shortcode...
1479
  $m = array();
1480
  foreach( $args as $n => $v ){
@@ -1488,7 +1570,8 @@ class Custom_Menu_Wizard_Widget extends WP_Widget {
1488
  unset( $args );
1489
 
1490
  //NB at v3.0.0, the shortcode changed from custom_menu_wizard to cmwizard (the previous version is still supported)
1491
- return $asJSON ? json_encode( $m ) : '[cmwizard ' . implode( ' ', $m ) . '/]';
 
1492
 
1493
  } //end cmw_shortcode()
1494
 
59
  }
60
 
61
  //sanitize $instance...
62
+ $instance = self::cmw_settings( $instance, array(), __FUNCTION__ );
63
 
64
  //if no populated menus exist, suggest the user go create one...
65
  if( ( $menus = $this->cmw_scan_menus( $instance['menu'], $instance['branch'] ) ) === false ){
128
  $isNotByBranch = $instance['filter'] != 'branch'; // disableifnot-br (is NOT Branch filter)
129
  $isNotBranchCurrentItem = $isNotByBranch || !empty( $instance['branch'] ); // disableifnot-br-ci (is NOT "Branch:Current Item")
130
  $isNotFallbackParentCurrent = $isNotBranchCurrentItem || !in_array( $instance['fallback'], array('parent', 'current') ); //disableifnot-fb-pc (is NOT set to fall back to parent or current)
131
+ $isNotSwitchable = empty( $instance['switch_if'] ) || empty( $instance['switch_at'] ); // disableifnot-sw (missing either the condition of the processing stage)
132
 
133
  //NB the 'onchange' wrapper holds any text required by the "assist"
134
  ?>
137
  data-cmw-v36plus='<?php echo $this->cmw_wp_version('3.6', true) ? 'true' : 'false'; ?>'
138
  data-cmw-dialog-prompt='<?php _e('Click an item to toggle &quot;Current Menu Item&quot;'); ?>'
139
  data-cmw-dialog-output='<?php _e('Basic Output'); ?>'
140
+ data-cmw-dialog-alternative='<?php _e('Alternative settings'); ?>'
141
  data-cmw-dialog-fallback='<?php _e('Fallback invoked'); ?>'
142
  data-cmw-dialog-inclusions='<?php _e('Inclusions : 0'); ?>'
143
  data-cmw-dialog-exclusions='<?php _e('Exclusions : 0'); ?>'
451
 
452
  </div><!-- end .cmw-disableifnot-br-ci --><?php $this->cmw_disableif( 'pop' ); ?>
453
 
454
+ <div>
455
+ <div class="cmw-indented"><?php _e('If no Current Item can be found:'); ?>
456
+ <br />
457
+ <?php $this->cmw_formfield_checkbox( $instance, 'fallback_ci_parent',
458
+ array(
459
+ 'label' => __('Try items marked as Parent of Current')
460
+ ) ); ?>
461
+ <span class="cmw-small-block cmw-indented"><em class="cmw-colour-grey"><?php _e('This is a last resort to determine a "Current Item"'); ?></em></span>
462
+ </div>
463
+ </div>
464
+
465
  <?php $this->cmw_close_a_field_section(); ?>
466
 
467
  <?php
485
  </div>
486
 
487
  <div>
488
+ <?php _e('Set Title from:'); ?>
489
 
490
  <div class="cmw-indented">
491
  <?php $this->cmw_formfield_checkbox( $instance, 'title_from_current',
516
  </div>
517
 
518
  <div>
519
+ <?php _e('Change UL to OL:'); ?>
520
  <br />
521
  <?php $this->cmw_formfield_checkbox( $instance, 'ol_root',
522
  array(
644
 
645
  <?php $this->cmw_close_a_field_section(); ?>
646
 
647
+ <?php
648
+ /**
649
+ * v3.1.0 start collapsible section : 'Alternative'
650
+ */
651
+ $this->cmw_open_a_field_section( $instance, __('Alternative'), 'fs_alternative' ); ?>
652
+
653
+ <div>
654
+ <?php $this->cmw_assist_link(); ?>
655
+
656
+ <label for="<?php echo $this->get_field_id('switch_if'); ?>" class="cmw-followed-by"><?php _e('On condition:'); ?></label>
657
+ <br /><select id="<?php echo $this->get_field_id('switch_if'); ?>" class="cmw-switchable cmw-listen"
658
+ <?php $this->cmw_disableif(); ?> name="<?php echo $this->get_field_name('switch_if'); ?>">
659
+ <option value="" <?php selected( $instance['switch_if'], '' ); ?>>&nbsp;</option>
660
+ <option value="current" <?php selected( $instance['switch_if'], 'current' ); ?>><?php _e('Current Item is in...'); ?></option>
661
+ <option value="no-current" <?php selected( $instance['switch_if'], 'no-current' ); ?>><?php _e('Current Item is NOT in...'); ?></option>
662
+ <option value="no-output" <?php selected( $instance['switch_if'], 'no-output' ); ?>><?php _e('No Output from...'); ?></option>
663
+ </select>
664
+
665
+ <select id="<?php echo $this->get_field_id('switch_at'); ?>" class="cmw-switchable cmw-listen"
666
+ <?php $this->cmw_disableif(); ?> name="<?php echo $this->get_field_name('switch_at'); ?>">
667
+ <option value="" <?php selected( $instance['switch_at'], '' ); ?>>&nbsp;</option>
668
+ <option value="menu" <?php selected( $instance['switch_at'], 'menu' ); ?>><?php echo _e('Menu'); ?></option>
669
+ <option value="primary" <?php selected( $instance['switch_at'], 'primary' ); ?>><?php echo _e('Primary Filter'); ?></option>
670
+ <option value="secondary" <?php selected( $instance['switch_at'], 'secondary' ); ?>><?php echo _e('Secondary Filter'); ?></option>
671
+ <option value="inclusions" <?php selected( $instance['switch_at'], 'inclusions' ); ?>><?php echo _e('Inclusions'); ?></option>
672
+ <option value="output" <?php selected( $instance['switch_at'], 'output' ); ?>><?php echo _e('Final Output'); ?></option>
673
+ </select>
674
+
675
+ <br />
676
+ <label class="cmw-disableifnot-sw<?php $this->cmw_disableif( 'push', $isNotSwitchable ); ?>"><?php _e('Then switch settings to:'); ?>
677
+ <br /><textarea rows="3" cols="20" <?php $this->cmw_disableif(); ?> id="<?php echo $this->get_field_id('switch_to'); ?>"
678
+ name="<?php echo $this->get_field_name('switch_to'); ?>"
679
+ class="widefat"><?php echo $instance['switch_to']; ?></textarea>
680
+ </label><!-- end .cmw-disableifnot-sw --><?php $this->cmw_disableif( 'pop' ); ?>
681
+ <span class="cmw-small-block cmw-indented"><em class="cmw-colour-grey">Enter/Paste a [cmwizard.../] shortcode</em></span>
682
+
683
+ </div>
684
+
685
+ <?php $this->cmw_close_a_field_section(); ?>
686
+
687
+ <div class="cmw-border-top">
688
+ <div class="cmw-shortcode-nojs cmw-small-block"><?php _e('With Javascript disabled, the shortcode below is only guaranteed to be accurate when you <em>initially enter</em> Edit mode!'); ?></div>
689
+ <div class="cmw-shortcode-wrap"><code class="widget-<?php echo $this->id_base; ?>-shortcode ui-corner-all"
690
+ title="<?php _e('shortcode'); ?>"><?php echo $this->cmw_shortcode( array_merge( $instance, array( 'menu' => $menus['selectedMenu'] ) ) ); ?></code></div>
691
+ </div>
692
 
693
  </div>
694
  <?php
715
  return $this->cmw_legacy_update( $new_instance, $old_instance );
716
  }
717
 
718
+ return self::cmw_settings(
719
  $new_instance,
720
  //allow a filter to return true, whereby any previous settings (now possibly unused) will be wiped instead of being allowed to remain...
721
  //eg. add_filter( 'custom_menu_wizard_wipe_on_update', [filter_function], 10, 1 ) => true
743
  }
744
 
745
  //sanitize $instance...
746
+ $instance = self::cmw_settings( $instance, array(), __FUNCTION__ );
747
+ //holds information determined by the walker...
748
+ $this->_cmw_walker = array();
749
+
750
  //v1.1.0 As of WP v3.6, wp_nav_menu() automatically prevents any HTML output if there are no items...
751
  $instance['hide_empty'] = $instance['hide_empty'] && $this->cmw_wp_version('3.6');
752
 
761
  //no menu, no output...
762
  if ( !empty( $menu ) ){
763
 
764
+ //unless told not to, put the shortcode equiv. into a data item...
765
+ //NB: to turn this off (example):
766
+ // add_filter( 'custom_menu_wizard_settings_pre_widget', 'cmw_no_cmws', 10, 2 );
767
+ // function cmw_no_cmws( $instance, $id_base ){ $instance['cmws_off'] = true; return $instance; }
768
+ $dataCMWS = empty( $instance['cmws_off'] ) ? " data-cmws='" . esc_attr( $this->cmw_shortcode( $instance, true ) ) . "'" : '';
769
+
770
  if( !empty( $instance['container_class'] ) ){
771
  //the menu-[menu->slug]-container class gets applied by WP UNLESS an alternative
772
  //container class is supplied in the params - I'm going to set the param such that
776
  }
777
 
778
  $instance['menu_class'] = preg_split( '/\s+/', $instance['menu_class'], -1, PREG_SPLIT_NO_EMPTY );
779
+ //add cmw-alternate-maybe & cmw-fellback-maybe classes to the menu and we'll remove or replace later...
780
+ $instance['menu_class'][] = 'cmw-alternate-maybe';
781
+ $instance['menu_class'][] = 'cmw-fellback-maybe';
 
782
  $instance['menu_class'] = implode( ' ', $instance['menu_class'] );
783
 
784
  $walker = new Custom_Menu_Wizard_Walker;
800
  );
801
  //for the walker's use...
802
  $params['_custom_menu_wizard']['_walker'] = array();
 
 
 
 
 
803
  //set wrapper to UL or OL...
804
  if( $instance['ol_root'] ){
805
  $params['items_wrap'] = '<ol id="%1$s" class="%2$s" data-cmwv="' . $instance['cmwv'] . '"' . $dataCMWS . '>%3$s</ol>';
831
  //only put something out if there is something to put out...
832
  if( !empty( $out ) ){
833
 
834
+ //check to see if the settings have been changed, either as a result of invoking an alternative
835
+ //configuration, or due to the application of a custom_menu_wizard_walker_change_settings filter...
836
+ if( !empty( $this->_cmw_walker['instances'] ) ){
837
+ $instance = $this->_cmw_walker['instances']['new'];
838
+ }
839
+
840
  //title from : priority is current -> current root -> branch -> branch root...
841
  //note that none actually have to be present in the results
842
  foreach( array('current', 'current_root', 'branch', 'branch_root') as $v){
853
 
854
  //remove/replace the cmw-fellback-maybe class...
855
  $out = str_replace(
856
+ array(
857
+ 'cmw-fellback-maybe',
858
+ 'cmw-alternate-maybe'
859
+ ),
860
+ array(
861
+ empty( $this->_cmw_walker['fellback'] ) ? '' : 'cmw-fellback-' . $this->_cmw_walker['fellback'],
862
+ empty( $this->_cmw_walker['alternative'] ) ? '' : 'cmw-invoked-alternative'
863
+ ),
864
  $out );
865
 
866
  //try to add widget_class (if specified) to before_widget...
916
  /**
917
  * either pushes, pops, or echoes last of, the disabled attributes array
918
  * note that if accessibility mode is on, nothing should get disabled!
919
+ * as of 3.1.0, nothing gets disabled, just coloured grey (incl. legacy versions)!
920
  *
921
  * @param string $action 'pop' or 'push'
922
  * @param boolean $test What to push
929
  if( $action == 'push' ){
930
  if( $test && !$this->_cmw_accessibility ){
931
  //append disabled attribute...
932
+ //v3.1.0 : nothing gets disabled, including any legacy stuff!
933
+ // $this->_cmw_disableif[] = 'disabled="disabled"';
934
+ $this->_cmw_disableif[] = '';
935
  //and echo disabled class...
936
  echo ' cmw-colour-grey';
937
  }else{
1263
  * @param string Name of the calling method
1264
  * @return array Sanitized widget settings
1265
  */
1266
+ public static function cmw_settings( $from_instance, $base_instance = false, $method = 'widget' ){
1267
 
1268
  /* old (pre v3) settings...
1269
  //switches...
1288
  foreach( array(
1289
  'allow_all_root' => 0, //v3.0.0
1290
  'depth_rel_current' => 0,
1291
+ 'fallback_ci_parent' => 0, //v3.1.0 enables fallback determination of current item to item having current_item_parent set
1292
  'fallback_siblings' => 0, //v3.0.0 sort of replaces fallback_include_parent_siblings
1293
  'flat_output' => 0,
1294
  'hide_title' => 0,
1307
  'fs_output' => 1,
1308
  'fs_container' => 1,
1309
  'fs_classes' => 1,
1310
+ 'fs_links' => 1,
1311
+ 'fs_alternative' => 1 //v3.1.0
1312
  ) as $k => $v ){
1313
 
1314
  if( $method == 'update' ){
1347
  'exclude_level' => '', //v3.0.0 (1 or more digits, possibly with an appended '-' or '+')
1348
  'fallback' => '', //v3.0.0 replace fallback_no_children ('', 'parent', 'current', 'quit')
1349
  'include_level' => '', //v3.0.4 (1 or more digits, possibly with an appended '-' or '+')
1350
+ 'switch_if' => '', //v3.1.0 ('', 'current', 'no-current', 'no-output')
1351
+ 'switch_at' => '', //v3.1.0 (same as for contains_current)
1352
+ 'switch_to' => '', //v3.1.0 (a [cmwizard .../] shortcode)
1353
  'menu_class' => 'menu-widget',
1354
  'widget_class' => '',
1355
  'cmwv' => ''
1361
  $instance[ $k ] = esc_attr( trim( $instance[ $k ] ) );
1362
  }
1363
  }
1364
+ if( $method == 'widget' && !empty( $instance['switch_to'] ) ){
1365
+ $instance['switch_to'] = apply_filters( 'custom_menu_wizard_sanitize_alternative', $instance['switch_to'] );
1366
+ }
1367
 
1368
  //html strings : values are defaults...
1369
  foreach( array(
1423
  }
1424
  unset( $instance['include_root'] );
1425
 
 
 
 
1426
  return $instance;
1427
 
1428
  } //end cmw_settings()
1526
  $args['title_from'] = $n;
1527
  }
1528
  //switches...
1529
+ foreach( array('allow_all_root', 'siblings', 'flat_output', 'ol_root', 'ol_sub', 'fallback_ci_parent') as $n ){
1530
  if( $instance[ $n ] ){
1531
  $args[ $n ] = 1;
1532
  }
1552
  $args[ $n ] = array( $m[1] );
1553
  }
1554
  }
1555
+ //alternative...
1556
+ if( !empty( $instance['switch_if'] ) && !empty( $instance['switch_at'] ) ){
1557
+ $args['alternative'] = array( $instance['switch_if'], $instance['switch_at'] );
1558
+ $content = apply_filters( 'custom_menu_wizard_sanitize_alternative', $instance['switch_to'] );
1559
+ }
1560
  //build the shortcode...
1561
  $m = array();
1562
  foreach( $args as $n => $v ){
1570
  unset( $args );
1571
 
1572
  //NB at v3.0.0, the shortcode changed from custom_menu_wizard to cmwizard (the previous version is still supported)
1573
+ //for JSON, don't output content...
1574
+ return $asJSON ? json_encode( $m ) : '[cmwizard ' . implode( ' ', $m ) . ( empty( $content ) ? '/]' : ']' . $content . '[/cmwizard]' );
1575
 
1576
  } //end cmw_shortcode()
1577
 
readme.txt CHANGED
@@ -4,7 +4,7 @@ Donate link: https://www.paypal.com/cgi-bin/webscr?cmd=_s-xclick&hosted_button_i
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: 4.0
7
- Stable tag: 3.0.4
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.
@@ -31,6 +31,7 @@ Features include:
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),
@@ -39,7 +40,13 @@ can be found under [Other Notes](http://wordpress.org/plugins/custom-menu-wizard
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 :
@@ -47,7 +54,7 @@ there are probably a couple of very common scenarios:
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 :
@@ -233,7 +240,7 @@ or below the `Starting at` level, and do not include any items that would break
233
  * **Current Item is in** *select*
234
 
235
  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
236
- for output at a particular stage in the filter proccessing.
237
 
238
  * *"Menu"* : the current menu item has to be somewhere within the selected menu.
239
  * *"Primary Filter"* : the current menu item has to be within the scope of the selected primary filter. So if you selected, say, a child
@@ -245,10 +252,10 @@ or below the `Starting at` level, and do not include any items that would break
245
 
246
  == Fallbacks Section ==
247
 
248
- Fallbacks get applied at the Secondary Filter stage, and their eligibility and application are therefore determined and
249
- governed by the other Secondary Filter settings.
250
 
251
- There is one fallback, and it only comes into play (possibly) when a `Branch` filter
252
  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,
253
  and would normally include some of the current item's descendants (eg. `Starting at` "the Branch", `For Depth` "1 level" does *not* invoke
254
  the fallback).
@@ -281,6 +288,16 @@ The fallback allows for the occasion when the current menu item
281
  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
282
  fallback option to "1"? Or maybe A, B, C, and C's immediate children, by setting "2"?
283
 
 
 
 
 
 
 
 
 
 
 
284
  == Output Section ==
285
 
286
  * **Hierarchical** *radio (default On)*
@@ -364,6 +381,34 @@ The fallback allows for the occasion when the current menu item
364
 
365
  Text or HTML that will be placed immediately after each menu item's link text.
366
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
367
  == SHORTCODE PARAMETERS ==
368
 
369
  *NB. Version 2 documentation is [here](http://plugins.svn.wordpress.org/custom-menu-wizard/tags/3.0.0/v210-readme.html#Shortcode-Parameters).*
@@ -469,7 +514,7 @@ under [Filters Section](http://wordpress.org/plugins/custom-menu-wizard/other_no
469
  for an explanation of the respective settings.
470
 
471
  = fallback =
472
- *string* : There are 2 main options for fallback (ref. [Fallbacks Section](http://wordpress.org/plugins/custom-menu-wizard/other_notes/#Fallbacks-Section) above)...
473
 
474
  * *"parent"* : Sets the widget's `Starting at` Fallback option to "-1 (parent)"
475
  * *"current"* : Sets the widget's `Starting at` Fallback option to "the Current Item"
@@ -481,6 +526,10 @@ Optionally, "+siblings" can also be used (comma-separated, with or without a dep
481
  "current" fallback item should also be included. The order of the comma-separated values is not important, so "current,+siblings,1" is the
482
  same as "current,1,+siblings", and "2,parent" is the same as "parent,2", etc.
483
 
 
 
 
 
484
  = flat_output =
485
  *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.
486
 
@@ -523,6 +572,42 @@ Please note that the shortcode usage - a simple tag name - is much more restrict
523
  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)).
524
  Please note that the shortcode usage - a simple tag name - is much more restrictive than the widget's options, which allow HTML.
525
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
526
  = title_tag =
527
  *string* : An optional tag name (eg. "h1", "h3", etc) to replace the default "h2" used to enclose the widget title.
528
  Please note that this option has no equivalent in the widget options, because it *only* applies when a widget is instantiated via a shortcode.
@@ -561,6 +646,12 @@ Example : `[cmwizard findme=1 title="Posts containing a CMW shortcode..."/]`
561
  [cmwizard menu="animals" branch="small animals" start_at=children contains_current=primary/]
562
  `
563
 
 
 
 
 
 
 
564
  == Installation ==
565
 
566
  1. EITHER Upload the zip package via 'Plugins > Add New > Upload' in your WP Admin
@@ -609,6 +700,9 @@ The red cross to the left of each menu item toggles the Exclusions setting for t
609
  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
610
  work in the same way.
611
 
 
 
 
612
  Once you are happy with the results, having tested all possible settings of "current menu item" (if it applies), then simply Save the widget.
613
  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!).
614
  The widget does not have to Saved to *test* any of the options.
@@ -670,10 +764,18 @@ Note that output from this shortcode extension is restricted to users with edit_
670
  5. Container Section
671
  6. Classes Section
672
  7. Links Section
673
- 8. Widget's "assist"
 
674
 
675
  == Changelog ==
676
 
 
 
 
 
 
 
 
677
  = 3.0.4 =
678
  * bugfix : corrected the display of the "No Current Item!" warning in the "assist"
679
  * bugfix : corrected the enabling/disabling of a couple of fields in the widget form, and tweaked the indentation for better responsiveness
@@ -793,6 +895,11 @@ Note that output from this shortcode extension is restricted to users with edit_
793
 
794
  == Upgrade Notice ==
795
 
 
 
 
 
 
796
  = 3.0.4 =
797
  Fixed a couple of minor bugs with the "assist" and the widget form, and corrected a bug with accessibility mode when javascript is enabled.
798
  Extended Include Root Items to allow selection by level, as is provided for Exclusions by Level (eg. include_root=1 is now include_level="1").
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: 4.0
7
+ Stable tag: 3.1.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.
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
+ * **NEW** Specify an alternative configuration to use under certain conditions (dual-scenario capability)
35
 
36
  Current documentation for the [Widget Options](http://wordpress.org/plugins/custom-menu-wizard/other_notes/#WIDGET-OPTIONS),
37
  and the associated [Shortcode Parameters](http://wordpress.org/plugins/custom-menu-wizard/other_notes/#SHORTCODE-PARAMETERS),
40
  **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
41
  there are probably a couple of very common scenarios:
42
 
43
+ 1. Show an entire menu...
44
+ * Drag a new Custom Menu Wizard widget into the sidebar, and give it a title (if you want one)
45
+ * Select the menu you wish to use (if it's not already selected)
46
+ * Save the widget!
47
+ * *Equivalent shortcode resembles `[cmwizard menu=N title="Your Title"/]`*
48
+
49
+ 2. Show the current menu item, plus any descendants...
50
  * Drag a new Custom Menu Wizard widget into the sidebar, and give it a title (if you want one)
51
  * Select the menu you wish to use (if it's not already selected)
52
  * Open the FILTERS section :
54
  * Save the widget!
55
  * *Equivalent shortcode resembles `[cmwizard menu=N title="Your Title" branch=current/]`*
56
 
57
+ 3. Show just the descendants of the current menu item (if there are any)...
58
  * Drag a new Custom Menu Wizard widget into the sidebar, and give it a title (if you want one)
59
  * Select the menu you wish to use (if it's not already selected)
60
  * Open the FILTERS section :
240
  * **Current Item is in** *select*
241
 
242
  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
243
+ for output at a particular stage in the filter processing.
244
 
245
  * *"Menu"* : the current menu item has to be somewhere within the selected menu.
246
  * *"Primary Filter"* : the current menu item has to be within the scope of the selected primary filter. So if you selected, say, a child
252
 
253
  == Fallbacks Section ==
254
 
255
+ The **"If Current Item has no children"** fallback gets applied at the Secondary Filter stage, and its eligibility and
256
+ application are therefore determined and governed by the other Secondary Filter settings.
257
 
258
+ It only comes into play (possibly) when a `Branch` filter
259
  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,
260
  and would normally include some of the current item's descendants (eg. `Starting at` "the Branch", `For Depth` "1 level" does *not* invoke
261
  the fallback).
288
  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
289
  fallback option to "1"? Or maybe A, B, C, and C's immediate children, by setting "2"?
290
 
291
+ The **"If no Current Item can be found"** fallback is new to v3.1.0. It gets applied right at the start of processing, when determining
292
+ which of the menu items (if any) should be regarded as the unique "Current Item" by this widget. Under certain conditions, WordPress
293
+ will mark an item as being the parent of a current item ... but there won't actually be a current item marked! This occurs, for example,
294
+ when displaying a full post for which there is no specific related menu item, yet there *is* a menu item for a Category that the
295
+ displayed post belongs to : WordPress will then mark the related Category as being the parent of the current item (the post) even though
296
+ it can't mark the post as being the current item (because there's no specific item for it within the menu).
297
+
298
+ Enabling this fallback will make the widget look for these situations - only as a last resort! - and set (one of) the found "parent" item(s)
299
+ as the Current Item.
300
+
301
  == Output Section ==
302
 
303
  * **Hierarchical** *radio (default On)*
381
 
382
  Text or HTML that will be placed immediately after each menu item's link text.
383
 
384
+ == Alternative Section ===
385
+
386
+ This is new at v3.1.0 and provides a limited dual-scenario capability, based on a couple of conditions. For example, let's say you
387
+ want to show the Current Item and its immediate children, *but* if there isn't a Current Item then you want to show the top 2 levels
388
+ of the menu : previously this was not possible solely with CMW, but now you can configure the main widget settings for the "current item"
389
+ scenario, and add an Alternative setting for when no Current Item can be determined.
390
+
391
+ * **On condition** *2 selects*
392
+
393
+ Select the appropriate condition for when your Alternative configuration should be used, and also the stage within the
394
+ Filter processing when this condition should be tested for (similar to the Qualifier, `Current Item is in`). You need
395
+ values in both selects for the Alternative to be considered.
396
+
397
+ * **Then switch settings to** *textarea*
398
+
399
+ This should contain a CMW-generated shortcode equivalent of the configuration that you want to switch to. Please note that leaving
400
+ this empty will **not** prevent the Alternative kicking in if the conditions are set and met! An empty `switch to` will merely default
401
+ to the CMW's base settings (Level 1, unlimited Depth). Also note that Alternatives cannot be nested : a primary configuration is
402
+ allowed one chance to switch and that's it, so providing an Alternative-that-has-an-Alternative will not work.
403
+
404
+ The Assist *will work* with an Alternative - in that it displays the appropriate output - but it can get confusing as to which
405
+ configuration set is being used. There is a message displayed whenever the Alternative kicks in (green if successful, red if it
406
+ should have kicked in but couldn't due to an error in the alternative settings) so please take note of it, because the Assist
407
+ *cannot* be used to modify the Alternative settings, only the primary ones.
408
+
409
+ A bit more information about the Alternative is available
410
+ in [this article](http://www.wizzud.com/2014/10/03/custom-menu-wizard-wordpress-plugin-version-3-1/).
411
+
412
  == SHORTCODE PARAMETERS ==
413
 
414
  *NB. Version 2 documentation is [here](http://plugins.svn.wordpress.org/custom-menu-wizard/tags/3.0.0/v210-readme.html#Shortcode-Parameters).*
514
  for an explanation of the respective settings.
515
 
516
  = fallback =
517
+ *string* : There are 2 main options for the *"If Current Item has no children"* fallback (ref. [Fallbacks Section](http://wordpress.org/plugins/custom-menu-wizard/other_notes/#Fallbacks-Section) above)...
518
 
519
  * *"parent"* : Sets the widget's `Starting at` Fallback option to "-1 (parent)"
520
  * *"current"* : Sets the widget's `Starting at` Fallback option to "the Current Item"
526
  "current" fallback item should also be included. The order of the comma-separated values is not important, so "current,+siblings,1" is the
527
  same as "current,1,+siblings", and "2,parent" is the same as "parent,2", etc.
528
 
529
+ = fallback_ci_parent =
530
+ *switch, off by default, 1 to enable* : See widget's *"If no Current Item can be found"* fallback in the
531
+ [Fallbacks Section](http://wordpress.org/plugins/custom-menu-wizard/other_notes/#Fallbacks-Section) above.
532
+
533
  = flat_output =
534
  *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.
535
 
572
  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)).
573
  Please note that the shortcode usage - a simple tag name - is much more restrictive than the widget's options, which allow HTML.
574
 
575
+ = alternative =
576
+ *string* : This is 2 settings separated by a comma, reflecting the `On condition` options under the
577
+ [Alternative Section](http://wordpress.org/plugins/custom-menu-wizard/other_notes/#Alternative-Section) above.
578
+ Possible values are:
579
+
580
+ * One of "current", "no-current" or "no-output" : the condition to test for
581
+ * One of "menu", "primary", "secondary", "inclusions", or "output" : the stage at which to test the condition
582
+
583
+ Eg. `alternative="no-current,inclusions"` would test for the absence of a Current Item in the filtered menu items, having completed
584
+ the Inclusions stage, and attempt to switch to the Alternative settings.
585
+
586
+ The actual Alternative settings - a cut-down shortcode - are placed as content between the shortcodes start and end tags, and this is
587
+ the only time that the use of a self-terminating shortcode is not sufficient. When specifiying the Alternative settings, *do not*
588
+ include the square brackets, otherwise WordPress will interpret it as a nested shortcode!
589
+
590
+ For example, to set a primary configuration of "show Current Branch plus any kids", with an Alternative of "show top 2 levels" if no
591
+ current item can be found anywhere in the menu...
592
+
593
+ `[cmwizard menu=NN branch=current alternative="no-current,menu"]depth=2[/cmwizard]`
594
+
595
+ Alternatively, you could switch it around and say the primary configuration is "show top 2 levels", with an Alternative of
596
+ "show Current Branch plus kids" if a current item *can* be found within the menu...
597
+
598
+ `[cmwizard menu=NN depth=2 alternative="current,menu"]branch=current[/cmwizard]`
599
+
600
+ Note that Alternative (eg. "branch=current") does not require a `menu` option, because you can't change the menu so the primary
601
+ configuration's setting is always used.
602
+
603
+ As ever, the best way to construct a full shortcode, including an alternative, is to use the Assist : Use one instance of the CMW
604
+ widget to build your Alternative settings, copy the equivalent shortcode into the Alternative option of a second instance of the CMW
605
+ widget, and then continue configuring that second instance to be your primary configuration; your final shortcode can simply be lifted
606
+ from the second instance!
607
+
608
+ A bit more information about the Alternative option is available
609
+ in [this article](http://www.wizzud.com/2014/10/03/custom-menu-wizard-wordpress-plugin-version-3-1/).
610
+
611
  = title_tag =
612
  *string* : An optional tag name (eg. "h1", "h3", etc) to replace the default "h2" used to enclose the widget title.
613
  Please note that this option has no equivalent in the widget options, because it *only* applies when a widget is instantiated via a shortcode.
646
  [cmwizard menu="animals" branch="small animals" start_at=children contains_current=primary/]
647
  `
648
 
649
+ * Show the entire "main" menu entitled "Main Menu" *unless* there's a current menu item, in which case show the current menu item, its siblings and its immediate children, and entitle it "Nearest and Dearest!"
650
+
651
+ `
652
+ [cmwizard menu=main title="Main Menu"]title="Nearest and Dearest!" branch=current depth=2 siblings=1[/cmwizard]
653
+ `
654
+
655
  == Installation ==
656
 
657
  1. EITHER Upload the zip package via 'Plugins > Add New > Upload' in your WP Admin
700
  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
701
  work in the same way.
702
 
703
+ Note that if a green "Alternate settings" message is showing then the ticks and crosses buttons will show the approriate Alternative
704
+ settings but they will be slightly opaque and they will *not* be clickable!
705
+
706
  Once you are happy with the results, having tested all possible settings of "current menu item" (if it applies), then simply Save the widget.
707
  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!).
708
  The widget does not have to Saved to *test* any of the options.
764
  5. Container Section
765
  6. Classes Section
766
  7. Links Section
767
+ 8. Alternative Section
768
+ 9. Widget's "assist"
769
 
770
  == Changelog ==
771
 
772
+ = 3.1.0 =
773
+ * addition : new Alternative section which takes a cmwizard shortcode and conditionally applies it as an entirely new widget configuration
774
+ * addition : new fallback switch which enables an item marked as current_item_parent to be used as current item when no other current item is found
775
+ * bugfix : updated the determination of current item so that a paged (?paged=2, etc) Home page still shows Home page as being current
776
+ * bugfix : fixed code introduced in v3.0.4 that prevented CMW script loading on the customizer page - when the Widget Customizer plugin is loaded - for WordPress v3.8 and below
777
+ * bugfix : stop disabling selected fields based on other settings, because this caused the customizer to wipe values that may have been still required
778
+
779
  = 3.0.4 =
780
  * bugfix : corrected the display of the "No Current Item!" warning in the "assist"
781
  * bugfix : corrected the enabling/disabling of a couple of fields in the widget form, and tweaked the indentation for better responsiveness
895
 
896
  == Upgrade Notice ==
897
 
898
+ = 3.1.0 =
899
+ Added an Alternative section which gives a dual-scenario capability, such as "show Config A, but if a current item is present then show Config B"
900
+ Added a new option to enable a "last resort" determination of current item as being an item marked as the parent of a current item, even though no current item is actually present.
901
+ Fixed a bug with the paging of a Home blogging page, and stopped disabling widget fields so that the customizer does not "lose" values. Also fixed customizer for WordPress pre v3.9 running Widget Customizer plugin.
902
+
903
  = 3.0.4 =
904
  Fixed a couple of minor bugs with the "assist" and the widget form, and corrected a bug with accessibility mode when javascript is enabled.
905
  Extended Include Root Items to allow selection by level, as is provided for Exclusions by Level (eg. include_root=1 is now include_level="1").