diff --git a/misc/tabledrag.js b/misc/tabledrag.js index fed674c..2358eec 100644 --- a/misc/tabledrag.js +++ b/misc/tabledrag.js @@ -104,10 +104,16 @@ 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 (('ontouchstart' in window) || window.DocumentTouch && document instanceof DocumentTouch) { + $(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); }); + } + else { + $(document).bind('mousemove', function (event) { return self.dragRow(event, self); }); + $(document).bind('mouseup', function (event) { return self.dropRow(event, self); }); + } }; /** @@ -266,73 +272,33 @@ Drupal.tableDrag.prototype.makeDraggable = function (item) { $('td:first', item).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) { - // 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) { - $('a.tabledrag-handle', self.rowObject.element).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'); - } - - // Hack for IE6 that flickers uncontrollably if select lists are moved. - if (navigator.userAgent.indexOf('MSIE 6.') != -1) { - $('select', this.table).css('display', 'none'); - } - - // Hack for Konqueror, prevent the blur handler from firing. - // Konqueror always gives links focus, even after returning false on mousedown. - self.safeBlur = false; - - // Call optional placeholder function. - self.onDrag(); - return false; - }); + if (('ontouchstart' in window) || window.DocumentTouch && document instanceof DocumentTouch) { + handle.bind('touchstart', function (event) { + event.preventDefault(); + event = event.originalEvent.touches[0]; + self.dragStart(event, self, item); + }); + } + else { + handle.mousedown(function (event) { + event.preventDefault(); + self.dragStart(event, self, item); + }); + } // Prevent the anchor tag from jumping us to the top of the page. handle.click(function () { return false; }); - // Similar to the hover event, add a class when the handle is focused. + // Set blur cleanup when a handle is focused. handle.focus(function () { - $(this).addClass('tabledrag-handle-hover'); self.safeBlur = true; }); - // Remove the handle class on blur and fire the same function as a mouseup. + // On blur, fire the same function as a touchend/mouseup. This is used to + // update values after a row has been moved through the keyboard support. handle.blur(function (event) { - $(this).removeClass('tabledrag-handle-hover'); if (self.rowObject && self.safeBlur) { self.dropRow(event, self); } @@ -460,14 +426,55 @@ Drupal.tableDrag.prototype.makeDraggable = function (item) { }; /** - * Mousemove event handler, bound to document. + * Pointer event initiator, creates drag object and information. + * + * @param jQuery.Event event + * The event object that trigger the drag. + * @param Drupal.tableDrag self + * The drag handle. + * @param DOM item + * The item that that is being dragged. + */ +Drupal.tableDrag.prototype.dragStart = function (event, self, item) { + // Create a new dragObject recording the pointer information. + self.dragObject = {}; + self.dragObject.initOffset = self.getPointerOffset(item, event); + self.dragObject.initPointerCoords = self.pointerCoords(event); + if (self.indentEnabled) { + self.dragObject.indentPointerPos = self.dragObject.initPointerCoords; + } + + // 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, 'pointer', 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'); + } +} + +/** + * Pointer 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.currentPointerCoords = self.pointerCoords(event); + var y = self.currentPointerCoords.y - self.dragObject.initOffset.y; + var x = self.currentPointerCoords.x - self.dragObject.initOffset.x; // Check for row swapping and vertical scrolling. if (y != self.oldY) { @@ -475,7 +482,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.currentPointerCoords.y); // Stop any current scrolling. clearInterval(self.scrollInterval); // Continue scrolling if the mouse has moved in the scroll direction. @@ -498,14 +505,14 @@ 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; - // Set the number of indentations the mouse has been moved left or right. + var xDiff = self.currentPointerCoords.x - self.dragObject.indentPointerPos.x; + // Set the number of indentations the pointer 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 // restricted according to the rows around this row. var indentChange = self.rowObject.indent(indentDiff); - // Update table and mouse indentations. - self.dragObject.indentMousePos.x += self.indentAmount * indentChange * self.rtl; + // Update table and pointer indentations. + self.dragObject.indentPointerPos.x += self.indentAmount * indentChange * self.rtl; self.indentCount = Math.max(self.indentCount, self.rowObject.indents); } @@ -514,11 +521,10 @@ Drupal.tableDrag.prototype.dragRow = function (event, self) { }; /** - * Mouseup event handler, bound to document. - * Blur event handler, bound to drag handle for keyboard support. + * Pointerup behaviour. */ Drupal.tableDrag.prototype.dropRow = function (event, self) { - // Drop row functionality shared between mouseup and blur events. + // Drop row functionality. if (self.rowObject != null) { var droppedRow = self.rowObject.element; // The row is already in the right place so we just release it. @@ -556,9 +562,8 @@ Drupal.tableDrag.prototype.dropRow = function (event, self) { self.rowObject = null; } - // Functionality specific only to mouseup event. + // Functionality specific only to pointerup events. if (self.dragObject != null) { - $('.tabledrag-handle', droppedRow).removeClass('tabledrag-handle-hover'); self.dragObject = null; $('body').removeClass('drag'); @@ -572,9 +577,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.pointerCoords = function (event) { if (event.pageX || event.pageY) { return { x: event.pageX, y: event.pageY }; } @@ -585,13 +590,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 a pointer 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) { - var docPos = $(target).offset(); - var mousePos = this.mouseCoords(event); - return { x: mousePos.x - docPos.left, y: mousePos.y - docPos.top }; +Drupal.tableDrag.prototype.getPointerOffset = function (target, event) { + var docPos = $(target).offset(); + var pointerPos = this.pointerCoords(event); + return { x: pointerPos.x - docPos.left, y: pointerPos.y - docPos.top }; }; /** @@ -837,7 +842,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.currentPointerCoords.y); var aboveTable = self.scrollY > self.table.topY; var belowTable = self.scrollY + self.windowHeight < self.table.bottomY; if (scrollAmount > 0 && belowTable || scrollAmount < 0 && aboveTable) {