to your HTML.
- Add class="draggable" to any table you might like to reorder.
- Drag the headers around to reorder them.
This is code was based on:
- Stuart Langridge's SortTable (kryogenix.org/code/browser/sorttable)
- Mike Hall's draggable class (http://www.brainjar.com/dhtml/drag/)
- A discussion of permuting table columns on comp.lang.javascript
Licensed under the MIT license.
*/
// Here's the notice from Mike Hall's draggable script:
//*****************************************************************************
// Do not remove this notice.
//
// Copyright 2001 by Mike Hall.
// See http://www.brainjar.com for terms of use.
//*****************************************************************************
dragtable = {
// How far should the mouse move before it's considered a drag, not a click?
dragRadius2: 100,
setMinDragDistance: function(x) {
dragtable.dragRadius2 = x * x;
},
// How long should cookies persist? (in days)
cookieDays: 365,
setCookieDays: function(x) {
dragtable.cookieDays = x;
},
// Determine browser and version.
// TODO: eliminate browser sniffing except where it's really necessary.
Browser: function() {
var ua, s, i;
this.isIE = false;
this.isNS = false;
this.version = null;
ua = navigator.userAgent;
s = "MSIE";
if ((i = ua.indexOf(s)) >= 0) {
this.isIE = true;
this.version = parseFloat(ua.substr(i + s.length));
return;
}
s = "Netscape6/";
if ((i = ua.indexOf(s)) >= 0) {
this.isNS = true;
this.version = parseFloat(ua.substr(i + s.length));
return;
}
// Treat any other "Gecko" browser as NS 6.1.
s = "Gecko";
if ((i = ua.indexOf(s)) >= 0) {
this.isNS = true;
this.version = 6.1;
return;
}
},
browser: null,
// Detect all draggable tables and attach handlers to their headers.
init: function() {
// Don't initialize twice
if (arguments.callee.done) return;
arguments.callee.done = true;
if (_dgtimer) clearInterval(_dgtimer);
if (!document.createElement || !document.getElementsByTagName) return;
dragtable.dragObj.zIndex = 0;
dragtable.browser = new dragtable.Browser();
forEach(document.getElementsByTagName('table'), function(table) {
if (table.className.search(/\bdraggable\b/) != -1) {
dragtable.makeDraggable(table);
}
});
},
// The thead business is taken straight from sorttable.
makeDraggable: function(table) {
if (table.getElementsByTagName('thead').length == 0) {
the = document.createElement('thead');
the.appendChild(table.rows[0]);
table.insertBefore(the,table.firstChild);
}
// Safari doesn't support table.tHead, sigh
if (table.tHead == null) {
table.tHead = table.getElementsByTagName('thead')[0];
}
var headers = table.tHead.rows[0].cells;
for (var i = 0; i < headers.length; i++) {
headers[i].onmousedown = dragtable.dragStart;
}
// Replay reorderings from cookies if there are any.
if (dragtable.cookiesEnabled() && table.id &&
table.className.search(/\bforget-ordering\b/) == -1) {
dragtable.replayDrags(table);
}
},
// Global object to hold drag information.
dragObj: new Object(),
// Climb up the DOM until there's a tag that matches.
findUp: function(elt, tag) {
do {
if (elt.nodeName && elt.nodeName.search(tag) != -1)
return elt;
} while (elt = elt.parentNode);
return null;
},
// clone an element, copying its style and class.
fullCopy: function(elt, deep) {
var new_elt = elt.cloneNode(deep);
new_elt.className = elt.className;
forEach(elt.style,
function(value, key, object) {
if (value == null) return;
if (typeof(value) == "string" && value.length == 0) return;
new_elt.style[key] = elt.style[key];
});
return new_elt;
},
eventPosition: function(event) {
var x, y;
if (dragtable.browser.isIE) {
x = window.event.clientX + document.documentElement.scrollLeft
+ document.body.scrollLeft;
y = window.event.clientY + document.documentElement.scrollTop
+ document.body.scrollTop;
return {x: x, y: y};
}
return {x: event.pageX, y: event.pageY};
},
// Determine the position of this element on the page. Many thanks to Magnus
// Kristiansen for help making this work with "position: fixed" elements.
absolutePosition: function(elt, stopAtRelative) {
var ex = 0, ey = 0;
do {
var curStyle = dragtable.browser.isIE ? elt.currentStyle
: window.getComputedStyle(elt, '');
var supportFixed = !(dragtable.browser.isIE &&
dragtable.browser.version < 7);
if (stopAtRelative && curStyle.position == 'relative') {
break;
} else if (supportFixed && curStyle.position == 'fixed') {
// Get the fixed el's offset
ex += parseInt(curStyle.left, 10);
ey += parseInt(curStyle.top, 10);
// Compensate for scrolling
ex += document.body.scrollLeft;
ey += document.body.scrollTop;
// End the loop
break;
} else {
ex += elt.offsetLeft;
ey += elt.offsetTop;
}
} while (elt = elt.offsetParent);
return {x: ex, y: ey};
},
// MouseDown handler -- sets up the appropriate mousemove/mouseup handlers
// and fills in the global dragtable.dragObj object.
dragStart: function(event, id) {
var el;
var x, y;
var dragObj = dragtable.dragObj;
var browser = dragtable.browser;
if (browser.isIE)
dragObj.origNode = window.event.srcElement;
else
dragObj.origNode = event.target;
var pos = dragtable.eventPosition(event);
// Drag the entire table cell, not just the element that was clicked.
dragObj.origNode = dragtable.findUp(dragObj.origNode, /T[DH]/);
// Since a column header can't be dragged directly, duplicate its contents
// in a div and drag that instead.
// TODO: I can assume a tHead...
var table = dragtable.findUp(dragObj.origNode, "TABLE");
dragObj.table = table;
dragObj.startCol = dragtable.findColumn(table, pos.x);
if (dragObj.startCol == -1) return;
var new_elt = dragtable.fullCopy(table, false);
new_elt.style.margin = '0';
// Copy the entire column
var copySectionColumn = function(sec, col) {
var new_sec = dragtable.fullCopy(sec, false);
forEach(sec.rows, function(row) {
var cell = row.cells[col];
var new_tr = dragtable.fullCopy(row, false);
if (row.offsetHeight) new_tr.style.height = row.offsetHeight + "px";
var new_td = dragtable.fullCopy(cell, true);
if (cell.offsetWidth) new_td.style.width = cell.offsetWidth + "px";
new_tr.appendChild(new_td);
new_sec.appendChild(new_tr);
});
return new_sec;
};
// First the heading
if (table.tHead) {
new_elt.appendChild(copySectionColumn(table.tHead, dragObj.startCol));
}
forEach(table.tBodies, function(tb) {
new_elt.appendChild(copySectionColumn(tb, dragObj.startCol));
});
if (table.tFoot) {
new_elt.appendChild(copySectionColumn(table.tFoot, dragObj.startCol));
}
var obj_pos = dragtable.absolutePosition(dragObj.origNode, true);
new_elt.style.position = "absolute";
new_elt.style.left = obj_pos.x + "px";
new_elt.style.top = obj_pos.y + "px";
new_elt.style.width = dragObj.origNode.offsetWidth + "px";
new_elt.style.height = dragObj.origNode.offsetHeight + "px";
new_elt.style.opacity = 0.7;
// Hold off adding the element until this is clearly a drag.
dragObj.addedNode = false;
dragObj.tableContainer = dragObj.table.parentNode || document.body;
dragObj.elNode = new_elt;
// Save starting positions of cursor and element.
dragObj.cursorStartX = pos.x;
dragObj.cursorStartY = pos.y;
dragObj.elStartLeft = parseInt(dragObj.elNode.style.left, 10);
dragObj.elStartTop = parseInt(dragObj.elNode.style.top, 10);
if (isNaN(dragObj.elStartLeft)) dragObj.elStartLeft = 0;
if (isNaN(dragObj.elStartTop)) dragObj.elStartTop = 0;
// Update element's z-index.
dragObj.elNode.style.zIndex = ++dragObj.zIndex;
// Capture mousemove and mouseup events on the page.
if (browser.isIE) {
document.attachEvent("onmousemove", dragtable.dragMove);
document.attachEvent("onmouseup", dragtable.dragEnd);
window.event.cancelBubble = true;
window.event.returnValue = false;
} else {
document.addEventListener("mousemove", dragtable.dragMove, true);
document.addEventListener("mouseup", dragtable.dragEnd, true);
event.preventDefault();
}
},
// Move the floating column header with the mouse
// TODO: Reorder columns as the mouse moves for a more interactive feel.
dragMove: function(event) {
var x, y;
var dragObj = dragtable.dragObj;
// Get cursor position with respect to the page.
var pos = dragtable.eventPosition(event);
var dx = dragObj.cursorStartX - pos.x;
var dy = dragObj.cursorStartY - pos.y;
if (!dragObj.addedNode && dx * dx + dy * dy > dragtable.dragRadius2) {
dragObj.tableContainer.insertBefore(dragObj.elNode, dragObj.table);
dragObj.addedNode = true;
}
// Move drag element by the same amount the cursor has moved.
var style = dragObj.elNode.style;
style.left = (dragObj.elStartLeft + pos.x - dragObj.cursorStartX) + "px";
style.top = (dragObj.elStartTop + pos.y - dragObj.cursorStartY) + "px";
if (dragtable.browser.isIE) {
window.event.cancelBubble = true;
window.event.returnValue = false;
} else {
event.preventDefault();
}
},
// Stop capturing mousemove and mouseup events.
// Determine which (if any) column we're over and shuffle the table.
dragEnd: function(event) {
if (dragtable.browser.isIE) {
document.detachEvent("onmousemove", dragtable.dragMove);
document.detachEvent("onmouseup", dragtable.dragEnd);
} else {
document.removeEventListener("mousemove", dragtable.dragMove, true);
document.removeEventListener("mouseup", dragtable.dragEnd, true);
}
// If the floating header wasn't added, the mouse didn't move far enough.
var dragObj = dragtable.dragObj;
if (!dragObj.addedNode) {
return;
}
dragObj.tableContainer.removeChild(dragObj.elNode);
// Determine whether the drag ended over the table, and over which column.
var pos = dragtable.eventPosition(event);
var table_pos = dragtable.absolutePosition(dragObj.table);
if (pos.y < table_pos.y ||
pos.y > table_pos.y + dragObj.table.offsetHeight) {
return;
}
var targetCol = dragtable.findColumn(dragObj.table, pos.x);
if (targetCol != -1 && targetCol != dragObj.startCol) {
dragtable.moveColumn(dragObj.table, dragObj.startCol, targetCol);
if (dragObj.table.id && dragtable.cookiesEnabled() &&
dragObj.table.className.search(/\bforget-ordering\b/) == -1) {
dragtable.rememberDrag(dragObj.table.id, dragObj.startCol, targetCol);
}
}
},
// Which column does the x value fall inside of? x should include scrollLeft.
findColumn: function(table, x) {
var header = table.tHead.rows[0].cells;
for (var i = 0; i < header.length; i++) {
//var left = header[i].offsetLeft;
var pos = dragtable.absolutePosition(header[i]);
//if (left <= x && x <= left + header[i].offsetWidth) {
if (pos.x <= x && x <= pos.x + header[i].offsetWidth) {
return i;
}
}
return -1;
},
// Move a column of table from start index to finish index.
// Based on the "Swapping table columns" discussion on comp.lang.javascript.
// Assumes there are columns at sIdx and fIdx
moveColumn: function(table, sIdx, fIdx) {
var row, cA;
var i=table.rows.length;
while (i--){
row = table.rows[i]
var x = row.removeChild(row.cells[sIdx]);
if (fIdx < row.cells.length) {
row.insertBefore(x, row.cells[fIdx]);
} else {
row.appendChild(x);
}
}
// For whatever reason, sorttable tracks column indices this way.
// Without a manual update, clicking one column will sort on another.
var headrow = table.tHead.rows[0].cells;
for (var i=0; i
API Name Cumulative Time(ms) % of Total Time # of Calls Avg Time(ms) Max Time(ms) Min Time(ms)
clEnqueueReadBuffer 100469.22316 94.39770 21 4784.24872 10246.61089 0.00126 clBuildProgram 5942.19600 5.58310 1 5942.19600 5942.19600 5942.19600 clCreateCommandQueue 17.40373 0.01635 1 17.40373 17.40373 17.40373 clEnqueueNDRangeKernel 1.95404 0.00184 11 0.17764 1.83537 0.00463 clEnqueueMapBuffer 0.72264 0.00068 5 0.14453 0.45335 0.06108 clEnqueueWriteBuffer 0.23948 0.00023 43 0.00557 0.02312 0.00080 clGetPlatformInfo 0.03365 0.00003 2 0.01683 0.03224 0.00141 clCreateProgramWithSource 0.02371 0.00002 1 0.02371 0.02371 0.02371 clGetDeviceInfo 0.01595 0.00001 4 0.00399 0.01361 0.00052 clCreateBuffer 0.01036 0.00001 5 0.00207 0.00416 0.00105 clGetProgramBuildInfo 0.00875 0.00001 1 0.00875 0.00875 0.00875 clCreateContext 0.00802 0.00001 1 0.00802 0.00802 0.00802 clGetDeviceIDs 0.00553 0.00001 1 0.00553 0.00553 0.00553 clCreateKernel 0.00393 0.00000 1 0.00393 0.00393 0.00393 clSetKernelArg 0.00075 0.00000 5 0.00015 0.00044 0.00006 clGetKernelWorkGroupInfo 0.00071 0.00000 1 0.00071 0.00071 0.00071