PageSourceSearch

https://www.semae.fr/wp-content/plugins/ninja-forms-conditionals/assets/js/min/front-end.js?ver=7.1.2

js semae.fr collected 2026-09-25 04:37:09 UTC 42,648 bytes, 1,246 lines download raw bytes

vendor: 12,633 bytes, lines 1-348
1(function () {
2/**
3 * @license almond 0.3.1 Copyright (c) 2011-2014, The Dojo Foundation All Rights Reserved.
4 * Available via the MIT or new BSD license.
5 * see: http://github.com/jrburke/almond for details
6 */
7//Going sloppy to avoid 'use strict' string cost, but strict practices should
8//be followed.
9/*jslint sloppy: true */
10/*global setTimeout: false */
11
12var requirejs, require, define;
13(function (undef) {
14    var main, req, makeMap, handlers,
15        defined = {},
16        waiting = {},
17        config = {},
18        defining = {},
19        hasOwn = Object.prototype.hasOwnProperty,
20        aps = [].slice,
21        jsSuffixRegExp = /\.js$/;
22
23    function hasProp(obj, prop) {
24        return hasOwn.call(obj, prop);
25    }
26
27    /**
28     * Given a relative module name, like ./something, normalize it to
29     * a real name that can be mapped to a path.
30     * @param {String} name the relative name
31     * @param {String} baseName a real name that the name arg is relative
32     * to.
33     * @returns {String} normalized name
34     */
35    function normalize(name, baseName) {
36        var nameParts, nameSegment, mapValue, foundMap, lastIndex,
37            foundI, foundStarMap, starI, i, j, part,
38            baseParts = baseName && baseName.split("/"),
39            map = config.map,
40            starMap = (map && map['*']) || {};
41
42        //Adjust any relative paths.
43        if (name && name.charAt(0) === ".") {
44            //If have a base name, try to normalize against it,
45            //otherwise, assume it is a top-level require that will
46            //be relative to baseUrl in the end.
47            if (baseName) {
48                name = name.split('/');
49                lastIndex = name.length - 1;
50
51                // Node .js allowance:
52                if (config.nodeIdCompat && jsSuffixRegExp.test(name[lastIndex])) {
53                    name[lastIndex] = name[lastIndex].replace(jsSuffixRegExp, '');
54                }
55
56                //Lop off the last part of baseParts, so that . matches the
57                //"directory" and not name of the baseName's module. For instance,
58                //baseName of "one/two/three", maps to "one/two/three.js", but we
59                //want the directory, "one/two" for this normalization.
60                name = baseParts.slice(0, baseParts.length - 1).concat(name);
61
62                //start trimDots
63                for (i = 0; i < name.length; i += 1) {
64                    part = name[i];
65                    if (part === ".") {
66                        name.splice(i, 1);
67                        i -= 1;
68                    } else if (part === "..") {
69                        if (i === 1 && (name[2] === '..' || name[0] === '..')) {
70                            //End of the line. Keep at least one non-dot
71                            //path segment at the front so it can be mapped
72                            //correctly to disk. Otherwise, there is likely
73                            //no path mapping for a path starting with '..'.
74                            //This can still fail, but catches the most reasonable
75                            //uses of ..
76                            break;
77                        } else if (i > 0) {
78                            name.splice(i - 1, 2);
79                            i -= 2;
80                        }
81                    }
82                }
83                //end trimDots
84
85                name = name.join("/");
86            } else if (name.indexOf('./') === 0) {
87                // No baseName, so this is ID is resolved relative
88                // to baseUrl, pull off the leading dot.
89                name = name.substring(2);
90            }
91        }
92
93        //Apply map config if available.
94        if ((baseParts || starMap) && map) {
95            nameParts = name.split('/');
96
97            for (i = nameParts.length; i > 0; i -= 1) {
98                nameSegment = nameParts.slice(0, i).join("/");
99
100                if (baseParts) {
101                    //Find the longest baseName segment match in the config.
102                    //So, do joins on the biggest to smallest lengths of baseParts.
103                    for (j = baseParts.length; j > 0; j -= 1) {
104                        mapValue = map[baseParts.slice(0, j).join('/')];
105
106                        //baseName segment has  config, find if it has one for
107                        //this name.
108                        if (mapValue) {
109                            mapValue = mapValue[nameSegment];
110                            if (mapValue) {
111                                //Match, update name to the new value.
112                                foundMap = mapValue;
113                                foundI = i;
114                                break;
115                            }
116                        }
117                    }
118                }
119
120                if (foundMap) {
121                    break;
122                }
123
124                //Check for a star map match, but just hold on to it,
125                //if there is a shorter segment match later in a matching
126                //config, then favor over this star map.
127                if (!foundStarMap && starMap && starMap[nameSegment]) {
128                    foundStarMap = starMap[nameSegment];
129                    starI = i;
130                }
131            }
132
133            if (!foundMap && foundStarMap) {
134                foundMap = foundStarMap;
135                foundI = starI;
136            }
137
138            if (foundMap) {
139                nameParts.splice(0, foundI, foundMap);
140                name = nameParts.join('/');
141            }
142        }
143
144        return name;
145    }
146
147    function makeRequire(relName, forceSync) {
148        return function () {
149            //A version of a require function that passes a moduleName
150            //value for items that may need to
151            //look up paths relative to the moduleName
152            var args = aps.call(arguments, 0);
153
154            //If first arg is not require('string'), and there is only
155            //one arg, it is the array form without a callback. Insert
156            //a null so that the following concat is correct.
157            if (typeof args[0] !== 'string' && args.length === 1) {
158                args.push(null);
159            }
160            return req.apply(undef, args.concat([relName, forceSync]));
161        };
162    }
163
164    function makeNormalize(relName) {
165        return function (name) {
166            return normalize(name, relName);
167        };
168    }
169
170    function makeLoad(depName) {
171        return function (value) {
172            defined[depName] = value;
173        };
174    }
175
176    function callDep(name) {
177        if (hasProp(waiting, name)) {
178            var args = waiting[name];
179            delete waiting[name];
180            defining[name] = true;
181            main.apply(undef, args);
182        }
183
184        if (!hasProp(defined, name) && !hasProp(defining, name)) {
185            throw new Error('No ' + name);
186        }
187        return defined[name];
188    }
189
190    //Turns a plugin!resource to [plugin, resource]
191    //with the plugin being undefined if the name
192    //did not have a plugin prefix.
193    function splitPrefix(name) {
194        var prefix,
195            index = name ? name.indexOf('!') : -1;
196        if (index > -1) {
197            prefix = name.substring(0, index);
198            name = name.substring(index + 1, name.length);
199        }
200        return [prefix, name];
201    }
202
203    /**
204     * Makes a name map, normalizing the name, and using a plugin
205     * for normalization if necessary. Grabs a ref to plugin
206     * too, as an optimization.
207     */
208    makeMap = function (name, relName) {
209        var plugin,
210            parts = splitPrefix(name),
211            prefix = parts[0];
212
213        name = parts[1];
214
215        if (prefix) {
216            prefix = normalize(prefix, relName);
217            plugin = callDep(prefix);
218        }
219
220        //Normalize according
221        if (prefix) {
222            if (plugin && plugin.normalize) {
223                name = plugin.normalize(name, makeNormalize(relName));
224            } else {
225                name = normalize(name, relName);
226            }
227        } else {
228            name = normalize(name, relName);
229            parts = splitPrefix(name);
230            prefix = parts[0];
231            name = parts[1];
232            if (prefix) {
233                plugin = callDep(prefix);
234            }
235        }
236
237        //Using ridiculous property names for space reasons
238        return {
239            f: prefix ? prefix + '!' + name : name, //fullName
240            n: name,
241            pr: prefix,
242            p: plugin
243        };
244    };
245
246    function makeConfig(name) {
247        return function () {
248            return (config && config.config && config.config[name]) || {};
249        };
250    }
251
252    handlers = {
253        require: function (name) {
254            return makeRequire(name);
255        },
256        exports: function (name) {
257            var e = defined[name];
258            if (typeof e !== 'undefined') {
259                return e;
260            } else {
261                return (defined[name] = {});
262            }
263        },
264        module: function (name) {
265            return {
266                id: name,
267                uri: '',
268                exports: defined[name],
269                config: makeConfig(name)
270            };
271        }
272    };
273
274    main = function (name, deps, callback, relName) {
275        var cjsModule, depName, ret, map, i,
276            args = [],
277            callbackType = typeof callback,
278            usingExports;
279
280        //Use name if no relName
281        relName = relName || name;
282
283        //Call the callback to define the module, if necessary.
284        if (callbackType === 'undefined' || callbackType === 'function') {
285            //Pull out the defined dependencies and pass the ordered
286            //values to the callback.
287            //Default to [require, exports, module] if no deps
288            deps = !deps.length && callback.length ? ['require', 'exports', 'module'] : deps;
289            for (i = 0; i < deps.length; i += 1) {
290                map = makeMap(deps[i], relName);
291                depName = map.f;
292
293                //Fast path CommonJS standard dependencies.
294                if (depName === "require") {
295                    args[i] = handlers.require(name);
296                } else if (depName === "exports") {
297                    //CommonJS module spec 1.1
298                    args[i] = handlers.exports(name);
299                    usingExports = true;
300                } else if (depName === "module") {
301                    //CommonJS module spec 1.1
302                    cjsModule = args[i] = handlers.module(name);
303                } else if (hasProp(defined, depName) ||
304                           hasProp(waiting, depName) ||
305                           hasProp(defining, depName)) {
306                    args[i] = callDep(depName);
307                } else if (map.p) {
308                    map.p.load(map.n, makeRequire(relName, true), makeLoad(depName), {});
309                    args[i] = defined[depName];
310                } else {
311                    throw new Error(name + ' missing ' + depName);
312                }
313            }
314
315            ret = callback ? callback.apply(defined[name], args) : undefined;
316
317            if (name) {
318                //If setting exports via "module" is in play,
319                //favor that over return value and exports. After that,
320                //favor a non-undefined return value over exports use.
321                if (cjsModule && cjsModule.exports !== undef &&
322                        cjsModule.exports !== defined[name]) {
323                    defined[name] = cjsModule.exports;
324                } else if (ret !== undef || !usingExports) {
325                    //Use the return value from the function.
326                    defined[name] = ret;
327                }
328            }
329        } else if (name) {
330            //May just be an object definition for the module. Only
331            //worry about defining if have a module name.
332            defined[name] = callback;
333        }
334    };
335
336    requirejs = require = req = function (deps, callback, relName, forceSync, alt) {
337        if (typeof deps === "string") {
338            if (handlers[deps]) {
339                //callback in this case is really relName
340                return handlers[deps](callback);
341            }
342            //Just return the module wanted. In this scenario, the
343            //deps arg is the module name, and second arg (if passed)
344            //is just the relName.
345            //Normalize module name, if it contains . or ..
346            return callDep(makeMap(deps, callback).f);
347        } else if (!deps.splice) {
348            //deps is a config object, not an array.
349            config = deps;
350            if (config.deps) {
351                req(config.deps, config.callback);
352            }
353            if (!callback) {
354                return;
355            }
356
357            if (callback.splice) {
358                //callback is an array, which means it is a dependency list.
359                //Adjust args if there are dependencies
360                deps = callback;
361                callback = relName;
362                relName = null;
363            } else {
364                deps = undef;
365            }
366        }
367
368        //Support require(['a'])
369        callback = callback || function () {};
370
371        //If relName is a function, it is an errback handler,
372        //so remove it.
373        if (typeof relName === 'function') {
374            relName = forceSync;
375            forceSync = alt;
376        }
377
378        //Simulate async callback;
379        if (forceSync) {
380            main(undef, deps, callback, relName);
381        } else {
382            //Using a non-zero value because of concern for what old browsers
383            //do, and latest browsers "upgrade" to 4 if lower value is used:
384            //http://www.whatwg.org/specs/web-apps/current-work/multipage/timers.html#dom-windowtimers-settimeout:
385            //If want a value immediately, use require('id') instead -- something
386            //that works in almond on the global level, but not guaranteed and
387            //unlikely to work in other AMD implementations.
388            setTimeout(function () {
389                main(undef, deps, callback, relName);
390            }, 4);
391        }
392
393        return req;
394    };
395
396    /**
397     * Just drops the config on the floor, but returns req in case
398     * the config return value is used.
399     */
400    req.config = function (cfg) {
401        return req(cfg);
402    };
403
404    /**
405     * Expose module registry for debugging and tooling
406     */
407    requirejs._defined = defined;
408
409    define = function (name, deps, callback) {
410        if (typeof name !== 'string') {
411            throw new Error('See almond README: incorrect module build, no module name');
412        }
413
414        //This module may not have dependencies
415        if (!deps.splice) {
416            //deps is not an array, so probably means
417            //an object literal or factory function for
418            //the value. Adjust args.
419            callback = deps;
420            deps = [];
421        }
422
423        if (!hasProp(defined, name) && !hasProp(waiting, name)) {
424            waiting[name] = [name, deps, callback];
425        }
426    };
427
428    define.amd = {
429        jQuery: true
430    };
431}());
432
433define("../lib/almond", function(){});
434
435define( 'models/whenModel',[], function() {
436	var model = Backbone.Model.extend( {
437		initialize: function( models, options ) {
438			/*
439			 * If our key or comparator is empty, don't do anything else.
440			 */
441			if ( ! this.get( 'key' ) || ! this.get( 'comparator' ) ) return;
442
443			/*
444			 * Our key could be a field or a calc.
445			 * We need to setup a listener on either the field or calc model for changes.
446			 */
447			if ( 'calc' == this.get( 'type' ) ) { // We have a calculation key
448				/*
449				 * Get our calc model
450				 */
451				var calcModel = nfRadio.channel( 'form-' + this.collection.options.condition.collection.formModel.get( 'id' ) ).request( 'get:calc', this.get( 'key' ) );
452
453				if( 'undefined' == typeof calcModel ) return;
454
455				/*
456				 * When we update our calculation, update our compare
457				 */
458				this.listenTo( calcModel, 'change:value', this.updateCalcCompare );
459				/*
460				 * Update our compare status.
461				 */
462				this.updateCalcCompare( calcModel );
463			} else { // We have a field key
464				// Get our field model
465				var fieldModel = nfRadio.channel( 'form-' + options.condition.collection.formModel.get( 'id' ) ).request( 'get:fieldByKey', this.get( 'key' ) );
466
467				if( 'undefined' == typeof fieldModel ) return;
468
469				// When we change the value of our field, update our compare status.
470				fieldModel.on( 'change:value', this.updateFieldCompare, this );
471				// When we keyup in our field, maybe update our compare status.
472				this.listenTo( nfRadio.channel( 'field-' + fieldModel.get( 'id' ) ), 'keyup:field', this.maybeupdateFieldCompare );
473				// Update our compare status.
474				this.updateFieldCompare( fieldModel );
475
476				/*
477				 * TODO: This should be moved to the show_field/hide_field file because it is specific to showing and hiding.
478				 * Create a radio message here so that the specific JS file can hook into whenModel init.
479				 */
480				fieldModel.on( 'change:visible', this.updateFieldCompare, this );
481			}
482		},
483
484		updateCalcCompare: function( calcModel ) {
485			this.updateCompare( calcModel.get( 'value' ) );
486		},
487
488		maybeupdateFieldCompare: function( el, fieldModel, keyCode ) {
489			if( 'checkbox' == fieldModel.get( 'type' ) ){
490                var fieldValue = ( 'checked' == jQuery( el ).attr( 'checked' ) ) ? 1 : 0;
491            } else if( 'listcheckbox' == fieldModel.get( 'type' ) ) {
492				// This field isn't a single element, so we need to reference the fieldModel, instead of the DOM.
493                var fieldValue = fieldModel.get( 'value' ).join();
494            } else if ( 'listradio' == fieldModel.get( 'type' ) ) {
495				/*
496				 * Use the field model's actual selected value rather than jQuery(el).val().
497				 * jQuery(el).val() returns the value attribute of whichever radio button has
498				 * focus, even if it has not been selected by the user. When tabbing into a
499				 * radio field, the keyup event fires on the focused (but unselected) radio
500				 * button, causing jQuery(el).val() to return that option's value and
501				 * incorrectly trigger conditions. The field model value only reflects a
502				 * genuinely selected option.
503				 */
504				var fieldValue = fieldModel.get( 'value' );
505            } else if ( 'date' == fieldModel.get ('type' ) ) {
506				var fieldValue = fieldModel.get( 'value' );
507
508				if ( _.isEmpty( fieldValue ) ) {
509					fieldValue = '1970/01/01';
510				}
511
512				let date_mode = fieldModel.get( 'date_mode' );
513				if ( 'undefined' == typeof date_mode ) { // If 'date_mode' is undefined, then we assume it's date_only.
514					date_mode = 'date_only';
515				}
516				let date = 0;
517				// If we're in time_only mode, then we need to use 1970-01-01 as our date.
518				if ( 'time_only' == fieldModel.get( 'date_mode' ) ) {
519					date = '1970/01/01';
520				} else {
521					date = fieldValue;
522				}
523
524				// Convert field value into a timestamp
525				let hour = fieldModel.get( 'selected_hour' );
526				if ( 'undefined' == typeof hour ) {
527					hour = '00';
528				}
529
530				let minute = fieldModel.get( 'selected_minute' );
531				if ( 'undefined' == typeof minute ) {
532					minute = '00';
533				}
534
535				// If we have a date_and_time field, but we haven't selected a date yet, we don't need to compare.
536				if ( 'date_and_time' == date_mode && '1970/01/01' == date ) {
537					fieldValue = false;
538				} else {
539					fieldValue = date + ' ' + hour + ':' + minute + ' UT';
540
541					let dateObject = new Date( fieldValue );
542					fieldValue = Math.floor( dateObject.getTime() / 1000 );					
543				}
544			} else {
545				var fieldValue = jQuery( el ).val();
546			}
547
548			this.updateFieldCompare( fieldModel, null, fieldValue );
549		},
550
551		updateCompare: function( value ) {
552			var this_val = this.get( 'value' );
553
554			// if this is a calcModel then let's convert to number for comparison
555			if ( 'calc' === this.get( 'type' ) ) {
556				this_val = Number( this_val );
557				value = Number( value );
558			}
559			// Check to see if the value of the field model value COMPARATOR the value of our when condition is true.
560			var status = this.compareValues[ this.get( 'comparator' ) ]( value, this_val );
561			this.set( 'status', status );
562		},
563
564		updateFieldCompare: function( fieldModel, val, fieldValue ) {
565			if ( _.isEmpty( fieldValue ) ) {
566				fieldValue = fieldModel.get( 'value' );
567			}
568
569			// Change the value of checkboxes to match the new convention.
570			if( 'checkbox' == fieldModel.get( 'type' ) ) {
571				if( 0 == fieldValue ) {
572					fieldValue = 'unchecked';
573				} else {
574					fieldValue = 'checked';
575				}
576			} else if ( 'date' == fieldModel.get( 'type' ) ) {
577				if ( _.isEmpty( fieldValue ) ) {
578					fieldValue = '1970/01/01';
579				}
580
581				let date_mode = fieldModel.get( 'date_mode' );
582				if ( 'undefined' == typeof date_mode ) { // If 'date_mode' is undefined, then we assume it's date_only.
583					date_mode = 'date_only';
584				}
585				let date = 0;
586				// If we're in time_only mode, then we need to use 1970-01-01 as our date.
587				if ( 'time_only' == fieldModel.get( 'date_mode' ) ) {
588					date = '1970/01/01';
589				} else {
590					date = fieldValue;
591				}
592
593				// Convert field value into a timestamp
594				let hour = fieldModel.get( 'selected_hour' );
595				if ( 'undefined' == typeof hour ) {
596					hour = '00';
597				}
598
599				let ampm = fieldModel.get( 'selected_ampm' );
600				if ( 'undefined' != typeof ampm ) {
601					// Convert our hour into 24 hr format.
602					if ( 'pm' == ampm && '12' != hour ) {
603						hour = parseInt( hour ) + 12;
604					} else if ( 'am' == ampm && '12' == hour ) {
605						hour = '00';
606					}
607				}
608
609				let minute = fieldModel.get( 'selected_minute' );
610				if ( 'undefined' == typeof minute ) {
611					minute = '00';
612				}
613
614				// If we have a date_and_time field, but we haven't selected a date yet, we don't need to compare.
615				if ( 'date_and_time' == date_mode && '1970/01/01' == date ) {
616					fieldValue = false;
617				} else {
618					fieldValue = date + ' ' + hour + ':' + minute + ' UT';
619
620					let dateObject = new Date( fieldValue );
621					fieldValue = Math.floor( dateObject.getTime() / 1000 );					
622				}
623			}
624
625			this.updateCompare( fieldValue );
626
627			/*
628			 * TODO: This should be moved to the show_field/hide_field file because it is specific to showing and hiding.
629			 */
630			if ( ! fieldModel.get( 'visible' ) ) {
631				this.set( 'status', false );
632			}			
633		},
634
635		compareValues: {
636			'equal': function( a, b ) {
637				return a == b;
638			},
639			'notequal': function( a, b ) {
640				return a != b;
641			},
642			'contains': function( a, b ) {
643				if ( jQuery.isArray( a ) ) {
644					/*
645					 * If a is an array, then we're searching for an index.
646					 */
647					return a.indexOf( b ) >= 0;
648				} else {
649					/*
650					 * If a is a string, then we're searching for a string position.
651					 *
652					 * If our b value has quotes in it, we want to find that exact word or phrase.
653					 */
654					if ( b.indexOf( '"' ) >= 0 ) {
655						b = b.replace( /['"]+/g, '' );
656						return new RegExp("\\b" + b + "\\b").test( a );
657					}
658					return a.toLowerCase().indexOf( b.toLowerCase() ) >= 0; 				
659				}
660			},
661			'notcontains': function( a, b ) {
662				return ! this.contains( a, b );
663			},
664			'greater': function( a, b ) {
665				/*
666				 * In 2.9.x, you could use the greater and less like string count.
667				 * i.e. if textbox > (empty string) do something.
668				 * This recreates that ability.
669				 */
670				if ( jQuery.isNumeric( b ) ) {
671					return parseFloat( a ) > parseFloat( b );
672				} else if ( 'string' == typeof a ) {
673					return 0 < a.length;
674				}
675				
676			},
677			'less': function( a, b ) {
678				/*
679				 * In 2.9.x, you could use the greater and less like string count.
680				 * i.e. if textbox > (empty string) do something.
681				 * This recreates that ability.
682				 */
683				if ( jQuery.isNumeric( b ) ) {
684					return parseFloat( a ) < parseFloat( b );
685				} else if ( 'string' == typeof a ) {
686					return 0 >= a.length;
687				}
688		
689			},
690			'greaterequal': function( a, b ) {
691				return parseFloat( a ) > parseFloat( b ) || parseFloat( a ) == parseFloat( b );
692			},
693			'lessequal': function( a, b ) {
694				return parseFloat( a ) < parseFloat( b ) || parseFloat( a ) == parseFloat( b );
695			}
696		} 
697	} );
698	
699	return model;
700} );
701define( 'models/whenCollection',['models/whenModel'], function( WhenModel ) {
702	var collection = Backbone.Collection.extend( {
703		model: WhenModel,
704
705		initialize: function( models, options ) {
706			this.options = options;
707		}
708	} );
709	return collection;
710} );
711define( 'models/conditionModel',[ 'models/whenCollection' ], function( WhenCollection ) {
712	var model = Backbone.Model.extend( {
713		initialize: function( options ) {
714			/*
715			 * Our "when" statement will be like:
716			 * When field1 == value
717			 * AND field2 == value
718			 *
719			 * We need to create a collection out of this when statement, with each row as a model.
720			 */
721			this.set( 'when', new WhenCollection( this.get( 'when' ), { condition: this } ) );
722			/*
723			 * When we update any of our "when" models' status, check to see if we should send a message.
724			 */
725			this.get( 'when' ).on( 'change:status', this.checkWhen, this );
726			/*
727			 * Check our initial status;
728			 * Deferred via setTimeout to allow all field relationships (e.g. Confirm field pairings)
729			 * to be fully established before conditions first evaluate on page load.
730			 */
731			setTimeout( function() {
732				this.checkWhen();
733			}.bind( this ), 0 );
734		},
735
736		checkWhen: function() {
737			/*
738			 * If we have any OR connectors, then any status being true should trigger pass.
739			 * Otherwise, we need every status to be true.
740			 */
741			var statusResults = this.get( 'when' ).pluck( 'status' );
742
743			var connectors = this.get( 'when' ).pluck( 'connector' );
744			var allAND = _.every( _.values( connectors ), function( v ) { return v == 'AND' }, this );
745			if ( allAND ) {
746				var status = _.every( _.values( statusResults ), function(v) { return v; }, this );
747			} else {
748				var status = _.some( _.values( statusResults ), function(v) { return v; }, this );
749			}
750
751			if ( status ) {
752			   	/*
753			 	 * Send out a request for each of our "then" statements.
754			 	 */
755				_.each( this.get( 'then' ), function( then, index ) {
756					nfRadio.channel( 'condition:trigger' ).request( then.trigger, this, then );
757				}, this );
758			} else {
759				/*
760				 * Send out a request for each of our "else" statements.
761				 */
762				_.each( this.get( 'else' ), function( elseData, index ) {
763					nfRadio.channel( 'condition:trigger' ).request( elseData.trigger, this, elseData );
764				}, this );
765			}
766		}
767	} );
768
769	return model;
770} );
771
772define( 'models/conditionCollection',['models/conditionModel'], function( ConditionModel ) {
773	var collection = Backbone.Collection.extend( {
774		model: ConditionModel,
775
776		initialize: function( models, options ) {
777			this.formModel = options.formModel;
778		}
779	} );
780	return collection;
781} );
782/**
783 * Initialise condition collection
784 * 
785 * @package Ninja Forms Conditional Logic
786 * @copyright (c) 2016 WP Ninjas
787 * @since 3.0
788 */
789define( 'controllers/initCollection',[ 'models/conditionCollection' ], function( ConditionCollection ) {
790	var controller = Marionette.Object.extend( {
791		initialize: function( formModel ) {
792			this.collection = new ConditionCollection( formModel.get( 'conditions' ), { formModel: formModel } );
793            this.listenTo(nfRadio.channel('fields'), 'reset:collection', this.resetCollection);
794		},
795        resetCollection: function( fieldsCollection ) {
796            var formModel = fieldsCollection.options.formModel;
797            this.collection = new ConditionCollection( formModel.get( 'conditions' ), { formModel: formModel } );
798        }
799	});
800
801	return controller;
802} );
803/**
804 * Handle showing/hiding fields
805 * 
806 * @package Ninja Forms Conditional Logic
807 * @copyright (c) 2016 WP Ninjas
808 * @since 3.0
809 */
810define( 'controllers/showHide',[], function() {
811	var controller = Marionette.Object.extend( {
812		initialize: function() {
813			nfRadio.channel( 'condition:trigger' ).reply( 'hide_field', this.hideField, this );
814			nfRadio.channel( 'condition:trigger' ).reply( 'show_field', this.show
814Field, this );
815		},
816
817		hideField: function( conditionModel, then ) {
818			var formId = conditionModel.collection.formModel.get( 'id' );
819			var targetFieldModel = nfRadio.channel( 'form-' + formId ).request( 'get:fieldByKey', then.key );
820
821			if( 'undefined' == typeof targetFieldModel ) return;
822			targetFieldModel.set( 'visible', false );
823            if ( ! targetFieldModel.get( 'clean' ) ) {
824				targetFieldModel.trigger( 'change:value', targetFieldModel );
825			}
826
827			nfRadio.channel( 'fields' ).request( 'remove:error', targetFieldModel.get( 'id' ), 'required-error' );
828
829			// For repeater fields, mark child field models as not visible so JS
830			// validation skips their required check on submission.
831			if ( 'repeater' === targetFieldModel.get( 'type' ) ) {
832				this.setRepeaterChildrenVisible( targetFieldModel, false );
833			}
834		},
835
836		/**
837		 * Set the visible state on all child field models of a Repeater field.
838		 *
839		 * Child models live inside the Repeater's own sets collection, not in the
840		 * top-level form field collection. When visible is false, NF core's
841		 * validateModelData skips required validation for those fields.
842		 */
843		setRepeaterChildrenVisible: function( repeaterModel, visible ) {
844			var sets = repeaterModel.get( 'sets' );
845			if ( ! sets ) return;
846
847			sets.each( function( set ) {
848				var fields = set.get( 'fields' );
849				if ( ! fields ) return;
850
851				fields.each( function( fieldModel ) {
852					fieldModel.set( 'visible', visible );
853					if ( ! visible ) {
854						nfRadio.channel( 'fields' ).request( 'remove:error', fieldModel.get( 'id' ), 'required-error' );
855					}
856				} );
857			} );
858		},
859
860		showField: function( conditionModel, then ) {
861			var targetFieldModel = nfRadio.channel( 'form-' + conditionModel.collection.formModel.get( 'id' ) ).request( 'get:fieldByKey', then.key );
862			//TODO: Add an error to let the user know the show/hide field is empty.
863			if( 'undefined' == typeof targetFieldModel ) return;
864			targetFieldModel.set( 'visible', true );
865            if ( ! targetFieldModel.get( 'clean' ) ) {
866                targetFieldModel.trigger( 'change:value', targetFieldModel );
867			}
868			// For repeater fields, restore child field models to visible so
869			// required validation applies again when the Repeater is shown.
870			if ( 'repeater' === targetFieldModel.get( 'type' ) ) {
871				this.setRepeaterChildrenVisible( targetFieldModel, true );
872			}
873			if ( 'recaptcha' === targetFieldModel.get( 'type' ) ) {
874				this.renderRecaptcha();
875			}
876			if ( 'turnstile' === targetFieldModel.get( 'type' ) ) {
877				this.renderTurnstile();
878			}
879			var viewEl = { el: nfRadio.channel( 'form-' + conditionModel.collection.formModel.get( 'id' ) ).request( 'get:el' ) };
880            nfRadio.channel( 'form' ).request( 'init:help', viewEl );
881		},
882
883		renderRecaptcha: function() {
884			jQuery( '.g-recaptcha' ).each( function() {
885                var callback = jQuery( this ).data( 'callback' );
886                var fieldID = jQuery( this ).data( 'fieldid' );
887                if ( typeof window[ callback ] !== 'function' ){
888                    window[ callback ] = function( response ) {
889                        nfRadio.channel( 'recaptcha' ).request( 'update:response', response, fieldID );
890                    };
891                }
892				var opts = {
893					theme: jQuery( this ).data( 'theme' ),
894					sitekey: jQuery( this ).data( 'sitekey' ),
895					callback: callback
896				};
897				
898				grecaptcha.render( jQuery( this )[0], opts );
899			} );
900		},
901
902		renderTurnstile: function() {
903			// Ensure turnstile API is loaded
904			if ( typeof turnstile === 'undefined' ) {
905				return;
906			}
907
908			jQuery( '.cf-turnstile, .nf-cf-turnstile' ).each( function() {
909				var element = this;
910				var sitekey = jQuery( element ).data( 'sitekey' );
911				var fieldID = jQuery( element ).data( 'fieldid' );
912				
913				// Skip if no sitekey or already rendered
914				if ( ! sitekey || jQuery( element ).children().length > 0 ) {
915					return;
916				}
917
918				try {
919					// Create callback function for this specific field
920					var callbackName = 'nfTurnstileCallback_' + fieldID;
921					
922					// Define the callback function
923					window[ callbackName ] = function( token ) {
924						// Update the hidden input field
925						var input = document.getElementById( 'nf-field-' + fieldID );
926						if ( input ) {
927							input.value = token;
928							jQuery( input ).trigger( 'change' );
929							
930							// Remove error states
931							jQuery( input ).closest( '.field-wrap' ).removeClass( 'nf-error' );
932							jQuery( input ).closest( '.field-wrap' ).find( '.nf-error-msg' ).remove();
933						}
934
935						// Update via radio channel if available
936						if ( typeof nfRadio !== 'undefined' && nfRadio.channel ) {
937							try {
938								nfRadio.channel( 'turnstile' ).request( 'update:response', token, fieldID );
939							} catch( e ) {
940								// Silent fail
941							}
942						}
943					};
944
945					// Render the turnstile widget
946					turnstile.render( element, {
947						sitekey: sitekey,
948						theme: jQuery( element ).data( 'theme' ) || 'auto',
949						size: jQuery( element ).data( 'size' ) || 'normal',
950						callback: callbackName
951					} );
952					
953				} catch( e ) {
954					// Silent fail for turnstile render errors
955				}
956			} );
957		}
958	});
959
960	return controller;
961} );
962/**
963 * Setting/unsetting required.
964 * 
965 * @package Ninja Forms Conditional Logic
966 * @copyright (c) 2019 WP Ninjas
967 * @since 3.0
968 */
969define( 'controllers/changeRequired',[], function() {
970	var controller = Marionette.Object.extend( {
971		initialize: function() {
972			nfRadio.channel( 'condition:trigger' ).reply( 'set_required', this.setRequired, this );
973			nfRadio.channel( 'condition:trigger' ).reply( 'unset_required', this.unsetRequired, this );
974		},
975
976		setRequired: function( conditionModel, then ) {
977			var targetFieldModel = nfRadio.channel( 'form-' + conditionModel.collection.formModel.get( 'id' ) ).request( 'get:fieldByKey', then.key );
978
979			if( 'undefined' == typeof targetFieldModel ) return;
980            targetFieldModel.set( 'required', 1 );
981			targetFieldModel.trigger( 'reRender', targetFieldModel );
982		},
983
984		unsetRequired: function( conditionModel, then ) {
985			var targetFieldModel = nfRadio.channel( 'form-' + conditionModel.collection.formModel.get( 'id' ) ).request( 'get:fieldByKey', then.key );
986
987			if( 'undefined' == typeof targetFieldModel ) return;
988            targetFieldModel.set( 'required', 0 );
989            targetFieldModel.trigger( 'reRender', targetFieldModel );
990            // Ensure we resolve any errors when the field is no longer required.
991			nfRadio.channel( 'fields' ).request( 'remove:error', targetFieldModel.get( 'id' ), 'required-error' );
992        }
993        
994	});
995
996	return controller;
997} );
998/**
999 * Handle adding or removing an option from our list
1000 * 
1001 * @package Ninja Forms Conditional Logic
1002 * @copyright (c) 2016 WP Ninjas
1003 * @since 3.0
1004 */
1005define( 'controllers/showHideOption',[], function() {
1006	var controller = Marionette.Object.extend( {
1007		initialize: function() {
1008			nfRadio.channel( 'condition:trigger' ).reply( 'show_option', this.showOption, this );
1009
1010			nfRadio.channel( 'condition:trigger' ).reply( 'hide_option', this.hideOption, this );
1011		},
1012
1013		showOption: function( conditionModel, then ) {
1014			var option = this.getOption( conditionModel, then );
1015			option.visible = true;
1016			this.updateFieldModel( conditionModel, then );
1017		},
1018
1019		hideOption: function( conditionModel, then ) {
1020			var option = this.getOption( conditionModel, then );
1021			option.visible = false;
1022			this.updateFieldModel( conditionModel, then );
1023		},
1024
1025		getFieldModel: function( conditionModel, then ) {
1026			return nfRadio.channel( 'form-' + conditionModel.collection.formModel.get( 'id' ) ).request( 'get:fieldByKey', then.key );
1027		},
1028
1029		getOption: function( conditionModel, then ) {
1030			var targetFieldModel = this.getFieldModel( conditionModel, then );
1031			var options = targetFieldModel.get( 'options' );
1032			return _.find( options, function( option ) { return option.value == then.value } );
1033		},
1034
1035		updateFieldModel: function( conditionModel, then ) {
1036			var targetFieldModel = this.getFieldModel( conditionModel, then );
1037			var options = targetFieldModel.get( 'options' );
1038			targetFieldModel.set( 'options', options );
1039			targetFieldModel.trigger( 'reRender' );
1040		}
1041	});
1042
1043	return controller;
1044} );
1045/**
1046 * Handle changing a field's value
1047 * 
1048 * @package Ninja Forms Conditional Logic
1049 * @copyright (c) 2016 WP Ninjas
1050 * @since 3.0
1051 */
1052define( 'controllers/changeValue',[], function() {
1053	var controller = Marionette.Object.extend( {
1054		initialize: function() {
1055			nfRadio.channel( 'condition:trigger' ).reply( 'change_value', this.changeValue, this );
1056		},
1057
1058		changeValue: function( conditionModel, then ) {
1059			var targetFieldModel = nfRadio.channel( 'form-' + conditionModel.collection.formModel.get( 'id' ) ).request( 'get:fieldByKey', then.key );
1060			/*
1061			 * If we have a checkbox then we need to change the value that is set
1062			 * of the then variable to a 1 or 0 to re-render on the front end when
1063			 * the condition is met.
1064			 */
1065			if( 'checkbox' == targetFieldModel.get( 'type' ) ) {
1066				// We also need to do the opposite of the value that is in the changed model.
1067				if( 'unchecked' == targetFieldModel.changed.value ) {
1068					then.value = 1;
1069                } else if( 'checked' == targetFieldModel ) {
1070					then.value = 0;
1071				}
1072			}
1073            /*
1074             * Change the value of our field model, and then trigger a re-render of its view.
1075             */
1076			targetFieldModel.set( 'value', then.value );
1077			targetFieldModel.trigger( 'reRender', targetFieldModel );
1078		},
1079
1080	});
1081	return controller;
1082} );
1083/**
1084 * Handle selecting/deselecting list options
1085 * 
1086 * @package Ninja Forms Conditional Logic
1087 * @copyright (c) 2016 WP Ninjas
1088 * @since 3.0
1089 */
1090define( 'controllers/selectDeselect',[], function() {
1091	var controller = Marionette.Object.extend( {
1092		initialize: function() {
1093			nfRadio.channel( 'condition:trigger' ).reply( 'select_option', this.selectOption, this );
1094
1095			nfRadio.channel( 'condition:trigger' ).reply( 'deselect_option', this.deselectOption, this );
1096		},
1097
1098		selectOption: function( conditionModel, then ) {
1099			/*
1100			 * Get our field model and set this option's "selected" property to 1
1101			 */
1102			var targetFieldModel = nfRadio.channel( 'form-' + conditionModel.collection.formModel.get( 'id' ) ).request( 'get:fieldByKey', then.key );
1103
1104
1105			if( _.contains( [ 'listselect', 'listcountry', 'liststate' ], targetFieldModel.get( 'type' ) ) ) { // TODO: Make this more dynamic.
1106				targetFieldModel.set('clean', false); // Allows for changes to default values.
1107			}
1108
1109			var options = targetFieldModel.get( 'options' );
1110
1111			var option = _.find( options, { value: then.value } );
1112			option.selected = 1;
1113
1114			targetFieldModel.set( 'options', options );
1115
1116			if( _.contains( [ 'listselect', 'listcountry', 'liststate' ], targetFieldModel.get( 'type' ) ) ) { // TODO: Make this more dynamic.
1117				targetFieldModel.set( 'value', option.value ); // Propagate the selected option to the model's value.
1118			} else {
1119				var value = targetFieldModel.get( 'value' );
1120				if ( _.isArray( value ) ) {
1121                    if ( 0 > value.indexOf( option.value ) ) {
1122                        value.push( option.value );
1123                        // Set the value to nothing so it knows that something has changed.
1124                        targetFieldModel.set( 'value', '' );
1125                    }
1126				} else {
1127					value = option.value;
1128				}
1129				
1130				targetFieldModel.set( 'value', value ); // Propagate the selected option to the model's value.
1131			}
1132
1133			/*
1134			 * Re render our field
1135			 */
1136			targetFieldModel.trigger( 'reRender', targetFieldModel );
1137		},
1138
1139		deselectOption: function( conditionModel, then ) {
1140			/*
1141			 * When we are trying to deselect our option, we need to change it's "selected" property to 0 AND change its value.
1142			 */
1143			var targetFieldModel = nfRadio.channel( 'form-' + conditionModel.collection.formModel.get( 'id' ) ).request( 'get:fieldByKey', then.key );
1144
1145			/*
1146			 * Set "selected" to 0.
1147			 */
1148			var options = targetFieldModel.get( 'options' );
1149			var option = _.find( options, { value: then.value } );
1150			option.selected = 0;
1151			targetFieldModel.set( 'options', options );
1152
1153			/*
1154			 * Update our value
1155			 */
1156			var currentValue = targetFieldModel.get( 'value' );
1157			if ( _.isArray( currentValue ) ) {
1158				currentValue = _.without( currentValue, then.value );
1159			} else {
1160				currentValue = '';
1161			}
1162			targetFieldModel.set( 'value', currentValue );
1163
1164			/*
1165			 * Re render our field
1166			 */
1167			targetFieldModel.trigger( 'reRender', targetFieldModel );
1168		},
1169
1170	});
1171
1172	return controller;
1173} );
1174/**
1175 * Keep an internal record for which actions are active and deactive.
1176 * 
1177 * @package Ninja Forms Conditional Logic
1178 * @copyright (c) 2016 WP Ninjas
1179 * @since 3.0
1180 */
1181define( 'controllers/actions',[], function() {
1182	var controller = Marionette.Object.extend( {
1183		actions: {},
1184		
1185		initialize: function() {
1186			/*
1187			 * Listen for activate/deactivate action messages.
1188			 */
1189			nfRadio.channel( 'condition:trigger' ).reply( 'activate_action', this.activateAction, this );
1190			nfRadio.channel( 'condition:trigger' ).reply( 'deactivate_action', this.deactivateAction, this );
1191		
1192			/*
1193			 * Reply to requests for action status.
1194			 */
1195			nfRadio.channel( 'actions' ).reply( 'get:status', this.getStatus, this );
1196		},
1197
1198		activateAction: function( conditionModel, thenObject ) {
1199			this.actions[ thenObject.key ] = true;
1200			console.log( 'activate action' );
1201		},
1202
1203		deactivateAction: function( conditionModel, thenObject ) {
1204			console.log( 'deactivate action' );
1205			this.actions[ thenObject.key ] = false;
1206		},
1207
1208		getStatus: function( $id ) {
1209			return this.actions[ $id ];
1210		}
1211	});
1212
1213	return controller;
1214} );
1215var nfRadio = Backbone.Radio;
1216
1217require( [ 'controllers/initCollection', 'controllers/showHide', 'controllers/changeRequired', 'controllers/showHideOption', 'controllers/changeValue', 'controllers/selectDeselect', 'controllers/actions' ], function( InitCollection, ShowHide, ChangeRequired, ShowHideOption, ChangeValue, SelectDeselect, Actions ) {
1218
1219	var NFConditionalLogic = Marionette.Application.extend( {
1220
1221		initialize: function( options ) {
1222			this.listenTo( nfRadio.channel( 'form' ), 'after:loaded', this.loadControllers );
1223		},
1224
1225		loadControllers: function( formModel ) {
1226			new ShowHide();
1227			new ChangeRequired();
1228			new ShowHideOption();
1229			new ChangeValue();
1230			new SelectDeselect();
1231			new Actions();
1232			new InitCollection( formModel );
1233		},
1234
1235		onStart: function() {
1236			
1237		}
1238	} );
1239
1240	var nfConditionalLogic = new NFConditionalLogic();
1241	nfConditionalLogic.start();
1242} );
1243define("main", function(){});
1244
1245}());
1246//# sourceMappingURL=front-end.js.map

Line numbers count LF bytes from the start of the resource, as the search results do. Vendor segments are library code the classifier recognised; they are stored but not indexed. Bytes are shown as Latin1 characters, one per byte.