[BUGFIX] Decouple pasting from drag & drop handling 70/57970/3
authorAndreas Fernandez <a.fernandez@scripting-base.de>
Mon, 20 Aug 2018 17:25:15 +0000 (19:25 +0200)
committerMathias Brodala <mbrodala@pagemachine.de>
Wed, 22 Aug 2018 07:08:48 +0000 (09:08 +0200)
The "Paste" action now does not depend on the `DragDrop` anymore.
Previously, the `onDrop` event callback was called manually which is
wrong in that case, as the callback does far more calculations than
necessary when doing a simple paste action.

In the same run, the DragDrop module has been simplified, the module now
doesn't know anything about pasting content elements anymore.

Resolves: #85912
Releases: master
Change-Id: I3a8943e90a92c0ad4afec9e87091f9cd1878c34c
Reviewed-on: https://review.typo3.org/57970
Tested-by: TYPO3com <no-reply@typo3.com>
Reviewed-by: Markus Klein <markus.klein@typo3.org>
Reviewed-by: Manuel Selbach <manuel_selbach@yahoo.de>
Tested-by: Manuel Selbach <manuel_selbach@yahoo.de>
Reviewed-by: Mathias Brodala <mbrodala@pagemachine.de>
Tested-by: Mathias Brodala <mbrodala@pagemachine.de>
typo3/sysext/backend/Resources/Private/TypeScript/LayoutModule/DragDrop.ts
typo3/sysext/backend/Resources/Public/JavaScript/LayoutModule/DragDrop.js
typo3/sysext/backend/Resources/Public/JavaScript/LayoutModule/Paste.js

index 1418faa..7080c97 100644 (file)
@@ -170,12 +170,9 @@ class DragDrop {
     const newColumn = DragDrop.getColumnPositionForElement($droppableElement);
 
     $droppableElement.removeClass(DragDrop.dropPossibleHoverClass);
-    const $pasteAction = typeof $draggableElement === 'number';
 
     // send an AJAX requst via the AjaxDataHandler
-    const contentElementUid: number = $pasteAction === true ?
-      <number>$draggableElement :
-      parseInt((<JQuery>$draggableElement).data('uid'), 10);
+    const contentElementUid: number = parseInt((<JQuery>$draggableElement).data('uid'), 10);
 
     if (typeof(contentElementUid) === 'number' && contentElementUid > 0) {
       let parameters: Parameters = {};
@@ -213,27 +210,15 @@ class DragDrop {
           }
         };
         // TODO Make sure we actually have a JQuery object here, not only cast it
-        DragDrop.ajaxAction($droppableElement, <JQuery>$draggableElement, parameters, copyAction, $pasteAction);
+        DragDrop.ajaxAction($droppableElement, <JQuery>$draggableElement, parameters, copyAction);
       } else {
         parameters.data.tt_content[contentElementUid] = {
           colPos: colPos,
           sys_language_uid: language
         };
-        if ($pasteAction) {
-          parameters = {
-            CB: {
-              paste: 'tt_content|' + targetPid,
-              update: {
-                colPos: colPos,
-                sys_language_uid: language
-              }
-            }
-          };
-        } else {
-          parameters.cmd.tt_content[contentElementUid] = {move: targetPid};
-        }
+        parameters.cmd.tt_content[contentElementUid] = {move: targetPid};
         // fire the request, and show a message if it has failed
-        DragDrop.ajaxAction($droppableElement, <JQuery>$draggableElement, parameters, copyAction, $pasteAction);
+        DragDrop.ajaxAction($droppableElement, <JQuery>$draggableElement, parameters, copyAction);
       }
     }
   }
