674124b7df5f6ed346d129958d9d884b0a493a65 tdreszer Wed Jun 1 16:45:10 2011 -0700 Painful work to stop leaking subtrack rows when dragging set. Temporarily checking in commented out debug code because of the pain to get here. diff --git src/hg/js/jquery.tablednd.js src/hg/js/jquery.tablednd.js index 37e53cf..af1251b 100644 --- src/hg/js/jquery.tablednd.js +++ src/hg/js/jquery.tablednd.js @@ -98,30 +98,31 @@ // This is bound to each matching table, set up the defaults and override with user options this.tableDnDConfig = jQuery.extend({ onDragStyle: null, onDropStyle: null, // Add in the default class for whileDragging onDragClass: "tDnD_whileDrag", onDrop: null, onDragStart: null, scrollAmount: 5, serializeRegexp: /[^\-]*$/, // The regular expression to use to trim row IDs serializeParamName: null, // If you want to specify another parameter name instead of the table ID dragHandle: null, // If you give the name of a class here, then only Cells with this class will be draggable dragObjects: [], // UCSC: Allows setting multiple rows to be dragged at one time downOffset: 0, // UCSC: Dragging set, then offset Y to bottom of set upOffset: 0, // UCSC: Dragging set, then offset Y to bottom of set + mouseMoving: false,// UCSC: Prevent overlapping calls to mouse move dragStartIndex : 0 }, options || {}); // Now make the rows draggable jQuery.tableDnD.makeDraggable(this); }); // Now we need to capture the mouse up and mouse move event // We can use bind so that we don't interfere with other event handlers jQuery(document) .bind('mousemove', jQuery.tableDnD.mousemove) .bind('mouseup', jQuery.tableDnD.mouseup); // Don't break the chain return this; }, @@ -248,131 +249,174 @@ ///////return {x:left, y:top}; return {x:left, y:top, height:eHeight}; ///////////// Height was added by tim because of tall tracks }, mousemove: function(ev) { if(jQuery.tableDnD == undefined) { jQuery(document) .unbind('mousemove')//, jQuery.tableDnD.mousemove); .unbind('mouseup');//, jQuery.tableDnD.mouseup); return; } if (jQuery.tableDnD.dragObject == null) { return; } + ////////// UCSC + if (jQuery.tableDnD.currentTable.mouseMoving == true) + return; + jQuery.tableDnD.currentTable.mouseMoving = true; + ////////// UCSC var dragObj = jQuery(jQuery.tableDnD.dragObject); var config = jQuery.tableDnD.currentTable.tableDnDConfig; var mousePos = jQuery.tableDnD.mouseCoords(ev); var y = mousePos.y - jQuery.tableDnD.mouseOffset.y; + ////////// UCSC added truncation and ignoring old zero + y = y.toPrecision(); + if (jQuery.tableDnD.oldY == 0) { + jQuery.tableDnD.oldY = y; + } + ////////// UCSC + //auto scroll the window var yOffset = window.pageYOffset; if (document.all) { // Windows version //yOffset=document.body.scrollTop; if (typeof document.compatMode != 'undefined' && document.compatMode != 'BackCompat') { yOffset = document.documentElement.scrollTop; } else if (typeof document.body != 'undefined') { yOffset=document.body.scrollTop; } } if (mousePos.y-yOffset < config.scrollAmount) { window.scrollBy(0, -config.scrollAmount); } else { var windowHeight = window.innerHeight ? window.innerHeight : document.documentElement.clientHeight ? document.documentElement.clientHeight : document.body.clientHeight; if (windowHeight-(mousePos.y-yOffset) < config.scrollAmount) { window.scrollBy(0, config.scrollAmount); } } - - if (y != jQuery.tableDnD.oldY) { + ///// UCSC if (y != jQuery.tableDnD.oldY) { + if (Math.abs(y - jQuery.tableDnD.oldY) > 8) { //// UCSC some minimal move before handling // work out if we're going up or down... var movingDown = y > jQuery.tableDnD.oldY; // update the old value ////// UCSC jQuery.tableDnD.oldY = y; // Do this below, only when rows have moved. // update the style to show we're dragging if (config.onDragClass) { ////// UCSC if (config.dragObjects.length > 1) config.dragObjects.addClass(config.onDragClass); else ////// UCSC dragObj.addClass(config.onDragClass); } else { ////// UCSC if (config.dragObjects.length > 1) config.css(config.onDragStyle); else ////// UCSC dragObj.css(config.onDragStyle); } // If we're over a row then move the dragged row to there so that the user sees the // effect dynamically var currentRow = jQuery.tableDnD.findDropTargetRow(dragObj, y); + ////// UCSC + // While dragObjects is the set, the order could vary from table order. Therefore us rowIndexes. + var rows = jQuery.tableDnD.currentTable.rows; + var firstDragRowIx = 9999; // Discover indexes + var lastDragRowIx = 0; + if (config.dragObjects.length > 1) { + for (var ix=0;ix < config.dragObjects.length;ix++) { + var thisIx = $( config.dragObjects[ix] ).attr('rowIndex'); + if (firstDragRowIx > thisIx) + firstDragRowIx = thisIx; + if (lastDragRowIx < thisIx) + lastDragRowIx = thisIx; + } if (movingDown) - currentRow = jQuery.tableDnD.findDropTargetRow(config.dragObjects[config.dragObjects.length - 1], y + config.downOffset); + currentRow = jQuery.tableDnD.findDropTargetRow(rows[lastDragRowIx], y + config.downOffset); else - currentRow = jQuery.tableDnD.findDropTargetRow(config.dragObjects[0], y + config.upOffset); + currentRow = jQuery.tableDnD.findDropTargetRow(rows[firstDragRowIx], y + config.upOffset); } ////// UCSC if (currentRow) { + ////// UCSC if (config.dragObjects.length > 1) { - if (movingDown && config.dragObjects[config.dragObjects.length - 1] != currentRow) { - try { // use try/catch because sometimes rows go missing when moving down - // can't just insert currentRow above, because there may be more than one row that needs to move up - //$( currentRow ).insertBefore( $( config.dragObjects[0] ) ); - var curRowIx = $( currentRow ).attr('rowIndex'); - if (curRowIx == (jQuery.tableDnD.currentTable.rows.length - 1)) { - // Even though this is method is bad on fast drags, - // getting to the end seems to only work on slow moves anyway. - // plus numerous other strateges failed to get this to work at all. - $( currentRow ).insertBefore( $( config.dragObjects[0] ) ); - } else - $(config.dragObjects).insertBefore( $(currentRow).next() ); - jQuery.tableDnD.oldY = y; - } - catch (err) { // just put them all back - for(var ix=0;ix < config.dragObjects.length; ix++) { - $(config.dragObjects[ix]).insertBefore( currentRow ); + var targetRowIx = $( currentRow ).attr('rowIndex'); + if (targetRowIx >= 0 && targetRowIx < rows.length) { + + if (movingDown) { // && config.dragObjects[config.dragObjects.length - 1] != currentRow) { + // A whole new tack: since movingUp never fails, always move target (and others) up + if ((lastDragRowIx - firstDragRowIx) == (config.dragObjects.length - 1) + && firstDragRowIx >= 0 + && lastDragRowIx < targetRowIx) { + var plusIx=0; + for(var ix=lastDragRowIx+1; ix <= targetRowIx; ix++) { + //try { // use try/catch because sometimes rows go missing when moving + $( rows[ix] ).insertBefore( $( rows[firstDragRowIx + plusIx] ) ); + plusIx++; + //} catch (err) { + // warn('movingDown: lastDragRowIx:'+lastDragRowIx+' targetRowIx:'+targetRowIx+' y:'+y+' oldY:'+jQuery.tableDnD.oldY+'<BR>' + err); + //} } + jQuery.tableDnD.oldY = y; + } //else + // warn('down blocked: targetRowIx:'+targetRowIx+' dragRows:'+firstDragRowIx+'-'+lastDragRowIx+' y:'+y+' oldY:'+jQuery.tableDnD.oldY); + + } else if (!movingDown) { // && config.dragObjects[0] != currentRow) { + if ((lastDragRowIx - firstDragRowIx) == (config.dragObjects.length - 1) + && firstDragRowIx >= 0 + && firstDragRowIx > targetRowIx) { + var plusIx=0; + for(var ix=firstDragRowIx; ix <= lastDragRowIx; ix++) { + //try { // use try/catch because sometimes rows go missing when moving + $(rows[ix]).insertBefore( rows[targetRowIx + plusIx] ); + plusIx++; + //} catch (err) { // just put them all back + // warn('movingUp: targetRowIx:'+targetRowIx+' dragRows:'+firstDragRowIx+'-'+lastDragRowIx+' y:'+y+' oldY:'+jQuery.tableDnD.oldY+'<BR>' + err); + //} } - } else if (!movingDown && config.dragObjects[0] != currentRow) { - $(config.dragObjects).insertBefore( currentRow ); jQuery.tableDnD.oldY = y; + } //else + // warn('up blocked: targetRowIx:'+targetRowIx+' dragRows:'+firstDragRowIx+'-'+lastDragRowIx+' y:'+y+' oldY:'+jQuery.tableDnD.oldY); } + } else + warn('blocked: targetRowIx:'+targetRowIx+' dragRows:'+firstDragRowIx+'-'+lastDragRowIx+' y:'+y+' oldY:'+jQuery.tableDnD.oldY); } else { ////// UCSC // TODO worry about what happens when there are multiple TBODIES if (movingDown && jQuery.tableDnD.dragObject != currentRow) { jQuery.tableDnD.dragObject.parentNode.insertBefore(jQuery.tableDnD.dragObject, currentRow.nextSibling); - jQuery.tableDnD.oldY = y; } else if (! movingDown && jQuery.tableDnD.dragObject != currentRow) { jQuery.tableDnD.dragObject.parentNode.insertBefore(jQuery.tableDnD.dragObject, currentRow); - jQuery.tableDnD.oldY = y; } + jQuery.tableDnD.oldY = y; } ////// UCSC } } + jQuery.tableDnD.currentTable.mouseMoving = false; ////////// UCSC return false; }, /** We're only worried about the y position really, because we can only move rows up and down */ findDropTargetRow: function(draggedRow, y) { var rows = jQuery.tableDnD.currentTable.rows; for (var i=0; i<rows.length; i++) { var row = rows[i]; var rowY = this.getPosition(row).y; var rowHeight = parseInt(row.offsetHeight)/2; if (row.offsetHeight == 0) { rowY = this.getPosition(row.firstChild).y; rowHeight = parseInt(row.firstChild.offsetHeight)/2; }