如何在jQuery Selectable的Selecting事件中控制Selected事件触发?
Great question! The jQuery UI Selectable component doesn’t have a built-in way to block the selected event directly from within selecting, but we can implement your confirmation flow with a few straightforward workarounds. Here’s how to do it:
Core Idea
We’ll intercept the native selecting behavior, pause it to show your confirmation prompt, then manually trigger the selection (and selected event) only if the user confirms. We’ll use a flag to avoid infinite event loops.
1. Basic Implementation with Native Confirm Dialog
This uses the browser’s built-in confirm() (synchronous) to keep things simple:
<ul id="selectable"> <li class="ui-widget-content">Item 1</li> <li class="ui-widget-content">Item 2</li> <li class="ui-widget-content">Item 3</li> </ul>
$(function() { // Flag to distinguish manual confirmation triggers from native events let isConfirmingSelection = false; $("#selectable").selectable({ selecting: function(event, ui) { // Skip if this is our manual confirmation trigger if (isConfirmingSelection) return; // Cancel the native temporary selection state ui.selecting.removeClass("ui-selecting"); const targetItem = ui.selecting; // Show confirmation prompt if (confirm("确定要选中这个元素吗?")) { isConfirmingSelection = true; // Apply the selected state manually targetItem.addClass("ui-selected"); // Trigger the selected event to run your existing logic $(this).trigger("selected", { selected: targetItem[0] }); isConfirmingSelection = false; } }, selected: function(event, ui) { // Your post-selection logic goes here console.log("选中了:", ui.selected.textContent); } }); });
2. Handling Asynchronous Modals (e.g., Custom Modal)
If you’re using a custom asynchronous modal (instead of the native confirm), we need to track the pending selection and handle the modal’s confirm/cancel events separately:
$(function() { let pendingSelectionItem = null; let isConfirmingSelection = false; $("#selectable").selectable({ selecting: function(event, ui) { if (isConfirmingSelection) return; ui.selecting.removeClass("ui-selecting"); pendingSelectionItem = ui.selecting; // Open your custom confirmation modal $("#confirmSelectionModal").show(); }, selected: function(event, ui) { console.log("选中了:", ui.selected.textContent); } }); // Confirm button click handler $("#confirmBtn").on("click", function() { $("#confirmSelectionModal").hide(); if (pendingSelectionItem) { isConfirmingSelection = true; pendingSelectionItem.addClass("ui-selected"); $("#selectable").trigger("selected", { selected: pendingSelectionItem[0] }); isConfirmingSelection = false; pendingSelectionItem = null; } }); // Cancel button click handler $("#cancelBtn").on("click", function() { $("#confirmSelectionModal").hide(); pendingSelectionItem = null; }); });
3. Alternative: Build a Custom Selection Component
If you want more control without relying on Selectable’s event chain, you can roll your own lightweight selection logic. This avoids workarounds entirely:
$(function() { $("#selectable li").on("click", function() { const $item = $(this); if (confirm("确定要选中这个元素吗?")) { $item.toggleClass("ui-selected"); // Handle selection state changes directly const action = $item.hasClass("ui-selected") ? "选中" : "取消选中"; console.log(`${action}了:`, $item.text()); } }); });
Key Notes
- The
isConfirmingSelectionflag prevents infinite loops by skipping our custom logic when we’re manually triggering the selection. - Removing the
ui-selectingclass cancels the native selection flow, so theselectedevent won’t fire unless we trigger it manually. - For asynchronous modals, always clear the
pendingSelectionItemvariable to avoid leftover state.
内容的提问来源于stack exchange,提问作者Azaz ul Haq

