1/** 2 * Shared conditional field operator evaluation and required-field helpers. 3 */ 4window.CFKEF = window.CFKEF || {}; 5 6CFKEF.checkFieldLogic = function (compareFieldValue, conditionOperation, compareValue) { 7 var decode = typeof CFKEF.decodeHtml === 'function' 8 ? CFKEF.decodeHtml 9 : function (text) { 10 return text == null ? '' : String(text); 11 }; 12 13 conditionOperation = decode(conditionOperation); 14 compareValue = compareValue === null ? decode(compareValue) : decode(compareValue).trim(); 15 var valueA = compareFieldValue === null ? decode(compareFieldValue) : String(compareFieldValue).trim(); 16 17 var values = valueA.split(',').map(function (v) { 18 return v.trim(); 19 }); 20 var matchFound = values.some(function (v) { 21 return v === compareValue; 22 }); 23 24 switch (conditionOperation) { 25 case '==': 26 return matchFound && valueA !== ''; 27 case '!=': 28 return !matchFound && valueA !== ''; 29 case 'e': 30 return valueA === ''; 31 case '!e': 32 return valueA !== ''; 33 case 'c': 34 return valueA.includes(compareValue); 35 case '!c': 36 return valueA !== '' && !valueA.includes(compareValue); 37 case '^': 38 return valueA.startsWith(compareValue); 39 case '~': 40 return valueA.endsWith(compareValue); 41 case '>': 42 return parseInt(valueA, 10) > parseInt(compareValue, 10); 43 case '<': 44 return parseInt(valueA, 10) < parseInt(compareValue, 10); 45 case '>=': 46 return parseInt(valueA, 10) >= parseInt(compareValue, 10); 47 case '<=': 48 return parseInt(valueA, 10) <= parseInt(compareValue, 10); 49 default: 50 return false; 51 } 52}; 53 54/** 55 * Demo values used when hiding required fields so HTML5 validation still passes. 56 * 57 * @param {string} nodeName 58 * @param {string} type 59 * @param {Object} [opts] 60 * @param {boolean} [opts.telWithPlus] 61 * @return {string|null} 62 */ 63CFKEF.getDemoValueForControl = function (nodeName, type, opts) { 64 opts = opts || {}; 65 nodeName = (nodeName || '').toLowerCase(); 66 type = (type || '').toLowerCase(); 67 68 if (nodeName === 'textarea') { 69 return 'cool_plugins'; 70 } 71 if (nodeName === 'select') { 72 return null; 73 } 74 if (type === 'email') { 75 return '[email protected]'; 76 } 77 if (type === 'url') { 78 return 'https://testing.com'; 79 } 80 if (type === 'tel') { 81 return opts.telWithPlus ? '+1234567890' : '1234567890'; 82 } 83 if (type === 'number') { 84 return '000'; 85 } 86 if (type === 'date') { 87 return '1003-01-01'; 88 } 89 if (type === 'time') { 90 return '11:59'; 91 } 92 return 'cool23plugins'; 93}; 94 95/** 96 * Evaluate show/hide logic for a field given a value getter. 97 * 98 * @param {Object} logicValue 99 * @param {Function} getFieldValueFn function(fieldId): string 100 * @return {boolean} true when the field should be visible 101 */ 102CFKEF.evaluateLogicRules = function (logicValue, getFieldValueFn) { 103 var displayMode = (logicValue && logicValue.display_mode) || 'show'; 104 var fireAction = (logicValue && logicValue.fire_action) || 'All'; 105 var logicData = logicValue && Array.isArray(logicValue.logic_data) ? logicValue.logic_data : []; 106 var checks = []; 107 108 logicData.forEach(function (rule) { 109 if (!rule || !rule.cfef_logic_field_id) { 110 return; 111 } 112 checks.push( 113 CFKEF.checkFieldLogic( 114 getFieldValueFn(rule.cfef_logic_field_id), 115 rule.cfef_logic_field_is, 116 rule.cfef_logic_compare_value 117 ) 118 ); 119 }); 120 121 if (!checks.length) { 122 return false; 123 } 124 125 // Free/Atomic path only evaluates AND ("All"); OR ("Any") is Pro. 126 if (fireAction !== 'All') { 127 return true; 128 } 129 130 var result = checks.every(function (v) { 131 return v === true; 132 }); 133 134 return displayMode === 'show' ? result : !result; 135}; 136 137/** 138 * Apply demo values to required controls inside a collection (Atomic-style). 139 * 140 * @param {jQuery} $controls 141 * @param {Object} [opts] 142 * @param {string} [opts.fileUploadClass] 143 * @param {boolean} [opts.telWithPlus] 144 */ 145CFKEF.applyRequiredDemoOnControls = function ($controls, opts) { 146 opts = opts || {}; 147 var $ = window.jQuery; 148 if (!$ || !$controls || !$controls.each) { 149 return; 150 } 151 152 $controls.each(function () { 153 var control = $(this); 154 var nodeName = (control.prop('nodeName') || '').toLowerCase(); 155 var type = (control.attr('type') || '').toLowerCase(); 156 var isRequired = 157 control.prop('required') || 158 control.attr('required') !== undefined || 159 control.attr('aria-required') === 'true'; 160 161 if (!isRequired) { 162 return; 163 } 164 165 if (type === 'checkbox' || type === 'radio') { 166 var groupControls = $controls.filter('[type="' + type + '"][name="' + control.attr('name') + '"]'); 167 var checkedControl = groupControls.filter(':checked'); 168 if (typeof control.data('cfefOriginalCheckedValue') === 'undefined') { 169 control.data('cfefOriginalCheckedValue', checkedControl.length ? checkedControl.val() : ''); 170 } 171 if (!checkedControl.length && groupControls.length) { 172 var firstControl = groupControls.first(); 173 firstControl.prop('checked', true); 174 firstControl.data('cfefDemoApplied', true); 175 } else if (checkedControl.length) { 176 groupControls.prop('checked', false); 177 var firstChecked = groupControls.first(); 178 firstChecked.prop('checked', true); 179 firstChecked.data('cfefDemoApplied', true); 180 } 181 return; 182 } 183 184 if (nodeName === 'select') { 185 if (typeof control.data('cfefOriginalValue') === 'undefined') { 186 control.data('cfefOriginalValue', control.val() || ''); 187 } 188 var firstOption = control.find("option[value!='']").first(); 189 if (!firstOption.length) { 190 firstOption = control.find('option').first(); 191 } 192 if (firstOption.length) { 193 control.val(firstOption.val()); 194 control.data('cfefDemoApplied', true); 195 } 196 return; 197 } 198 199 if (opts.fileUploadClass && control.hasClass(opts.fileUploadClass)) { 200 var accept = control.attr('accept') || ''; 201 var firstType = accept.split(',')[0] || 'png'; 202 var fileName = 'cool-formkit-placeholder.' + firstType; 203 var defaultImage = new File([], fileName, { type: 'image/png' }); 204 var container = new DataTransfer(); 205 container.items.add(defaultImage); 206 control[0].files = container.files; 207 return; 208 } 209 210 if (typeof control.data('cfefOriginalValue') === 'undefined') { 211 control.data('cfefOriginalValue', control.val() || ''); 212 } 213 control.val(CFKEF.getDemoValueForControl(nodeName, type, { telWithPlus: !!opts.telWithPlus })); 214 control.data('cfefDemoApplied', true); 215 }); 216}; 217 218/** 219 * Restore demo values previously applied by applyRequiredDemoOnControl
219s. 220 * 221 * @param {jQuery} $controls 222 * @param {Object} [opts] 223 * @param {string} [opts.fileUploadClass] 224 */ 225CFKEF.restoreRequiredDemoOnControls = function ($controls, opts) { 226 opts = opts || {}; 227 var $ = window.jQuery; 228 if (!$ || !$controls || !$controls.each) { 229 return; 230 } 231 232 $controls.each(function () { 233 var control = $(this); 234 235 if (opts.fileUploadClass && control.hasClass(opts.fileUploadClass)) { 236 var accept = control.attr('accept') || ''; 237 var firstType = accept.split(',')[0] || 'png'; 238 var fileName = 'cool-formkit-placeholder.' + firstType; 239 var inputValue = control.val() || ''; 240 if (inputValue.indexOf(fileName) !== -1) { 241 control.val(''); 242 } 243 return; 244 } 245 246 if (control.data('cfefDemoApplied') !== true) { 247 return; 248 } 249 250 var type = (control.attr('type') || '').toLowerCase(); 251 if (type === 'checkbox' || type === 'radio') { 252 var groupName = control.attr('name'); 253 if (groupName) { 254 var groupControls = $controls.filter('[type="' + type + '"][name="' + groupName + '"]'); 255 var originalCheckedValue = control.data('cfefOriginalCheckedValue'); 256 groupControls.prop('checked', false); 257 if (originalCheckedValue) { 258 groupControls.filter('[value="' + originalCheckedValue + '"]').first().prop('checked', true); 259 } 260 } else { 261 control.prop('checked', false); 262 } 263 control.removeData('cfefOriginalCheckedValue'); 264 } else { 265 var originalValue = control.data('cfefOriginalValue'); 266 control.val(typeof originalValue === 'undefined' ? '' : originalValue); 267 control.removeData('cfefOriginalValue'); 268 } 269 control.removeData('cfefDemoApplied'); 270 }); 271}; 272 273/** 274 * Convert YYYY-MM-DD to MM/DD/YYYY for logic comparisons. 275 * 276 * @param {string} dateStr 277 * @return {string} 278 */ 279CFKEF.formatDateToMDY = function (dateStr) { 280 if (!dateStr || typeof dateStr !== 'string') { 281 return dateStr || ''; 282 } 283 var parts = dateStr.split('-'); 284 if (parts.length !== 3) { 285 return dateStr; 286 } 287 return parts[1] + '/' + parts[2] + '/' + parts[0]; 288}; 289 290/** 291 * Convert 24h HH:MM to 12h display for logic comparisons. 292 * 293 * @param {string} time 294 * @return {string} 295 */ 296CFKEF.convertTimeTo12Hour = function (time) { 297 if (!time || typeof time !== 'string') { 298 return time || ''; 299 } 300 var parts = time.split(':'); 301 if (parts.length < 2) { 302 return time; 303 } 304 var hours = parseInt(parts[0], 10); 305 var minutes = parts[1]; 306 var period = hours >= 12 ? 'PM' : 'AM'; 307 var hours12 = hours % 12 || 12; 308 return String(hours12).padStart(2, '0') + ':' + minutes + ' ' + period; 309};
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.