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 * When we update our calculation, update our compare 454 */ 455 this.listenTo( calcModel, 'change:value', this.updateCalcCompare ); 456 /* 457 * Update our compare status. 458 */ 459 this.updateCalcCompare( calcModel ); 460 } else { // We have a field key 461 // Get our field model 462 var fieldModel = nfRadio.channel( 'form-' + options.condition.collection.formModel.get( 'id' ) ).request( 'get:fieldByKey', this.get( 'key' ) ); 463 464 if( 'undefined' == typeof fieldModel ) return; 465 466 // When we change the value of our field, update our compare status. 467 fieldModel.on( 'change:value', this.updateFieldCompare, this ); 468 // When we keyup in our field, maybe update our compare status. 469 this.listenTo( nfRadio.channel( 'field-' + fieldModel.get( 'id' ) ), 'keyup:field', this.maybeupdateFieldCompare ); 470 // Update our compare status. 471 this.updateFieldCompare( fieldModel ); 472 473 /* 474 * TODO: This should be moved to the show_field/hide_field file because it is specific to showing and hiding. 475 * Create a radio message here so that the specific JS file can hook into whenModel init. 476 */ 477 fieldModel.on( 'change:visible', this.updateFieldCompare, this ); 478 } 479 }, 480 481 updateCalcCompare: function( calcModel ) { 482 this.updateCompare( calcModel.get( 'value' ) ); 483 }, 484 485 maybeupdateFieldCompare: function( el, fieldModel, keyCode ) { 486 if( 'checkbox' == fieldModel.get( 'type' ) ){ 487 var fieldValue = ( 'checked' == jQuery( el ).attr( 'checked' ) ) ? 1 : 0; 488 } else if( 'listcheckbox' == fieldModel.get( 'type' ) ) { 489 // This field isn't a single element, so we need to reference the fieldModel, instead of the DOM. 490 var fieldValue = fieldModel.get( 'value' ).join(); 491 } else if ( 'date' == fieldModel.get ('type' ) ) { 492 var fieldValue = fieldModel.get( 'value' ); 493 494 if ( _.isEmpty( fieldValue ) ) { 495 fieldValue = '1970/01/01'; 496 } 497 498 let date_mode = fieldModel.get( 'date_mode' ); 499 if ( 'undefined' == typeof date_mode ) { // If 'date_mode' is undefined, then we assume it's date_only. 500 date_mode = 'date_only'; 501 } 502 let date = 0; 503 // If we're in time_only mode, then we need to use 1970-01-01 as our date. 504 if ( 'time_only' == fieldModel.get( 'date_mode' ) ) { 505 date = '1970/01/01'; 506 } else { 507 date = fieldValue; 508 } 509 510 // Convert field value into a timestamp 511 let hour = fieldModel.get( 'selected_hour' ); 512 if ( 'undefined' == typeof hour ) { 513 hour = '00'; 514 } 515 516 let minute = fieldModel.get( 'selected_minute' ); 517 if ( 'undefined' == typeof minute ) { 518 minute = '00'; 519 } 520 521 // If we have a date_and_time field, but we haven't selected a date yet, we don't need to compare. 522 if ( 'date_and_time' == date_mode && '1970/01/01' == date ) { 523 fieldValue = false;
524 } else { 525 fieldValue = date + ' ' + hour + ':' + minute + ' UT'; 526 527 let dateObject = new Date( fieldValue ); 528 fieldValue = Math.floor( dateObject.getTime() / 1000 ); 529 } 530 } else { 531 var fieldValue = jQuery( el ).val(); 532 } 533 534 this.updateFieldCompare( fieldModel, null, fieldValue ); 535 }, 536 537 updateCompare: function( value ) { 538 var this_val = this.get( 'value' ); 539 540 // if this is a calcModel then let's convert to number for comparison 541 if ( 'calc' === this.get( 'type' ) ) { 542 this_val = Number( this_val ); 543 value = Number( value ); 544 } 545 // Check to see if the value of the field model value COMPARATOR the value of our when condition is true. 546 var status = this.compareValues[ this.get( 'comparator' ) ]( value, this_val ); 547 this.set( 'status', status ); 548 }, 549 550 updateFieldCompare: function( fieldModel, val, fieldValue ) { 551 if ( _.isEmpty( fieldValue ) ) { 552 fieldValue = fieldModel.get( 'value' ); 553 } 554 555 // Change the value of checkboxes to match the new convention. 556 if( 'checkbox' == fieldModel.get( 'type' ) ) { 557 if( 0 == fieldValue ) { 558 fieldValue = 'unchecked'; 559 } else { 560 fieldValue = 'checked'; 561 } 562 } else if ( 'date' == fieldModel.get( 'type' ) ) { 563 if ( _.isEmpty( fieldValue ) ) { 564 fieldValue = '1970/01/01'; 565 } 566 567 let date_mode = fieldModel.get( 'date_mode' ); 568 if ( 'undefined' == typeof date_mode ) { // If 'date_mode' is undefined, then we assume it's date_only. 569 date_mode = 'date_only'; 570 } 571 let date = 0; 572 // If we're in time_only mode, then we need to use 1970-01-01 as our date. 573 if ( 'time_only' == fieldModel.get( 'date_mode' ) ) { 574 date = '1970/01/01'; 575 } else { 576 date = fieldValue; 577 } 578 579 // Convert field value into a timestamp 580 let hour = fieldModel.get( 'selected_hour' ); 581 if ( 'undefined' == typeof hour ) { 582 hour = '00'; 583 } 584 585 let ampm = fieldModel.get( 'selected_ampm' ); 586 if ( 'undefined' != typeof ampm ) { 587 // Convert our hour into 24 hr format. 588 if ( 'pm' == ampm && '12' != hour ) { 589 hour = parseInt( hour ) + 12; 590 } else if ( 'am' == ampm && '12' == hour ) { 591 hour = '00'; 592 } 593 } 594 595 let minute = fieldModel.get( 'selected_minute' ); 596 if ( 'undefined' == typeof minute ) { 597 minute = '00'; 598 } 599 600 // If we have a date_and_time field, but we haven't selected a date yet, we don't need to compare. 601 if ( 'date_and_time' == date_mode && '1970/01/01' == date ) { 602 fieldValue = false; 603 } else { 604 fieldValue = date + ' ' + hour + ':' + minute + ' UT'; 605 606 let dateObject = new Date( fieldValue ); 607 fieldValue = Math.floor( dateObject.getTime() / 1000 ); 608 } 609 } 610 611 this.updateCompare( fieldValue ); 612 613 /* 614 * TODO: This should be moved to the show_field/hide_field file because it is specific to showing and hiding. 615 */ 616 if ( ! fieldModel.get( 'visible' ) ) { 617 this.set( 'status', false ); 618 } 619 }, 620 621 compareValues: { 622 'equal': function( a, b ) { 623 return a == b; 624 }, 625 'notequal': function( a, b ) { 626 return a != b; 627 }, 628 'contains': function( a, b ) { 629 if ( jQuery.isArray( a ) ) { 630 /* 631 * If a is an array, then we're searching for an index. 632 */ 633 return a.indexOf( b ) >= 0; 634 } else { 635 /* 636 * If a is a string, then we're searching for a string position. 637 * 638 * If our b value has quotes in it, we want to find that exact word or phrase. 639 */ 640 if ( b.indexOf( '"' ) >= 0 ) { 641 b = b.replace( /['"]+/g, '' ); 642 return new RegExp("\\b" + b + "\\b").test( a ); 643 } 644 return a.toLowerCase().indexOf( b.toLowerCase() ) >= 0; 645 } 646 }, 647 'notcontains': function( a, b ) { 648 return ! this.contains( a, b ); 649 }, 650 'greater': function( a, b ) { 651 /* 652 * In 2.9.x, you could use the greater and less like string count. 653 * i.e. if textbox > (empty string) do something. 654 * This recreates that ability. 655 */ 656 if ( jQuery.isNumeric( b ) ) { 657 return parseFloat( a ) > parseFloat( b ); 658 } else if ( 'string' == typeof a ) { 659 return 0 < a.length; 660 } 661 662 }, 663 'less': function( a, b ) { 664 /* 665 * In 2.9.x, you could use the greater and less like string count. 666 * i.e. if textbox > (empty string) do something. 667 * This recreates that ability. 668 */ 669 if ( jQuery.isNumeric( b ) ) { 670 return parseFloat( a ) < parseFloat( b ); 671 } else if ( 'string' == typeof a ) { 672 return 0 >= a.length; 673 } 674 675 }, 676 'greaterequal': function( a, b ) { 677 return parseFloat( a ) > parseFloat( b ) || parseFloat( a ) == parseFloat( b ); 678 }, 679 'lessequal': function( a, b ) { 680 return parseFloat( a ) < parseFloat( b ) || parseFloat( a ) == parseFloat( b ); 681 } 682 } 683 } ); 684 685 return model; 686} ); 687define( 'models/whenCollection',['models/whenModel'], function( WhenModel ) { 688 var collection = Backbone.Collection.extend( { 689 model: WhenModel, 690 691 initialize: function( models, options ) { 692 this.options = options; 693 } 694 } ); 695 return collection; 696} ); 697define( 'models/conditionModel',[ 'models/whenCollection' ], function( WhenCollection ) { 698 var model = Backbone.Model.extend( { 699 initialize: function( options ) { 700 /* 701 * Our "when" statement will be like: 702 * When field1 == value 703 * AND field2 == value 704 * 705 * We need to create a collection out of this when statement, with each row as a model. 706 */ 707 this.set( 'when', new WhenCollection( this.get( 'when' ), { condition: this } ) ); 708 /* 709 * When we update any of our "when" models' status, check to see if we should send a message. 710 */ 711 this.get( 'when' ).on( 'change:status', this.checkWhen, this ); 712 /* 713 * Check our initial status; 714 */ 715 this.checkWhen(); 716 }, 717 718 checkWhen: function() { 719 /* 720 * If we have any OR connectors, then any status being true should trigger pass. 721 * Otherwise, we need every status to be true. 722 */ 723 var statusResults = this.get( 'when' ).pluck( 'status' ); 724 725 var connectors = this.get( 'when' ).pluck( 'connector' ); 726 var allAND = _.every( _.values( connectors ), function( v ) { return v == 'AND' }, this ); 727 if ( allAND ) { 728 var status = _.every( _.values( statusResults ), function(v) { return v; }, this ); 729 } else { 730 var status = _.some( _.values( statusResults ), function(v) { return v; }, this ); 731 } 732 733 if ( status ) { 734 /* 735 * Send out a request for each of our "then" statements. 736 */ 737 _.each( this.get( 'then' ), function( then, index ) { 738 nfRadio.channel( 'condition:trigger' ).request( then.trigger, this, then ); 739 }, this ); 740 } else { 741 /* 742 * Send out a request for each of our "else" statements. 743 */ 744 _.each( this.get( 'else' ), function( elseData, index ) { 745 nfRadio.channel( 'condition:trigger' ).request( elseData.trigger, this, elseData ); 746 }, this ); 747 } 748 } 749 } ); 750 751 return model; 752} ); 753define( 'models/conditionCollection',['models/conditionModel'], function( ConditionModel ) { 754 var collection = Backbone.Collection.extend( { 755 model: ConditionModel, 756 757 initialize: function( models, options ) { 758 this.formModel = options.formModel; 759 } 760 } ); 761 return collection; 762} ); 763/** 764 * Initialise condition collection 765 * 766 * @package Ninja Forms Conditional Logic 767 * @copyright (c) 2016 WP Ninjas 768 * @since 3.0 769 */ 770define( 'controllers/initCollection',[ 'models/conditionCollection' ], function( ConditionCollection ) { 771 var controller = Marionette.Object.extend( { 772 initialize: function( formModel ) { 773 this.collection = new ConditionCollection( formModel.get( 'conditions' ), { formModel: formModel } ); 774 this.listenTo(nfRadio.channel('fields'), 'reset:collection', this.resetCollection); 775 }, 776 resetCollection: function( fieldsCollection ) { 777 var formModel = fieldsCollection.options.formModel; 778 this.collection = new ConditionCollection( formModel.get( 'conditions' ), { formModel: formModel } ); 779 } 780 }); 781 782 return controller; 783} ); 784/** 785 * Handle showing/hiding fields 786 * 787 * @package Ninja Forms Conditional Logic 788 * @copyright (c) 2016 WP Ninjas 789 * @since 3.0 790 */ 791define( 'controllers/showHide',[], function() { 792 var controller = Marionette.Object.extend( { 793 initialize: function() { 794 nfRadio.channel( 'condition:trigger' ).reply( 'hide_field', this.hideField, this ); 795 nfRadio.channel( 'condition:trigger' ).reply( 'show_field', this.show
795Field, this ); 796 }, 797 798 hideField: function( conditionModel, then ) { 799 var targetFieldModel = nfRadio.channel( 'form-' + conditionModel.collection.formModel.get( 'id' ) ).request( 'get:fieldByKey', then.key ); 800 801 if( 'undefined' == typeof targetFieldModel ) return; 802 targetFieldModel.set( 'visible', false ); 803 if ( ! targetFieldModel.get( 'clean' ) ) { 804 targetFieldModel.trigger( 'change:value', targetFieldModel ); 805 } 806 807 nfRadio.channel( 'fields' ).request( 'remove:error', targetFieldModel.get( 'id' ), 'required-error' ); 808 }, 809 810 showField: function( conditionModel, then ) { 811 var targetFieldModel = nfRadio.channel( 'form-' + conditionModel.collection.formModel.get( 'id' ) ).request( 'get:fieldByKey', then.key ); 812 //TODO: Add an error to let the user know the show/hide field is empty. 813 if( 'undefined' == typeof targetFieldModel ) return; 814 targetFieldModel.set( 'visible', true ); 815 if ( ! targetFieldModel.get( 'clean' ) ) { 816 targetFieldModel.trigger( 'change:value', targetFieldModel ); 817 } 818 if ( 'recaptcha' === targetFieldModel.get( 'type' ) ) { 819 this.renderRecaptcha(); 820 } 821 var viewEl = { el: nfRadio.channel( 'form-' + conditionModel.collection.formModel.get( 'id' ) ).request( 'get:el' ) }; 822 nfRadio.channel( 'form' ).request( 'init:help', viewEl ); 823 }, 824 825 renderRecaptcha: function() { 826 jQuery( '.g-recaptcha' ).each( function() { 827 var callback = jQuery( this ).data( 'callback' ); 828 var fieldID = jQuery( this ).data( 'fieldid' ); 829 if ( typeof window[ callback ] !== 'function' ){ 830 window[ callback ] = function( response ) { 831 nfRadio.channel( 'recaptcha' ).request( 'update:response', response, fieldID ); 832 }; 833 } 834 var opts = { 835 theme: jQuery( this ).data( 'theme' ), 836 sitekey: jQuery( this ).data( 'sitekey' ), 837 callback: callback 838 }; 839 840 grecaptcha.render( jQuery( this )[0], opts ); 841 } ); 842 } 843 }); 844 845 return controller; 846} ); 847/** 848 * Setting/unsetting required. 849 * 850 * @package Ninja Forms Conditional Logic 851 * @copyright (c) 2019 WP Ninjas 852 * @since 3.0 853 */ 854define( 'controllers/changeRequired',[], function() { 855 var controller = Marionette.Object.extend( { 856 initialize: function() { 857 nfRadio.channel( 'condition:trigger' ).reply( 'set_required', this.setRequired, this ); 858 nfRadio.channel( 'condition:trigger' ).reply( 'unset_required', this.unsetRequired, this ); 859 }, 860 861 setRequired: function( conditionModel, then ) { 862 var targetFieldModel = nfRadio.channel( 'form-' + conditionModel.collection.formModel.get( 'id' ) ).request( 'get:fieldByKey', then.key ); 863 864 if( 'undefined' == typeof targetFieldModel ) return; 865 targetFieldModel.set( 'required', 1 ); 866 targetFieldModel.trigger( 'reRender', targetFieldModel ); 867 }, 868 869 unsetRequired: function( conditionModel, then ) { 870 var targetFieldModel = nfRadio.channel( 'form-' + conditionModel.collection.formModel.get( 'id' ) ).request( 'get:fieldByKey', then.key ); 871 872 if( 'undefined' == typeof targetFieldModel ) return; 873 targetFieldModel.set( 'required', 0 ); 874 targetFieldModel.trigger( 'reRender', targetFieldModel ); 875 // Ensure we resolve any errors when the field is no longer required. 876 nfRadio.channel( 'fields' ).request( 'remove:error', targetFieldModel.get( 'id' ), 'required-error' ); 877 } 878 879 }); 880 881 return controller; 882} ); 883/** 884 * Handle adding or removing an option from our list 885 * 886 * @package Ninja Forms Conditional Logic 887 * @copyright (c) 2016 WP Ninjas 888 * @since 3.0 889 */ 890define( 'controllers/showHideOption',[], function() { 891 var controller = Marionette.Object.extend( { 892 initialize: function() { 893 nfRadio.channel( 'condition:trigger' ).reply( 'show_option', this.showOption, this ); 894 895 nfRadio.channel( 'condition:trigger' ).reply( 'hide_option', this.hideOption, this ); 896 }, 897 898 showOption: function( conditionModel, then ) { 899 var option = this.getOption( conditionModel, then ); 900 option.visible = true; 901 this.updateFieldModel( conditionModel, then ); 902 }, 903 904 hideOption: function( conditionModel, then ) { 905 var option = this.getOption( conditionModel, then ); 906 option.visible = false;
907 this.updateFieldModel( conditionModel, then ); 908 }, 909 910 getFieldModel: function( conditionModel, then ) { 911 return nfRadio.channel( 'form-' + conditionModel.collection.formModel.get( 'id' ) ).request( 'get:fieldByKey', then.key ); 912 }, 913 914 getOption: function( conditionModel, then ) { 915 var targetFieldModel = this.getFieldModel( conditionModel, then ); 916 var options = targetFieldModel.get( 'options' ); 917 return _.find( options, function( option ) { return option.value == then.value } ); 918 }, 919 920 updateFieldModel: function( conditionModel, then ) { 921 var targetFieldModel = this.getFieldModel( conditionModel, then ); 922 var options = targetFieldModel.get( 'options' ); 923 targetFieldModel.set( 'options', options ); 924 targetFieldModel.trigger( 'reRender' ); 925 } 926 }); 927 928 return controller; 929} ); 930/** 931 * Handle changing a field's value 932 * 933 * @package Ninja Forms Conditional Logic 934 * @copyright (c) 2016 WP Ninjas 935 * @since 3.0 936 */ 937define( 'controllers/changeValue',[], function() { 938 var controller = Marionette.Object.extend( { 939 initialize: function() { 940 nfRadio.channel( 'condition:trigger' ).reply( 'change_value', this.changeValue, this ); 941 }, 942 943 changeValue: function( conditionModel, then ) { 944 var targetFieldModel = nfRadio.channel( 'form-' + conditionModel.collection.formModel.get( 'id' ) ).request( 'get:fieldByKey', then.key ); 945 /* 946 * If we have a checkbox then we need to change the value that is set 947 * of the then variable to a 1 or 0 to re-render on the front end when 948 * the condition is met. 949 */ 950 if( 'checkbox' == targetFieldModel.get( 'type' ) ) { 951 // We also need to do the opposite of the value that is in the changed model. 952 if( 'unchecked' == targetFieldModel.changed.value ) { 953 then.value = 1; 954 } else if( 'checked' == targetFieldModel ) { 955 then.value = 0; 956 } 957 } 958 /* 959 * Change the value of our field model, and then trigger a re-render of its view. 960 */ 961 targetFieldModel.set( 'value', then.value ); 962 targetFieldModel.trigger( 'reRender', targetFieldModel ); 963 }, 964 965 }); 966 return controller; 967} ); 968/** 969 * Handle selecting/deselecting list options 970 * 971 * @package Ninja Forms Conditional Logic 972 * @copyright (c) 2016 WP Ninjas 973 * @since 3.0 974 */ 975define( 'controllers/selectDeselect',[], function() { 976 var controller = Marionette.Object.extend( { 977 initialize: function() { 978 nfRadio.channel( 'condition:trigger' ).reply( 'select_option', this.selectOption, this ); 979 980 nfRadio.channel( 'condition:trigger' ).reply( 'deselect_option', this.deselectOption, this ); 981 }, 982 983 selectOption: function( conditionModel, then ) { 984 /* 985 * Get our field model and set this option's "selected" property to 1 986 */ 987 var targetFieldModel = nfRadio.channel( 'form-' + conditionModel.collection.formModel.get( 'id' ) ).request( 'get:fieldByKey', then.key ); 988 989 990 if( _.contains( [ 'listselect', 'listcountry', 'liststate' ], targetFieldModel.get( 'type' ) ) ) { // TODO: Make this more dynamic. 991 targetFieldModel.set('clean', false); // Allows for changes to default values. 992 } 993 994 var options = targetFieldModel.get( 'options' ); 995 996 var option = _.find( options, { value: then.value } ); 997 option.selected = 1; 998 999 targetFieldModel.set( 'options', options ); 1000 1001 if( _.contains( [ 'listselect', 'listcountry', 'liststate' ], targetFieldModel.get( 'type' ) ) ) { // TODO: Make this more dynamic. 1002 targetFieldModel.set( 'value', option.value ); // Propagate the selected option to the model's value. 1003 } else { 1004 var value = targetFieldModel.get( 'value' ); 1005 if ( _.isArray( value ) ) { 1006 if ( 0 > value.indexOf( option.value ) ) { 1007 value.push( option.value ); 1008 // Set the value to nothing so it knows that something has changed. 1009 targetFieldModel.set( 'value', '' ); 1010 } 1011 } else { 1012 value = option.value; 1013 } 1014 1015 targetFieldModel.set( 'value', value ); // Propagate the selected option to the model's value. 1016 } 1017 1018 /* 1019 * Re render our field 1020 */ 1021 targetFieldModel.trigger( 'reRender', targetFieldModel ); 1022 }, 1023 1024 deselectOption: function( conditionModel, then ) { 1025 /*
1026 * When we are trying to deselect our option, we need to change it's "selected" property to 0 AND change its value. 1027 */ 1028 var targetFieldModel = nfRadio.channel( 'form-' + conditionModel.collection.formModel.get( 'id' ) ).request( 'get:fieldByKey', then.key ); 1029 1030 /* 1031 * Set "selected" to 0. 1032 */ 1033 var options = targetFieldModel.get( 'options' ); 1034 var option = _.find( options, { value: then.value } ); 1035 option.selected = 0; 1036 targetFieldModel.set( 'options', options ); 1037 1038 /* 1039 * Update our value 1040 */ 1041 var currentValue = targetFieldModel.get( 'value' ); 1042 if ( _.isArray( currentValue ) ) { 1043 currentValue = _.without( currentValue, then.value ); 1044 } else { 1045 currentValue = ''; 1046 } 1047 targetFieldModel.set( 'value', currentValue ); 1048 1049 /* 1050 * Re render our field 1051 */ 1052 targetFieldModel.trigger( 'reRender', targetFieldModel ); 1053 }, 1054 1055 }); 1056 1057 return controller; 1058} ); 1059/** 1060 * Keep an internal record for which actions are active and deactive. 1061 * 1062 * @package Ninja Forms Conditional Logic 1063 * @copyright (c) 2016 WP Ninjas 1064 * @since 3.0 1065 */ 1066define( 'controllers/actions',[], function() { 1067 var controller = Marionette.Object.extend( { 1068 actions: {}, 1069 1070 initialize: function() { 1071 /* 1072 * Listen for activate/deactivate action messages. 1073 */ 1074 nfRadio.channel( 'condition:trigger' ).reply( 'activate_action', this.activateAction, this ); 1075 nfRadio.channel( 'condition:trigger' ).reply( 'deactivate_action', this.deactivateAction, this ); 1076 1077 /* 1078 * Reply to requests for action status. 1079 */ 1080 nfRadio.channel( 'actions' ).reply( 'get:status', this.getStatus, this ); 1081 }, 1082 1083 activateAction: function( conditionModel, thenObject ) { 1084 this.actions[ thenObject.key ] = true; 1085 console.log( 'activate action' ); 1086 }, 1087 1088 deactivateAction: function( conditionModel, thenObject ) { 1089 console.log( 'deactivate action' ); 1090 this.actions[ thenObject.key ] = false; 1091 }, 1092 1093 getStatus: function( $id ) { 1094 return this.actions[ $id ]; 1095 } 1096 }); 1097 1098 return controller; 1099} ); 1100var nfRadio = Backbone.Radio; 1101 1102require( [ 'controllers/initCollection', 'controllers/showHide', 'controllers/changeRequired', 'controllers/showHideOption', 'controllers/changeValue', 'controllers/selectDeselect', 'controllers/actions' ], function( InitCollection, ShowHide, ChangeRequired, ShowHideOption, ChangeValue, SelectDeselect, Actions ) { 1103 1104 var NFConditionalLogic = Marionette.Application.extend( { 1105 1106 initialize: function( options ) { 1107 this.listenTo( nfRadio.channel( 'form' ), 'after:loaded', this.loadControllers ); 1108 }, 1109 1110 loadControllers: function( formModel ) { 1111 new ShowHide(); 1112 new ChangeRequired(); 1113 new ShowHideOption(); 1114 new ChangeValue(); 1115 new SelectDeselect(); 1116 new Actions(); 1117 new InitCollection( formModel ); 1118 }, 1119 1120 onStart: function() { 1121 1122 } 1123 } ); 1124 1125 var nfConditionalLogic = new NFConditionalLogic(); 1126 nfConditionalLogic.start(); 1127} ); 1128define("main", function(){}); 1129 1130}()); 1131//# 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.