PluginProbe
King Addons for Elementor – 100+ Elementor Widgets, 4 000+ Elementor Templates, WooCommerce Builder, Mega Menu, Popup Builder / 51.1.87
King Addons for Elementor – 100+ Elementor Widgets, 4 000+ Elementor Templates, WooCommerce Builder, Mega Menu, Popup Builder v51.1.87
51.1.87 51.1.86 51.1.84 51.1.85 51.1.83 51.1.82 51.1.81 51.1.79 51.1.78 51.1.77 51.1.76 51.1.74 51.1.75 51.1.65 51.1.64 51.1.63 trunk 51.1.14 51.1.2 51.1.35 51.1.36 51.1.37 51.1.38 51.1.39 51.1.44 All 41 releases
← All changes | includes/widgets/Pricing_Calculator/script.js +146 -222 51.1.14 → 51.1.87 View file →
@@ -36,9 +36,9 @@
36 36 var $summaryItems = $calculator.find('.king-pricing-calculator__summary-items');
37 37 var $calculateButton = $calculator.find('.king-pricing-calculator__calculate-button');
38 38
39 39 // Debug info - log initial calculator settings
40 - console.log('Calculator initialized with base price:', basePrice);
40 + // console.log('Calculator initialized with base price:', basePrice);
41 41
42 42 // Get ajaxurl from localized script if it exists, fallback to global
43 43 var ajaxUrl = (typeof king_addons_calculator_vars !== 'undefined') ? king_addons_calculator_vars.ajaxurl : (typeof ajaxurl !== 'undefined' ? ajaxurl : '');
44 44 // Get nonces from localized script
@@ -55,8 +55,23 @@
55 55 func.apply(context, args);
56 56 }, wait);
57 57 };
58 58 };
59 +
60 + // Sanitize potentially user-controlled strings before inserting into HTML.
61 + // Uses DOMPurify for robust XSS protection.
62 + var sanitizeHtml = function(value) {
63 + if (typeof DOMPurify !== 'undefined') {
64 + return DOMPurify.sanitize(String(value), {ALLOWED_TAGS: [], ALLOWED_ATTR: []});
65 + }
66 + // Fallback if DOMPurify not loaded
67 + return String(value)
68 + .replace(/&/g, '&')
69 + .replace(/</g, '&lt;')
70 + .replace(/>/g, '&gt;')
71 + .replace(/"/g, '&quot;')
72 + .replace(/'/g, '&#039;');
73 + };
59 74
60 75 // Initialize field values and events
61 76 initFields($fields);
62 77
@@ -108,15 +123,15 @@
108 123 var $field = $(this);
109 124 var fieldType = $field.data('field-type');
110 125
111 126 // Debug info - log field attributes
112 - console.log('Field:', fieldType, 'Price Type:', $field.data('price-type'), 'Price:', $field.data('price'));
127 + // console.log('Field:', fieldType, 'Price Type:', $field.data('price-type'), 'Price:', $field.data('price'));
113 128
114 129 // Check if custom formula is used (Pro feature)
115 130 if ($field.data('price-type') === 'custom') {
116 131 // Show a one-time console message
117 132 if (!window.customFormulaMessageShown) {
118 - console.info('Custom formula calculation requires Pro version.');
133 + // console.info('Custom formula calculation requires Pro version.');
119 134 window.customFormulaMessageShown = true;
120 135 }
121 136 }
122 137
@@ -223,8 +238,10 @@
223 238 }
224 239
225 240 /**
226 241 * Calculate the total price based on all field values
242 + * Fields are processed in DOM order, applying each operation sequentially.
243 + * This allows for proper calculation order (e.g., multiply first two values, then add third).
227 244 */
228 245 function calculatePrice() {
229 246 try {
230 247 // Start with base price
@@ -231,13 +248,13 @@
231 248 var total = basePrice;
232 249 var summaryHtml = '';
233 250
234 251 // Debug info
235 - console.log('Starting calculation with base price:', total);
252 + // console.log('Starting calculation with base price:', total);
236 253
237 254 // Advanced Formula will be applied after default calculation
238 255
239 - // First handle additions
256 + // Process all fields in DOM order (sequential calculation)
240 257 $fields.each(function() {
241 258 var $field = $(this);
242 259 var fieldType = $field.data('field-type');
243 260 var priceType = $field.data('price-type');
@@ -244,24 +261,17 @@
244 261 var fieldLabel = $field.find('.king-pricing-calculator__field-label').text();
245 262 var fieldValue = 0;
246 263 var fieldPrice = 0;
247 264 var subTotal = 0;
265 + var beforeOp = total;
248 266
249 - if (priceType !== 'add') {
250 - return; // Skip non-addition fields on first pass
251 - }
252 -
253 267 try {
268 + // Get field value and price based on field type
254 269 switch (fieldType) {
255 270 case 'number':
256 271 var $input = $field.find('input[type="number"]');
257 272 fieldValue = parseFloat($input.val());
258 273 fieldPrice = parseFloat($field.data('price'));
259 -
260 - if (!isNaN(fieldValue) && !isNaN(fieldPrice)) {
261 - subTotal = fieldValue * fieldPrice;
262 - total += subTotal;
263 - }
264 274 break;
265 275
266 276 case 'range':
267 277 var $range = $field.find('input[type="range"]');
@@ -266,39 +276,22 @@
266 276 case 'range':
267 277 var $range = $field.find('input[type="range"]');
268 278 fieldValue = parseFloat($range.val());
269 279 fieldPrice = parseFloat($field.data('price'));
270 -
271 - if (!isNaN(fieldValue) && !isNaN(fieldPrice)) {
272 - subTotal = fieldValue * fieldPrice;
273 - total += subTotal;
274 - }
275 280 break;
276 281
277 282 case 'select':
278 283 var $select = $field.find('select');
279 284 var $option = $select.find('option:selected');
280 -
281 285 fieldValue = $option.text();
282 286 fieldPrice = parseFloat($option.data('price'));
283 -
284 - if (!isNaN(fieldPrice)) {
285 - subTotal = fieldPrice;
286 - total += subTotal;
287 - }
288 287 break;
289 288
290 289 case 'radio':
291 290 var $radio = $field.find('input[type="radio"]:checked');
292 -
293 291 if ($radio.length) {
294 292 fieldValue = $radio.siblings('label').text();
295 293 fieldPrice = parseFloat($radio.data('price'));
296 -
297 - if (!isNaN(fieldPrice)) {
298 - subTotal = fieldPrice;
299 - total += subTotal;
300 - }
301 294 }
302 295 break;
303 296
304 297 case 'checkbox':
@@ -303,207 +296,104 @@
303 296
304 297 case 'checkbox':
305 298 case 'switch':
306 299 var $checkbox = $field.find('input[type="checkbox"]');
307 -
308 300 if ($checkbox.is(':checked')) {
309 301 fieldValue = 'Yes';
310 302 fieldPrice = parseFloat($field.data('price'));
311 -
312 - if (!isNaN(fieldPrice)) {
313 - subTotal = fieldPrice;
314 - total += subTotal;
315 - }
316 303 } else {
317 304 fieldValue = 'No';
305 + fieldPrice = 0;
318 306 }
319 307 break;
320 308 }
321 309
322 - // Add to summary if there's a value and subtotal
323 - if (fieldValue !== '' && fieldValue !== 0 && subTotal !== 0) {
324 - summaryHtml += '<div class="king-pricing-calculator__summary-item">' +
325 - '<span class="king-pricing-calculator__summary-label">' + fieldLabel + ': ' + fieldValue + '</span>' +
326 - '<span class="king-pricing-calculator__summary-value">' + formatPrice(subTotal) + '</span>' +
327 - '</div>';
328 - }
329 -
330 - // Debug info
331 - console.log('Field:', fieldLabel, 'Type:', fieldType, 'Value:', fieldValue, 'Price:', fieldPrice, 'Subtotal:', subTotal);
332 -
333 - } catch (fieldError) {
334 - console.error('Error processing field for addition:', fieldError);
335 - }
336 - });
337 -
338 - // Debug info
339 - console.log('After additions, total is:', total);
340 -
341 - // Then handle multiplications
342 - $fields.each(function() {
343 - var $field = $(this);
344 - var fieldType = $field.data('field-type');
345 - var priceType = $field.data('price-type');
346 - var fieldLabel = $field.find('.king-pricing-calculator__field-label').text();
347 - var fieldValue = 0;
348 - var fieldPrice = 0;
349 - var beforeMult = total;
350 -
351 - if (priceType !== 'multiply') {
352 - return; // Skip non-multiplication fields on second pass
353 - }
354 -
355 - try {
356 - switch (fieldType) {
357 - case 'number':
358 - var $input = $field.find('input[type="number"]');
359 - fieldValue = parseFloat($input.val());
360 -
361 - if (!isNaN(fieldValue) && fieldValue !== 0) {
362 - beforeMult = total;
363 - total *= fieldValue;
364 -
365 - summaryHtml += '<div class="king-pricing-calculator__summary-item">' +
366 - '<span class="king-pricing-calculator__summary-label">' + fieldLabel + ': ' + fieldValue + '</span>' +
367 - '<span class="king-pricing-calculator__summary-value">' + formatPrice(total - beforeMult) + '</span>' +
368 - '</div>';
310 + // Apply the operation based on price type
311 + if (priceType === 'add') {
312 + // For number/range: multiply value by price per unit, then add
313 + if (fieldType === 'number' || fieldType === 'range') {
314 + if (!isNaN(fieldValue) && !isNaN(fieldPrice)) {
315 + subTotal = fieldValue * fieldPrice;
316 + total += subTotal;
369 317 }
370 - break;
371 -
372 - case 'range':
373 - var $range = $field.find('input[type="range"]');
374 - fieldValue = parseFloat($range.val());
375 -
318 + } else {
319 + // For select/radio/checkbox: add the price directly
320 + if (!isNaN(fieldPrice)) {
321 + subTotal = fieldPrice;
322 + total += subTotal;
323 + }
324 + }
325 +
326 + // Add to summary if there's a contribution
327 + if (subTotal !== 0) {
328 + summaryHtml += '<div class="king-pricing-calculator__summary-item">' +
329 + '<span class="king-pricing-calculator__summary-label">' + sanitizeHtml(fieldLabel) + ': ' + sanitizeHtml(fieldValue) + '</span>' +
330 + '<span class="king-pricing-calculator__summary-value">+' + sanitizeHtml(formatPrice(subTotal)) + '</span>' +
331 + '</div>';
332 + }
333 +
334 + // console.log('Field (add):', fieldLabel, 'Value:', fieldValue, 'Price:', fieldPrice, 'Subtotal:', subTotal, 'Total:', total);
335 +
336 + } else if (priceType === 'multiply') {
337 + // For number/range: multiply total by the field value
338 + if (fieldType === 'number' || fieldType === 'range') {
376 339 if (!isNaN(fieldValue) && fieldValue !== 0) {
377 - beforeMult = total;
340 + beforeOp = total;
378 341 total *= fieldValue;
379 342
380 343 summaryHtml += '<div class="king-pricing-calculator__summary-item">' +
381 - '<span class="king-pricing-calculator__summary-label">' + fieldLabel + ': ' + fieldValue + '</span>' +
382 - '<span class="king-pricing-calculator__summary-value">' + formatPrice(total - beforeMult) + '</span>' +
344 + '<span class="king-pricing-calculator__summary-label">' + sanitizeHtml(fieldLabel) + ': ×' + sanitizeHtml(fieldValue) + '</span>' +
345 + '<span class="king-pricing-calculator__summary-value">' + sanitizeHtml(formatPrice(total - beforeOp)) + '</span>' +
383 346 '</div>';
384 347 }
385 - break;
386 -
387 - case 'select':
388 - var $select = $field.find('select');
389 - var $option = $select.find('option:selected');
390 -
391 - fieldValue = $option.text();
392 - fieldPrice = parseFloat($option.data('price'));
393 -
348 + } else {
349 + // For select/radio/checkbox: multiply total by the price
394 350 if (!isNaN(fieldPrice) && fieldPrice !== 0) {
395 - beforeMult = total;
351 + beforeOp = total;
396 352 total *= fieldPrice;
397 353
398 354 summaryHtml += '<div class="king-pricing-calculator__summary-item">' +
399 - '<span class="king-pricing-calculator__summary-label">' + fieldLabel + ': ' + fieldValue + '</span>' +
400 - '<span class="king-pricing-calculator__summary-value">' + formatPrice(total - beforeMult) + '</span>' +
355 + '<span class="king-pricing-calculator__summary-label">' + sanitizeHtml(fieldLabel) + ': ' + sanitizeHtml(fieldValue) + ' (×' + sanitizeHtml(fieldPrice) + ')</span>' +
356 + '<span class="king-pricing-calculator__summary-value">' + sanitizeHtml(formatPrice(total - beforeOp)) + '</span>' +
401 357 '</div>';
402 358 }
403 - break;
404 -
405 - case 'radio':
406 - var $radio = $field.find('input[type="radio"]:checked');
407 -
408 - if ($radio.length) {
409 - fieldValue = $radio.siblings('label').text();
410 - fieldPrice = parseFloat($radio.data('price'));
411 -
412 - if (!isNaN(fieldPrice) && fieldPrice !== 0) {
413 - beforeMult = total;
414 - total *= fieldPrice;
415 -
416 - summaryHtml += '<div class="king-pricing-calculator__summary-item">' +
417 - '<span class="king-pricing-calculator__summary-label">' + fieldLabel + ': ' + fieldValue + '</span>' +
418 - '<span class="king-pricing-calculator__summary-value">' + formatPrice(total - beforeMult) + '</span>' +
419 - '</div>';
420 - }
421 - }
422 - break;
423 -
424 - case 'checkbox':
425 - case 'switch':
426 - var $checkbox = $field.find('input[type="checkbox"]');
427 -
428 - if ($checkbox.is(':checked')) {
429 - fieldValue = 'Yes';
430 - fieldPrice = parseFloat($field.data('price'));
431 -
432 - if (!isNaN(fieldPrice) && fieldPrice !== 0) {
433 - beforeMult = total;
434 - total *= fieldPrice;
435 -
436 - summaryHtml += '<div class="king-pricing-calculator__summary-item">' +
437 - '<span class="king-pricing-calculator__summary-label">' + fieldLabel + ': ' + fieldValue + '</span>' +
438 - '<span class="king-pricing-calculator__summary-value">' + formatPrice(total - beforeMult) + '</span>' +
439 - '</div>';
440 - }
441 - }
442 - break;
443 - }
444 -
445 - // Debug info
446 - console.log('Field (multiply):', fieldLabel, 'Type:', fieldType, 'Value:', fieldValue, 'BeforeMult:', beforeMult, 'After:', total);
447 -
448 - } catch (fieldError) {
449 - console.error('Error processing field for multiplication:', fieldError);
450 - }
451 - });
452 -
453 - // Then handle custom formula (fallback to addition in free version)
454 - $fields.each(function() {
455 - var $field = $(this);
456 - var fieldType = $field.data('field-type');
457 - var priceType = $field.data('price-type');
458 -
459 - if (priceType !== 'custom') {
460 - return; // Skip non-custom fields
461 - }
462 -
463 - try {
464 - // In the free version, just treat custom formula as add
465 - var fieldLabel = $field.find('.king-pricing-calculator__field-label').text();
466 - var fieldValue, fieldPrice, subTotal = 0;
467 -
468 - switch (fieldType) {
469 - case 'number':
470 - case 'range':
471 - var $input = fieldType === 'number' ?
472 - $field.find('input[type="number"]') :
473 - $field.find('input[type="range"]');
474 -
475 - fieldValue = parseFloat($input.val());
476 - fieldPrice = parseFloat($field.data('price'));
477 -
359 + }
360 +
361 + // console.log('Field (multiply):', fieldLabel, 'Value:', fieldValue, 'BeforeOp:', beforeOp, 'Total:', total);
362 +
363 + } else if (priceType === 'custom') {
364 + // In the free version, treat custom formula as add (fallback)
365 + if (fieldType === 'number' || fieldType === 'range') {
478 366 if (!isNaN(fieldValue) && !isNaN(fieldPrice)) {
479 - // Fallback to addition in free version
480 367 subTotal = fieldValue * fieldPrice;
481 368 total += subTotal;
482 369
483 370 summaryHtml += '<div class="king-pricing-calculator__summary-item">' +
484 371 '<span class="king-pricing-calculator__summary-label">' +
485 - fieldLabel + ': ' + fieldValue +
372 + sanitizeHtml(fieldLabel) + ': ' + sanitizeHtml(fieldValue) +
486 373 ' <small>(Pro formula fallback)</small>' +
487 374 '</span>' +
488 - '<span class="king-pricing-calculator__summary-value">' + formatPrice(subTotal) + '</span>' +
375 + '<span class="king-pricing-calculator__summary-value">' + sanitizeHtml(formatPrice(subTotal)) + '</span>' +
489 376 '</div>';
490 377 }
491 - break;
378 + } else if (!isNaN(fieldPrice)) {
379 + subTotal = fieldPrice;
380 + total += subTotal;
492 381
493 - case 'select':
494 - case 'radio':
495 - case 'checkbox':
496 - case 'switch':
497 - // Handle similar to add, with pro notice
498 - // Implementation follows similar pattern to the addition case
499 - break;
382 + summaryHtml += '<div class="king-pricing-calculator__summary-item">' +
383 + '<span class="king-pricing-calculator__summary-label">' +
384 + sanitizeHtml(fieldLabel) + ': ' + sanitizeHtml(fieldValue) +
385 + ' <small>(Pro formula fallback)</small>' +
386 + '</span>' +
387 + '<span class="king-pricing-calculator__summary-value">' + sanitizeHtml(formatPrice(subTotal)) + '</span>' +
388 + '</div>';
389 + }
390 +
391 + // console.log('Field (custom/fallback):', fieldLabel, 'Added:', subTotal, 'Total:', total);
500 392 }
501 -
502 - console.log('Custom formula field (free fallback):', fieldLabel, 'Added:', subTotal);
503 -
393 +
504 394 } catch (fieldError) {
505 - console.error('Error processing custom formula field:', fieldError);
395 + // console.error('Error processing field:', fieldLabel, fieldError);
506 396 }
507 397 });
508 398
509 399 // Advanced Formula override (Pro) after default calculation loops
@@ -535,10 +425,10 @@
535 425 }
536 426 });
537 427
538 428 // For debugging custom formulas
539 - console.log('Available field IDs:', fieldsMap);
540 - console.log('User-friendly field aliases:', aliasMap);
429 + // console.log('Available field IDs:', fieldsMap);
430 + // console.log('User-friendly field aliases:', aliasMap);
541 431
542 432 // Apply chosen formula on the aggregated total
543 433 var newTotal = total;
544 434 if (formulaType === 'exponential') {
@@ -550,14 +440,48 @@
550 440 newTotal = total > 0 ? Math.log(total) / Math.log(logBase) : 0;
551 441 } else if (formulaType === 'custom') {
552 442 var customCode = $calculator.data('customFormula') || '';
553 443 try {
444 + // Security fix: Only allow safe mathematical operations
445 + if (!isCustomFormulaSafe(customCode)) {
446 + // console.error('Custom formula contains unsafe code');
447 + return;
448 + }
554 449 // Pass both the full field map and user-friendly aliases
555 450 var fn = new Function('fields', 'basePrice', 'aliases', customCode);
556 451 newTotal = fn(fieldsMap, basePrice, aliasMap);
557 452 } catch (e) {
558 - console.error('Custom formula error:', e);
453 + // console.error('Custom formula error:', e);
559 454 }
455 +
456 + function isCustomFormulaSafe(formula) {
457 + // Only allow safe mathematical operations
458 + var safePatterns = [
459 + /^[0-9+\-*/().\s]+$/, // Basic math
460 + /Math\.(abs|round|ceil|floor|min|max|pow|sqrt|sin|cos|tan|log|exp|PI|E)/g, // Safe Math functions
461 + ];
462 +
463 + for (var i = 0; i < safePatterns.length; i++) {
464 + if (safePatterns[i].test(formula)) {
465 + return true;
466 + }
467 + }
468 +
469 + // Check for dangerous patterns
470 + var dangerousPatterns = [
471 + /eval|Function|new|this|window|document|script|alert|prompt|confirm/g,
472 + /[\[\]{}]/g, // Object/array notation
473 + /\w+\s*\(/g, // Function calls (except Math functions already checked)
474 + ];
475 +
476 + for (var i = 0; i < dangerousPatterns.length; i++) {
477 + if (dangerousPatterns[i].test(formula)) {
478 + return false;
479 + }
480 + }
481 +
482 + return true;
483 + }
560 484 }
561 485 // Override total with formula result
562 486 total = (typeof newTotal === 'number' && !isNaN(newTotal)) ? newTotal : total;
563 487 }
@@ -563,14 +487,14 @@
563 487 }
564 488
565 489 // Final check to prevent NaN
566 490 if (isNaN(total)) {
567 - console.error('Total calculation resulted in NaN');
491 + // console.error('Total calculation resulted in NaN');
568 492 total = basePrice;
569 493 }
570 494
571 495 // Debug info
572 - console.log('Final total:', total);
496 + // console.log('Final total:', total);
573 497
574 498 // Update the total price
575 499 $totalPrice.text(formatPrice(total));
576 500
@@ -576,9 +500,9 @@
576 500
577 501 // Update the summary items
578 502 $summaryItems.html(summaryHtml);
579 503 } catch(e) {
580 - console.error('Calculation error:', e);
504 + // console.error('Calculation error:', e);
581 505 $totalPrice.text(formatPrice(basePrice));
582 506 }
583 507 }
584 508
@@ -586,9 +510,9 @@
586 510 * Format a price number with proper separators
587 511 */
588 512 function formatPrice(number) {
589 513 if (isNaN(number)) {
590 - console.error('Attempting to format NaN as price');
514 + // console.error('Attempting to format NaN as price');
591 515 number = 0;
592 516 }
593 517 var parts = number.toFixed(decimalPlaces).toString().split('.');
594 518 parts[0] = parts[0].replace(/\B(?=(\d{3})+(?!\d))/g, thousandSeparator);
@@ -632,15 +556,15 @@
632 556 conditionalRules = $calculator.data('conditionalRules');
633 557
634 558 // If that doesn't work, try to get the raw attribute and parse it
635 559 if (!conditionalRules && $calculator.attr('data-conditional-rules')) {
636 - console.log('Found data-conditional-rules attribute, trying to parse:', $calculator.attr('data-conditional-rules'));
560 + // console.log('Found data-conditional-rules attribute, trying to parse:', $calculator.attr('data-conditional-rules'));
637 561 conditionalRules = JSON.parse($calculator.attr('data-conditional-rules'));
638 562 }
639 563
640 - console.log('Conditional rules loaded:', conditionalRules);
564 + // console.log('Conditional rules loaded:', conditionalRules);
641 565 } catch (e) {
642 - console.error('Error parsing conditional rules:', e);
566 + // console.error('Error parsing conditional rules:', e);
643 567 }
644 568
645 569 // Add to Cart Integration
646 570 $calculator.find('.king-pricing-calculator-pro__add-to-cart-button').on('click', function() {
@@ -822,9 +746,9 @@
822 746 // Save to localStorage
823 747 localStorage.setItem(storageKey, JSON.stringify(fieldsData));
824 748 alert('Calculation saved successfully.');
825 749 } catch (error) {
826 - console.error('Error saving calculation:', error);
750 + // console.error('Error saving calculation:', error);
827 751 alert('There was an error saving your calculation. Please try again.');
828 752 }
829 753 });
830 754
@@ -882,9 +806,9 @@
882 806 } else {
883 807 alert('Calculation loaded successfully.');
884 808 }
885 809 } catch (error) {
886 - console.error('Error loading calculation:', error);
810 + // console.error('Error loading calculation:', error);
887 811 alert('There was an error loading your calculation. The saved data may be corrupted.');
888 812 }
889 813 });
890 814
@@ -889,9 +813,9 @@
889 813 });
890 814
891 815 // Conditional Logic
892 816 if (conditionalRules) {
893 - console.log('Conditional rules found:', conditionalRules);
817 + // console.log('Conditional rules found:', conditionalRules);
894 818 function evaluateCondition(val, operator, expected) {
895 819 try {
896 820 // Convert values for proper comparison
897 821 var compVal = val;
@@ -903,9 +827,9 @@
903 827 compExpected = parseFloat(expected);
904 828
905 829 // Check if we have valid numbers
906 830 if (isNaN(compVal) || isNaN(compExpected)) {
907 - console.warn('Invalid numeric comparison with NaN:', val, operator, expected);
831 + // console.warn('Invalid numeric comparison with NaN:', val, operator, expected);
908 832 return false;
909 833 }
910 834 }
911 835
@@ -915,9 +839,9 @@
915 839 return operator === 'is_checked' ? compVal === true : compVal === false;
916 840 }
917 841
918 842 // Log the comparison
919 - console.log('Comparing:', compVal, operator, compExpected);
843 + // console.log('Comparing:', compVal, operator, compExpected);
920 844
921 845 // Perform the comparison
922 846 switch (operator) {
923 847 case 'equal': return compVal == compExpected;
@@ -927,14 +851,14 @@
927 851 case 'contains': return ('' + compVal).indexOf(compExpected) !== -1;
928 852 default: return false;
929 853 }
930 854 } catch (e) {
931 - console.error('Error evaluating condition:', e);
855 + // console.error('Error evaluating condition:', e);
932 856 return false;
933 857 }
934 858 }
935 859 $.each(conditionalRules, function(_, rule) {
936 - console.log('Processing rule:', rule);
860 + // console.log('Processing rule:', rule);
937 861
938 862 // Improve field selection to handle both custom IDs and auto-generated IDs
939 863 var $ifField, $targetField;
940 864
@@ -951,21 +875,21 @@
951 875 // Try finding a field with a custom ID (king-calc-*)
952 876 $targetField = $calculator.find('[data-field-id="king-calc-' + rule.target_field + '"]');
953 877 }
954 878
955 - console.log('Condition field found:', $ifField.length > 0, 'Target field found:', $targetField.length > 0);
879 + // console.log('Condition field found:', $ifField.length > 0, 'Target field found:', $targetField.length > 0);
956 880
957 881 // Log actual field IDs to help debug
958 882 if ($ifField.length > 0) {
959 - console.log('If field ID:', $ifField.data('field-id'));
883 + // console.log('If field ID:', $ifField.data('field-id'));
960 884 }
961 885 if ($targetField.length > 0) {
962 - console.log('Target field ID:', $targetField.data('field-id'));
886 + // console.log('Target field ID:', $targetField.data('field-id'));
963 887 }
964 888
965 889 // If either field is not found, skip this rule
966 890 if (!$ifField.length || !$targetField.length) {
967 - console.warn('Could not find one or both fields for this rule, skipping');
891 + // console.warn('Could not find one or both fields for this rule, skipping');
968 892 return true; // Continue to next rule
969 893 }
970 894
971 895 function applyRule() {
@@ -972,9 +896,9 @@
972 896 var val;
973 897 var type = $ifField.data('field-type');
974 898
975 899 // Log the field type to debug
976 - console.log('Evaluating field type:', type);
900 + // console.log('Evaluating field type:', type);
977 901
978 902 if (type === 'checkbox' || type === 'switch') {
979 903 val = $ifField.find('input[type="checkbox"]').prop('checked');
980 904 } else if (type === 'radio') {
@@ -983,12 +907,12 @@
983 907 val = $ifField.find('input, select').val();
984 908 }
985 909
986 910 // Log the actual field value
987 - console.log('Field value:', val, 'comparing with:', rule.value, 'using operator:', rule.operator);
911 + // console.log('Field value:', val, 'comparing with:', rule.value, 'using operator:', rule.operator);
988 912
989 913 var result = evaluateCondition(val, rule.operator, rule.value);
990 - console.log('Condition evaluation result:', result);
914 + // console.log('Condition evaluation result:', result);
991 915
992 916 // Apply the action based on the result
993 917 try {
994 918 switch (rule.action) {
@@ -1027,18 +951,18 @@
1027 951 case 'set_value':
1028 952 if (result) {
1029 953 var $input = $targetField.find('input, select');
1030 954 $input.val(rule.set_value).trigger('change');
1031 - console.log('Set value to:', rule.set_value);
955 + // console.log('Set value to:', rule.set_value);
1032 956 }
1033 957 break;
1034 958 }
1035 959 } catch (e) {
1036 - console.error('Error applying action:', e);
960 + // console.error('Error applying action:', e);
1037 961 }
1038 962
1039 963 // Log the action taken
1040 - console.log('Applied action:', rule.action, 'with result:', result);
964 + // console.log('Applied action:', rule.action, 'with result:', result);
1041 965 }
1042 966 $ifField.on('change input', applyRule);
1043 967
1044 968 // Also execute immediately once to set initial state