Issues (377)

modules/field-dependencies/field-dependencies.js (2 issues)

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++ ) {
0 ignored issues
show
Coding Style Performance introduced by
The use of object.length inside a loop condition is not allowed; assign the return value to a variable and use the variable in the loop condition instead
Loading history...
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++ ) {
0 ignored issues
show
Coding Style Performance introduced by
The use of object.length inside a loop condition is not allowed; assign the return value to a variable and use the variable in the loop condition instead
Loading history...
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