PageSourceSearch

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

js freelancersunion.org collected 2026-09-24 08:25:46 UTC 50,067 bytes, 1,409 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				// For date_and_time fields, picking the hour/minute/am-pm only updates
472				// those attributes (not 'value') until the form is actually submitted
473				// (see NF core changeDate.js: changeHoursMinutes). Without these listeners,
474				// the comparison stays frozen at whatever time was selected (usually 00:00)
475				// when the date was first picked, and never re-evaluates as the visitor
476				// picks a time.
477				fieldModel.on( 'change:selected_hour change:selected_minute change:selected_ampm', this.updateFieldCompare, this );
478				// When we keyup in our field, maybe update our compare status.
479				this.listenTo( nfRadio.channel( 'field-' + fieldModel.get( 'id' ) ), 'keyup:field', this.maybeupdateFieldCompare );
480				// Update our compare status.
481				this.updateFieldCompare( fieldModel );
482
483				/*
484				 * TODO: This should be moved to the show_field/hide_field file because it is specific to showing and hiding.
485				 * Create a radio message here so that the specific JS file can hook into whenModel init.
486				 */
487				fieldModel.on( 'change:visible', this.updateFieldCompare, this );
488			}
489		},
490
491		updateCalcCompare: function( calcModel ) {
492			this.updateCompare( calcModel.get( 'value' ) );
493		},
494
495		maybeupdateFieldCompare: function( el, fieldModel, keyCode ) {
496			if( 'checkbox' == fieldModel.get( 'type' ) ){
497                var fieldValue = ( 'checked' == jQuery( el ).attr( 'checked' ) ) ? 1 : 0;
498            } else if( 'listcheckbox' == fieldModel.get( 'type' ) ) {
499				// This field isn't a single element, so we need to reference the fieldModel, instead of the DOM.
500                var fieldValue = fieldModel.get( 'value' ).join();
501            } else if ( 'listradio' == fieldModel.get( 'type' ) ) {
502				/*
503				 * Use the field model's actual selected value rather than jQuery(el).val().
504				 * jQuery(el).val() returns the value attribute of whichever radio button has
505				 * focus, even if it has not been selected by the user. When tabbing into a
506				 * radio field, the keyup event fires on the focused (but unselected) radio
507				 * button, causing jQuery(el).val() to return that option's value and
508				 * incorrectly trigger conditions. The field model value only reflects a
509				 * genuinely selected option.
510				 */
511				var fieldValue = fieldModel.get( 'value' );
512            } else if ( 'date' == fieldModel.get ('type' ) ) {
513				var fieldValue = fieldModel.get( 'value' );
514				var fieldHadValue = ! _.isEmpty( fieldValue );
515
516				if ( _.isEmpty( fieldValue ) ) {
517					if ( 1 == fieldModel.get( 'date_default' ) ) {
518						var now = new Date();
519						fieldValue = now.getFullYear() + '/' + ( '0' + ( now.getMonth() + 1 ) ).slice( -2 ) + '/' + ( '0' + now.getDate() ).slice( -2 );
520					} else {
521						fieldValue = '1970/01/01';
522					}
523				}
524
525				let date_mode = fieldModel.get( 'date_mode' );
526				if ( 'undefined' == typeof date_mode ) { // If 'date_mode' is undefined, then we assume it's date_only.
527					date_mode = 'date_only';
528				}
529				let date = 0;
530				// If we're in time_only mode, then we need to use 1970-01-01 as our date.
531				if ( 'time_only' == fieldModel.get( 'date_mode' ) ) {
532					date = '1970/01/01';
533				} else {
534					// Parse the submitted value using the field's own configured date_format,
535					// instead of handing a format-dependent string straight to `new Date()`.
536					date = fieldHadValue ? this.normalizeDateToISO( fieldValue, fieldModel ) : fieldValue;
537				}
538
539				// Convert field value into a timestamp
540				let hour = fieldModel.get( 'selected_hour' );
541				if ( 'undefined' == typeof hour ) {
542					hour = '00';
543				}
544
545				let minute = fieldModel.get( 'selected_minute' );
546				if ( 'undefined' == typeof minute ) {
547					minute = '00';
548				}
549
550				// If we have a date_and_time field, but we haven't selected a date yet, we don't need to compare.
551				if ( 'date_and_time' == date_mode && '1970/01/01' == date ) {
552					fieldValue = false;
553				} else {
554					fieldValue = date + ' ' + hour + ':' + minute + ' UT';
555
556					let dateObject = new Date( fieldValue );
557					fieldValue = Math.floor( dateObject.getTime() / 1000 );					
558				}
559			} else {
560				var fieldValue = jQuery( el ).val();
561			}
562
563			this.updateFieldCompare( fieldModel, null, fieldValue );
564		},
565
566		/**
567		 * Convert a date field's raw submitted value into a Y/m/d order string
568		 * ("normalized ISO"), parsing it according to the field's own date_format
569		 * setting rather than assuming YYYY-MM-DD. Falls back to the original string
570		 * unchanged if the field's flatpickr instance/format can't be resolved (e.g.
571		 * a hidden or programmatically-set field), preserving prior behavior for
572		 * those cases.
573		 *
574		 * @param {string} dateString Raw value straight from the field model.
575		 * @param {object} fieldModel Backbone field model for the date field.
576		 * @return {string} Y/m/d date string, or the original value if it couldn't be parsed.
577		 */
578		normalizeDateToISO: function( dateString, fieldModel ) {
579			var format = fieldModel.get( 'date_format' );
580			var el = document.querySelector( "[name='nf-field-" + fieldModel.get( 'id' ) + "']" );
581
582			if ( ! el || ! el._flatpickr || ! format ) {
583				return dateString;
584			}
585
586			var parsed = el._flatpickr.parseDate( dateString, format );
587
588			if ( ! parsed || isNaN( parsed.getTime() ) ) {
589				return dateString;
590			}
591
592			return parsed.getFullYear() + '/' + ( '0' + ( parsed.getMonth() + 1 ) ).slice( -2 ) + '/' + ( '0' + parsed.getDate() ).slice( -2 );
593		},
594
595		updateCompare: function( value, dateMode ) {
596			var this_val = this.get( 'value' );
597
598			// if this is a calcModel then let's convert to number for comparison
599			if ( 'calc' === this.get( 'type' ) ) {
600				this_val = Number( this_val );
601				value = Number( value );
602			} else if ( 'undefined' != typeof dateMode ) {
603				// The stored condition target may have been created while the field was in a
604				// different date_mode (e.g. a time baked in from Date and Time mode, now that
605				// the field is Date Only). Disregard whichever component (date, or time-of-day)
606				// the current mode doesn't actually capture.
607				value = this.normalizeForDateMode( value, dateMode );
608				this_val = this.normalizeForDateMode( this_val, dateMode );
609			}
610			// Check to see if the value of the field model value COMPARATOR the value of our when condition is true.
611			var status = this.compareValues[ this.get( 'comparator' ) ]( value, this_val );
612			this.set( 'status', status );
613		},
614
615		normalizeForDateMode: function( epoch, dateMode ) {
616			if ( false === epoch || null === epoch || 'undefined' == typeof epoch || isNaN( epoch ) ) {
617				return epoch;
618			}
619
620			var DAY_IN_SECONDS = 86400;
621
622			if ( 'date_only' === dateMode ) {
623				return epoch - ( epoch % DAY_IN_SECONDS );
624			}
625
626			if ( 'time_only' === dateMode ) {
627				return ( ( epoch % DAY_IN_SECONDS ) + DAY_IN_SECONDS ) % DAY_IN_SECONDS;
628			}
629
630			return epoch;
631		},
632
633		updateFieldCompare: function( fieldModel, val, fieldValue ) {
634			if ( _.isEmpty( fieldValue ) ) {
635				fieldValue = fieldModel.get( 'value' );
636			}
637
638			var date_mode;
639
640			// Change the value of checkboxes to match the new convention.
641			if( 'checkbox' == fieldModel.get( 'type' ) ) {
642				if( 0 == fieldValue ) {
643					fieldValue = 'unchecked';
644				} else {
645					fieldValue = 'checked';
646				}
647			} else if ( 'date' == fieldModel.get( 'type' ) ) {
648				// NF core's fieldDate.js sets the model's 'value' to an object
649				// ({date, hour, minute, ampm}) right at form submission (beforeSubmit),
650				// instead of the plain date string used everywhere else. Extract the date
651				// portion here so normalizeDateToISO() always receives a string — otherwise
652				// its flatpickr parseDate() call receives the object and logs "Invalid date
653				// provided", falling back to the (still-an-object) value unchanged.
654				if ( _.isObject( fieldValue ) ) {
655					fieldValue = fieldValue.date;
656				}
657
658				var fieldHadValue = ! _.isEmpty( fieldValue );
659
660				if ( _.isEmpty( fieldValue ) ) {
661					if ( 1 == fieldModel.get( 'date_default' ) ) {
662						var now = new Date();
663						fieldValue = now.getFullYear() + '/' + ( '0' + ( now.getMonth() + 1 ) ).slice( -2 ) + '/' + ( '0' + now.getDate() ).slice( -2 );
664					} else {
665						fieldValue = '1970/01/01';
666					}
667				}
668
669				date_mode = fieldModel.get( 'date_mode' );
670				if ( 'undefined' == typeof date_mode ) { // If 'date_mode' is undefined, then we assume it's date_only.
671					date_mode = 'date_only';
672				}
673				let date = 0;
674				// If we're in time_only mode, then we need to use 1970-01-01 as our date.
675				if ( 'time_only' == fieldModel.get( 'date_mode' ) ) {
676					date = '1970/01/01';
677				} else {
678					// Parse the submitted value using the field's own configured date_format,
679					// instead of handing a format-dependent string straight to `new Date()`.
680					date = fieldHadValue ? this.normalizeDateToISO( fieldValue, fieldModel ) : fieldValue;
681				}
682
683				// Convert field value into a timestamp
684				let hour = fieldModel.get( 'selected_hour' );
685				if ( 'undefined' == typeof hour ) {
686					hour = '00';
687				}
688
689				let ampm = fieldModel.get( 'selected_ampm' );
690				if ( 'undefined' != typeof ampm ) {
691					// Convert our hour into 24 hr format.
692					if ( 'pm' == ampm && '12' != hour ) {
693						hour = parseInt( hour ) + 12;
694					} else if ( 'am' == ampm && '12' == hour ) {
695						hour = '00';
696					}
697				}
698
699				let minute = fieldModel.get( 'selected_minute' );
700				if ( 'undefined' == typeof minute ) {
701					minute = '00';
702				}
703
704				// If we have a date_and_time field, but we haven't selected a date yet, we don't need to compare.
705				if ( 'date_and_time' == date_mode && '1970/01/01' == date ) {
706					fieldValue = false;
707				} else {
708					fieldValue = date + ' ' + hour + ':' + minute + ' UT';
709
710					let dateObject = new Date( fieldValue );
711					fieldValue = Math.floor( dateObject.getTime() / 1000 );
712				}
713			}
714
715			this.updateCompare( fieldValue, date_mode );
716
717			/*
718			 * TODO: This should be moved to the show_field/hide_field file because it is specific to showing and hiding.
719			 */
720			if ( ! fieldModel.get( 'visible' ) ) {
721				this.set( 'status', false );
722			}
723		},
724
725		compareValues: {
726			'equal': function( a, b ) {
727				return a == b;
728			},
729			'notequal': function( a, b ) {
730				return a != b;
731			},
732			'contains': function( a, b ) {
733				if ( jQuery.isArray( a ) ) {
734					/*
735					 * If a is an array, then we're searching for an index.
736					 */
737					return a.indexOf( b ) >= 0;
738				} else {
739					/*
740					 * If a is a string, then we're searching for a string position.
741					 *
742					 * If our b value has quotes in it, we want to find that exact word or phrase.
743					 */
744					if ( b.indexOf( '"' ) >= 0 ) {
745						b = b.replace( /['"]+/g, '' );
746						return new RegExp("\\b" + b + "\\b").test( a );
747					}
748					return a.toLowerCase().indexOf( b.toLowerCase() ) >= 0; 				
749				}
750			},
751			'notcontains': function( a, b ) {
752				return ! this.contains( a, b );
753			},
754			'greater': function( a, b ) {
755				/*
756				 * In 2.9.x, you could use the greater and less like string count.
757				 * i.e. if textbox > (empty string) do something.
758				 * This recreates that ability.
759				 */
760				if ( jQuery.isNumeric( b ) ) {
761					return parseFloat( a ) > parseFloat( b );
762				} else if ( 'string' == typeof a ) {
763					return 0 < a.length;
764				}
765				
766			},
767			'less': function( a, b ) {
768				/*
769				 * In 2.9.x, you could use the greater and less like string count.
770				 * i.e. if textbox > (empty string) do something.
771				 * This recreates that ability.
772				 */
773				if ( jQuery.isNumeric( b ) ) {
774					return parseFloat( a ) < parseFloat( b );
775				} else if ( 'string' == typeof a ) {
776					return 0 >= a.length;
777				}
778		
779			},
780			'greaterequal': function( a, b ) {
781				return parseFloat( a ) > parseFloat( b ) || parseFloat( a ) == parseFloat( b );
782			},
783			'lessequal': function( a, b ) {
784				return parseFloat( a ) < parseFloat( b ) || parseFloat( a ) == parseFloat( b );
785			}
786		} 
787	} );
788	
789	return model;
790} );
791define( 'models/whenCollection',['models/whenModel'], function( WhenModel ) {
792	var collection = Backbone.Collection.extend( {
793		model: WhenModel,
794
795		initialize: function( models, options ) {
796			this.options = options;
797		}
798	} );
799	return collection;
800} );
801define( 'models/conditionModel',[ 'models/whenCollection' ], function( WhenCollection ) {
802	var model = Backbone.Model.extend( {
803		initialize: function( options ) {
804			/*
805			 * Our "when" statement will be like:
806			 * When field1 == value
807			 * AND field2 == value
808			 *
809			 * We need to create a collection out of this when statement, with each row as a model.
810			 */
811			this.set( 'when', new WhenCollection( this.get( 'when' ), { condition: this } ) );
812			/*
813			 * When we update any of our "when" models' status, check to see if we should send a message.
814			 */
815			this.get( 'when' ).on( 'change:status', this.checkWhen, this );
816			/*
817			 * Check our initial status;
818			 * Deferred via setTimeout to allow all field relationships (e.g. Confirm field pairings)
819			 * to be fully established before conditions first evaluate on page load.
820			 */
821			setTimeout( function() {
822				this.checkWhen();
823			}.bind( this ), 0 );
824		},
825
826		checkWhen: function() {
827			/*
828			 * If we have any OR connectors, then any status being true should trigger pass.
829			 * Otherwise, we need every status to be true.
830			 */
831			var statusResults = this.get( 'when' ).pluck( 'status' );
832
833			var connectors = this.get( 'when' ).pluck( 'connector' );
834			var allAND = _.every( _.values( connectors ), function( v ) { return v == 'AND' }, this );
835			if ( allAND ) {
836				var status = _.every( _.values( statusResults ), function(v) { return v; }, this );
837			} else {
838				var status = _.some( _.values( statusResults ), function(v) { return v; }, this );
839			}
840
841			if ( status ) {
842			   	/*
843			 	 * Send out a request for each of our "then" statements.
844			 	 */
845				_.each( this.get( 'then' ), function( then, index ) {
846					nfRadio.channel( 'condition:trigger' ).request( then.trigger, this, then );
847				}, this );
848			} else {
849				/*
850				 * Send out a request for each of our "else" statements.
851				 */
852				_.each( this.get( 'else' ), function( elseData, index ) {
853					nfRadio.channel( 'condition:trigger' ).request( elseData.trigger, this, elseData );
854				}, this );
855			}
856		}
857	} );
858
859	return model;
860} );
861
862define( 'models/conditionCollection',['models/conditionModel'], function( ConditionModel ) {
863	var collection = Backbone.Collection.extend( {
864		model: ConditionModel,
865
866		initialize: function( models, options ) {
867			this.formModel = options.formModel;
868		}
869	} );
870	return collection;
871} );
872/**
873 * Initialise condition collection
874 * 
875 * @package Ninja Forms Conditional Logic
876 * @copyright (c) 2016 WP Ninjas
877 * @since 3.0
878 */
879define( 'controllers/initCollection',[ 'models/conditionCollection' ], function( ConditionCollection ) {
880	var controller = Marionette.Object.extend( {
881		initialize: function( formModel ) {
882			this.collection = new ConditionCollection( formModel.get( 'conditions' ), { formModel: formModel } );
883            this.listenTo(nfRadio.channel('fields'), 'reset:collection', this.resetCollection);
884		},
885        resetCollection: function( fieldsCollection ) {
886            var formModel = fieldsCollection.options.formModel;
887            this.collection = new ConditionCollection( formModel.get( 'conditions' ), { formModel: formModel } );
888        }
889	});
890
891	return controller;
892} );
893/**
894 * Handle showing/hiding fields
895 * 
896 * @package Ninja Forms Conditional Logic
897 * @copyright (c) 2016 WP Ninjas
898 * @since 3.0
899 */
900define( 'controllers/showHide',[], function() {
901	var controller = Marionette.Object.extend( {
902		initialize: function() {
903			nfRadio.channel( 'condition:trigger' ).reply( 'hide_field', this.hideField, this );
904			nfRadio.channel( 'condition:trigger' ).reply( 'show_field', this.show
904Field, this );
905		},
906
907		hideField: function( conditionModel, then ) {
908			var formId = conditionModel.collection.formModel.get( 'id' );
909			var targetFieldModel = nfRadio.channel( 'form-' + formId ).request( 'get:fieldByKey', then.key );
910
911			if( 'undefined' == typeof targetFieldModel ) return;
912			targetFieldModel.set( 'visible', false );
913            if ( ! targetFieldModel.get( 'clean' ) ) {
914				targetFieldModel.trigger( 'change:value', targetFieldModel );
915			}
916
917			nfRadio.channel( 'fields' ).request( 'remove:error', targetFieldModel.get( 'id' ), 'required-error' );
918
919			// For repeater fields, mark child field models as not visible so JS
920			// validation skips their required check on submission.
921			if ( 'repeater' === targetFieldModel.get( 'type' ) ) {
922				this.setRepeaterChildrenVisible( targetFieldModel, false );
923			}
924		},
925
926		/**
927		 * Set the visible state on all child field models of a Repeater field.
928		 *
929		 * Child models live inside the Repeater's own sets collection, not in the
930		 * top-level form field collection. When visible is false, NF core's
931		 * validateModelData skips required validation for those fields.
932		 */
933		setRepeaterChildrenVisible: function( repeaterModel, visible ) {
934			var sets = repeaterModel.get( 'sets' );
935			if ( ! sets ) return;
936
937			sets.each( function( set ) {
938				var fields = set.get( 'fields' );
939				if ( ! fields ) return;
940
941				fields.each( function( fieldModel ) {
942					fieldModel.set( 'visible', visible );
943					if ( ! visible ) {
944						nfRadio.channel( 'fields' ).request( 'remove:error', fieldModel.get( 'id' ), 'required-error' );
945					}
946				} );
947			} );
948		},
949
950		showField: function( conditionModel, then ) {
951			var targetFieldModel = nfRadio.channel( 'form-' + conditionModel.collection.formModel.get( 'id' ) ).request( 'get:fieldByKey', then.key );
952			//TODO: Add an error to let the user know the show/hide field is empty.
953			if( 'undefined' == typeof targetFieldModel ) return;
954			targetFieldModel.set( 'visible', true );
955            if ( ! targetFieldModel.get( 'clean' ) ) {
956                targetFieldModel.trigger( 'change:value', targetFieldModel );
957			}
958			// For repeater fields, restore child field models to visible so
959			// required validation applies again when the Repeater is shown.
960			if ( 'repeater' === targetFieldModel.get( 'type' ) ) {
961				this.setRepeaterChildrenVisible( targetFieldModel, true );
962			}
963			if ( 'recaptcha' === targetFieldModel.get( 'type' ) ) {
964				this.renderRecaptcha();
965			}
966			if ( 'turnstile' === targetFieldModel.get( 'type' ) ) {
967				this.renderTurnstile();
968			}
969			var viewEl = { el: nfRadio.channel( 'form-' + conditionModel.collection.formModel.get( 'id' ) ).request( 'get:el' ) };
970            nfRadio.channel( 'form' ).request( 'init:help', viewEl );
971		},
972
973		renderRecaptcha: function() {
974			jQuery( '.g-recaptcha' ).each( function() {
975                var callback = jQuery( this ).data( 'callback' );
976                var fieldID = jQuery( this ).data( 'fieldid' );
977                if ( typeof window[ callback ] !== 'function' ){
978                    window[ callback ] = function( response ) {
979                        nfRadio.channel( 'recaptcha' ).request( 'update:response', response, fieldID );
980                    };
981                }
982				var opts = {
983					theme: jQuery( this ).data( 'theme' ),
984					sitekey: jQuery( this ).data( 'sitekey' ),
985					callback: callback
986				};
987				
988				grecaptcha.render( jQuery( this )[0], opts );
989			} );
990		},
991
992		renderTurnstile: function() {
993			// Ensure turnstile API is loaded
994			if ( typeof turnstile === 'undefined' ) {
995				return;
996			}
997
998			jQuery( '.cf-turnstile, .nf-cf-turnstile' ).each( function() {
999				var element = this;
1000				var sitekey = jQuery( element ).data( 'sitekey' );
1001				var fieldID = jQuery( element ).data( 'fieldid' );
1002				
1003				// Skip if no sitekey or already rendered
1004				if ( ! sitekey || jQuery( element ).children().length > 0 ) {
1005					return;
1006				}
1007
1008				try {
1009					// Create callback function for this specific field
1010					var callbackName = 'nfTurnstileCallback_' + fieldID;
1011					
1012					// Define the callback function
1013					window[ callbackName ] = function( token ) {
1014						// Update the hidden input field
1015						var input = document.getElementById( 'nf-field-' + fieldID );
1016						if ( input ) {
1017							input.value = token;
1018							jQuery( input ).trigger( 'change' );
1019							
1020							// Remove error states
1021							jQuery( input ).closest( '.field-wrap' ).removeClass( 'nf-error' );
1022							jQuery( input ).closest( '.field-wrap' ).find( '.nf-error-msg' ).remove();
1023						}
1024
1025						// Update via radio channel if available
1026						if ( typeof nfRadio !== 'undefined' && nfRadio.channel ) {
1027							try {
1028								nfRadio.channel( 'turnstile' ).request( 'update:response', token, fieldID );
1029							} catch( e ) {
1030								// Silent fail
1031							}
1032						}
1033					};
1034
1035					// Render the turnstile widget
1036					turnstile.render( element, {
1037						sitekey: sitekey,
1038						theme: jQuery( element ).data( 'theme' ) || 'auto',
1039						size: jQuery( element ).data( 'size' ) || 'normal',
1040						callback: callbackName
1041					} );
1042					
1043				} catch( e ) {
1044					// Silent fail for turnstile render errors
1045				}
1046			} );
1047		}
1048	});
1049
1050	return controller;
1051} );
1052/**
1053 * Setting/unsetting required.
1054 * 
1055 * @package Ninja Forms Conditional Logic
1056 * @copyright (c) 2019 WP Ninjas
1057 * @since 3.0
1058 */
1059define( 'controllers/changeRequired',[], function() {
1060	var controller = Marionette.Object.extend( {
1061		initialize: function() {
1062			nfRadio.channel( 'condition:trigger' ).reply( 'set_required', this.setRequired, this );
1063			nfRadio.channel( 'condition:trigger' ).reply( 'unset_required', this.unsetRequired, this );
1064		},
1065
1066		setRequired: function( conditionModel, then ) {
1067			var targetFieldModel = nfRadio.channel( 'form-' + conditionModel.collection.formModel.get( 'id' ) ).request( 'get:fieldByKey', then.key );
1068
1069			if( 'undefined' == typeof targetFieldModel ) return;
1070            targetFieldModel.set( 'required', 1 );
1071			targetFieldModel.trigger( 'reRender', targetFieldModel );
1072		},
1073
1074		unsetRequired: function( conditionModel, then ) {
1075			var targetFieldModel = nfRadio.channel( 'form-' + conditionModel.collection.formModel.get( 'id' ) ).request( 'get:fieldByKey', then.key );
1076
1077			if( 'undefined' == typeof targetFieldModel ) return;
1078            targetFieldModel.set( 'required', 0 );
1079            targetFieldModel.trigger( 'reRender', targetFieldModel );
1080            // Ensure we resolve any errors when the field is no longer required.
1081			nfRadio.channel( 'fields' ).request( 'remove:error', targetFieldModel.get( 'id' ), 'required-error' );
1082        }
1083        
1084	});
1085
1086	return controller;
1087} );
1088/**
1089 * Handle adding or removing an option from our list
1090 * 
1091 * @package Ninja Forms Conditional Logic
1092 * @copyright (c) 2016 WP Ninjas
1093 * @since 3.0
1094 */
1095define( 'controllers/showHideOption',[], function() {
1096	var controller = Marionette.Object.extend( {
1097		initialize: function() {
1098			nfRadio.channel( 'condition:trigger' ).reply( 'show_option', this.showOption, this );
1099
1100			nfRadio.channel( 'condition:trigger' ).reply( 'hide_option', this.hideOption, this );
1101		},
1102
1103		showOption: function( conditionModel, then ) {
1104			var option = this.getOption( conditionModel, then );
1105			option.visible = true;
1106			this.restoreFieldValue( conditionModel, then, option );
1107			this.updateFieldModel( conditionModel, then );
1108		},
1109
1110		hideOption: function( conditionModel, then ) {
1111			var option = this.getOption( conditionModel, then );
1112			option.visible = false;
1113			this.applyFallbackValue( conditionModel, then, option );
1114			this.updateFieldModel( conditionModel, then );
1115		},
1116
1117		getFieldModel: function( conditionModel, then ) {
1118			return nfRadio.channel( 'form-' + conditionModel.collection.formModel.get( 'id' ) ).request( 'get:fieldByKey', then.key );
1119		},
1120
1121		getOption: function( conditionModel, then ) {
1122			var targetFieldModel = this.getFieldModel( conditionModel, then );
1123			var options = targetFieldModel.get( 'options' );
1124			return _.find( options, function( option ) { return option.value == then.value } );
1125		},
1126
1127		/**
1128		 * If the option being hidden is the field's current value, fall back to the
1129		 * first remaining visible option (or blank). The original value is remembered
1130		 * so showOption can restore it automatically - unless the user picks a
1131		 * different option manually in the meantime (see bindManualOverrideListener).
1132		 */
1133		applyFallbackValue: function( conditionModel, then, hiddenOption ) {
1134			var targetFieldModel = this.getFieldModel( conditionModel, then );
1135			var currentValue = targetFieldModel.get( 'value' );
1136
1137			if ( hiddenOption.visible || currentValue != hiddenOption.value ) return;
1138
1139			// Only remember the original value the first time we fall back, so a
1140			// cascade of hides (multiple options hidden at once) still reverts to
1141			// the value the user actually had selected before any of this happened.
1142			if ( ! targetFieldModel.get( 'clAutoFallback' ) ) {
1143				targetFieldModel.set( 'clAutoFallbackValue', currentValue );
1144				targetFieldModel.set( 'clAutoFallback', true );
1145				this.bindManualOverrideListener( targetFieldModel );
1146			}
1147
1148			var options = targetFieldModel.get( 'options' );
1149			var firstVisibleOption = _.find( options, function( option ) {
1150				return option.visible !== false;
1151			} );
1152
1153			this.setFieldValue( targetFieldModel, firstVisibleOption ? firstVisibleOption.value : '' );
1154		},
1155
1156		/**
1157		 * If the option becoming visible is the one we auto-fell-back from, restore
1158		 * it - but only while that fallback is still active (i.e. the user hasn't
1159		 * manually selected something else since it was hidden).
1160		 */
1161		restoreFieldValue: function( conditionModel, then, shownOption ) {
1162			var targetFieldModel = this.getFieldModel( conditionModel, then );
1163
1164			if ( ! targetFieldModel.get( 'clAutoFallback' ) ) return;
1165			if ( targetFieldModel.get( 'clAutoFallbackValue' ) != shownOption.value ) return;
1166
1167			this.setFieldValue( targetFieldModel, shownOption.value );
1168			targetFieldModel.unset( 'clAutoFallback' );
1169			targetFieldModel.unset( 'clAutoFallbackValue' );
1170		},
1171
1172		/**
1173		 * Sets the field's value and notifies merge tags / dependent fields, mirroring
1174		 * the change:value handling other conditional logic actions (e.g. showHide) use.
1175		 */
1176		setFieldValue: function( targetFieldModel, value ) {
1177			targetFieldModel.set( 'value', value );
1178			if ( ! targetFieldModel.get( 'clean' ) ) {
1179				targetFieldModel.trigger( 'change:value', targetFieldModel );
1180			}
1181		},
1182
1183		/**
1184		 * A real user interaction (change/blur on the field itself) means any value
1185		 * we auto-assigned as a fallback is no longer "ours" to revert - it's now the
1186		 * user's deliberate choice, so clear our tracking and leave it alone.
1187		 */
1188		bindManualOverrideListener: function( targetFieldModel ) {
1189			if ( targetFieldModel.clManualListenerBound ) return;
1190			targetFieldModel.clManualListenerBound = true;
1191
1192			this.listenTo( nfRadio.channel( 'field-' + targetFieldModel.get( 'id' ) ), 'change:field', function() {
1193				targetFieldModel.unset( 'clAutoFallback' );
1194				targetFieldModel.unset( 'clAutoFallbackValue' );
1195			} );
1196		},
1197
1198		updateFieldModel: function( conditionModel, then ) {
1199			var targetFieldModel = this.getFieldModel( conditionModel, then );
1200			var options = targetFieldModel.get( 'options' );
1201			targetFieldModel.set( 'options', options );
1202			targetFieldModel.trigger( 'reRender' );
1203		}
1204	});
1205
1206	return controller;
1207} );
1208/**
1209 * Handle changing a field's value
1210 * 
1211 * @package Ninja Forms Conditional Logic
1212 * @copyright (c) 2016 WP Ninjas
1213 * @since 3.0
1214 */
1215define( 'controllers/changeValue',[], function() {
1216	var controller = Marionette.Object.extend( {
1217		initialize: function() {
1218			nfRadio.channel( 'condition:trigger' ).reply( 'change_value', this.changeValue, this );
1219		},
1220
1221		changeValue: function( conditionModel, then ) {
1222			var targetFieldModel = nfRadio.channel( 'form-' + conditionModel.collection.formModel.get( 'id' ) ).request( 'get:fieldByKey', then.key );
1223			/*
1224			 * If we have a checkbox then we need to change the value that is set
1225			 * of the then variable to a 1 or 0 to re-render on the front end when
1226			 * the condition is met.
1227			 */
1228			if( 'checkbox' == targetFieldModel.get( 'type' ) ) {
1229				// We also need to do the opposite of the value that is in the changed model.
1230				if( 'unchecked' == targetFieldModel.changed.value ) {
1231					then.value = 1;
1232                } else if( 'checked' == targetFieldModel ) {
1233					then.value = 0;
1234				}
1235			}
1236            /*
1237             * Change the value of our field model, and then trigger a re-render of its view.
1238             */
1239			targetFieldModel.set( 'value', then.value );
1240			targetFieldModel.trigger( 'reRender', targetFieldModel );
1241		},
1242
1243	});
1244	return controller;
1245} );
1246/**
1247 * Handle selecting/deselecting list options
1248 * 
1249 * @package Ninja Forms Conditional Logic
1250 * @copyright (c) 2016 WP Ninjas
1251 * @since 3.0
1252 */
1253define( 'controllers/selectDeselect',[], function() {
1254	var controller = Marionette.Object.extend( {
1255		initialize: function() {
1256			nfRadio.channel( 'condition:trigger' ).reply( 'select_option', this.selectOption, this );
1257
1258			nfRadio.channel( 'condition:trigger' ).reply( 'deselect_option', this.deselectOption, this );
1259		},
1260
1261		selectOption: function( conditionModel, then ) {
1262			/*
1263			 * Get our field model and set this option's "selected" property to 1
1264			 */
1265			var targetFieldModel = nfRadio.channel( 'form-' + conditionModel.collection.formModel.get( 'id' ) ).request( 'get:fieldByKey', then.key );
1266
1267
1268			if( _.contains( [ 'listselect', 'listcountry', 'liststate' ], targetFieldModel.get( 'type' ) ) ) { // TODO: Make this more dynamic.
1269				targetFieldModel.set('clean', false); // Allows for changes to default values.
1270			}
1271
1272			var options = targetFieldModel.get( 'options' );
1273
1274			var option = _.find( options, { value: then.value } );
1275			option.selected = 1;
1276
1277			targetFieldModel.set( 'options', options );
1278
1279			if( _.contains( [ 'listselect', 'listcountry', 'liststate' ], targetFieldModel.get( 'type' ) ) ) { // TODO: Make this more dynamic.
1280				targetFieldModel.set( 'value', option.value ); // Propagate the selected option to the model's value.
1281			} else {
1282				var value = targetFieldModel.get( 'value' );
1283				if ( _.isArray( value ) ) {
1284                    if ( 0 > value.indexOf( option.value ) ) {
1285                        value.push( option.value );
1286                        // Set the value to nothing so it knows that something has changed.
1287                        targetFieldModel.set( 'value', '' );
1288                    }
1289				} else {
1290					value = option.value;
1291				}
1292				
1293				targetFieldModel.set( 'value', value ); // Propagate the selected option to the model's value.
1294			}
1295
1296			/*
1297			 * Re render our field
1298			 */
1299			targetFieldModel.trigger( 'reRender', targetFieldModel );
1300		},
1301
1302		deselectOption: function( conditionModel, then ) {
1303			/*
1304			 * When we are trying to deselect our option, we need to change it's "selected" property to 0 AND change its value.
1305			 */
1306			var targetFieldModel = nfRadio.channel( 'form-' + conditionModel.collection.formModel.get( 'id' ) ).request( 'get:fieldByKey', then.key );
1307
1308			/*
1309			 * Set "selected" to 0.
1310			 */
1311			var options = targetFieldModel.get( 'options' );
1312			var option = _.find( options, { value: then.value } );
1313			option.selected = 0;
1314			targetFieldModel.set( 'options', options );
1315
1316			/*
1317			 * Update our value
1318			 */
1319			var currentValue = targetFieldModel.get( 'value' );
1320			if ( _.isArray( currentValue ) ) {
1321				currentValue = _.without( currentValue, then.value );
1322			} else {
1323				currentValue = '';
1324			}
1325			targetFieldModel.set( 'value', currentValue );
1326
1327			/*
1328			 * Re render our field
1329			 */
1330			targetFieldModel.trigger( 'reRender', targetFieldModel );
1331		},
1332
1333	});
1334
1335	return controller;
1336} );
1337/**
1338 * Keep an internal record for which actions are active and deactive.
1339 * 
1340 * @package Ninja Forms Conditional Logic
1341 * @copyright (c) 2016 WP Ninjas
1342 * @since 3.0
1343 */
1344define( 'controllers/actions',[], function() {
1345	var controller = Marionette.Object.extend( {
1346		actions: {},
1347		
1348		initialize: function() {
1349			/*
1350			 * Listen for activate/deactivate action messages.
1351			 */
1352			nfRadio.channel( 'condition:trigger' ).reply( 'activate_action', this.activateAction, this );
1353			nfRadio.channel( 'condition:trigger' ).reply( 'deactivate_action', this.deactivateAction, this );
1354		
1355			/*
1356			 * Reply to requests for action status.
1357			 */
1358			nfRadio.channel( 'actions' ).reply( 'get:status', this.getStatus, this );
1359		},
1360
1361		activateAction: function( conditionModel, thenObject ) {
1362			this.actions[ thenObject.key ] = true;
1363			console.log( 'activate action' );
1364		},
1365
1366		deactivateAction: function( conditionModel, thenObject ) {
1367			console.log( 'deactivate action' );
1368			this.actions[ thenObject.key ] = false;
1369		},
1370
1371		getStatus: function( $id ) {
1372			return this.actions[ $id ];
1373		}
1374	});
1375
1376	return controller;
1377} );
1378var nfRadio = Backbone.Radio;
1379
1380require( [ 'controllers/initCollection', 'controllers/showHide', 'controllers/changeRequired', 'controllers/showHideOption', 'controllers/changeValue', 'controllers/selectDeselect', 'controllers/actions' ], function( InitCollection, ShowHide, ChangeRequired, ShowHideOption, ChangeValue, SelectDeselect, Actions ) {
1381
1382	var NFConditionalLogic = Marionette.Application.extend( {
1383
1384		initialize: function( options ) {
1385			this.listenTo( nfRadio.channel( 'form' ), 'after:loaded', this.loadControllers );
1386		},
1387
1388		loadControllers: function( formModel ) {
1389			new ShowHide();
1390			new ChangeRequired();
1391			new ShowHideOption();
1392			new ChangeValue();
1393			new SelectDeselect();
1394			new Actions();
1395			new InitCollection( formModel );
1396		},
1397
1398		onStart: function() {
1399			
1400		}
1401	} );
1402
1403	var nfConditionalLogic = new NFConditionalLogic();
1404	nfConditionalLogic.start();
1405} );
1406define("main", function(){});
1407
1408}());
1409//# 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.