| 12
 3
 4
 5
 6
 7
 8
 9
 10
 11
 12
 13
 14
 15
 16
 17
 18
 19
 20
 21
 22
 23
 24
 25
 26
 27
 28
 29
 30
 31
 32
 33
 34
 35
 36
 37
 38
 39
 40
 41
 42
 43
 44
 45
 46
 47
 48
 49
 50
 51
 52
 53
 54
 55
 56
 57
 58
 59
 60
 61
 62
 63
 64
 65
 66
 67
 68
 69
 70
 71
 72
 73
 74
 75
 76
 77
 78
 79
 80
 81
 82
 83
 84
 85
 86
 87
 88
 89
 90
 91
 92
 93
 94
 95
 96
 97
 98
 99
 100
 101
 102
 103
 104
 105
 106
 107
 108
 109
 110
 111
 112
 113
 114
 115
 116
 117
 118
 119
 120
 121
 122
 123
 124
 125
 126
 127
 128
 129
 130
 131
 132
 133
 134
 135
 136
 137
 138
 139
 140
 141
 142
 143
 144
 145
 146
 147
 148
 149
 150
 151
 152
 153
 154
 155
 156
 157
 158
 159
 160
 161
 162
 163
 164
 165
 166
 167
 168
 169
 170
 171
 172
 173
 174
 175
 176
 177
 178
 179
 180
 181
 182
 183
 184
 185
 
 |  
var currenttable = null;
 
document.onmousemove = function(ev){
    if (currenttable && currenttable.dragObject) {
        ev   = ev || window.event;
        var mousePos = currenttable.mouseCoords(ev);
        var y = mousePos.y - currenttable.mouseOffset.y;
        if (y != currenttable.oldY) {
            // work out if we're going up or down...
            var movingDown = y > currenttable.oldY;
            // update the old value
            currenttable.oldY = y;
            // update the style to show we're dragging
            currenttable.dragObject.style.backgroundColor = "#eee";
            // If we're over a cell then move the dragged cell to there so that the user sees the
            // effect dynamically
            var currentCell = currenttable.findDropTargetCell(y);
            if (currentCell) {
                if (movingDown && currenttable.dragObject != currentCell) {
                    currenttable.dragObject.parentNode.insertBefore(currenttable.dragObject, currentCell.nextSibling);
                } else if (! movingDown && currenttable.dragObject != currentCell) {
                    currenttable.dragObject.parentNode.insertBefore(currenttable.dragObject, currentCell);
                }
            }
        }
 
        return false;
    }
}
 
// Similarly for the mouseup
document.onmouseup   = function(ev){
    if (currenttable && currenttable.dragObject) {
        var droppedCell = currenttable.dragObject;
        // If we have a dragObject, then we need to release it,
        // The cell will already have been moved to the right place so we just reset stuff
        droppedCell.style.backgroundColor = 'transparent';
        currenttable.dragObject   = null;
        // And then call the onDrop method in case anyone wants to do any post processing
        currenttable.onDrop(currenttable.table, droppedCell);
        currenttable = null; // let go of the table too
    }
}
 
 
/** get the source element from an event in a way that works for IE and Firefox and Safari
 * @param evt the source event for Firefox (but not IE--IE uses window.event) */
function getEventSource(evt) {
    if (window.event) {
        evt = window.event; // For IE
        return evt.srcElement;
    } else {
        return evt.target; // For Firefox
    }
}
 
/**
 * Encapsulate table Drag and Drop in a class. We'll have this as a Singleton
 * so we don't get scoping problems.
 */
