Passed
Push — master ( cddcf6...1d3855 )
by Alexander
01:59
created

tcms/static/js/lib/tablednd.js (4 issues)

javascript_analysis.weak_equality

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