Lasse
Lasse

Reputation: 29

problem with jquery sortable and guids

I have

<ul id="test-list" class="ui-sortable" >
   <li id="876e45a4-6a27-4f7b-95ca-9e2500f11801">text1</li>
   <li id="4df36ffb-561a-4eaa-9b1c-9e2500f16d6b">text2</li>
   <li id="cc4a57d5-1567-403c-888f-9e2500f1c171">text3</li>
</ul>

but $('#test-list').sortable('serialize'); does a string like this: 876e45a4-6a27-4f7b-95ca[]=9e2500f11801&79fbfdf7-e9b1-4e96-8e42[]=9e2400d2abb7&4df36ffb-561a-4eaa-9b1c[]

removing last 12 chars of id

Any ideas why?

Upvotes: 3

Views: 1495

Answers (4)

eclaude
eclaude

Reputation: 885

For RFC 4122 like 876e45a4-6a27-4f7b-95ca-9e2500f11801 you can add parameter.

$(this).sortable('serialize', {expression:(/(.+)[_](.+)/)})

Upvotes: 4

Xman82FTW
Xman82FTW

Reputation: 21

I was having the same issue. The way I solved it was by changing the view's code to replace the dash character with the empty string:

<div id="divItems">
@foreach (var item in Model)
{
    <div id="@string.Format("item_{0}", item.Id.ToString().Replace("-", string.Empty))">
        @item.Title
    </div>
}
</div>

Note: I used div instead of ul/li for my situation.

My javascript looks like this:

$("div#divItems").sortable({
    cursor: "move",
    update: function (event, ui) {
        var container = $(this);
        var sequence = container.sortable("serialize", { key: "Sequence" });
        $.post("@Url.Action("EditSequence")", sequence, function (data) {
            if (data.success) {
                container.fadeTo("normal", 0, function () {
                    container.fadeTo("normal", 1);
                });
            } else {
                alert(data.message);
            }
        });
    }
});

Note: I changed the key to 'Sequence' and the fadeTo() combo is used for visual feedback to the user that the sequence saved successfully.

My Controller Action method looks like this:

// POST: /Showcase/EditSequence?Sequence=<Guid List>
[Authorize]
[HttpPost]
public ActionResult EditSequence(List<Guid> Sequence)
{
    try
    {
        for (int i = 0; i < Sequence.Count; i++)
        {
            var item = repos.GetSingle(Sequence[i]);
            if (item != null)
            {
                item.Seq = (i + 1);
            }
        }

        repos.Save();

        return Json(new { success = true, message = "Sequence has been saved!" }, JsonRequestBehavior.DenyGet);
    }
    catch (Exception ex)
    {
        return Json(new { success = false, message = ex.Message }, JsonRequestBehavior.DenyGet);
    }
}

The model binder takes care of converting the Guid strings without the dashes into a List<Guid> bound to the Sequence parameter.

Upvotes: 2

T.J. Crowder
T.J. Crowder

Reputation: 1074989

Two things:

Sortable.serialize's IDs

Are you sure Sortable's serialize does what you're expecting it to do? According to the docs, it expects the ID of each sortable element to be in the form setname_number. The IDs are expected to have an underscore in them, but will fall back to using an = or -; from the docs:

It works by default by looking at the id of each item in the format 'setname_number', and it spits out a hash like "setname[]=number&setname[]=number".
...They must be in the form: "set_number" For example, a 3 element list with id attributes foo_1, foo_5, foo_2 will serialize to foo[]=1&foo[]=5&foo[]=2. You can use an underscore, equal sign or hyphen to separate the set and number. For example foo=1 or foo-1 or foo_1 all serialize to foo[]=1.

(My emphasis.) So not having seen an underscore (_), apparently it's falling back to using the last hyphen (-) it sees.

id format for use with CSS

Separately, id values for use with CSS cannot begin with a digit; from the spec:

In CSS, identifiers (including element names, classes, and IDs in selectors) can contain only the characters [a-zA-Z0-9] and ISO 10646 characters U+00A1 and higher, plus the hyphen (-) and the underscore (_); they cannot start with a digit, or a hyphen followed by a digit.

(These restrictions are not true for id in HTML, which just can't contain spaces and has to have at least one character if given, but CSS is more restrictive.)

Since you're using CSS selectors with jQuery, it would probably be best to ensure that the id attributes are valid CSS. (Perhaps you could preprocess them to be "G" followed by the GUID with the dashes converted to x, that sort of thing, so the IDs are G876e45a4x6a27x4f7bx95cax9e2500f11801 and the like.) Then you'll want to give them an underscore and suffix as per the above.

Upvotes: 5

Orbling
Orbling

Reputation: 20612

Changing it to $('#test-list').sortable('serialize').replace(/=\[\]/g, '-') works around the weird issue, but it must be some oddity in the jQuery UI code with the long IDs. I will look further.

Update

Right the offending code in jquery.ui.sortable.js in the serialize() routine is:

$(items).each(function() {
    var res = ($(o.item || this).attr(o.attribute || 'id') || '').match(o.expression || (/(.+)[-=_](.+)/));
    if(res) str.push((o.key || res[1]+'[]')+'='+(o.key && o.expression ? res[1] : res[2]));
});

This is deliberately functionality, it is detecting ids containing a dash (-), equals or underscore, and treating them as array values, left/right dividing array and key values. Perhaps use a bar | instead, or amend serialize() for your usage.

Upvotes: 1

Related Questions