JavaScript Page /Include/jquery.tablednd_0_5.js (VB.NET)
1: /**
2: * TableDnD plug-in for JQuery, allows you to drag and drop table rows
3: * You can set up various options to control how the system will work
4: * Copyright (c) Denis Howlett <denish@isocra.com>
5: * Licensed like jQuery, see http://docs.jquery.com/License.
6: *
7: * Configuration options:
8: *
9: * onDragStyle
10: * This is the style that is assigned to the row during drag. There are limitations to the styles that can be
11: * associated with a row (such as you can't assign a border--well you can, but it won't be
12: * displayed). (So instead consider using onDragClass.) The CSS style to apply is specified as
13: * a map (as used in the jQuery css(...) function).
14: * onDropStyle
15: * This is the style that is assigned to the row when it is dropped. As for onDragStyle, there are limitations
16: * to what you can do. Also this replaces the original style, so again consider using onDragClass which
17: * is simply added and then removed on drop.
18: * onDragClass
19: * This class is added for the duration of the drag and then removed when the row is dropped. It is more
20: * flexible than using onDragStyle since it can be inherited by the row cells and other content. The default
21: * is class is tDnD_whileDrag. So to use the default, simply customise this CSS class in your
22: * stylesheet.
23: * onDrop
24: * Pass a function that will be called when the row is dropped. The function takes 2 parameters: the table
25: * and the row that was dropped. You can work out the new order of the rows by using
26: * table.rows.
27: * onDragStart
28: * Pass a function that will be called when the user starts dragging. The function takes 2 parameters: the
29: * table and the row which the user has started to drag.
30: * onAllowDrop
31: * Pass a function that will be called as a row is over another row. If the function returns true, allow
32: * dropping on that row, otherwise not. The function takes 2 parameters: the dragged row and the row under
33: * the cursor. It returns a boolean: true allows the drop, false doesn't allow it.
34: * scrollAmount
35: * This is the number of pixels to scroll if the user moves the mouse cursor to the top or bottom of the
36: * window. The page should automatically scroll up or down as appropriate (tested in IE6, IE7, Safari, FF2,
37: * FF3 beta
38: * dragHandle
39: * This is the name of a class that you assign to one or more cells in each row that is draggable. If you
40: * specify this class, then you are responsible for setting cursor: move in the CSS and only these cells
41: * will have the drag behaviour. If you do not specify a dragHandle, then you get the old behaviour where
42: * the whole row is draggable.
43: *
44: * Other ways to control behaviour:
45: *
46: * Add class="nodrop" to any rows for which you don't want to allow dropping, and class="nodrag" to any rows
47: * that you don't want to be draggable.
48: *
49: * Inside the onDrop method you can also call $.tableDnD.serialize() this returns a string of the form
50: * <tableID>[]=<rowID1>&<tableID>[]=<rowID2> so that you can send this back to the server. The table must have
51: * an ID as must all the rows.
52: *
53: * Other methods:
54: *
55: * $("...").tableDnDUpdate()
56: * Will update all the matching tables, that is it will reapply the mousedown method to the rows (or handle cells).
57: * This is useful if you have updated the table rows using Ajax and you want to make the table draggable again.
58: * The table maintains the original configuration (so you don't have to specify it again).
59: *
60: * $("...").tableDnDSerialize()
61: * Will serialize and return the serialized string as above, but for each of the matching tables--so it can be
62: * called from anywhere and isn't dependent on the currentTable being set up correctly before calling
63: *
64: * Known problems:
65: * - Auto-scoll has some problems with IE7 (it scrolls even when it shouldn't), work-around: set scrollAmount to 0
66: *
67: * Version 0.2: 2008-02-20 First public version
68: * Version 0.3: 2008-02-07 Added onDragStart option
69: * Made the scroll amount configurable (default is 5 as before)
70: * Version 0.4: 2008-03-15 Changed the noDrag/noDrop attributes to nodrag/nodrop classes
71: * Added onAllowDrop to control dropping
72: * Fixed a bug which meant that you couldn't set the scroll amount in both directions
73: * Added serialize method
74: * Version 0.5: 2008-05-16 Changed so that if you specify a dragHandle class it doesn't make the whole row
75: * draggable
76: * Improved the serialize method to use a default (and settable) regular expression.
77: * Added tableDnDupate() and tableDnDSerialize() to be called when you are outside the table
78: */
79: jQuery.tableDnD = {
80: /** Keep hold of the current table being dragged */
81: currentTable : null,
82: /** Keep hold of the current drag object if any */
83: dragObject: null,
84: /** The current mouse offset */
85: mouseOffset: null,
86: /** Remember the old value of Y so that we don't do too much processing */
87: oldY: 0,
88:
89: /** Actually build the structure */
90: build: function(options) {
91: // Set up the defaults if any
92:
93: this.each(function() {
94: // This is bound to each matching table, set up the defaults and override with user options
95: this.tableDnDConfig = jQuery.extend({
96: onDragStyle: null,
97: onDropStyle: null,
98:                 // Add in the default class for whileDragging
99:                 onDragClass: "tDnD_whileDrag",
100: onDrop: null,
101: onDragStart: null,
102: scrollAmount: 5,
103:                 serializeRegexp: /[^\-]*$/, // The regular expression to use to trim row IDs
104:                 serializeParamName: null, // If you want to specify another parameter name instead of the table ID
105: dragHandle: null // If you give the name of a class here, then only Cells with this class will be draggable
106: }, options || {});
107: // Now make the rows draggable
108: jQuery.tableDnD.makeDraggable(this);
109: });
110:
111: // Now we need to capture the mouse up and mouse move event
112: // We can use bind so that we don't interfere with other event handlers
113: jQuery(document)
114: .bind('mousemove', jQuery.tableDnD.mousemove)
115: .bind('mouseup', jQuery.tableDnD.mouseup);
116:
117: // Don't break the chain
118: return this;
119: },
120:
121: /** This function makes all the rows on the table draggable apart from those marked as "NoDrag" */
122: makeDraggable: function(table) {
123: var config = table.tableDnDConfig;
124:         if (table.tableDnDConfig.dragHandle) {
125:             // We only need to add the event to the specified cells
126:             var cells = jQuery("td."+table.tableDnDConfig.dragHandle, table);
127:             cells.each(function() {
128:                 // The cell is bound to "this"
129: jQuery(this).mousedown(function(ev) {
130: jQuery.tableDnD.dragObject = this.parentNode;
131: jQuery.tableDnD.currentTable = table;
132: jQuery.tableDnD.mouseOffset = jQuery.tableDnD.getMouseOffset(this, ev);
133: if (config.onDragStart) {
134: // Call the onDrop method if there is one
135: config.onDragStart(table, this);
136: }
137: return false;
138: });
139:             })
140:         } else {
141:             // For backwards compatibility, we add the event to the whole row
142:      var rows = jQuery("tr", table); // get all the rows as a wrapped set
143:      rows.each(function() {
144:                 // Iterate through each row, the row is bound to "this"
145:                 var row = jQuery(this);
146:                 if (! row.hasClass("nodrag")) {
147:      row.mousedown(function(ev) {
148:      if (ev.target.tagName == "TD") {
149:      jQuery.tableDnD.dragObject = this;
150:      jQuery.tableDnD.currentTable = table;
151:      jQuery.tableDnD.mouseOffset = jQuery.tableDnD.getMouseOffset(this, ev);
152:      if (config.onDragStart) {
153:      // Call the onDrop method if there is one
154:      config.onDragStart(table, this);
155:      }
156:      return false;
157:      }
158:      }).css("cursor", "move"); // Store the tableDnD object
159:                 }
160:             });
161:         }
162:     },
163:
164:     updateTables: function() {
165:         this.each(function() {
166:             // this is now bound to each matching table
167:             if (this.tableDnDConfig) {
168:                 jQuery.tableDnD.makeDraggable(this);
169:             }
170:         })
171:     },
172:
173: /** Get the mouse coordinates from the event (allowing for browser differences) */
174: mouseCoords: function(ev){
175: if(ev.pageX || ev.pageY){
176: return {x:ev.pageX, y:ev.pageY};
177: }
178: return {
179: x:ev.clientX + document.body.scrollLeft - document.body.clientLeft,
180: y:ev.clientY + document.body.scrollTop - document.body.clientTop
181: };
182: },
183:
184: /** Given a target element and a mouse event, get the mouse offset from that element.
185: To do this we need the element's position and the mouse position */
186: getMouseOffset: function(target, ev) {
187: ev = ev || window.event;
188:
189: var docPos = this.getPosition(target);
190: var mousePos = this.mouseCoords(ev);
191: return {x:mousePos.x - docPos.x, y:mousePos.y - docPos.y};
192: },
193:
194: /** Get the position of an element by going up the DOM tree and adding up all the offsets */
195: getPosition: function(e){
196: var left = 0;
197: var top = 0;
198: /** Safari fix -- thanks to Luis Chato for this! */
199: if (e.offsetHeight == 0) {
200: /** Safari 2 doesn't correctly grab the offsetTop of a table row
201: this is detailed here:
202: http://jacob.peargrove.com/blog/2006/technical/table-row-offsettop-bug-in-safari/
203: the solution is likewise noted there, grab the offset of a table cell in the row - the firstChild.
204: note that firefox will return a text node as a first child, so designing a more thorough
205: solution may need to take that into account, for now this seems to work in firefox, safari, ie */
206: e = e.firstChild; // a table cell
207: }
208:
209: while (e.offsetParent){
210: left += e.offsetLeft;
211: top += e.offsetTop;
212: e = e.offsetParent;
213: }
214:
215: left += e.offsetLeft;
216: top += e.offsetTop;
217:
218: return {x:left, y:top};
219: },
220:
221: mousemove: function(ev) {
222: if (jQuery.tableDnD.dragObject == null) {
223: return;
224: }
225:
226: var dragObj = jQuery(jQuery.tableDnD.dragObject);
227: var config = jQuery.tableDnD.currentTable.tableDnDConfig;
228: var mousePos = jQuery.tableDnD.mouseCoords(ev);
229: var y = mousePos.y - jQuery.tableDnD.mouseOffset.y;
230: //auto scroll the window
231:      var yOffset = window.pageYOffset;
232:          if (document.all) {
233:      // Windows version
234:      //yOffset=document.body.scrollTop;
235:      if (typeof document.compatMode != 'undefined' &&
236:      document.compatMode != 'BackCompat') {
237:      yOffset = document.documentElement.scrollTop;
238:      }
239:      else if (typeof document.body != 'undefined') {
240:      yOffset=document.body.scrollTop;
241:      }
242:
243:      }
244:         
245:         if (mousePos.y-yOffset < config.scrollAmount) {
246:          window.scrollBy(0, -config.scrollAmount);
247:      } else {
248: var windowHeight = window.innerHeight ? window.innerHeight
249: : document.documentElement.clientHeight ? document.documentElement.clientHeight : document.body.clientHeight;
250: if (windowHeight-(mousePos.y-yOffset) < config.scrollAmount) {
251: window.scrollBy(0, config.scrollAmount);
252: }
253: }
254:
255:
256: if (y != jQuery.tableDnD.oldY) {
257: // work out if we're going up or down...
258: var movingDown = y > jQuery.tableDnD.oldY;
259: // update the old value
260: jQuery.tableDnD.oldY = y;
261: // update the style to show we're dragging
262:             if (config.onDragClass) {
263:                 dragObj.addClass(config.onDragClass);
264:             } else {
265:      dragObj.css(config.onDragStyle);
266:             }
267: // If we're over a row then move the dragged row to there so that the user sees the
268: // effect dynamically
269: var currentRow = jQuery.tableDnD.findDropTargetRow(dragObj, y);
270: if (currentRow) {
271: // TODO worry about what happens when there are multiple TBODIES
272: if (movingDown && jQuery.tableDnD.dragObject != currentRow) {
273: jQuery.tableDnD.dragObject.parentNode.insertBefore(jQuery.tableDnD.dragObject, currentRow.nextSibling);
274: } else if (! movingDown && jQuery.tableDnD.dragObject != currentRow) {
275: jQuery.tableDnD.dragObject.parentNode.insertBefore(jQuery.tableDnD.dragObject, currentRow);
276: }
277: }
278: }
279:
280: return false;
281: },
282:
283: /** We're only worried about the y position really, because we can only move rows up and down */
284: findDropTargetRow: function(draggedRow, y) {
285: var rows = jQuery.tableDnD.currentTable.rows;
286: for (var i=0; i<rows.length; i++) {
287: var row = rows[i];
288: var rowY = this.getPosition(row).y;
289: var rowHeight = parseInt(row.offsetHeight)/2;
290: if (row.offsetHeight == 0) {
291: rowY = this.getPosition(row.firstChild).y;
292: rowHeight = parseInt(row.firstChild.offsetHeight)/2;
293: }
294: // Because we always have to insert before, we need to offset the height a bit
295: if ((y > rowY - rowHeight) && (y < (rowY + rowHeight))) {
296: // that's the row we're over
297:                 // If it's the same as the current row, ignore it
298:                 if (row == draggedRow) {return null;}
299: var config = jQuery.tableDnD.currentTable.tableDnDConfig;
300: if (config.onAllowDrop) {
301: if (config.onAllowDrop(draggedRow, row)) {
302: return row;
303: } else {
304: return null;
305: }
306: } else {
307:                     // If a row has nodrop class, then don't allow dropping (inspired by John Tarr and Famic)
308: var nodrop = jQuery(row).hasClass("nodrop");
309: if (! nodrop) {
310: return row;
311: } else {
312: return null;
313: }
314: }
315: return row;
316: }
317: }
318: return null;
319: },
320:
321: mouseup: function(e) {
322: if (jQuery.tableDnD.currentTable && jQuery.tableDnD.dragObject) {
323: var droppedRow = jQuery.tableDnD.dragObject;
324: var config = jQuery.tableDnD.currentTable.tableDnDConfig;
325: // If we have a dragObject, then we need to release it,
326: // The row will already have been moved to the right place so we just reset stuff
327:             if (config.onDragClass) {
328:      jQuery(droppedRow).removeClass(config.onDragClass);
329:             } else {
330:      jQuery(droppedRow).css(config.onDropStyle);
331:             }
332: jQuery.tableDnD.dragObject = null;
333: if (config.onDrop) {
334: // Call the onDrop method if there is one
335: config.onDrop(jQuery.tableDnD.currentTable, droppedRow);
336: }
337: jQuery.tableDnD.currentTable = null; // let go of the table too
338: }
339: },
340:
341: serialize: function() {
342: if (jQuery.tableDnD.currentTable) {
343: return jQuery.tableDnD.serializeTable(jQuery.tableDnD.currentTable);
344: } else {
345: return "Error: No Table id set, you need to set an id on your table and every row";
346: }
347: },
348:
349:     serializeTable: function(table) {
350: var result = "";
351: var tableId = table.id;
352: var rows = table.rows;
353: for (var i=0; i<rows.length; i++) {
354: if (result.length > 0) result += "&";
355: var rowId = rows[i].id;
356: if (rowId && rowId && table.tableDnDConfig && table.tableDnDConfig.serializeRegexp) {
357: rowId = rowId.match(table.tableDnDConfig.serializeRegexp)[0];
358: }
359:
360: result += tableId + '[]=' + rowId;
361: }
362: return result;
363:     },
364:
365:     serializeTables: function() {
366: var result = "";
367: this.each(function() {
368:             // this is now bound to each matching table
369:             result += jQuery.tableDnD.serializeTable(this);
370:         });
371: return result;
372: }
373:
374: }
375:
376: jQuery.fn.extend(
377:     {
378:         tableDnD : jQuery.tableDnD.build,
379:         tableDnDUpdate : jQuery.tableDnD.updateTables,
380:         tableDnDSerialize: jQuery.tableDnD.serializeTables
381:     }
382: );

.NET Documentation Tool is © 2002 - 2009 Winnersh Triangle Web Solutions Limited.