|
1
|
|
|
var kirkiDependencies = { |
|
|
|
|
|
|
2
|
|
|
|
|
3
|
|
|
listenTo: {}, |
|
4
|
|
|
|
|
5
|
|
|
init: function() { |
|
6
|
|
|
var self = this; |
|
|
|
|
|
|
7
|
|
|
|
|
8
|
|
|
wp.customize.control.each( function( control ) { |
|
9
|
|
|
self.showKirkiControl( control ); |
|
10
|
|
|
} ); |
|
11
|
|
|
|
|
12
|
|
|
_.each( self.listenTo, function( slaves, master ) { |
|
13
|
|
|
_.each( slaves, function( slave ) { |
|
14
|
|
|
wp.customize( master, function( setting ) { |
|
15
|
|
|
var setupControl = function( control ) { |
|
|
|
|
|
|
16
|
|
|
var setActiveState, |
|
|
|
|
|
|
17
|
|
|
isDisplayed; |
|
18
|
|
|
|
|
19
|
|
|
isDisplayed = function() { |
|
20
|
|
|
return self.showKirkiControl( wp.customize.control( slave ) ); |
|
21
|
|
|
}; |
|
22
|
|
|
setActiveState = function() { |
|
23
|
|
|
control.active.set( isDisplayed() ); |
|
24
|
|
|
}; |
|
25
|
|
|
|
|
26
|
|
|
setActiveState(); |
|
27
|
|
|
setting.bind( setActiveState ); |
|
28
|
|
|
control.active.validate = isDisplayed; |
|
29
|
|
|
}; |
|
30
|
|
|
wp.customize.control( slave, setupControl ); |
|
31
|
|
|
} ); |
|
32
|
|
|
} ); |
|
33
|
|
|
} ); |
|
34
|
|
|
}, |
|
35
|
|
|
|
|
36
|
|
|
/** |
|
37
|
|
|
* Should we show the control? |
|
38
|
|
|
* |
|
39
|
|
|
* @since 3.0.17 |
|
40
|
|
|
* @param {string|object} control - The control-id or the control object. |
|
41
|
|
|
* @returns {bool} |
|
42
|
|
|
*/ |
|
43
|
|
|
showKirkiControl: function( control ) { |
|
44
|
|
|
var self = this, |
|
|
|
|
|
|
45
|
|
|
show = true, |
|
46
|
|
|
isOption = ( |
|
47
|
|
|
control.params && // Check if control.params exists. |
|
48
|
|
|
control.params.kirkiOptionType && // Check if option_type exists. |
|
49
|
|
|
'option' === control.params.kirkiOptionType && // We're using options. |
|
50
|
|
|
control.params.kirkiOptionName && // Check if option_name exists. |
|
51
|
|
|
! _.isEmpty( control.params.kirkiOptionName ) // Check if option_name is not empty. |
|
52
|
|
|
), |
|
53
|
|
|
i; |
|
54
|
|
|
|
|
55
|
|
|
|
|
56
|
|
|
if ( _.isString( control ) ) { |
|
57
|
|
|
control = wp.customize.control( control ); |
|
|
|
|
|
|
58
|
|
|
} |
|
59
|
|
|
|
|
60
|
|
|
// Exit early if control not found or if "required" argument is not defined. |
|
61
|
|
|
if ( 'undefined' === typeof control || ( control.params && _.isEmpty( control.params.required ) ) ) { |
|
62
|
|
|
return true; |
|
63
|
|
|
} |
|
64
|
|
|
|
|
65
|
|
|
// Loop control requirements. |
|
66
|
|
|
for ( i = 0; i < control.params.required.length; i++ ) { |
|
67
|
|
|
if ( ! self.checkCondition( control.params.required[ i ], control, isOption, 'AND' ) ) { |
|
68
|
|
|
show = false; |
|
69
|
|
|
} |
|
70
|
|
|
} |
|
71
|
|
|
return show; |
|
72
|
|
|
}, |
|
73
|
|
|
|
|
74
|
|
|
/** |
|
75
|
|
|
* Check a condition. |
|
76
|
|
|
* |
|
77
|
|
|
* @param {Object} requirement - The requirement, inherited from showKirkiControl. |
|
78
|
|
|
* @param {Object} control - The control object. |
|
79
|
|
|
* @param {bool} isOption - Whether it's an option or not. |
|
80
|
|
|
* @param {string} relation - Can be one of 'AND' or 'OR'. |
|
81
|
|
|
*/ |
|
82
|
|
|
checkCondition: function( requirement, control, isOption, relation ) { |
|
83
|
|
|
var self = this, |
|
|
|
|
|
|
84
|
|
|
childRelation = ( 'AND' === relation ) ? 'OR' : 'AND', |
|
85
|
|
|
nestedItems, |
|
86
|
|
|
i; |
|
87
|
|
|
|
|
88
|
|
|
// Tweak for using active callbacks with serialized options instead of theme_mods. |
|
89
|
|
|
if ( isOption && requirement.setting ) { |
|
90
|
|
|
|
|
91
|
|
|
// Make sure we don't already have the option_name in there. |
|
92
|
|
|
if ( -1 === requirement.setting.indexOf( control.params.kirkiOptionName + '[' ) ) { |
|
93
|
|
|
requirement.setting = control.params.kirkiOptionName + '[' + requirement.setting + ']'; |
|
94
|
|
|
} |
|
95
|
|
|
} |
|
96
|
|
|
|
|
97
|
|
|
// If an array of other requirements nested, we need to process them separately. |
|
98
|
|
|
if ( 'undefined' !== typeof requirement[0] && 'undefined' === typeof requirement.setting ) { |
|
99
|
|
|
nestedItems = []; |
|
100
|
|
|
|
|
101
|
|
|
// Loop sub-requirements. |
|
102
|
|
|
for ( i = 0; i < requirement.length; i++ ) { |
|
103
|
|
|
nestedItems.push( self.checkCondition( requirement[ i ], control, isOption, childRelation ) ); |
|
104
|
|
|
} |
|
105
|
|
|
|
|
106
|
|
|
// OR relation. Check that true is part of the array. |
|
107
|
|
|
if ( 'OR' === childRelation ) { |
|
108
|
|
|
return ( -1 !== nestedItems.indexOf( true ) ); |
|
109
|
|
|
} |
|
110
|
|
|
|
|
111
|
|
|
// AND relation. Check that false is not part of the array. |
|
112
|
|
|
return ( -1 === nestedItems.indexOf( false ) ); |
|
113
|
|
|
} |
|
114
|
|
|
|
|
115
|
|
|
// Early exit if setting is not defined. |
|
116
|
|
|
if ( 'undefined' === typeof wp.customize.control( requirement.setting ) ) { |
|
117
|
|
|
return true; |
|
118
|
|
|
} |
|
119
|
|
|
|
|
120
|
|
|
self.listenTo[ requirement.setting ] = self.listenTo[ requirement.setting ] || []; |
|
121
|
|
|
if ( -1 === self.listenTo[ requirement.setting ].indexOf( control.id ) ) { |
|
122
|
|
|
self.listenTo[ requirement.setting ].push( control.id ); |
|
123
|
|
|
} |
|
124
|
|
|
|
|
125
|
|
|
return self.evaluate( |
|
126
|
|
|
requirement.value, |
|
127
|
|
|
wp.customize.control( requirement.setting ).setting._value, |
|
128
|
|
|
requirement.operator |
|
129
|
|
|
); |
|
130
|
|
|
}, |
|
131
|
|
|
|
|
132
|
|
|
/** |
|
133
|
|
|
* Figure out if the 2 values have the relation we want. |
|
134
|
|
|
* |
|
135
|
|
|
* @since 3.0.17 |
|
136
|
|
|
* @param {mixed} value1 - The 1st value. |
|
137
|
|
|
* @param {mixed} value2 - The 2nd value. |
|
138
|
|
|
* @param {string} operator - The comparison to use. |
|
139
|
|
|
* @returns {bool} |
|
140
|
|
|
*/ |
|
141
|
|
|
evaluate: function( value1, value2, operator ) { |
|
142
|
|
|
var found = false; |
|
|
|
|
|
|
143
|
|
|
|
|
144
|
|
|
if ( '===' === operator ) { |
|
145
|
|
|
return value1 === value2; |
|
146
|
|
|
} |
|
147
|
|
|
if ( '==' === operator || '=' === operator || 'equals' === operator || 'equal' === operator ) { |
|
148
|
|
|
return value1 == value2; |
|
149
|
|
|
} |
|
150
|
|
|
if ( '!==' === operator ) { |
|
151
|
|
|
return value1 !== value2; |
|
152
|
|
|
} |
|
153
|
|
|
if ( '!=' === operator || 'not equal' === operator ) { |
|
154
|
|
|
return value1 != value2; |
|
155
|
|
|
} |
|
156
|
|
|
if ( '>=' === operator || 'greater or equal' === operator || 'equal or greater' === operator ) { |
|
157
|
|
|
return value2 >= value1; |
|
158
|
|
|
} |
|
159
|
|
|
if ( '<=' === operator || 'smaller or equal' === operator || 'equal or smaller' === operator ) { |
|
160
|
|
|
return value2 <= value1; |
|
161
|
|
|
} |
|
162
|
|
|
if ( '>' === operator || 'greater' === operator ) { |
|
163
|
|
|
return value2 > value1; |
|
164
|
|
|
} |
|
165
|
|
|
if ( '<' === operator || 'smaller' === operator ) { |
|
166
|
|
|
return value2 < value1; |
|
167
|
|
|
} |
|
168
|
|
|
if ( 'contains' === operator || 'in' === operator ) { |
|
169
|
|
|
if ( _.isArray( value1 ) && _.isArray( value2 ) ) { |
|
170
|
|
|
_.each( value2, function( value ) { |
|
171
|
|
|
if ( value1.includes( value ) ) { |
|
|
|
|
|
|
172
|
|
|
found = true; |
|
173
|
|
|
return false; |
|
174
|
|
|
} |
|
175
|
|
|
} ); |
|
176
|
|
|
return found; |
|
177
|
|
|
} |
|
178
|
|
|
if ( _.isArray( value2 ) ) { |
|
179
|
|
|
_.each( value2, function( value ) { |
|
180
|
|
|
if ( value == value1 ) { // jshint ignore:line |
|
181
|
|
|
found = true; |
|
182
|
|
|
} |
|
183
|
|
|
} ); |
|
184
|
|
|
return found; |
|
185
|
|
|
} |
|
186
|
|
|
if ( _.isObject( value2 ) ) { |
|
187
|
|
|
if ( ! _.isUndefined( value2[ value1 ] ) ) { |
|
188
|
|
|
found = true; |
|
189
|
|
|
} |
|
190
|
|
|
_.each( value2, function( subValue ) { |
|
191
|
|
|
if ( value1 === subValue ) { |
|
192
|
|
|
found = true; |
|
193
|
|
|
} |
|
194
|
|
|
} ); |
|
195
|
|
|
return found; |
|
196
|
|
|
} |
|
197
|
|
|
if ( _.isString( value2 ) ) { |
|
198
|
|
|
if ( _.isString( value1 ) ) { |
|
199
|
|
|
return ( -1 < value1.indexOf( value2 ) && -1 < value2.indexOf( value1 ) ); |
|
200
|
|
|
} |
|
201
|
|
|
return -1 < value1.indexOf( value2 ); |
|
202
|
|
|
} |
|
203
|
|
|
} |
|
204
|
|
|
return value1 == value2; |
|
205
|
|
|
} |
|
206
|
|
|
}; |
|
207
|
|
|
|
|
208
|
|
|
jQuery( document ).ready( function() { |
|
209
|
|
|
kirkiDependencies.init(); |
|
210
|
|
|
} ); |
|
211
|
|
|
|
Since ECMAScript 6, you can create block-scoped vars or constants with the keywords
letorconst. These variables/constants are only valid in the code block where they have been declared.Consider the following two pieces of code:
and
The variable is not defined otuside of its block. This limits bleeding of variables into other contexts.
To know more about this ECMA6 feature, look at the MDN pages on let and const.