Please see #452678: Data loss when using tabledrag to re-order items for a CCK text field using tinymce/CKEditor for a fuller description of the problem. That issue is specifically for wysiwyg, but the problem is a generic issue for iframes within draggable rows. When a row is swapped, the action of moving it within the dom causes reload of iframe, which potentially has several problems, the most annoying one that I've come across being in the context of the wysiwyg module using tinymce as the editor.

To properly fix this within wysiwyg, it would be ideal if there was a way to add a listener to the before row swap and after row swap events. Those listeners could implement specific solutions, such as detaching/attaching editors, but the specifics of those listeners is beyond the scope of this issue. What I'm asking for in this issue is for there to be *some way* by which to register those listeners.

Specifically, I'm asking for some event/hook/function to get called at the beginning of Drupal.tableDrag.prototype.row.prototype.swap, and at the end. Perhaps this.onSwap() is sufficient for the end, I'm not sure, except as far as I can tell, there's no easy way to register an onSwap for every row without clobbering an existing onSwap(). But I confess to not really understanding the architecture behind tabledrag.js.

As an alternate to making this specific enhancement to Drupal.tableDrag.prototype.row.prototype.swap, if the jquery aop plugin were included in core (the way jquery.form.js is), that would also address my needs. However, unless that plugin is in core, I don't think the wysiwyg module will want to use it.

Basically, what I'm asking for boils down to this: for D6, I needed to create the wysiwygcck module in order to not have the tinymce editor break after a tabledrag row swap. The relevant code from that module is:

/**
 * Extend tabledrag.js's default row swapping behavior to take into account
 * that wysiwyg editors are usually in an iframe, and iframes get reloaded when moved
 * in the dom.
 */
if (Drupal.tableDrag) {
  jQuery.aop.around({target: Drupal.tableDrag.prototype.row.prototype, method: 'swap'}, function(invocation) {
    // TODO: What's the proper way to handle situation where this.group has
    // multiple items?
    if (this.group.length > 1) {
      return invocation.proceed();
    }
    
    // Get the editor instances in the row being dragged. If there aren't any, let tabledrag's
    // default implementation proceed.
    var position = invocation.arguments[0];
    var referenceRow = invocation.arguments[1];
    var thisRow = this.group[0];
    var instances = Drupal.wysiwygcck.getInstances(thisRow);
    if (!instances) {
      return invocation.proceed();
    }
    
    // If thisRow is the same as referenceRow, then nothing will happen during a swap.
    // However, letting the default swap behavior run will result in the editors' iframes
    // being reloaded and messed up, so instead, we just force nothing to happen.
    if (thisRow == referenceRow) {
      return;
    }
    
    // If we reached here, it means we need to let tabledrag swap the rows. However,
    // if the editors have iframes, they'll probably get messed up by the swap, 
    // so we want to detach the editors before the swap, and reattach them after the swap.
    for (var id in instances) {
      Drupal.wysiwygDetach(thisRow, instances[id]);
    };
    result = invocation.proceed();
    for (var id in instances) {
      Drupal.wysiwygAttach(thisRow, instances[id]);
    };
    
    return result;
  });
}

For D7, I would like this functionality to be part of the wysiwyg module rather than an add-on module, but I don't think the jquery aop approach would be considered acceptable unless the drupal community decides that we want jquery aop as part of core. So I'm asking for us to either make jquery aop part of core, or for a change to tabledrag.js so that jquery aop isn't needed for this.

Thanks!

Comments

sun’s picture

That's basically the same as #561726: ajax.js and tabledrag.js need to implement Drupal.detachBehaviors(), just not about ajax.js.

effulgentsia’s picture

Title: Provide hook for before/after tabledrag row swap (needed for wysiwyg) » tabledrag.js does not implement Drupal.detachBehaviors()
Category: task » bug
Status: Active » Needs review
StatusFileSize
new3.03 KB
new662 bytes

Thanks sun! Given that, here's the patch.

I'm also attaching a tester module. @sun, feel free to use it as a starting point for a tester of #561726: ajax.js and tabledrag.js need to implement Drupal.detachBehaviors(). I won't have time before code-freeze to help with that issue, but if it's still unresolved in a couple weeks, I'll be able to help then.

The tester module, iframesrc, creates a field and widget. The widget presents an iframe that can be navigated. The field stores the value of the last url visited in that iframe. I doubt this is a useful feature, but it tests the same issue that occurs in wysiwyg: namely how do you keep information that's within an iframe synchronized with a different element that is outside the iframe that is used for storing the value of the field instance.

Here's the test that's relevant for this issue:

  1. Enable the iframesrc module
  2. Add a iframesrc field (number of values = unlimited) to a content type
  3. Go to the node creation for for that type
  4. Add another item for the iframesrc field, so that there are two, so that you can rearrange their order with tabledrag
  5. Each of the two items shows an iframe with a starting src of the site home page. Now navigate on each of them to a different url.
  6. Drag one of them above/below the other one to trigger a row swap and observe what happens

Without this patch, after a row swap, the iframe is reloaded with its initial src. With this patch, the iframe is reloaded with the url it was on prior to the row swap.

Status: Needs review » Needs work

The last submitted patch failed testing.

sun’s picture

Issue tags: +API clean-up

Introducing a new tag for feature freeze: API clean-up.

sun’s picture

Issue tags: +D7 API clean-up

Tagging absolutely critical clean-ups for D7. Do not touch this tag. Please either help with this or one of the other patches having this tag.

effulgentsia’s picture

Status: Needs work » Needs review

Patch #2 still works fine for me. Want to see what testbot thinks.

effulgentsia’s picture

StatusFileSize
new3.01 KB

Updated tester module. See #2 for what it does.

effulgentsia’s picture

Status: Needs review » Closed (duplicate)
gisle’s picture

Issue tags: -D7 API clean-up

Official tag is "API clean-up" - https://www.drupal.org/node/1207020