5

I am making use of the jQuery UI sortable interaction and Jeditable. The idea being that a user can reorder elements and affect the content of those elements. What I am running into is that the onblur event that I have Jeditable setup to listen for is being swallowed by the jQuery sortable listener.

A user can click on a Jeditable element and that element becomes editable, but when they click away if they click on an li that is sortable the onblur event is ignored. The event is not ignored if they click outside the li. How can I make Jeditable aware of the blur event when they click inside an li?

Here's a jsFiddle illustrating the problem

HTML Markup

<ul class="elementlist">
    <li id="elementSk_10">
        <span class="editable-element" id="10">TEXT!</span>
    </li>
    <li id="elementSk_33">
        <span class="editable-element" id="33">Some text</span>
    </li>
</ul>

Jeditable

$('.editable-element').editable('http://jsfiddle.net/echo/jsonp/', {
    onblur: 'submit',
    width: 250,
    indicator: 'Saving...'
});

jQuery UI Sortable

$(".elementlist").sortable({
    update: function(event, ui) {
        var elementSerialized = $(this).sortable('serialize');
        $.post('http://jsfiddle.net/echo/jsonp/', {
            elementSk: $(this).sortable('serialize')
        });
    }
});​

Edit: In an attempt to clarify what's going on let me give a step by step walkthrough accompanied by screenshots.

  1. Click Some Text
  2. Click on li containing TEXT!
  3. Release click on TEXT!

screenshot of clicking on Some Text screenshot of clicking on li TEXT!

At this point I haven't reordered anything. Clicking on the li and releasing hasn't triggered the onblur for Jeditable. I would like the simple act of clicking away to trigger the onblur. If I do not wire up sortable this is how it works. I have to believe somehow the click on the li is being swallowed by sortable.


Here's another example with reordering but still no onblur.

  1. Click Some Text
  2. Click on li containing TEXT!
  3. Move TEXT! below Some Text
  4. Release hold on TEXT!

screenshot of clicking on Some Text screenshot of clicking on li TEXT! screenshot of release of li containing TEXT!

After reordering the elements and releasing the li containing TEXT! the onblur isn't captured. The elements are in a new order but the Some Text is still in an editable state.

All of that said here is what I would expect to happen:
Clicking on anything outside of a field currently being edited should cause the onblur of Jeditable to fire. Which is exactly what happens if jQuery sortable isn't wired up. When jQuery sortable is wired up to cause the onblur behavior I have to click outside of the sortable list elements.

ahsteele
  • 26,243
  • 28
  • 134
  • 248
  • FireFox for Windows, and I'm either not understanding or not able to reproduce (using your fiddle). If I click the LI to edit and click elsewhere, it triggers (as you say it will). If I click the LI to edit and click directly to another LI to edit, it triggers (which I believe you indicated would fail). – Greg Pettit Mar 08 '12 at 20:07
  • @GregPettit what I mean is that yeah I can move the other `li` but it doesn't cause the element being edit to save. So the onblur is essentially ignored. Clear as mud? – ahsteele Mar 08 '12 at 20:37
  • Pretty much. ;-) Try a 1.2.3. step-by step description of what to do. ;-) Here's what I just tried: 1.click LI to make it editable 2.click OTHER LI and drag it to rearrange order 3. release mouse-click. Result: re-ordered but first LI is still the editable one AND the onblur has triggered. – Greg Pettit Mar 08 '12 at 20:47
  • @GregPettit I added clarification to the question and I hope it helps. As a note I've tested in Chrome 17 and Firefox 10 and have the same behavior in both browsers. – ahsteele Mar 08 '12 at 21:18
  • Y'know, I think you explained it fine all along and I'm just not that sharp. I'm seeing the sortable's onblur triggering, not the jeditable's. Which is EXACTLY what you've said ALL ALONG! So sorry. – Greg Pettit Mar 09 '12 at 02:44

2 Answers2

4

Dug into Jeditable source code with the intention of modifying it. In reading came across some undocumented event hooks which made all the difference:

var onedit   = settings.onedit   || function() { }; 
var onsubmit = settings.onsubmit || function() { };
var onreset  = settings.onreset  || function() { };

Making use of these I am able to disable and then reenable the sortable:

var disableSortable = function(settings, self) {
    $(".elementlist").sortable('disable');
};

var enableSortable = function(settings, self) {
    $(".elementlist").sortable('enable');
};

$('.editable-element').editable('http://jsfiddle.net/echo/jsonp/', {
    onblur: 'submit',
    width: 250,
    indicator: 'Saving...',
    onedit: disableSortable,
    onsubmit: enableSortable,
    onreset: enableSortable
});

$(".elementlist").sortable({
    update: function(event, ui) {
        var elementSerialized = $(this).sortable('serialize');
        $.post('http://jsfiddle.net/echo/jsonp/', {
            elementSk: $(this).sortable('serialize')
        });
    }
});​

I have to reenable on both reset and submit for cases when the user presses ESC; which resets the form rather than submitting it. Here's a jsFiddle showing a working implementation of disabling the sortables and then reenabling them.

I don't love this solution, but it's good enough for now. I'd prefer to not have the onblur get swallowed by the jQuery UI sortable. To fix that though will require a lot more code spelunking than I feel like doing right now.

ahsteele
  • 26,243
  • 28
  • 134
  • 248
0

This isn't meant to be a definitive answer and I'm not gunning for the "accepted" here... just too much text for a comment.

I do believe you are correct in your first guess-- the event is getting swallowed. If you look at the sortable API, you can see that it expands upon onblur, subdividing the events into a series of more granular events that can have callbacks of their own. I wouldn't be surprised in the least if digging into that code shows that the original event is prevented from bubbling up by something possibly as simple as preventDefault or returnFalse in sortable's own event handler logic.

Or, it could be that when you are dragging the sortable element, you are dragging a clone of some sort, a visual copy of the LI that doesn't carry any actual event handlers. That's just a thought... again, comment space is just too limited.

Can't seem to load the fiddle right now either so I can't muck around and prove any concepts, but I wonder if you could directly intervene with the sortable handlers to intentionally cause blur on the element? Or better yet, figure out which jEditable function is triggered on blur, and bypass the blurring to trigger that function at the end of the sort function.

Greg Pettit
  • 10,749
  • 5
  • 53
  • 72
  • Found a [workable solution](http://stackoverflow.com/a/9640685/61654). Thanks for the back and forth! – ahsteele Mar 09 '12 at 20:41