function TableDnD() {
    /** Keep hold of the current drag object if any */
    this.dragObject = null;
    /** The current mouse offset */
    this.mouseOffset = null;
    /** The current table */
    this.table = null;
    /** Remember the old value of Y so that we don't do too much processing */
    this.oldY = 0;
 
    /** Initialise the drag and drop by capturing mouse move events */
    this.init = function(table) {
        this.table = table;
        var rows = table.tBodies[0].rows; //getElementsByTagName("td")
 
		for (var j=0; j<rows.length;j++) {
			var cells = table.tBodies[0].rows[j].cells;
			for (var i=0; i<cells.length; i++) {
				// John Tarr: added to ignore cells that I've added the NoDnD attribute to (Category and Header cells)
				var nodrag = cells[i].getAttribute("NoDrag")
				if (nodrag == null || nodrag == "undefined") { //There is no NoDnD attribute on cells I want to drag
					this.makeDraggable(cells[i]);
				}
			}
		}
	}
 
    /** This function is called when you drop a cell, so redefine it in your code
        to do whatever you want, for example use Ajax to update the server */
    this.onDrop = function(table, droppedCell) {
        // Do nothing for now
    }
 
	/** Get the position of an element by going up the DOM tree and adding up all the offsets */
    this.getPosition = function(e){
        var left = 0;
        var top  = 0;
 
		/** Safari fix -- thanks to Luis Chato for this! */
		if (e.offsetHeight == 0) {
			/** Safari 2 doesn't correctly grab the offsetTop of a table cell
			    this is detailed here:
			    http://jacob.peargrove.com/blog/2006/technical/table-cell-offsettop-bug-in-safari/
			    the solution is likewise noted there, grab the offset of a table cell in the cell - the firstChild.
			    note that firefox will return a text node as a first child, so designing a more thorough
			    solution may need to take that into account, for now this seems to work in firefox, safari, ie */
			e = e.firstChild; // a table cell
		}
 
        while (e.offsetParent){
            left += e.offsetLeft;
            top  += e.offsetTop;
		     e     = e.offsetParent;
        }
 
        left += e.offsetLeft;
		top  += e.offsetTop;
 
        return {x:left, y:top};
    }
 
	/** Get the mouse coordinates from the event (allowing for browser differences) */
    this.mouseCoords = function(ev){
        if(ev.pageX || ev.pageY){
            return {x:ev.pageX, y:ev.pageY};
        }
        return {
            x:ev.clientX + document.body.scrollLeft - document.body.clientLeft,
			y:ev.clientY + document.body.scrollTop  - document.body.clientTop
 
        };
    }
 
	/** 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 */
    this.getMouseOffset = function(target, ev){
        ev = ev || window.event;
 
        var docPos    = this.getPosition(target);
        var mousePos  = this.mouseCoords(ev);
        return {x:mousePos.x - docPos.x, y:mousePos.y - docPos.y};
    }
 
	/** Take an item and add an onmousedown method so that we can make it draggable */
    this.makeDraggable = function(item) {
        if(!item) return;
        var self = this; // Keep the context of the TableDnd inside the function
        item.onmousedown = function(ev) {
            // Need to check to see if we are an input or not, if we are an input, then
            // return true to allow normal processing
            var target = getEventSource(ev);
            if (target.tagName == 'INPUT' || target.tagName == 'SELECT') return true;
            currenttable = self;
            self.dragObject  = this;
            self.mouseOffset = self.getMouseOffset(this, ev);
            return false;
        }
        item.style.cursor = "move";
    }
 
    /** We're only worried about the y position really, because we can only move cells up and down */
    this.findDropTargetCell = function(y) {
        var rows = this.table.tBodies[0].rows;
		for (var j=0; j<rows.length;j++) {
			var cells = this.table.tBodies[0].rows[j].cells;
			for (var i=0; i<cells.length; i++) {
				var cell = cells[i];
				// John Tarr added to ignore cells that I've added the NoDnD attribute to (Header cells)
				var nodrop = cell.getAttribute("NoDrop");
				if (nodrop == null || nodrop == "undefined") {  //There is no NoDnD attribute on cells I want to drag
					var cellY    = this.getPosition(cell).y;
					var cellHeight = parseInt(cell.offsetHeight)/2;
 
					// Because we always have to insert before, we need to offset the height a bit
					if ((y > cellY - cellHeight) && (y < (cellY + cellHeight))) {
						// that's the cell we're over
						return cell;
					}
				}
			}
		}
		return null;
	}
} | 
Partager