After updating to script.aculo.us 1.7.1, my drag and drop code stopped firing when the drag was finished. Normally, the onUpdate function will be called when the process is finished. Apparently, as Josh Wehner and the serialize docs will tell you, every LI in the list must have an ID following a given format in order for onUpdate to fire. But what if you don’t wish to follow that format?

The first solution comes with a giant disclaimer attached to it — it is a hack in every way imaginable, and is only interesting because it works. So be cautious when using it, and save it for those last resort situations. The idea is to add a hidden LI element onChange so that when onUpdate fires script.aculo.us will detect an alteration in the list. Here is how you can create the sortable:

Sortable.create("my-list",
    {onChange:sortableOnChangeHack,
     onUpdate:updatePositions});

And when the user drags one item over another item in the list, sortableOnChangeHack will be called.

function sortableOnChangeHack() {
    if(!$('sortHack')) new Insertion.Bottom('my-list', '<li id=sortHack" class="hide"></li>');
}

Only one LI is needed. We don’t have to add one on every change. The LI is also given a class of hide, which is custom to our own code but just applies a display:none rule. Finally, when the user has dropped the LI, the processing function will fire.

function updatePositions() {
    if($('sortHack')) Element.remove('sortHack');
    // Process anything you need to here
}

The first thing to do here is remove the hacked LI element, and then run the rest of the function as normal.

The obvious question is why resort to a situation like this? In my case, my own code was dependent on unique ID’s for all LI elements, and those ID’s conflicted with the script.aculo.us ones. This leads to the next solution. I believe there is a way to change the pattern that script.aculo.us is looking for. In dragdrop.js, there is the following line:

SERIALIZE_RULE: /^[^_\-](?:[A-Za-z0-9\-\_]*)[_](.*)$/

This variable controls the pattern that the code is looking for. For example, if you would like for your pattern to be LI-X, you can change it to look like this:

SERIALIZE_RULE: /^[^_\-][LI-](.*)$/

This works and causes the onUpdate to fire, but it is never a good idea to edit the source code of the actual library. The solution would be to have a member function that sets this rule, but I can’t seem to find it. Does it exist?

HTML Form Builder
Ryan Campbell

Forcing onUpdate with Sortables by Ryan Campbell

This entry was posted 4 years ago and was filed under Notebooks.
Comments are currently closed.

· 6 Comments! ·

  1. Tobie Langel · 4 years ago

    Hi Ryan, why don’t you just add:

    <

    pre> Sortable.SERIALIZE_RULE: /^[^_-]LI-$/

    <

    pre>

    to wherever you store your application-specific JavaScript code ?

  2. Tobie Langel · 4 years ago

    Oh god! that’s some pretty ruined markup. Here’s what I meant:

    Sortable.SERIALIZE_RULE = /^[^_\-][LI-](.*)$/
  3. Ryan Campbell · 4 years ago

    Haha, good call. I can’t believe I overlooked that. Good, everything is working as it should.

  4. Francois · 4 years ago

    Actually, there is a parameter for that:

    Sortable.create(sortable, { (…) format: /(.*)/, onUpdate: this.saveContainer });

  5. David G. Paul · 3 years ago

    I’ve also found that the behaviour of onChange has changed too.

    On a page where I’m using the Sortable’s onChange event, using 1.6.4 it fired once whilst dragging it. Now in 1.7.1 beta (both 1 and 2, not sure which version between 1.6.4 this it was changed either) I get it fire constantly as you move the mose.

  6. David G. Paul · 3 years ago

    Actually a colleague has now found the solution to the problem with onChange firing onmousemove instead of when the sortable changes….