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