diff --git a/core/misc/tabledrag.js b/core/misc/tabledrag.js index f578d4a..28560d0 100644 --- a/core/misc/tabledrag.js +++ b/core/misc/tabledrag.js @@ -120,10 +120,18 @@ Drupal.tableDrag = function (table, tableSettings) { // manipulate form elements directly, rather than using drag-and-drop.. self.initColumns(); - // Add mouse bindings to the document. The self variable is passed along + // Add event bindings to the document. The self variable is passed along // as event handlers do not have direct access to the tableDrag object. - $(document).bind('mousemove', function (event) { return self.dragRow(event, self); }); - $(document).bind('mouseup', function (event) { return self.dropRow(event, self); }); + if (!Modernizr.touch) { + $(document).bind('mousemove', function (event) { return self.dragRow(event, self); }); + $(document).bind('mouseup', function (event) { return self.dropRow(event, self); }); + } + + if (Modernizr.touch) { + $(document).bind('touchmove', function (event) { return self.dragRow(event.originalEvent.touches[0], self); }); + $(document).bind('touchend', function (event) { return self.dropRow(event.originalEvent.touches[0], self); }); + } + // React to localStorage event showing or hiding weight columns. $(window).bind('storage', $.proxy(function (e) { // Only react to 'Drupal.tableDrag.showWeight' value change. @@ -316,53 +324,23 @@ Drupal.tableDrag.prototype.makeDraggable = function (item) { $item.find('td:first').prepend(handle); } - // Add hover action for the handle. - handle.hover(function () { - self.dragObject === null ? $(this).addClass('tabledrag-handle-hover') : null; - }, function () { - self.dragObject === null ? $(this).removeClass('tabledrag-handle-hover') : null; - }); - - // Add the mousedown action for the handle. - handle.mousedown(function (event) { - event.preventDefault(); - // Create a new dragObject recording the event information. - self.dragObject = {}; - self.dragObject.initMouseOffset = self.getMouseOffset(item, event); - self.dragObject.initMouseCoords = self.mouseCoords(event); - if (self.indentEnabled) { - self.dragObject.indentMousePos = self.dragObject.initMouseCoords; - } - - // If there's a lingering row object from the keyboard, remove its focus. - if (self.rowObject) { - $(self.rowObject.element).find('a.tabledrag-handle').blur(); - } - - // Create a new rowObject for manipulation of this row. - self.rowObject = new self.row(item, 'mouse', self.indentEnabled, self.maxDepth, true); - - // Save the position of the table. - self.table.topY = $(self.table).offset().top; - self.table.bottomY = self.table.topY + self.table.offsetHeight; - - // Add classes to the handle and row. - $(this).addClass('tabledrag-handle-hover'); - $(item).addClass('drag'); - - // Set the document to use the move cursor during drag. - $('body').addClass('drag'); - if (self.oldRowElement) { - $(self.oldRowElement).removeClass('drag-previous'); - } + // Conditionally add the touchstart action for the handle. + if (Modernizr.touch) { + handle.on('touchstart', function (event) { + event.preventDefault(); + event = event.originalEvent.touches[0]; + self.dragStart(event, self, item); + }); + } - // Hack for Konqueror, prevent the blur handler from firing. - // Konqueror always gives links focus, even after returning false on mousedown. - self.safeBlur = false; + // Conditionally add the mousedown action for the handle. + if (!Modernizr.touch) { + handle.mousedown(function (event) { + event.preventDefault(); + self.dragStart(event, self, item); + }); - // Call optional placeholder function. - self.onDrag(); - }); + } // Prevent the anchor tag from jumping us to the top of the page. handle.click(function (e) { @@ -510,15 +488,45 @@ Drupal.tableDrag.prototype.makeDraggable = function (item) { }); }; +Drupal.tableDrag.prototype.dragStart = function (event, self, item) { + // Create a new dragObject recording the event information. + self.dragObject = {}; + self.dragObject.initOffset = self.getEventOffset(item, event); + self.dragObject.initEventCoords = self.eventCoords(event); + if (self.indentEnabled) { + self.dragObject.indentMousePos = self.dragObject.initEventCoords; + } + + // If there's a lingering row object from the keyboard, remove its focus. + if (self.rowObject) { + $(self.rowObject.element).find('a.tabledrag-handle').blur(); + } + + // Create a new rowObject for manipulation of this row. + self.rowObject = new self.row(item, 'mouse', self.indentEnabled, self.maxDepth, true); + + // Save the position of the table. + self.table.topY = $(self.table).offset().top; + self.table.bottomY = self.table.topY + self.table.offsetHeight; + + // Add classes to the handle and row. + $(item).addClass('drag'); + + // Set the document to use the move cursor during drag. + $('body').addClass('drag'); + if (self.oldRowElement) { + $(self.oldRowElement).removeClass('drag-previous'); + } +} + /** - * Mousemove event handler, bound to document. + * Event movement handler, bound to document. */ Drupal.tableDrag.prototype.dragRow = function (event, self) { if (self.dragObject) { - self.currentMouseCoords = self.mouseCoords(event); - - var y = self.currentMouseCoords.y - self.dragObject.initMouseOffset.y; - var x = self.currentMouseCoords.x - self.dragObject.initMouseOffset.x; + self.currentEventCoords = self.eventCoords(event); + var y = self.currentEventCoords.y - self.dragObject.initOffset.y; + var x = self.currentEventCoords.x - self.dragObject.initOffset.x; // Check for row swapping and vertical scrolling. if (y !== self.oldY) { @@ -526,7 +534,7 @@ Drupal.tableDrag.prototype.dragRow = function (event, self) { self.oldY = y; // Update the old value. // Check if the window should be scrolled (and how fast). - var scrollAmount = self.checkScroll(self.currentMouseCoords.y); + var scrollAmount = self.checkScroll(self.currentEventCoords.y); // Stop any current scrolling. clearInterval(self.scrollInterval); // Continue scrolling if the mouse has moved in the scroll direction. @@ -549,7 +557,7 @@ Drupal.tableDrag.prototype.dragRow = function (event, self) { // Similar to row swapping, handle indentations. if (self.indentEnabled) { - var xDiff = self.currentMouseCoords.x - self.dragObject.indentMousePos.x; + var xDiff = self.currentEventCoords.x - self.dragObject.indentMousePos.x; // Set the number of indentations the mouse has been moved left or right. var indentDiff = Math.round(xDiff / self.indentAmount * self.rtl); // Indent the row with our estimated diff, which may be further @@ -571,7 +579,7 @@ Drupal.tableDrag.prototype.dragRow = function (event, self) { Drupal.tableDrag.prototype.dropRow = function (event, self) { var droppedRow, $droppedRow; - // Drop row functionality shared between mouseup and blur events. + // Drop row functionality shared between mouseup, touchend, and blur events. if (self.rowObject !== null) { droppedRow = self.rowObject.element; $droppedRow = $(droppedRow); @@ -625,9 +633,9 @@ Drupal.tableDrag.prototype.dropRow = function (event, self) { }; /** - * Get the mouse coordinates from the event (allowing for browser differences). + * Get the coordinates from the event (allowing for browser differences). */ -Drupal.tableDrag.prototype.mouseCoords = function (event) { +Drupal.tableDrag.prototype.eventCoords = function (event) { if (event.pageX || event.pageY) { return { x: event.pageX, y: event.pageY }; } @@ -638,13 +646,13 @@ Drupal.tableDrag.prototype.mouseCoords = function (event) { }; /** - * Given a target element and a mouse event, get the mouse offset from that - * element. To do this we need the element's position and the mouse position. + * Given a target element and an event, get the event offset from that + * element. To do this we need the element's position and the target position. */ -Drupal.tableDrag.prototype.getMouseOffset = function (target, event) { +Drupal.tableDrag.prototype.getEventOffset = function (target, event) { var docPos = $(target).offset(); - var mousePos = this.mouseCoords(event); - return { x: mousePos.x - docPos.left, y: mousePos.y - docPos.top }; + var eventPos = this.eventCoords(event); + return { x: eventPos.x - docPos.left, y: eventPos.y - docPos.top }; }; /** @@ -903,7 +911,7 @@ Drupal.tableDrag.prototype.setScroll = function (scrollAmount) { this.scrollInterval = setInterval(function () { // Update the scroll values stored in the object. - self.checkScroll(self.currentMouseCoords.y); + self.checkScroll(self.currentEventCoords.y); var aboveTable = self.scrollY > self.table.topY; var belowTable = self.scrollY + self.windowHeight < self.table.bottomY; if (scrollAmount > 0 && belowTable || scrollAmount < 0 && aboveTable) { diff --git a/core/modules/system/system.base.css b/core/modules/system/system.base.css index a0b66e6..97a56e0 100644 --- a/core/modules/system/system.base.css +++ b/core/modules/system/system.base.css @@ -101,7 +101,9 @@ a.tabledrag-handle .handle { padding: 0.42em 0.5em; /* LTR */ width: 13px; } -a.tabledrag-handle-hover .handle { +a.tabledrag-handle:hover .handle, +a.tabledrag-handle:focus .handle, +.touch .draggable.drag a.tabledrag-handle { background-position: 6px -11px; } div.indentation { diff --git a/core/modules/system/system.module b/core/modules/system/system.module index 5a90e3e..6fa697c 100644 --- a/core/modules/system/system.module +++ b/core/modules/system/system.module @@ -1348,6 +1348,7 @@ function system_library_info() { ), 'dependencies' => array( array('system', 'jquery'), + array('system', 'modernizr'), array('system', 'drupal'), array('system', 'drupalSettings'), array('system', 'jquery.once'),