开发者

dynamically enable/disable jquery sortable item

I have table rows that are sortable depending on whether certain radio buttons are checked or not. The sortables are initialized on document.ready as follows:

$(document).ready(function() {
    // Return a helper with preserved width of cells
    // handy code I got from http://lanitdev.wordpress.com/2009/07/23/make-table-rows-sortable-using-jquery-ui-sortable/
    var fixHelper = function(e, ui) {
        ui.children().each(function() {
            $(this).width($(this).width());
        });
        return ui;
    };
    // #opts = table id; tr.ui-state-disabled class = rows not sortable
    $("#opts tbody").sortable({
        items: 'tr:not(.ui-state-disabled)',
        cursor: 'crosshair',
        helper: fixHelper
    }).disableSelection();
});

I have the following function attached to the radio buttons (ids prefixed "active_") onchange which either adds or removes the ui-state-disabled class attribute from table rows (dynamic ids prefixed "opt_"):

    var toggleDrag = function(i){
    if ($('#active_'+i+'-0').is(':checked')) {
        $('#opt_'+i).addClass('ui-state-disabled');
    }
    if ($('#active_'+i+'-1').is(':checked')) {
        $('#opt_'+i).removeClass();
    }
    $("#opts tbody").sortable("option", "items", "tr:not(.ui-state-disabled)");
    //$("#opts tbody").sortable("refresh");
    //alert($('#opt_'+i).attr('class')); - alert indicates that the class attribute is being changed
    //$("#opts tbody").sortable("option", "cursor", "auto"); - this works!
}

If I select a radio button that should make a previously un-sortable row sortable, it works and I can drag and drop the row. The problem is if I select a radio button to make a row that previously was sortable, un-sortable, I can still drag and drop it. The setter .sortable("option", "items", "tr:not..etc") doesn't appear "un-register" a row if it was previously sortable. I also tried .sortable("refresh") with no luck. And I have checked to see if the class attribute is being changed with an alert and it is.

Any help with this would be greatly 开发者_开发知识库appreciated.


I ran into the same problem, that the items option doesn't seem to remove items which had been previously enabled.

The cancel option, however, does. Note that the disabled items will shift around to make room for the sortable ones (the spot is still available as a drop target), but dragging the disabled items themselves will not work. Using a disabled class also makes it easy to change the style based on whether or not the item is sortable (see on jsfiddle).

The code here is partially based on Bah Bah the Lamb's answer, but it has been greatly tidied and simplified.

The html:

<ul id="sorted-list">
   <li>
       <p><input type="checkbox" checked="true" /> Item 1</p>
    </li>
   <li>
       <p class="disabled"><input type="checkbox" /> Item 2</p>
   </li>
   <li>
       <p><input type="checkbox" checked="true" /> Item 3</p>
   </li>
</ul>

The jQuery:

$("#sorted-list").sortable({
    cancel:".disabled"
});

// add or remove the 'disabled' class based on the value of the checkbox
$("#sorted-list input").click(function() {
    if (this.checked) {
        $(this.parentElement).removeClass("disabled");
    } else { 
        $(this.parentElement).addClass("disabled");
    }
});

The CSS:

li {
  border: 1px solid #aaa;
  background-color: #eee;
  color:#555;
  padding: 5px;
}

.disabled {
  color:#ddd;
}


I had a similar problem and found an easy solution (but in my example I am using a sortable ul not a table, as there is more freedom with mark-up in ul's).

The idea behind it is to leave the list and all its items sortable, but remove the handle, thus disabling the individual item's ability to sort, as seen in this code

<ul id="sorted-list">
    <li>
        <div class="handle sortable">
            <p>Item 1</p>
            <input type="button" value="Disable Sort" />
        </div>
    </li>
    <li>
        <div class="handle sortable">
            <p>Item 2</p>
            <input type="button" value="Disable Sort" />
        </div>
    </li>
    <li>
        <div class="handle sortable">
            <p>Item 3</p>
            <input type="button" value="Disable Sort" />
        </div>
    </li>
    <li>
        <div class="handle sortable">
            <p>Item 4</p>
            <input type="button" value="Disable Sort" />
        </div>
    </li>
</ul>
<script>
    $("#sorted-list").sortable({
        items: "li",
        handle: ".handle.sortable"
    });
    $("#sorted-list").find("input").click(function() {
        if ($(this).closest(".handle").hasClass("sortable"))
            $(this).val("Enable Sort").closest(".handle").removeClass("sortable");
        else $(this).val("Disable Sort").closest(".handle").addClass("sortable");
    });
</script>


Try using the disabled option. http://jqueryui.com/demos/sortable/#option-disabled


I've been trying to do the same thing. I really wanted the items feature rather than disabled. As pointed out above, there is a weakness in the jQueryUI implementation whereby the sortable don't refresh the items list should the items matched by the selectors change.

To get around this, I simply destroyed and reinstantiated the sortabled. I've adapted Hannele's JSfiddle to demonstrate (http://jsfiddle.net/Sxg8D/140/).

$("#sorted-list").sortable({
    items:"li:not(.disabled)"
});

$("#sorted-list input").click(function() {
    if (this.checked) {
        $(this.parentElement).removeClass("disabled");
    } else { 
        $(this.parentElement).addClass("disabled");
    }

    $("#sorted-list")
        .sortable( "destroy" )
        .sortable({
            items:"li:not(.disabled)"
        });
});


I know this is old, but had a similar problem. I had my sortable items in groupings. I wanted certain groups to be sortable anywhere and some to only be sortable to a subsection of groups.

<div id="sortBlock">
    <div id="noSort class="itemBlock">
        <div class="item">
        <div class="item">
    </div>
    <div id="canSort" class="itemBlock">
        <div class="item">
        <div class="item">
    </div>
</div>

Items from noSort can sort anywhere. Items from canSort can only sort into other canSort blocks.

$("#sortBlock").sortable({
    items: "> div.itemBlock > .item"   // this makes sure only the sub items will be sortable
});

Then setting this rule after the init seemed to do the trick.

$("#sortBlock").sortable( "option", "items", "> div:not(#noSort) > .item");

Was trying to do it dynamically in the start/stop events, but this did the trick, not sure "why", so test well.

0

上一篇:

下一篇:

精彩评论

暂无评论...
验证码 换一张
取 消

最新问答

问答排行榜