1$(document).ready(function() { 2 $.fxbConditions = function(el, options) { 3 this.el = el; 4 this.$el = $(el); 5 this.options = $.extend({}, $.fxbConditions.defaultOptions, options); 6 }, 7 $.fxbConditions.parse = function (formId) { 8 var $form = $(formId); 9 $form.init_formConditions(); 10 }, 11 12 $.extend($.fxbConditions, 13 { 14 defaultOptions: { 15 fieldConditions: [], 16 animate: true 17 }, 18 19 helpers: { 20 normalize: function(value, preserveCase) { 21 if (value == null) { 22 return ""; 23 } 24 25 return preserveCase ? String(value) : String(value).toLowerCase(); 26 }, 27 28 toNumber: function(value) { 29 value = Number(value); 30 return isNaN(value) ? undefined : value; 31 }, 32 33 indexOf: function(str, value, startIndex, preserveCase) { 34 str = this.normalize(str, preserveCase); 35 value = this.normalize(value, preserveCase); 36 37 return str.indexOf(value, startIndex); 38 }, 39 40 endsWith: function(str, value, preserveCase) { 41 str = this.normalize(str, preserveCase); 42 value = this.normalize(value, preserveCase); 43 44 var lengthDiff = str.length - value.length; 45 return lengthDiff >= 0 && str.substring(lengthDiff) === value; 46 } 47 }, 48 49 actions: { 50 show: function($target) { 51 if (this.loaded && this.options.animate) { 52 if ($target.is(":hidden")) { 53 var $self = this; 54 $target.slideDown(function () { 55 $self.setRequired($target); 56 }); 57 58 return; 59 } 60 } else { 61 $target.show(); 62 } 63 64 this.setRequired($target); 65 }, 66 67 hide: function($target) { 68 if (this.loaded && this.options.animate) { 69 if ($target.is(":visible")) { 70 var $self = this; 71 $target.slideUp(function() { 72 $self.setRequired($target); 73 }); 74 75 return; 76 } 77 } else { 78 $target.hide(); 79 } 80 81 this.setRequired($target); 82 }, 83 84 enable: function($target) { 85 if ($target.is("input,select,textarea,button")) { 86 $target.prop("disabled", false); 87 this.setRequired($target); 88 } 89 }, 90 91 disable: function($target) { 92 if ($target.is("input,select,textarea,button")) { 93 $target.prop("disabled", true); 94 this.setRequired($target); 95 } 96 }, 97 98 "go to page": function($target, action, conditionsResult) { 99 $target.each(function(idx, target) { 100 if (target.name && 101 target.name.length && 102 $(target).is("input[type='submit'], button[type='submit']")) { 103 var $nextPageEl = this.$el.find("[name=\"" + target.name + "\"][data-sc-next-page]"); 104 if (!$nextPageEl.length) { 105 if (conditionsResult && action.value) { 106 var $currentEl = this.$el.find("[name=\"" + target.name + "\"]"); 107 $('<input>').attr({ 108 type: 'hidden', 109 name: target.name, 110 value: action.value, 111 'data-sc-next-page': "" 112 }).insertAfter($currentEl.last()); 113 } 114 115 return; 116 } 117 118 var value = action.value; 119 if (!conditionsResult) { 120 value = $nextPageEl.data("sc-next-page"); 121 122 for (var i = (this.executedActions.length - 1); i >= 0; i--) { 123 var prevAction = this.executedActions[i]; 124 if (prevAction.fieldId === action.fieldId && 125 prevAction.conditionsResult && 126 prevAction.actionType.toLowerCase() === "go to page") { 127 value = prevAction.value; 128 break; 129 } 130 } 131 } 132 133 $nextPageEl.val(value); 134 $nextPageEl.prop("disabled", !value); 135 } 136 }.bind(this)); 137 }, 138 139 // action pairs used for finding the opposite action to execute when conditions are not satisfied 140 actionLinks: { 141 show: "hide", 142 enable: "disable", 143 "go to page": "go to page" 144 }, 145 146 addAction: function(actionName, actionFn, oppositeActionName, oppositeActionFn) { 147 if (actionName && actionName.length) { 148 actionName = actionName.toLowerCase(); 149 150 this[actionName] = actionFn; 151 152 if (arguments.length === 2) { 153 return; 154 } 155 156 if (oppositeActionName && oppositeActionName.length) { 157 oppositeActionName = oppositeActionName.toLowerCase(); 158 159 this.actionLinks[actionName] = oppositeActionName; 160 if (arguments.length > 3) { 161 this[oppositeActionName] = oppositeActionFn; 162 } 163 } else { 164 delete this.actionLinks[actionName]; 165 } 166 } 167 }, 168 169 getAction: function(actionName, conditionsResult) { 170 if (actionName && actionName.length) { 171 actionName = actionName.toLowerCase(); 172 173 if (conditionsResult) { 174 return this[actionName]; 175 } 176 177 if (this.actionLinks.hasOwnProperty(actionName)) { 178 var oppositeActionName = this.actionLinks[actionName]; 179 return this[oppositeActionName]; 180 } else { 181 for (var property in this.actionLinks) { 182 if (this.actionLinks.hasOwnProperty(property) && 183 this.actionLinks[property] === actionName) { 184 return this[property]; 185 } 186 } 187 } 188 } 189 190 return this[actionName]; 191 } 192 }, 193 194 operators: { 195 "contains": function(conditionValue, fieldValue) { 196 return $.fxbConditions.helpers.indexOf(fieldValue, conditionValue) >= 0; 197 }, 198 199 "does not contain": function(conditionValue, fieldValue) { 200 return $.fxbConditions.helpers.indexOf(fieldValue, conditionValue) === -1; 201 }, 202 203 "starts with": function(conditionValue, fieldValue) { 204 return $.fxbConditions.helpers.indexOf(fieldValue, conditionValue) === 0; 205 }, 206 207 "does not start with": function(conditionValue, fieldValue) { 208 return $.fxbConditions.helpers.indexOf(fieldValue, conditionValue) !== 0; 209 }, 210 211 "ends with": function(conditionValue, fieldValue) { 212 return $.fxbConditions.helpers.endsWith(fieldValue, conditionValue); 213 }, 214 215 "does not end with": function(conditionValue, fieldValue) { 216 return !$.fxbConditions.helpers.endsWith(fieldValue, conditionValue); 217 }, 218 219 "is equal to": function(conditionValue, fieldValue) { 220 conditionValue = $.fxbConditions.helpers.normalize(conditionValue); 221 fieldValue = $.fxbConditions.helpers.normalize(fieldValue); 222 if (fieldValue === conditionValue) { 223 return true; 224 } 225 226 if (conditionValue.length) { 227 var left = $.fxbConditions.helpers.toNumber(conditionValue); 228 if (typeof left === "number") { 229 var right = $.fxbConditions.helpers.toNumber(fieldValue); 230 return typeof right === "number" && left === right; 231 } 232 } 233 234 return false; 235 }, 236 237 "is not equal to": function(conditionValue, fieldValue) { 238 conditionValue = $.fxbConditions.helpers.normalize(conditionValue); 239 fieldValue = $.fxbConditions.helpers.normalize(fieldValue); 240 if (fieldValue === conditionValue) { 241 return false; 242 } 243 244 if (conditionValue.length) { 245 var left = $.fxbConditions.helpers.toNumber(conditionValue); 246 if (typeof left === "number") { 247 var right = $.fxbConditions.helpers.toNumber(fieldValue);
248 return typeof right !== "number" || left !== right; 249 } 250 } 251 252 return true; 253 }, 254 255 "is greater than": function(conditionValue, fieldValue) { 256 conditionValue = $.fxbConditions.helpers.normalize(conditionValue); 257 fieldValue = $.fxbConditions.helpers.normalize(fieldValue); 258 259 if (conditionValue.length) { 260 var left = $.fxbConditions.helpers.toNumber(conditionValue); 261 if (typeof left === "number") { 262 var right = $.fxbConditions.helpers.toNumber(fieldValue); 263 return typeof right === "number" && right > left; 264 } 265 } 266 267 return fieldValue > conditionValue; 268 }, 269 270 "is greater than or equal to": function(conditionValue, fieldValue) { 271 conditionValue = $.fxbConditions.helpers.normalize(conditionValue); 272 fieldValue = $.fxbConditions.helpers.normalize(fieldValue); 273 274 if (fieldValue === conditionValue) { 275 return true; 276 } 277 278 if (conditionValue.length) { 279 var left = $.fxbConditions.helpers.toNumber(conditionValue); 280 if (typeof left === "number") { 281 var right = $.fxbConditions.helpers.toNumber(fieldValue); 282 return typeof right === "number" && right >= left; 283 } 284 } 285 286 return fieldValue >= conditionValue; 287 }, 288 289 "is less than": function(conditionValue, fieldValue) { 290 conditionValue = $.fxbConditions.helpers.normalize(conditionValue); 291 fieldValue = $.fxbConditions.helpers.normalize(fieldValue); 292 293 if (conditionValue.length) { 294 var left = $.fxbConditions.helpers.toNumber(conditionValue); 295 if (typeof left === "number") { 296 var right = $.fxbConditions.helpers.toNumber(fieldValue); 297 return typeof right === "number" && right < left; 298 } 299 } 300 301 return fieldValue < conditionValue; 302 }, 303 304 "is less than or equal to": function(conditionValue, fieldValue) { 305 conditionValue = $.fxbConditions.helpers.normalize(conditionValue); 306 fieldValue = $.fxbConditions.helpers.normalize(fieldValue); 307 308 if (fieldValue === conditionValue) { 309 return true; 310 } 311 312 if (conditionValue.length) { 313 var left = $.fxbConditions.helpers.toNumber(conditionValue); 314 if (typeof left === "number") { 315 var right = $.fxbConditions.helpers.toNumber(fieldValue); 316 return typeof right === "number" && right <= left; 317 } 318 } 319 320 return fieldValue <= conditionValue; 321 }, 322 323 addOperator: function(operatorName, operatorFn) { 324 if (operatorName && operatorName.length) { 325 this[operatorName.toLowerCase()] = operatorFn; 326 } 327 }, 328 329 getOperator: function(operatorName) { 330 return operatorName && operatorName.length ? this[operatorName.toLowerCase()] : null; 331 } 332 }, 333 334 prototype: { 335 initConditions: function(options) { 336 this.options = $.extend(true, this.options || {}, options); 337 338 if (!this.options.fieldConditions) { 339 return; 340 } 341 342 var sourceFields = []; 343 this.options.fieldConditions.forEach(function(fieldCondition) { 344 if (!fieldCondition || !fieldCondition.conditions) { 345 return; 346 } 347 348 fieldCondition.conditions.forEach(function(condition) { 349 if (condition.fieldId && sourceFields.indexOf(condition.fieldId) === -1) { 350 sourceFields.push(condition.fieldId); 351 var $source = this.$el.find("[data-sc-field-key=\"" + condition.fieldId + "\"]") 352 .filter(function() { 353 return $.fxbConditions.helpers.endsWith(this.name, "value"); 354 }); 355 if ($source.length) { 356 $source.on("change", this.applyConditions.bind(this)); 357 } 358 } 359 }.bind(this)); 360 }.bind(this)); 361 362 this.applyConditions(); 363 this.loaded = true; 364 }, 365 366 applyConditions: function() { 367 if (!this.options.fieldConditions) { 368 return; 369 } 370 371 this.executedActions = []; 372 this.fieldActions = {}; 373 374 this.options.fieldConditions.forEach(function(fieldCondition) { 375 if (fieldCondition && fieldCondition.actions && fieldCondition.actions.length) { 376 var conditionsResult = this.evaluateConditions(fieldCondition); 377 fieldCondition.actions.forEach(function(action) { 378 this.gatherFieldActions(action, conditionsResult); 379 }.bind(this)); 380 } 381 }.bind(this)); 382 383 for (var fieldId in this.fieldActions) { 384 if (!this.fieldActions.hasOwnProperty(fieldId)) continue; 385 for (var actionType in this.fieldActions[fieldId]) { 386 if (!this.fieldActions[fieldId].hasOwnProperty(actionType)) continue; 387 var action = this.fieldActions[fieldId][actionType].action; 388 var conditionsResult = this.fieldActions[fieldId][actionType].conditionsResult; 389 this.executeAction(action, conditionsResult); 390 } 391 } 392 }, 393 394 setRequired: function($targets) { 395 $targets.each(function(idx, target) { 396 var $target = $(target);
397 if ($target.is("input:not([type='submit']), select, textarea")) { 398 var name = target.name; 399 if (!$.fxbConditions.helpers.endsWith(name, "value") && !$.fxbConditions.helpers.endsWith(name, "Files") ) 400 return; 401 402 name = name.slice(0, -(name.length - name.lastIndexOf(".") - 1)) + "Required"; 403 var $requiredEl = this.$el.find("[name=\"" + name + "\"][data-sc-conditions-required]"), 404 isNotAccessible = $target.is(":hidden") || 405 $target.css("visibility") === "hidden" || 406 target.disabled; 407 408 if (!$requiredEl.length) { 409 if (isNotAccessible) { 410 var $currentEl = this.$el.find("[name=\"" + target.name + "\"]"); 411 $('<input>').attr({ 412 type: 'hidden', 413 name: name, 414 value: false, 415 "data-sc-conditions-required": "" 416 }).insertAfter($currentEl.last()); 417 } 418 419 return; 420 } 421 422 $requiredEl.val(false); 423 $requiredEl.prop("disabled", !isNotAccessible); 424 } else { 425 this.setRequired($target.find("input:not([type='submit']), select, textarea")); 426 } 427 }.bind(this)); 428 }, 429 430 executeAction: function(action, conditionsResult) { 431 if (action && action.fieldId && action.actionType) { 432 var $target = this.$el.find("[data-sc-field-key=\"" + action.fieldId + "\"]"); 433 if ($target.length) { 434 var actionFn = $.fxbConditions.actions.getAction(action.actionType, conditionsResult); 435 if (actionFn && typeof actionFn === "function") { 436 actionFn.call(this, $target, action, conditionsResult); 437 var executedAction = $.extend(true, 438 action, 439 { 440 conditionsResult: conditionsResult 441 }); 442 this.executedActions.push(executedAction); 443 } 444 } 445 } 446 }, 447 448 evaluateConditions: function(fieldCondition) { 449 if (!fieldCondition || !fieldCondition.conditions) return true; 450 451 var matchType = (fieldCondition.matchType || "").toLowerCase(); 452 switch (matchType) { 453 case "all": 454 return fieldCondition.conditions.every(this.isConditionSatisfied.bind(this)); 455 case "any": 456 default: 457 return fieldCondition.conditions.some(this.isConditionSatisfied.bind(this)); 458 } 459 }, 460 461 gatherFieldActions: function(action, conditionsResult) { 462 if (action && action.fieldId && action.actionType) { 463 if (typeof this.fieldActions[action.fieldId] === "undefined") { 464 this.fieldActions[action.fieldId] = {}; 465 } 466 467 if (typeof this.fieldActions[action.fieldId][action.actionType] === "undefined") { 468 this.fieldActions[action.fieldId][action.actionType] = { 469 action: action, 470 conditionsResult: conditionsResult 471 }; 472 } 473 // if a true conditionsResult finally appears for this particular fieldId and actionType, set it to true. 474 // from now on, it can never be set back to fal
474se again. 475 // (existing is deleted first to ensure this latest action appears at the bottom of the queue) 476 else if (!this.fieldActions[action.fieldId][action.actionType].conditionsResult && conditionsResult) { 477 delete this.fieldActions[action.fieldId][action.actionType]; 478 this.fieldActions[action.fieldId][action.actionType] = { 479 action: action, 480 conditionsResult: true 481 }; 482 } 483 } 484 }, 485 486 getValueList: function(fieldId) { 487 var $fieldEl = this.$el.find("[data-sc-field-key=\"" + fieldId + "\"]").filter(function() { 488 return $.fxbConditions.helpers.endsWith(this.name, "value"); 489 }); 490 491 var $listElements = $fieldEl.filter(function(idx, element) { 492 return element.type === "checkbox" || element.type === "radio"; 493 }); 494 495 var value; 496 if ($listElements.length) { 497 if ($listElements.length > 1) { 498 value = $listElements.filter(":checked").map(function() { 499 return $(this).val(); 500 }).get(); 501 if (!value.length) { 502 value.push(""); 503 } 504 } else { 505 value = [$listElements[0].checked ? "true" : "false"]; 506 } 507 } else { 508 value = [$fieldEl.val()]; 509 } 510 511 return value; 512 }, 513 514 isConditionSatisfied: function(condition) { 515 if (condition && condition.operator) { 516 var operatorFn = $.fxbConditions.operators.getOperator(condition.operator); 517 if (operatorFn && typeof operatorFn === "function") { 518 519 var valueList = this.getValueList(condition.fieldId); 520 var result = condition.operator === "is not equal to" 521 ? valueList.every(operatorFn.bind(this, condition.value)) 522 : valueList.some(operatorFn.bind(this, condition.value)); 523 return result; 524 }; 525 } 526 527 return false; 528 } 529 } 530 }); 531 532 $.fn.init_fxbConditions = function(options) { 533 return this.each(function() { 534 var conditions = $.data(this, "fxbForms.conditions"); 535 if (conditions) { 536 conditions.initConditions(options); 537 } else { 538 conditions = new $.fxbConditions(this, options); 539 $.data(this, "fxbForms.conditions", conditions); 540 conditions.initConditions(); 541 } 542 }); 543 }; 544 545 $.fn.init_formConditions = function() { 546 var input = this.find('input[data-sc-fxb-condition]'); 547 if (input) { 548 var conditions = JSON.parse(input.attr('value')); 549 if (conditions) { 550 if (typeof this.init_fxbConditions === 'function') { 551 this.init_fxbConditions(conditions); 552 } 553 } 554 } 555 }; 556 557 var forms = $("form[data-sc-fxb]"); 558 if (forms.length) { 559 forms.each(function () { 560 var formEl = $(this); 561 formEl.init_formConditions(); 562 }).parent().on("submit", "form[data-sc-fxb]", function () { 563 var $submitBtns = $(this).find("input[type='submit'], button[type='submit']"); 564 if ($submitBtns.length) { 565 $submitBtns.on("click", function () { 566 return false; 567 }); 568 } 569 }); 570 } 571});
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.