PluginProbe
QuadMenu – Mega Menu / 1.8.9
QuadMenu – Mega Menu v1.8.9
3.3.8 3.3.7 3.3.6 trunk 1.8.4 1.8.5 1.8.7 1.8.8 1.8.9 1.9.0 1.9.2 1.9.3 1.9.4 1.9.5 1.9.6 1.9.7 1.9.8 1.9.9 2.0.0 2.0.1 2.0.2 2.0.3 2.0.4 2.0.5 2.0.6 All 88 releases
quadmenu / lib / ReduxCore / inc / extensions / customizer / extension_customizer.js

extension_customizer.js in QuadMenu – Mega Menu 1.8.9, at lib/ReduxCore/inc/extensions/customizer/extension_customizer.js

396 lines 17.7 KB
No matching file
Up and down to move Enter to open Esc to close
Raw Download Zip
1 /* global jQuery, document, redux, redux_change, setting */
2
3 /*!
4 SerializeJSON jQuery plugin.
5 https://github.com/marioizquierdo/jquery.serializeJSON
6 version 2.6.0 (Apr, 2015)
7
8 Copyright (c) 2012, 2015 Mario Izquierdo
9 Dual licensed under the MIT (http://www.opensource.org/licenses/mit-license.php)
10 and GPL (http://www.opensource.org/licenses/gpl-license.php) licenses.
11 */
12 (function( $ ) {
13 "use strict";
14
15 // jQuery('form').serializeJSON()
16 $.fn.serializeJSON = function( options ) {
17 var serializedObject, formAsArray, keys, type, value, _ref, f, opts;
18 f = $.serializeJSON;
19 opts = f.setupOpts( options ); // calculate values for options {parseNumbers, parseBoolens, parseNulls}
20 formAsArray = this.serializeArray(); // array of objects {name, value}
21 f.readCheckboxUncheckedValues( formAsArray, this, opts ); // add {name, value} of unchecked checkboxes if needed
22
23 serializedObject = {};
24 $.each(
25 formAsArray, function( i, input ) {
26 keys = f.splitInputNameIntoKeysArray( input.name, opts );
27 type = keys.pop(); // the last element is always the type ("string" by default)
28 if ( type !== 'skip' ) { // easy way to skip a value
29 value = f.parseValue( input.value, type, opts ); // string, number, boolean or null
30 if ( opts.parseWithFunction && type === '_' ) value = opts.parseWithFunction( value, input.name ); // allow for custom parsing
31 f.deepSet( serializedObject, keys, value, opts );
32 }
33 }
34 );
35 return serializedObject;
36 };
37
38 // Use $.serializeJSON as namespace for the auxiliar functions
39 // and to define defaults
40 $.serializeJSON = {
41
42 defaultOptions: {
43 checkboxUncheckedValue: undefined, // to include that value for unchecked checkboxes (instead of ignoring them)
44
45 parseNumbers: false, // convert values like "1", "-2.33" to 1, -2.33
46 parseBooleans: false, // convert "true", "false" to true, false
47 parseNulls: false, // convert "null" to null
48 parseAll: false, // all of the above
49 parseWithFunction: null, // to use custom parser, a function like: function(val){ return parsed_val; }
50
51 customTypes: {}, // override defaultTypes
52 defaultTypes: {
53 string: function( str ) {
54 return String( str );
55 },
56 number: function( str ) {
57 return Number( str );
58 },
59 boolean: function( str ) {
60 return (["false", "null", "undefined", "", "0"].indexOf( str ) === -1);
61 },
62 null: function( str ) {
63 return (["false", "null", "undefined", "", "0"].indexOf( str ) !== -1) ? null : str;
64 },
65 array: function( str ) {
66 return JSON.parse( str );
67 },
68 object: function( str ) {
69 return JSON.parse( str );
70 },
71 auto: function( str ) {
72 return $.serializeJSON.parseValue(
73 str, null, {parseNumbers: true, parseBooleans: true, parseNulls: true}
74 );
75 } // try again with something like "parseAll"
76 },
77
78 useIntKeysAsArrayIndex: false, // name="foo[2]" value="v" => {foo: [null, null, "v"]}, instead of {foo: ["2": "v"]}
79 },
80
81 // Merge option defaults into the options
82 setupOpts: function( options ) {
83 var opt, validOpts, defaultOptions, optWithDefault, parseAll, f;
84 f = $.serializeJSON;
85
86 if ( options === null || options === undefined ) options = {}; // options ||= {}
87 defaultOptions = f.defaultOptions || {}; // defaultOptions
88
89 // Make sure that the user didn't misspell an option
90 validOpts = ['checkboxUncheckedValue', 'parseNumbers', 'parseBooleans', 'parseNulls', 'parseAll', 'parseWithFunction', 'customTypes', 'defaultTypes', 'useIntKeysAsArrayIndex']; // re-define because the user may override the defaultOptions
91 for ( opt in options ) {
92 if ( validOpts.indexOf( opt ) === -1 ) {
93 throw new Error(
94 "serializeJSON ERROR: invalid option '" + opt + "'. Please use one of " + validOpts.join(
95 ', '
96 )
97 );
98 }
99 }
100
101 // Helper to get the default value for this option if none is specified by the user
102 optWithDefault = function( key ) {
103 return (options[key] !== false) && (options[key] !== '') && (options[key] || defaultOptions[key]);
104 };
105
106 // Return computed options (opts to be used in the rest of the script)
107 parseAll = optWithDefault( 'parseAll' );
108 return {
109 checkboxUncheckedValue: optWithDefault( 'checkboxUncheckedValue' ),
110 parseNumbers: parseAll || optWithDefault( 'parseNumbers' ),
111 parseBooleans: parseAll || optWithDefault( 'parseBooleans' ),
112 parseNulls: parseAll || optWithDefault( 'parseNulls' ),
113 parseWithFunction: optWithDefault( 'parseWithFunction' ),
114 typeFunctions: $.extend( {}, optWithDefault( 'defaultTypes' ), optWithDefault( 'customTypes' ) ),
115 useIntKeysAsArrayIndex: optWithDefault( 'useIntKeysAsArrayIndex' ),
116 };
117 },
118
119 // Given a string, apply the type or the relevant "parse" options, to return the parsed value
120 parseValue: function( str, type, opts ) {
121 var typeFunction, f;
122 f = $.serializeJSON;
123
124 // Parse with a type if available
125 typeFunction = opts.typeFunctions && opts.typeFunctions[type];
126 if ( typeFunction ) return typeFunction( str ); // use specific type
127
128 // Otherwise, check if there is any auto-parse option enabled and use it.
129 if ( opts.parseNumbers && f.isNumeric( str ) ) return Number( str ); // auto: number
130 if ( opts.parseBooleans && (str === "true" || str === "false") ) return str === "true"; // auto: boolean
131 if ( opts.parseNulls && str == "null" ) return null; // auto: null
132
133 // If none applies, just return the str
134 return str;
135 },
136
137 isObject: function( obj ) {
138 return obj === Object( obj );
139 }, // is this variable an object?
140 isUndefined: function( obj ) {
141 return obj === void 0;
142 }, // safe check for undefined values
143 isValidArrayIndex: function( val ) {
144 return /^[0-9]+$/.test( String( val ) );
145 }, // 1,2,3,4 ... are valid array indexes
146 isNumeric: function( obj ) {
147 return obj - parseFloat( obj ) >= 0;
148 }, // taken from jQuery.isNumeric implementation. Not using jQuery.isNumeric to support old jQuery and Zepto versions
149
150 optionKeys: function( obj ) {
151 if ( Object.keys ) {
152 return Object.keys( obj );
153 } else {
154 var keys = [];
155 for ( var key in obj ) {
156 keys.push( key );
157 }
158
159 return keys;
160 }
161 }, // polyfill Object.keys to get option keys in IE<9
162
163 // Split the input name in programatically readable keys.
164 // The last element is always the type (default "_").
165 // Examples:
166 // "foo" => ['foo', '_']
167 // "foo:string" => ['foo', 'string']
168 // "foo:boolean" => ['foo', 'boolean']
169 // "[foo]" => ['foo', '_']
170 // "foo[inn][bar]" => ['foo', 'inn', 'bar', '_']
171 // "foo[inn[bar]]" => ['foo', 'inn', 'bar', '_']
172 // "foo[inn][arr][0]" => ['foo', 'inn', 'arr', '0', '_']
173 // "arr[][val]" => ['arr', '', 'val', '_']
174 // "arr[][val]:null" => ['arr', '', 'val', 'null']
175 splitInputNameIntoKeysArray: function( name, opts ) {
176 var keys, nameWithoutType, type, _ref, f;
177 f = $.serializeJSON;
178 _ref = f.extractTypeFromInputName( name, opts ), nameWithoutType = _ref[0], type = _ref[1];
179 keys = nameWithoutType.split( '[' ); // split string into array
180 keys = $.map(
181 keys, function( key ) {
182 return key.replace( /]/g, '' );
183 }
184 ); // remove closing brackets
185 if ( keys[0] === '' ) {
186 keys.shift();
187 } // ensure no opening bracket ("[foo][inn]" should be same as "foo[inn]")
188 keys.push( type ); // add type at the end
189 return keys;
190 },
191
192 // Returns [name-without-type, type] from name.
193 // "foo" => ["foo", '_']
194 // "foo:boolean" => ["foo", 'boolean']
195 // "foo[bar]:null" => ["foo[bar]", 'null']
196 extractTypeFromInputName: function( name, opts ) {
197 var match, validTypes, f;
198 if ( match = name.match( /(.*):([^:]+)$/ ) ) {
199 f = $.serializeJSON;
200
201 validTypes = f.optionKeys( opts ? opts.typeFunctions : f.defaultOptions.defaultTypes );
202 validTypes.push( 'skip' ); // skip is a special type that makes it easy to remove
203 if ( validTypes.indexOf( match[2] ) !== -1 ) {
204 return [match[1], match[2]];
205 } else {
206 throw new Error(
207 "serializeJSON ERROR: Invalid type " + match[2] + " found in input name '" + name + "', please use one of " + validTypes.join(
208 ', '
209 )
210 )
211 }
212 } else {
213 return [name, '_']; // no defined type, then use parse options
214 }
215 },
216
217 // Set a value in an object or array, using multiple keys to set in a nested object or array:
218 //
219 // deepSet(obj, ['foo'], v) // obj['foo'] = v
220 // deepSet(obj, ['foo', 'inn'], v) // obj['foo']['inn'] = v // Create the inner obj['foo'] object, if needed
221 // deepSet(obj, ['foo', 'inn', '123'], v) // obj['foo']['arr']['123'] = v //
222 //
223 // deepSet(obj, ['0'], v) // obj['0'] = v
224 // deepSet(arr, ['0'], v, {useIntKeysAsArrayIndex: true}) // arr[0] = v
225 // deepSet(arr, [''], v) // arr.push(v)
226 // deepSet(obj, ['arr', ''], v) // obj['arr'].push(v)
227 //
228 // arr = [];
229 // deepSet(arr, ['', v] // arr => [v]
230 // deepSet(arr, ['', 'foo'], v) // arr => [v, {foo: v}]
231 // deepSet(arr, ['', 'bar'], v) // arr => [v, {foo: v, bar: v}]
232 // deepSet(arr, ['', 'bar'], v) // arr => [v, {foo: v, bar: v}, {bar: v}]
233 //
234 deepSet: function( o, keys, value, opts ) {
235 var key, nextKey, tail, lastIdx, lastVal, f;
236 if ( opts == null ) opts = {};
237 f = $.serializeJSON;
238 if ( f.isUndefined( o ) ) {
239 throw new Error( "ArgumentError: param 'o' expected to be an object or array, found undefined" );
240 }
241 if ( !keys || keys.length === 0 ) {
242 throw new Error( "ArgumentError: param 'keys' expected to be an array with least one element" );
243 }
244
245 key = keys[0];
246
247 // Only one key, then it's not a deepSet, just assign the value.
248 if ( keys.length === 1 ) {
249 if ( key === '' ) {
250 o.push( value ); // '' is used to push values into the array (assume o is an array)
251 } else {
252 o[key] = value; // other keys can be used as object keys or array indexes
253 }
254
255 // With more keys is a deepSet. Apply recursively.
256 } else {
257 nextKey = keys[1];
258
259 // '' is used to push values into the array,
260 // with nextKey, set the value into the same object, in object[nextKey].
261 // Covers the case of ['', 'foo'] and ['', 'var'] to push the object {foo, var}, and the case of nested arrays.
262 if ( key === '' ) {
263 lastIdx = o.length - 1; // asume o is array
264 lastVal = o[lastIdx];
265 if ( f.isObject( lastVal ) && (f.isUndefined( lastVal[nextKey] ) || keys.length > 2) ) { // if nextKey is not present in the last object element, or there are more keys to deep set
266 key = lastIdx; // then set the new value in the same object element
267 } else {
268 key = lastIdx + 1; // otherwise, point to set the next index in the array
269 }
270 }
271
272 // '' is used to push values into the array "array[]"
273 if ( nextKey === '' ) {
274 if ( f.isUndefined( o[key] ) || !$.isArray( o[key] ) ) {
275 o[key] = []; // define (or override) as array to push values
276 }
277 } else {
278 if ( opts.useIntKeysAsArrayIndex && f.isValidArrayIndex( nextKey ) ) { // if 1, 2, 3 ... then use an array, where nextKey is the index
279 if ( f.isUndefined( o[key] ) || !$.isArray( o[key] ) ) {
280 o[key] = []; // define (or override) as array, to insert values using int keys as array indexes
281 }
282 } else { // for anything else, use an object, where nextKey is going to be the attribute name
283 if ( f.isUndefined( o[key] ) || !f.isObject( o[key] ) ) {
284 o[key] = {}; // define (or override) as object, to set nested properties
285 }
286 }
287 }
288
289 // Recursively set the inner object
290 tail = keys.slice( 1 );
291 f.deepSet( o[key], tail, value, opts );
292 }
293 },
294
295 // Fill the formAsArray object with values for the unchecked checkbox inputs,
296 // using the same format as the jquery.serializeArray function.
297 // The value of the unchecked values is determined from the opts.checkboxUncheckedValue
298 // and/or the data-unchecked-value attribute of the inputs.
299 readCheckboxUncheckedValues: function( formAsArray, $form, opts ) {
300 var selector, $uncheckedCheckboxes, $el, dataUncheckedValue, f;
301 if ( opts == null ) opts = {};
302 f = $.serializeJSON;
303
304 selector = 'input[type=checkbox][name]:not(:checked):not([disabled])';
305 $uncheckedCheckboxes = $form.find( selector ).add( $form.filter( selector ) );
306 $uncheckedCheckboxes.each(
307 function( i, el ) {
308 $el = $( el );
309 dataUncheckedValue = $el.attr( 'data-unchecked-value' );
310 if ( dataUncheckedValue ) { // data-unchecked-value has precedence over option opts.checkboxUncheckedValue
311 formAsArray.push( {name: el.name, value: dataUncheckedValue} );
312 } else {
313 if ( !f.isUndefined( opts.checkboxUncheckedValue ) ) {
314 formAsArray.push( {name: el.name, value: opts.checkboxUncheckedValue} );
315 }
316 }
317 }
318 );
319 }
320
321 };
322
323 }( window.jQuery || window.$ ));
324
325 (function( $ ) { //This functions first parameter is named $
326 'use strict';
327
328 redux.customizer = redux.customizer || {};
329
330 $( document ).ready(
331 function() {
332 redux.customizer.init();
333 }
334 );
335 redux.customizer.init = function() {
336 $( 'body' ).addClass( redux_customizer.body_class );
337 $( '.accordion-section.redux-section, .accordion-section.redux-panel, .accordion-section-title' ).click(
338 function() {
339 $.redux.initFields();
340 }
341 );
342
343 redux.args.disable_save_warn = true;
344 var reduxChange = redux_change;
345 redux_change = function( variable ) {
346 variable = $( variable );
347 reduxChange.apply( this, arguments );
348 redux.customizer.save( variable )
349 };
350
351 var redux_initFields = $.redux.initFields;
352 $.redux.initFiles = function() {
353 redux_initFields();
354 }
355 };
356
357 redux.customizer.save = function( $obj ) {
358 var $parent = $obj.hasClass( 'redux-field' ) ? $obj : $obj.parents( '.redux-field-container:first' );
359 redux.customizer.inputSave( $parent );
360 };
361 redux.customizer.inputSave = function( $parent ) {
362
363 if ( !$parent.hasClass( 'redux-field-container' ) ) {
364 $parent = $parent.parents( '[class^="redux-field-container"]' );
365 }
366
367 var $id = $parent.parent().find( '.redux-customizer-input' ).data( 'id' );
368
369 if ( !$id ) {
370 $parent = $parent.parents( '.redux-container-repeater:first' );
371 var $id = $parent.parent().find( '.redux-customizer-input' ).data( 'id' );
372 }
373
374 //var $nData = $parent.serializeJSON();
375 var $nData = $parent.find( ':input' ).serializeJSON();
376
377 $.each(
378 $nData, function( $k, $v ) {
379 $nData = $v;
380 }
381 );
382
383 var $key = $parent.parent().find( '.redux-customizer-input' ).data( 'key' );
384 if ( $nData[$key] ) {
385 $nData = $nData[$key];
386 }
387
388 var $control = wp.customize.control( $id );
389
390 // Customizer hack since they didn't code it to save order...
391 if ( JSON.stringify( $control.setting._value ) !== JSON.stringify( $nData ) ) {
392 $control.setting._value = null;
393 }
394 $control.setting.set( $nData );
395 }
396 })( jQuery );