@@ -241,31 +226,29 @@ class DragDrop {
   /**
    * this method does the actual AJAX request for both, the move and the copy action.
    *
-   * @param $droppableElement
-   * @param $draggableElement
-   * @param parameters
-   * @param $copyAction
-   * @param $pasteAction
+   * @param {JQuery} $droppableElement
+   * @param {JQuery} $draggableElement
+   * @param {Parameters} parameters
+   * @param {boolean} copyAction
    * @private
    */
-  public static ajaxAction($droppableElement: JQuery, $draggableElement: JQuery, parameters: Parameters,
-                           $copyAction: boolean, $pasteAction: boolean): void {
+  public static ajaxAction($droppableElement: JQuery, $draggableElement: JQuery, parameters: Parameters, copyAction: boolean): void {
     DataHandler.process(parameters).done(function(result: ResponseInterface): void {
       if (result.hasErrors) {
         return;
       }
 
       // insert draggable on the new position
-      if (!$pasteAction) {
-        if (!$droppableElement.parent().hasClass(DragDrop.contentIdentifier.substring(1))) {
-          $draggableElement.detach().css({top: 0, left: 0})
-            .insertAfter($droppableElement.closest(DragDrop.dropZoneIdentifier));
-        } else {
-          $draggableElement.detach().css({top: 0, left: 0})
-            .insertAfter($droppableElement.closest(DragDrop.contentIdentifier));
-        }
+      if (!$droppableElement.parent().hasClass(DragDrop.contentIdentifier.substring(1))) {
+        $draggableElement.detach().css({top: 0, left: 0})
+          .insertAfter($droppableElement.closest(DragDrop.dropZoneIdentifier));
+      } else {
+        $draggableElement.detach().css({top: 0, left: 0})
+          .insertAfter($droppableElement.closest(DragDrop.contentIdentifier));
+      }
+      if (copyAction) {
+        self.location.reload(true);
       }
-      self.location.reload(true);
     });
   }
 
index ca04c14..c0cfd17 100644 (file)
@@ -10,4 +10,4 @@
  *
  * The TYPO3 project - inspiring people to share!
  */
-define(["require","exports","jquery","../AjaxDataHandler","jquery-ui/droppable"],function(e,t,n,o){"use strict";Object.defineProperty(t,"__esModule",{value:!0});var a=function(){function e(){}return e.initialize=function(){n(e.contentIdentifier).draggable({handle:e.dragHeaderIdentifier,scope:"tt_content",cursor:"move",distance:20,revert:"invalid",zIndex:100,start:function(t,o){e.onDragStart(n(t.target))},stop:function(t,o){e.onDragStop(n(t.target))}}),n(e.dropZoneIdentifier).droppable({accept:this.contentIdentifier,scope:"tt_content",tolerance:"pointer",over:function(t,o){e.onDropHoverOver(n(o.draggable),n(t.target))},out:function(t,o){e.onDropHoverOut(n(o.draggable),n(t.target))},drop:function(t,o){e.onDrop(n(o.draggable),n(t.target),t)}})},e.onDragStart=function(t){e.originalStyles=t.get(0).style.cssText,t.children(e.dragIdentifier).addClass("dragitem-shadow"),t.append('<div class="ui-draggable-copy-message">'+TYPO3.lang["dragdrop.copy.message"]+"</div>"),t.children(e.dropZoneIdentifier).addClass("drag-start"),t.closest(e.columnIdentifier).removeClass("active"),t.find(e.dropZoneIdentifier).hide(),n(e.dropZoneIdentifier).each(function(t,o){var a=n(o);a.parent().find(".t3js-toggle-new-content-element-wizard").length?a.addClass(e.validDropZoneClass):a.closest(e.contentIdentifier).find("> "+e.addContentIdentifier+", > > "+e.addContentIdentifier).show()})},e.onDragStop=function(t){t.children(e.dragIdentifier).removeClass("dragitem-shadow"),t.children(e.dropZoneIdentifier).removeClass("drag-start"),t.closest(e.columnIdentifier).addClass("active"),t.find(e.dropZoneIdentifier).show(),t.find(".ui-draggable-copy-message").remove(),t.get(0).style.cssText=e.originalStyles,n(e.dropZoneIdentifier+"."+e.validDropZoneClass).removeClass(e.validDropZoneClass)},e.onDropHoverOver=function(t,n){n.hasClass(e.validDropZoneClass)&&n.addClass(e.dropPossibleHoverClass)},e.onDropHoverOut=function(t,n){n.removeClass(e.dropPossibleHoverClass)},e.onDrop=function(t,n,o){var a=e.getColumnPositionForElement(n);n.removeClass(e.dropPossibleHoverClass);var r="number"==typeof t,i=!0===r?t:parseInt(t.data("uid"),10);if("number"==typeof i&&i>0){var s={},d=n.closest(e.contentIdentifier).data("uid"),l=0;l=void 0===d?parseInt(o.target.offsetParent.getAttribute("data-page"),10):0-parseInt(d,10);var c=parseInt(n.closest("[data-language-uid]").data("language-uid"),10),p=0;0!==l&&(p=a),s.cmd={tt_content:{}},s.data={tt_content:{}};var g=o&&o.originalEvent.ctrlKey||n.hasClass("t3js-paste-copy");g?(s.cmd.tt_content[i]={copy:{action:"paste",target:l,update:{colPos:p,sys_language_uid:c}}},e.ajaxAction(n,t,s,g,r)):(s.data.tt_content[i]={colPos:p,sys_language_uid:c},r?s={CB:{paste:"tt_content|"+l,update:{colPos:p,sys_language_uid:c}}}:s.cmd.tt_content[i]={move:l},e.ajaxAction(n,t,s,g,r))}},e.ajaxAction=function(t,n,a,r,i){o.process(a).done(function(o){o.hasErrors||(i||(t.parent().hasClass(e.contentIdentifier.substring(1))?n.detach().css({top:0,left:0}).insertAfter(t.closest(e.contentIdentifier)):n.detach().css({top:0,left:0}).insertAfter(t.closest(e.dropZoneIdentifier))),self.location.reload(!0))})},e.getColumnPositionForElement=function(e){var t=e.closest("[data-colpos]");return!(!t.length||"undefined"===t.data("colpos"))&&t.data("colpos")},e.contentIdentifier=".t3js-page-ce",e.dragIdentifier=".t3-page-ce-dragitem",e.dragHeaderIdentifier=".t3js-page-ce-draghandle",e.dropZoneIdentifier=".t3js-page-ce-dropzone-available",e.columnIdentifier=".t3js-page-column",e.validDropZoneClass="active",e.dropPossibleHoverClass="t3-page-ce-dropzone-possible",e.addContentIdentifier=".t3js-page-new-ce",e.originalStyles="",e}();t.default=a,n(a.initialize)});
\ No newline at end of file
+define(["require","exports","jquery","../AjaxDataHandler","jquery-ui/droppable"],function(e,t,n,o){"use strict";Object.defineProperty(t,"__esModule",{value:!0});var a=function(){function e(){}return e.initialize=function(){n(e.contentIdentifier).draggable({handle:e.dragHeaderIdentifier,scope:"tt_content",cursor:"move",distance:20,revert:"invalid",zIndex:100,start:function(t,o){e.onDragStart(n(t.target))},stop:function(t,o){e.onDragStop(n(t.target))}}),n(e.dropZoneIdentifier).droppable({accept:this.contentIdentifier,scope:"tt_content",tolerance:"pointer",over:function(t,o){e.onDropHoverOver(n(o.draggable),n(t.target))},out:function(t,o){e.onDropHoverOut(n(o.draggable),n(t.target))},drop:function(t,o){e.onDrop(n(o.draggable),n(t.target),t)}})},e.onDragStart=function(t){e.originalStyles=t.get(0).style.cssText,t.children(e.dragIdentifier).addClass("dragitem-shadow"),t.append('<div class="ui-draggable-copy-message">'+TYPO3.lang["dragdrop.copy.message"]+"</div>"),t.children(e.dropZoneIdentifier).addClass("drag-start"),t.closest(e.columnIdentifier).removeClass("active"),t.find(e.dropZoneIdentifier).hide(),n(e.dropZoneIdentifier).each(function(t,o){var a=n(o);a.parent().find(".t3js-toggle-new-content-element-wizard").length?a.addClass(e.validDropZoneClass):a.closest(e.contentIdentifier).find("> "+e.addContentIdentifier+", > > "+e.addContentIdentifier).show()})},e.onDragStop=function(t){t.children(e.dragIdentifier).removeClass("dragitem-shadow"),t.children(e.dropZoneIdentifier).removeClass("drag-start"),t.closest(e.columnIdentifier).addClass("active"),t.find(e.dropZoneIdentifier).show(),t.find(".ui-draggable-copy-message").remove(),t.get(0).style.cssText=e.originalStyles,n(e.dropZoneIdentifier+"."+e.validDropZoneClass).removeClass(e.validDropZoneClass)},e.onDropHoverOver=function(t,n){n.hasClass(e.validDropZoneClass)&&n.addClass(e.dropPossibleHoverClass)},e.onDropHoverOut=function(t,n){n.removeClass(e.dropPossibleHoverClass)},e.onDrop=function(t,n,o){var a=e.getColumnPositionForElement(n);n.removeClass(e.dropPossibleHoverClass);var r=parseInt(t.data("uid"),10);if("number"==typeof r&&r>0){var i={},s=n.closest(e.contentIdentifier).data("uid"),d=0;d=void 0===s?parseInt(o.target.offsetParent.getAttribute("data-page"),10):0-parseInt(s,10);var l=parseInt(n.closest("[data-language-uid]").data("language-uid"),10),c=0;0!==d&&(c=a),i.cmd={tt_content:{}},i.data={tt_content:{}};var p=o&&o.originalEvent.ctrlKey||n.hasClass("t3js-paste-copy");p?(i.cmd.tt_content[r]={copy:{action:"paste",target:d,update:{colPos:c,sys_language_uid:l}}},e.ajaxAction(n,t,i,p)):(i.data.tt_content[r]={colPos:c,sys_language_uid:l},i.cmd.tt_content[r]={move:d},e.ajaxAction(n,t,i,p))}},e.ajaxAction=function(t,n,a,r){o.process(a).done(function(o){o.hasErrors||(t.parent().hasClass(e.contentIdentifier.substring(1))?n.detach().css({top:0,left:0}).insertAfter(t.closest(e.contentIdentifier)):n.detach().css({top:0,left:0}).insertAfter(t.closest(e.dropZoneIdentifier)),r&&self.location.reload(!0))})},e.getColumnPositionForElement=function(e){var t=e.closest("[data-colpos]");return!(!t.length||"undefined"===t.data("colpos"))&&t.data("colpos")},e.contentIdentifier=".t3js-page-ce",e.dragIdentifier=".t3-page-ce-dragitem",e.dragHeaderIdentifier=".t3js-page-ce-draghandle",e.dropZoneIdentifier=".t3js-page-ce-dropzone-available",e.columnIdentifier=".t3js-page-column",e.validDropZoneClass="active",e.dropPossibleHoverClass="t3-page-ce-dropzone-possible",e.addContentIdentifier=".t3js-page-new-ce",e.originalStyles="",e}();t.default=a,n(a.initialize)});
\ No newline at end of file
index c1d7146..3f1834b 100644 (file)
  * based on jQuery UI
  */
 define(['jquery',
-  'TYPO3/CMS/Backend/LayoutModule/DragDrop',
+  'TYPO3/CMS/Backend/AjaxDataHandler',
   'TYPO3/CMS/Backend/Modal',
   'TYPO3/CMS/Backend/Severity'
-], function($, DragDrop, Modal, Severity) {
+], function($, DataHandler, Modal, Severity) {
   'use strict';
 
   /**
@@ -29,7 +29,8 @@ define(['jquery',
    * @exports TYPO3/CMS/Backend/LayoutModule/Paste
    */
   var Paste = {
-    openedPopupWindow: []
+    openedPopupWindow: [],
+    elementIdentifier: '.t3js-page-ce'
   };
 
   /**
@@ -63,7 +64,7 @@ define(['jquery',
         });
       }
     });
-  }
+  };
 
   /**
    * generates the paste into / paste after modal
@@ -89,7 +90,7 @@ define(['jquery',
           btnClass: 'btn-' + Severity.getCssClass(severity),
           trigger: function() {
             Modal.currentModal.trigger('modal-dismiss');
-            DragDrop.onDrop($element.data('content'), $element, null);
+            Paste.execute($element);
           }
         }
       ];
@@ -109,7 +110,7 @@ define(['jquery',
           btnClass: 'btn-' + Severity.getCssClass(severity),
           trigger: function() {
             Modal.currentModal.trigger('modal-dismiss');
-            DragDrop.onDrop($element.data('content'), $element, null);
+            Paste.execute($element);
           }
         }
       ];
@@ -121,7 +122,55 @@ define(['jquery',
     } else {
       Modal.show(title, content, severity, buttons);
     }
-  }
+  };
+
+  /**
+   * @param {jQuery} $element
+   * @returns number
+   */
+  Paste.determineColumn = function($element) {
+    const $columnContainer = $element.closest('[data-colpos]');
+    if ($columnContainer.length && $columnContainer.data('colpos') !== 'undefined') {
+      return $columnContainer.data('colpos');
+    }
+
+    return 0;
+  };
+
+  /**
+   * Send an AJAX requst via the AjaxDataHandler
+   *
+   * @param {jQuery} $element
+   */
+  Paste.execute = function($element) {
+    const colPos = Paste.determineColumn($element);
+    const closestElement = $element.closest(Paste.elementIdentifier);
+    const targetFound = closestElement.data('uid');
+    let targetPid;
+    if (typeof targetFound === 'undefined') {
+      targetPid = parseInt(closestElement.data('page'), 10);
+    } else {
+      targetPid = 0 - parseInt(targetFound, 10);
+    }
+    const language = parseInt($element.closest('[data-language-uid]').data('language-uid'), 10);
+    const parameters = {
+      CB: {
+        paste: 'tt_content|' + targetPid,
+        update: {
+          colPos: colPos,
+          sys_language_uid: language
+        }
+      }
+    };
+
+    DataHandler.process(parameters).done(function(result) {
+      if (result.hasErrors) {
+        return;
+      }
+
+      window.location.reload(true);
+    });
+  };
 
   $(Paste.initialize);
   return Paste;