如何重构jQuery代码实现复选组选中统计与消息设置(避免重复)
Hey there! Let's fix that repetitive jQuery code and make it way more maintainable. First, let's spot the issue with your current code: you're binding the same change event twice, which means every checkbox change will update both groups' results—definitely not what you want. Here's how to refactor it to reuse logic by leveraging the group identifiers in your classes:
Step 1: Define Group Configurations
First, create a single object to store all group-specific messages. This way, adding new groups later only requires updating this config, not duplicating code:
// Group-specific message config: key = group ID (eg1, sth1), value = message set const groupConfigs = { eg1: { fewSelected: 'msg for 1 or 2 count in group EG1', manySelected: 'msg for 3 more count in group EG1', noneSelected: 'msg for none of the above in group EG1' }, sth1: { fewSelected: 'msg for 1 or 2 count in group STH1', manySelected: 'msg for 3 more count in group STH1', noneSelected: 'msg for none of the above in group STH1' } };
Step 2: Create Reusable Helper Functions
Next, write utility functions to handle group ID extraction and result updates—these will do the heavy lifting for all groups:
// Extract the group ID from the checkbox's class (e.g., adftg_eg1 → eg1) function getGroupId($checkbox) { const className = $checkbox.attr('class'); return className.split('_')[1]; } // Update count and message for a specific group function updateGroupResults(groupId) { const config = groupConfigs[groupId]; // Count checked non-"none" options in the group const selectedCount = $(`input.adftg_${groupId}[value^=q]:checked`).length; // Get the result inputs for this group const $countInput = $(`.${groupId}_count`); const $msgInput = $(`.${groupId}_msg`); // Determine which message to show if (selectedCount === 0) { // Check if "none of the above" is selected const isNoneChecked = $(`input.adftg_${groupId}[value=none]:checked`).length > 0; $countInput.val(0); $msgInput.val(isNoneChecked ? config.noneSelected : 'msg for none selected'); } else if (selectedCount < 3) { $countInput.val(selectedCount); $msgInput.val(config.fewSelected); } else { $countInput.val(selectedCount); $msgInput.val(config.manySelected); } }
Step 3: Bind Single Event Handlers
Now bind just two event handlers (one for regular checkboxes, one for "none" options) that use our helper functions:
// Handle changes to regular question checkboxes $('input[class^=adftg][value^=q]').change(function() { const groupId = getGroupId($(this)); updateGroupResults(groupId); }); // Handle changes to "none of the above" checkboxes $('input[class^=adftg][value=none]').change(function() { const groupId = getGroupId($(this)); updateGroupResults(groupId); });
Bonus: Improve HTML Structure (Optional but Recommended)
Your current class-based group identification works, but using data-* attributes makes the code more robust and readable (no relying on class name formatting). If you can modify your Drupal Webform's HTML output, add a data-group attribute to each checkbox:
<!-- Example for Group 1 checkboxes --> <input class="adftg" data-group="eg1" type="checkbox" value="q1"> Text here 1 <input class="adftg" data-group="eg1" type="checkbox" value="none"> none of the above <!-- Example for Group 2 checkboxes --> <input class="adftg" data-group="sth1" type="checkbox" value="q1"> Text here 1 <input class="adftg" data-group="sth1" type="checkbox" value="none"> none of the above
Then simplify the getGroupId function to use the data attribute:
function getGroupId($checkbox) { return $checkbox.data('group'); }
Note for Drupal Webform
Since you're working with a multi-page Drupal Webform, wrap all your code in $(document).ready() to ensure it runs after the DOM is fully loaded:
$(document).ready(function() { // All the code above goes here });
This refactor eliminates duplicate code, makes adding new groups trivial, and ensures each checkbox change only affects its own group's results. Perfect for keeping your long form maintainable!
内容的提问来源于stack exchange,提问作者Adam888

