f15adfb05205342c8821a6a227b08c7933678e4c
[Packages/TYPO3.CMS.git] / typo3 / sysext / backend / Resources / Public / JavaScript / LayoutModule / DragDrop.js
1 /*
2 * This file is part of the TYPO3 CMS project.
3 *
4 * It is free software; you can redistribute it and/or modify it under
5 * the terms of the GNU General Public License, either version 2
6 * of the License, or any later version.
7 *
8 * For the full copyright and license information, please read the
9 * LICENSE.txt file that was distributed with this source code.
10 *
11 * The TYPO3 project - inspiring people to share!
12 */
13
14 /**
15 * this JS code does the drag+drop logic for the Layout module (Web => Page)
16 * based on jQuery UI
17 */
18 define(['jquery', 'jquery-ui/sortable'], function ($) {
19
20 var DragDrop = {
21 contentIdentifier: '.t3js-page-ce',
22 dragIdentifier: '.t3js-page-ce-draghandle',
23 dropZoneAvailableIdentifier: '.t3js-page-ce-dropzone-available',
24 dropPossibleClass: 't3-page-ce-dropzone-possible',
25 sortableItemsIdentifier: '.t3js-page-ce-sortable',
26 columnIdentifier: '.t3js-page-column',
27 columnHolderIdentifier: '.t3js-page-columns',
28 addContentIdentifier: '.t3js-page-new-ce',
29 langClassPrefix: '.t3js-sortable-lang-'
30 };
31
32 /**
33 * initializes Drag+Drop for all content elements on the page
34 */
35 DragDrop.initialize = function() {
36 $('td[data-language-uid]').each(function() {
37 var connectWithClassName = DragDrop.langClassPrefix + $(this).data('language-uid');
38 $(connectWithClassName).sortable({
39 items: DragDrop.sortableItemsIdentifier,
40 connectWith: connectWithClassName,
41 handle: DragDrop.dragIdentifier,
42 distance: 20,
43 cursor: 'move',
44 helper: 'clone',
45 placeholder: DragDrop.dropPossibleClass,
46 tolerance: 'pointer',
47 start: function(e, ui) {
48 DragDrop.onSortStart($(this), ui);
49 },
50 stop: function(e, ui) {
51 DragDrop.onSortStop($(this), ui);
52 },
53 change: function(e, ui) {
54 DragDrop.onSortChange($(this), ui);
55 },
56 update: function(e, ui) {
57 if (this === ui.item.parent()[0]) {
58 DragDrop.onSortUpdate($(this), ui);
59 }
60 }
61 }).disableSelection();
62 });
63 };
64
65 /**
66 * Called when an item is about to be moved
67 */
68 DragDrop.onSortStart = function($container, ui) {
69 var $item = $(ui.item),
70 $helper = $(ui.helper),
71 $placeholder = $(ui.placeholder);
72
73 $placeholder.height($item.height() - $helper.find(DragDrop.addContentIdentifier).height());
74 DragDrop.changeDropzoneVisibility($container, $item);
75
76 // show all dropzones, except the own
77 $helper.find(DragDrop.dropZoneAvailableIdentifier).removeClass('active');
78 $container.parents(DragDrop.columnHolderIdentifier).find(DragDrop.addContentIdentifier).hide();
79 };
80
81 /**
82 * Called when the sorting stopped
83 */
84 DragDrop.onSortStop = function($container, ui) {
85 var $allColumns = $container.parents(DragDrop.columnHolderIdentifier);
86 $allColumns.find(DragDrop.addContentIdentifier).show();
87 $allColumns.find(DragDrop.dropZoneAvailableIdentifier + '.active').removeClass('active');
88 };
89
90 /**
91 * Called when the index of the element in the sortable list has changed
92 */
93 DragDrop.onSortChange = function($container, ui) {
94 var $placeholder = $(ui.placeholder);
95 DragDrop.changeDropzoneVisibility($container, $placeholder);
96 };
97
98 DragDrop.changeDropzoneVisibility = function($container, $subject) {
99 var $prev = $subject.prev(':visible'),
100 droppableClassName = DragDrop.langClassPrefix + $container.data('language-uid');
101
102 if ($prev.length === 0) {
103 $prev = $subject.prevUntil(':visible').last().prev();
104 }
105 $container.parents(DragDrop.columnHolderIdentifier).find(droppableClassName).find(DragDrop.contentIdentifier + ':not(.ui-sortable-helper)').not($prev).find(DragDrop.dropZoneAvailableIdentifier).addClass('active');
106 $prev.find(DragDrop.dropZoneAvailableIdentifier + '.active').removeClass('active');
107 };
108
109 /**
110 * Called when the new position of the element gets stored
111 */
112 DragDrop.onSortUpdate = function($container, ui) {
113 var $selectedItem = $(ui.item),
114 contentElementUid = parseInt($selectedItem.data('uid'));
115
116 // send an AJAX requst via the AjaxDataHandler
117 if (contentElementUid > 0) {
118 var parameters = {};
119 // add the information about a possible column position change
120 parameters['data'] = {tt_content: {}};
121 parameters['data']['tt_content'][contentElementUid] = {colPos: parseInt($container.data('colpos'))};
122 }
123
124 var targetContentElementUid = $selectedItem.prev().data('uid');
125 // the item was moved to the top of the colPos, so the page ID is used here
126 if (typeof targetContentElementUid === 'undefined') {
127 // the actual page is needed
128 targetContentElementUid = parseInt($container.find(DragDrop.contentIdentifier).first().data('page'));
129 } else {
130 // the negative value of the content element after where it should be moved
131 targetContentElementUid = parseInt(targetContentElementUid) * -1;
132 }
133
134 parameters['cmd'] = {tt_content: {}};
135 parameters['cmd']['tt_content'][contentElementUid] = {move: targetContentElementUid};
136 // fire the request, and show a message if it has failed
137 require(['TYPO3/CMS/Backend/AjaxDataHandler'], function(DataHandler) {
138 DataHandler.process(parameters).done(function(result) {
139 if (result.hasErrors) {
140 $container.sortable('cancel');
141 }
142 });
143 });
144 };
145
146 /**
147 * initialize function
148 */
149 return function() {
150 DragDrop.initialize();
151 return DragDrop;
152 }();
153 });