鼠标拖动表单特效
<html>
<head>
<title>Draggable (and Sortable) Table Columns</title>
<script type=text/javascript src="dragtable.js"></script>
<script type=text/javascript src="sorttable.js"></script>
<style type=text/css>
table.thin, table.thin td, table.thin tr, table.thin th {
border: thin solid black;
border-collapse: collapse;
background-color: white;
}
#fixed {
position: fixed;
left: 400px;
top: 100px;
}
</style>
</head>
<body>
<h3>普通表格</h3>
<table id=table class="thin draggable" cellpadding=2
style="background: white;">
<TR>
<Th>序号</Th>
<Th >书名</Th>
<Th>作者/译者</Th>
<Th>出版日期</Th>
<Th>价格</Th>
</TR>
<TR>
<TD>1</TD>
<TD>jquery基础教程</TD>
<TD>李松峰</TD>
<TD>2008/6</TD>
<TD>45.00</TD>
</TR>
<TR>
<TD>2</TD>
<TD>精通javascript</TD>
<TD>陈贤安</TD>
<TD>2008/2</TD>
<TD>33.80</TD>
</TR>
<TR>
<TD>3</TD>
<TD>Learning jquery</TD>
<TD>Karl</TD>
<TD>2007/10</TD>
<TD>50.00</TD>
</TR>
<TR>
<TD>4</TD>
<TD>pro javascript</TD>
<TD>john resig</TD>
<TD>2007/12</TD>
<TD>60.00</TD>
</TR>
<TR>
<TD>5</TD>
<TD>精通css</TD>
<TD>mazon</TD>
<TD>2007/2</TD>
<TD>46.00</TD>
</TR>
</table>
<h3>嵌套固定的表格</h3>
<table id=fixed>
<tr><td width=200> </td>
<td>
<table class="thin draggable" cellpadding=2 style="background: white;">
<thead>
<TR>
<Th>序号</Th>
<Th >书名</Th>
<Th>作者/译者</Th>
<Th>出版日期</Th>
<Th>价格</Th>
</TR>
</thead>
<TR>
<TD>1</TD>
<TD>jquery基础教程</TD>
<TD>李松峰</TD>
<TD>2008/6</TD>
<TD>45.00</TD>
</TR>
<TR>
<TD>2</TD>
<TD>精通javascript</TD>
<TD>陈贤安</TD>
<TD>2008/2</TD>
<TD>33.80</TD>
</TR>
<TR>
<TD>3</TD>
<TD>Learning jquery</TD>
<TD>Karl</TD>
<TD>2007/10</TD>
<TD>50.00</TD>
</TR>
<TR>
<TD>4</TD>
<TD>pro javascript</TD>
<TD>john resig</TD>
<TD>2007/12</TD>
<TD>60.00</TD>
</TR>
<TR>
<TD>5</TD>
<TD>精通css</TD>
<TD>mazon</TD>
<TD>2007/2</TD>
<TD>46.00</TD>
</TR>
</table>
</td>
</tr>
</table>
<h3>排序,拖动!</h3>
<table class="thin draggable sortable">
<tr>
<th>Column 1</th>
<th>Column 2</th>
<th>Column 3</th>
<th>Column 4</th>
<th>Column 5</th>
<th>Column 6</th>
<th>Column 7</th>
<th>Column 8</th>
<th>Column 9</th>
<th>Column 10</th>
<th>Column 11</th>
<th>Column 12</th>
<th>Column 13</th>
<th>Column 14</th>
<th>Column 15</th>
<th>Column 16</th>
<th>Column 17</th>
<th>Column 18</th>
<th>Column 19</th>
<th>Column 20</th>
</tr>
<tr>
<td>LEM16B0</td>
<td>A+heYkQ</td>
<td>Zn+jheU</td>
<td>BIwjnR4</td>
<td>D7AQNOo</td>
<td>+tX9hHU</td>
<td>lCzO3gY</td>
<td>NuNB5+8</td>
<td>NCROHls</td>
<td>YEXgX3w</td>
<td>BBpXIPo</td>
<td>PMuyFIA</td>
<td>Yp82t7I</td>
<td>Sag1G7M</td>
<td>e6h/gLo</td>
<td>7Zb3fwg</td>
<td>LdjkcAc</td>
<td>E8Tb2jI</td>
<td>c4Sito0</td>
<td>ieC5OlU</td>
</tr>
<tr>
<td>94xUs30</td>
<td>pK/dL+M</td>
<td>rwzS1QI</td>
<td>QdyJK8U</td>
<td>uL4Pu4s</td>
<td>nyQ/ZDY</td>
<td>za+6n4Q</td>
<td>YRMP7u0</td>
<td>xuisAbA</td>
<td>d1B/OCA</td>
<td>2pwKOqk</td>
<td>IsqlDJE</td>
<td>9lBp7ps</td>
<td>svb169c</td>
<td>tvUbJDQ</td>
<td>zzRc9qE</td>
<td>nbfwF0M</td>
<td>KUOP/YI</td>
<td>LkMzqnQ</td>
<td>9ZUTE1M</td>
</tr>
<tr>
<td>mVABl8A</td>
<td>aSdgW4c</td>
<td>cWhV7Cg</td>
<td>7Lsi9MY</td>
<td>1XHo9CY</td>
<td>oXHw03A</td>
<td>gzN2b+U</td>
<td>yItOtjM</td>
<td>SlzpATc</td>
<td>EkjTP4I</td>
<td>6UxwQxU</td>
<td>+SGuFwM</td>
<td>aUP8xvM</td>
<td>n8+TkLY</td>
<td>bWN8k5w</td>
<td>5Y1YI2Q</td>
<td>6Hmwecs</td>
<td>oacdZ6g</td>
<td>r3pV81E</td>
<td>qH70bhI</td>
</tr>
<tr>
<td>yGa10BQ</td>
<td>kxO5MNY</td>
<td>uchMlPw</td>
<td>r9y5LzI</td>
<td>T+TSpyo</td>
<td>i0GAQCU</td>
<td>JJHoQMg</td>
<td>aP5ZK60</td>
<td>4AD4uoA</td>
<td>xPzK9gI</td>
<td>kcl79tM</td>
<td>fUlf39w</td>
<td>V1QWcIU</td>
<td>ZGgJ20A</td>
<td>+lKd4DA</td>
<td>fD59uCU</td>
<td>vTytU5w</td>
<td>bSCub4E</td>
<td>IIqwfI4</td>
<td>ayZM5vA</td>
</tr>
<tr>
<td>Cp4Lw/A</td>
<td>RpsC81E</td>
<td>Jk92jek</td>
<td>2xG809k</td>
<td>MF8VEUo</td>
<td>mhhKCN8</td>
<td>pqljvo4</td>
<td>88h2DH0</td>
<td>0TH4lYs</td>
<td>nEE3XAs</td>
<td>kOK/yoo</td>
<td>zjJbmSo</td>
<td>HgW+Ut8</td>
<td>PzhK9m0</td>
<td>uGshM5o</td>
<td>3nf5FhE</td>
<td>AzLwBpk</td>
<td>i5CTrYU</td>
<td>6l5OWcg</td>
<td>MlNBIoU</td>
</tr>
<tr>
<td>AAqrvZc</td>
<td>hdS8Dgk</td>
<td>Hc56vB4</td>
<td>aZxg76g</td>
<td>tQVdO4Q</td>
<td>WQ91gCs</td>
<td>VgZG7uo</td>
<td>tvqxnVg</td>
<td>J2k5tQE</td>
<td>N3Rk5Ys</td>
<td>srAHGNg</td>
<td>a5GFpK4</td>
<td>H/79kOs</td>
<td>fYQ0DOI</td>
<td>CrotV3c</td>
<td>J2QyjM0</td>
<td>7H1BhKY</td>
<td>4tHYiQo</td>
<td>Jo8K6O0</td>
<td>3q8LY3Y</td>
</tr>
<tr>
<td>3hl1Gvk</td>
<td>f5kn8uE</td>
<td>Knzrvco</td>
<td>Z6EMG54</td>
<td>NKRvXCc</td>
<td>mIvuP5Y</td>
<td>xxPq/9Q</td>
<td>kgyfosg</td>
<td>JmApi2A</td>
<td>CWCVNQA</td>
<td>MnwuWsk</td>
<td>IEumljA</td>
<td>/b83PYo</td>
<td>WwzyxJ0</td>
<td>Hn7OQvo</td>
<td>2ztaFD8</td>
<td>4TQi9hk</td>
<td>fE8JC6I</td>
<td>qBiFpp4</td>
<td>kSNF3i0</td>
</tr>
<tr>
<td>mXnRzQs</td>
<td>MiaCbQc</td>
<td>EMqIwK8</td>
<td>yC0sMZM</td>
<td>n7QAagQ</td>
<td>VpUIZvE</td>
<td>c0V7MIo</td>
<td>8WqWZ5A</td>
<td>P8I7KGE</td>
<td>BeDYzq0</td>
<td>DHZlJSo</td>
<td>Au9Iufs</td>
<td>76g2x4o</td>
<td>zfPx+40</td>
<td>zo+lrE4</td>
<td>6gujThc</td>
<td>sMhrM48</td>
<td>KokWB2c</td>
<td>KfiXmr4</td>
<td>HOSRGwY</td>
</tr>
<tr>
<td>HbYCzQ8</td>
<td>LrG1Il0</td>
<td>bK50Btg</td>
<td>8Ioh12k</td>
<td>TZD8dEM</td>
<td>I1ESA4A</td>
<td>7a7KjqE</td>
<td>j3Tmrto</td>
<td>7FmcSGA</td>
<td>BYT5jC4</td>
<td>6/sjF2M</td>
<td>MubiSJA</td>
<td>npwmALE</td>
<td>wnTXa6s</td>
<td>qYsJuis</td>
<td>wLUPK7A</td>
<td>rvfWNo8</td>
<td>I716dtw</td>
<td>/N7KgeQ</td>
<td>WBA2jSk</td>
</tr>
<tr>
<td>99LCiQM</td>
<td>5LGxsCk</td>
<td>86vJTe0</td>
<td>hyNbHNs</td>
<td>ITdA8pk</td>
<td>GJzdeEo</td>
<td>AE14tCk</td>
<td>g8pKfFk</td>
<td>TiiQUNA</td>
<td>vUbVBVQ</td>
<td>0nFq96c</td>
<td>eCntsHE</td>
<td>U0F2FNE</td>
<td>tAabu3I</td>
<td>qiWwt10</td>
<td>hO6E59Y</td>
<td>Uc3ZZqg</td>
<td>y0rK5YM</td>
<td>3CdTEJA</td>
<td>kyV5Jrs</td>
</tr>
<tr>
<td>bT2butc</td>
<td>oVV0dmY</td>
<td>bfxYPBQ</td>
<td>gT5zWCg</td>
<td>jDerQkc</td>
<td>UpJIDlQ</td>
<td>bOygRNI</td>
<td>xTloGFE</td>
<td>I5g9JiY</td>
<td>1KuTY7o</td>
<td>edqhloc</td>
<td>7T7GZEg</td>
<td>+wSAKJA</td>
<td>szq/OXc</td>
<td>X4J3aHc</td>
<td>aKyAbpo</td>
<td>p4aahGo</td>
<td>aFJxHVs</td>
<td>MAFQwFo</td>
<td>IGJxsG4</td>
</tr>
<tr>
<td>jZ4gyiA</td>
<td>+BL9m8I</td>
<td>CzMENVg</td>
<td>xNYMGss</td>
<td>U4Z+BAM</td>
<td>IpJgAJs</td>
<td>dHFrfCI</td>
<td>uWGfMpI</td>
<td>6Za4A4U</td>
<td>nQ13z5E</td>
<td>Mau5ZBk</td>
<td>tJ3+2w4</td>
<td>fiAF59w</td>
<td>xt1sQq4</td>
<td>mZELYvY</td>
<td>QSoc718</td>
<td>Yxw6Mb8</td>
<td>tK3KzFU</td>
<td>n8BrUww</td>
<td>GpM8pqg</td>
</tr>
<tr>
<td>9RlW8Ck</td>
<td>YTRa0+8</td>
<td>oPXRkW0</td>
<td>oQd80QM</td>
<td>iTQstow</td>
<td>u2ZvxdM</td>
<td>0Nv4V18</td>
<td>/q7kN+E</td>
<td>Ub6zAzs</td>
<td>+k5MpDA</td>
<td>ac1vT+A</td>
<td>kW34QIM</td>
<td>jbifIQk</td>
<td>3GlMZt0</td>
<td>ruVOk5k</td>
<td>joPvrZQ</td>
<td>Sq9MWc8</td>
<td>bd2wS2E</td>
<td>M2kltY8</td>
<td>gi+sEpo</td>
</tr>
<tr>
<td>lCpaA5A</td>
<td>2c7+4eg</td>
<td>IwWlgOQ</td>
<td>nk1Rve4</td>
<td>uBVNdF4</td>
<td>mBXEuqc</td>
<td>PfE6KNg</td>
<td>gFfBzTk</td>
<td>88HPznk</td>
<td>7C7+5es</td>
<td>NWL7S9w</td>
<td>OUz6v+s</td>
<td>vtJoyJM</td>
<td>QI7aYUM</td>
<td>WMUvXgQ</td>
<td>ipbcVLI</td>
<td>Eo/7Kwo</td>
<td>QR9MUAQ</td>
<td>SB8ARiw</td>
<td>y8JAPCE</td>
</tr>
<tr>
<td>9G4PmnQ</td>
<td>JedMLCA</td>
<td>0ZqATEE</td>
<td>JckTgIk</td>
<td>b7rY4GE</td>
<td>/5CfGn8</td>
<td>xw7/QNU</td>
<td>a74hhVE</td>
<td>2sgzMns</td>
<td>IppLTrU</td>
<td>DFiN0qw</td>
<td>tm12Xtc</td>
<td>ubDUBQU</td>
<td>0v9E5iw</td>
<td>du56+Vg</td>
<td>zsIyvjo</td>
<td>Joa8eLM</td>
<td>+RKmB48</td>
<td>C9jixbg</td>
<td>QNh4OW4</td>
</tr>
<tr>
<td>K9LtcSQ</td>
<td>fqnP4BM</td>
<td>6z6orss</td>
<td>zGVSoAY</td>
<td>C8w2JLw</td>
<td>LvaNtpk</td>
<td>Bk/5btc</td>
<td>d4p4nXU</td>
<td>K/ohAxk</td>
<td>7WOIejQ</td>
<td>phGqwbU</td>
<td>uwA/0AQ</td>
<td>+enpIrc</td>
<td>QSNoCzI</td>
<td>a92VnfY</td>
<td>UbIclVA</td>
<td>uRFaI9g</td>
<td>swT5snQ</td>
<td>oP81nkQ</td>
<td>+vUtVeY</td>
</tr>
<tr>
<td>ZMJouu4</td>
<td>V0oaQKI</td>
<td>jJgkaOk</td>
<td>xQlVSyc</td>
<td>D7hfP5w</td>
<td>4PqBY9w</td>
<td>sCURxfo</td>
<td>kC/AW0E</td>
<td>nB3Q42A</td>
<td>1Ra9L70</td>
<td>BIW91K0</td>
<td>eOLZXmA</td>
<td>ltNpAgY</td>
<td>2L0kbpo</td>
<td>yaI2lao</td>
<td>VAPwyFU</td>
<td>hC+kKoQ</td>
<td>hSRoFyA</td>
<td>MZJoayo</td>
<td>7Bi+eLI</td>
</tr>
<tr>
<td>TD6KRlc</td>
<td>ZzimNzU</td>
<td>OZUuoXA</td>
<td>YOB5lWk</td>
<td>1ZuwM9k</td>
<td>SlbJEc8</td>
<td>Jq4cXP0</td>
<td>st4Vrdw</td>
<td>v17lP94</td>
<td>kh3j2Oo</td>
<td>wH93CtY</td>
<td>pq28jzY</td>
<td>mkxra3c</td>
<td>mzxc24U</td>
<td>hwmWnAk</td>
<td>4Jd/tuk</td>
<td>ufordAs</td>
<td>VvI/NVM</td>
<td>UEX5otI</td>
<td>cFILbrE</td>
</tr>
<tr>
<td>Em4oTRs</td>
<td>J94eTSY</td>
<td>pN8B1is</td>
<td>Vqy3BCA</td>
<td>0huBOOA</td>
<td>LPIQ9zM</td>
<td>hmqhHiE</td>
<td>mnJdL3I</td>
<td>oAz5MR8</td>
<td>4fujsiA</td>
<td>cRLLv4o</td>
<td>j3fDces</td>
<td>rsHcArU</td>
<td>0uyIAwg</td>
<td>WOEtJYE</td>
<td>qWy6/fw</td>
<td>IRnoszY</td>
<td>bjwBK2c</td>
<td>cIrlVXw</td>
<td>nH4CUfs</td>
</tr>
<tr>
<td>LPN+K4w</td>
<td>K/wLkbM</td>
<td>vdTlIEw</td>
<td>WHEfmf0</td>
<td>kBMpLIc</td>
<td>bPHy1/k</td>
<td>+DNqhck</td>
<td>R3dKIZQ</td>
<td>d62KKig</td>
<td>D3UbE28</td>
<td>ceUAvAo</td>
<td>2Gmfmcs</td>
<td>+Z8O0Ng</td>
<td>5532qf4</td>
<td>uVG+kDg</td>
<td>xOi41vU</td>
<td>u2o707E</td>
<td>V2ZVNmU</td>
<td>Ntw0pB4</td>
<td>XVdO14U</td>
</tr>
</table>
<br/>
工程地址:http://www.danvk.org/wp/dragtable/
<br/>
</body>
</html>

/**//*
dragtable v1.0
June 26, 2008
Dan Vanderkam, http://danvk.org/dragtable/
http://code.google.com/p/dragtable/
Instructions:
- Download this file
- Add <script src="dragtable.js"></script> 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;
},
// 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;
}
},
// 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(k)
{ new_elt.style[k] = elt.style[k]; });
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)
{
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 (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);
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;
new_elt.style.height = dragObj.origNode.offsetHeight;
// 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);
}
},
// 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<headrow.length; i++)
{
headrow[i].sorttable_columnindex = i;
}
}
}

/**//* ******************************************************************
Supporting functions: bundled here to avoid depending on a library
****************************************************************** */
// Dean Edwards/Matthias Miller/John Resig
// has a hook for dragtable.init already been added? (see below)
var dgListenOnLoad = false;

/**//* for Mozilla/Opera9 */
if (document.addEventListener)
{
dgListenOnLoad = true;
document.addEventListener("DOMContentLoaded", dragtable.init, false);
}

/**//* for Internet Explorer */
/**//*@cc_on @*/
/**//*@if (@_win32)
dgListenOnLoad = true;
document.write("<script id=__dt_onload defer src=javascript:void(0)><\/script>");
var script = document.getElementById("__dt_onload");
script.onreadystatechange = function() {
if (this.readyState == "complete") {
dragtable.init(); // call the onload handler
}
};
/*@end @*/

/**//* for Safari */
if (/WebKit/i.test(navigator.userAgent))
{ // sniff
dgListenOnLoad = true;
var _dgtimer = setInterval(function()
{
if (/loaded|complete/.test(document.readyState))
{
dragtable.init(); // call the onload handler
}
}, 10);
}

/**//* for other browsers */
/**//* Avoid this unless it's absolutely necessary (it breaks sorttable) */
if (!dgListenOnLoad)
{
window.onload = dragtable.init;
}
// Dean's forEach: http://dean.edwards.name/base/forEach.js
/**//*
forEach, version 1.0
Copyright 2006, Dean Edwards
License: http://www.opensource.org/licenses/mit-license.php
*/
// array-like enumeration
if (!Array.forEach)
{ // mozilla already supports this
Array.forEach = function(array, block, context)
{
for (var i = 0; i < array.length; i++)
{
block.call(context, array[i], i, array);
}
};
}
// generic enumeration
Function.prototype.forEach = function(object, block, context)
{
for (var key in object)
{
if (typeof this.prototype[key] == "undefined")
{
block.call(context, object[key], key, object);
}
}
};
// character enumeration
String.forEach = function(string, block, context)
{
Array.forEach(string.split(""), function(chr, index)
{
block.call(context, chr, index, string);
});
};
// globally resolve forEach enumeration
var forEach = function(object, block, context)
{
if (object)
{
var resolve = Object; // default
if (object instanceof Function)
{
// functions have a "length" property
resolve = Function;
} else if (object.forEach instanceof Function)
{
// the object implements a custom forEach method so use that
object.forEach(block, context);
return;
} else if (typeof object == "string")
{
// the object is a string
resolve = String;
} else if (typeof object.length == "number")
{
// the object is array-like
resolve = Array;
}
resolve.forEach(object, block, context);
}
};

/**//*
SortTable
version 2
7th April 2007
Stuart Langridge, http://www.kryogenix.org/code/browser/sorttable/
Instructions:
Download this file
Add <script src="sorttable.js"></script> to your HTML
Add class="sortable" to any table you'd like to make sortable
Click on the headers to sort
Thanks to many, many people for contributions and suggestions.
Licenced as X11: http://www.kryogenix.org/code/browser/licence.html
This basically means: do what you want with it.
*/

var stIsIE = /**//*@cc_on!@*/false;

sorttable =
{
init: function()
{
// quit if this function has already been called
if (arguments.callee.done) return;
// flag this function so we don't do the same thing twice
arguments.callee.done = true;
// kill the timer
if (_timer) clearInterval(_timer);
if (!document.createElement || !document.getElementsByTagName) return;
sorttable.DATE_RE = /^(\d\d?)[\/\.-](\d\d?)[\/\.-]((\d\d)?\d\d)$/;

forEach(document.getElementsByTagName('table'), function(table)
{
if (table.className.search(/\bsortable\b/) != -1)
{
sorttable.makeSortable(table);
}
});
},

makeSortable: function(table)
{
if (table.getElementsByTagName('thead').length == 0)
{
// table doesn't have a tHead. Since it should have, create one and
// put the first table row in it.
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];
if (table.tHead.rows.length != 1) return; // can't cope with two header rows
// Sorttable v1 put rows with a class of "sortbottom" at the bottom (as
// "total" rows, for example). This is B&R, since what you're supposed
// to do is put them in a tfoot. So, if there are sortbottom rows,
// for backwards compatibility, move them to tfoot (creating it if needed).
sortbottomrows = [];
for (var i=0; i<table.rows.length; i++)
{
if (table.rows[i].className.search(/\bsortbottom\b/) != -1)
{
sortbottomrows[sortbottomrows.length] = table.rows[i];
}
}
if (sortbottomrows)
{
if (table.tFoot == null)
{
// table doesn't have a tfoot. Create one.
tfo = document.createElement('tfoot');
table.appendChild(tfo);
}
for (var i=0; i<sortbottomrows.length; i++)
{
tfo.appendChild(sortbottomrows[i]);
}
delete sortbottomrows;
}
// work through each column and calculate its type
headrow = table.tHead.rows[0].cells;
for (var i=0; i<headrow.length; i++)
{
// manually override the type with a sorttable_type attribute
if (!headrow[i].className.match(/\bsorttable_nosort\b/))
{ // skip this col
mtch = headrow[i].className.match(/\bsorttable_([a-z0-9]+)\b/);
if (mtch)
{ override = mtch[1]; }
if (mtch && typeof sorttable["sort_"+override] == 'function')
{
headrow[i].sorttable_sortfunction = sorttable["sort_"+override];
} else
{
headrow[i].sorttable_sortfunction = sorttable.guessType(table,i);
}
// make it clickable to sort
headrow[i].sorttable_columnindex = i;
headrow[i].sorttable_tbody = table.tBodies[0];
dean_addEvent(headrow[i],"click", function(e)
{

if (this.className.search(/\bsorttable_sorted\b/) != -1)
{
// if we're already sorted by this column, just
// reverse the table, which is quicker
sorttable.reverse(this.sorttable_tbody);
this.className = this.className.replace('sorttable_sorted',
'sorttable_sorted_reverse');
this.removeChild(document.getElementById('sorttable_sortfwdind'));
sortrevind = document.createElement('span');
sortrevind.id = "sorttable_sortrevind";
sortrevind.innerHTML = stIsIE ? ' <font face="webdings">5</font>' : ' ▴';
this.appendChild(sortrevind);
return;
}
if (this.className.search(/\bsorttable_sorted_reverse\b/) != -1)
{
// if we're already sorted by this column in reverse, just
// re-reverse the table, which is quicker
sorttable.reverse(this.sorttable_tbody);
this.className = this.className.replace('sorttable_sorted_reverse',
'sorttable_sorted');
this.removeChild(document.getElementById('sorttable_sortrevind'));
sortfwdind = document.createElement('span');
sortfwdind.id = "sorttable_sortfwdind";
sortfwdind.innerHTML = stIsIE ? ' <font face="webdings">6</font>' : ' ▾';
this.appendChild(sortfwdind);
return;
}
// remove sorttable_sorted classes
theadrow = this.parentNode;
forEach(theadrow.childNodes, function(cell)
{
if (cell.nodeType == 1)
{ // an element
cell.className = cell.className.replace('sorttable_sorted_reverse','');
cell.className = cell.className.replace('sorttable_sorted','');
}
});
sortfwdind = document.getElementById('sorttable_sortfwdind');
if (sortfwdind)
{ sortfwdind.parentNode.removeChild(sortfwdind); }
sortrevind = document.getElementById('sorttable_sortrevind');
if (sortrevind)
{ sortrevind.parentNode.removeChild(sortrevind); }
this.className += ' sorttable_sorted';
sortfwdind = document.createElement('span');
sortfwdind.id = "sorttable_sortfwdind";
sortfwdind.innerHTML = stIsIE ? ' <font face="webdings">6</font>' : ' ▾';
this.appendChild(sortfwdind);
// build an array to sort. This is a Schwartzian transform thing,
// i.e., we "decorate" each row with the actual sort key,
// sort based on the sort keys, and then put the rows back in order
// which is a lot faster because you only do getInnerText once per row
row_array = [];
col = this.sorttable_columnindex;
rows = this.sorttable_tbody.rows;
for (var j=0; j<rows.length; j++)
{
row_array[row_array.length] = [sorttable.getInnerText(rows[j].cells[col]), rows[j]];
}
/**//* If you want a stable sort, uncomment the following line */
//sorttable.shaker_sort(row_array, this.sorttable_sortfunction);
/**//* and comment out this one */
row_array.sort(this.sorttable_sortfunction);
tb = this.sorttable_tbody;
for (var j=0; j<row_array.length; j++)
{
tb.appendChild(row_array[j][1]);
}
delete row_array;
});
}
}
},

guessType: function(table, column)
{
// guess the type of a column based on its first non-blank row
sortfn = sorttable.sort_alpha;
for (var i=0; i<table.tBodies[0].rows.length; i++)
{
text = sorttable.getInnerText(table.tBodies[0].rows[i].cells[column]);
if (text != '')
{
if (text.match(/^-?[??[\d,.]+%?$/))
{
return sorttable.sort_numeric;
}
// check for a date: dd/mm/yyyy or dd/mm/yy
// can have / or . or - as separator
// can be mm/dd as well
possdate = text.match(sorttable.DATE_RE)
if (possdate)
{
// looks like a date
first = parseInt(possdate[1]);
second = parseInt(possdate[2]);
if (first > 12)
{
// definitely dd/mm
return sorttable.sort_ddmm;
} else if (second > 12)
{
return sorttable.sort_mmdd;
} else
{
// looks like a date, but we can't tell which, so assume
// that it's dd/mm (English imperialism!) and keep looking
sortfn = sorttable.sort_ddmm;
}
}
}
}
return sortfn;
},

getInnerText: function(node)
{
// gets the text we want to use for sorting for a cell.
// strips leading and trailing whitespace.
// this is *not* a generic getInnerText function; it's special to sorttable.
// for example, you can override the cell text with a customkey attribute.
// it also gets .value for <input> fields.
hasInputs = (typeof node.getElementsByTagName == 'function') &&
node.getElementsByTagName('input').length;

if (node.getAttribute("sorttable_customkey") != null)
{
return node.getAttribute("sorttable_customkey");
}
else if (typeof node.textContent != 'undefined' && !hasInputs)
{
return node.textContent.replace(/^\s+|\s+$/g, '');
}
else if (typeof node.innerText != 'undefined' && !hasInputs)
{
return node.innerText.replace(/^\s+|\s+$/g, '');
}
else if (typeof node.text != 'undefined' && !hasInputs)
{
return node.text.replace(/^\s+|\s+$/g, '');
}
else
{
switch (node.nodeType)
{
case 3:
if (node.nodeName.toLowerCase() == 'input')
{
return node.value.replace(/^\s+|\s+$/g, '');
}
case 4:
return node.nodeValue.replace(/^\s+|\s+$/g, '');
break;
case 1:
case 11:
var innerText = '';
for (var i = 0; i < node.childNodes.length; i++)
{
innerText += sorttable.getInnerText(node.childNodes[i]);
}
return innerText.replace(/^\s+|\s+$/g, '');
break;
default:
return '';
}
}
},

reverse: function(tbody)
{
// reverse the rows in a tbody
newrows = [];
for (var i=0; i<tbody.rows.length; i++)
{
newrows[newrows.length] = tbody.rows[i];
}
for (var i=newrows.length-1; i>=0; i--)
{
tbody.appendChild(newrows[i]);
}
delete newrows;
},

/**//* sort functions
each sort function takes two parameters, a and b
you are comparing a[0] and b[0] */
sort_numeric: function(a,b)
{
aa = parseFloat(a[0].replace(/[^0-9.-]/g,''));
if (isNaN(aa)) aa = 0;
bb = parseFloat(b[0].replace(/[^0-9.-]/g,''));
if (isNaN(bb)) bb = 0;
return aa-bb;
},
sort_alpha: function(a,b)
{
if (a[0]==b[0]) return 0;
if (a[0]<b[0]) return -1;
return 1;
},
sort_ddmm: function(a,b)
{
mtch = a[0].match(sorttable.DATE_RE);
y = mtch[3]; m = mtch[2]; d = mtch[1];
if (m.length == 1) m = '0'+m;
if (d.length == 1) d = '0'+d;
dt1 = y+m+d;
mtch = b[0].match(sorttable.DATE_RE);
y = mtch[3]; m = mtch[2]; d = mtch[1];
if (m.length == 1) m = '0'+m;
if (d.length == 1) d = '0'+d;
dt2 = y+m+d;
if (dt1==dt2) return 0;
if (dt1<dt2) return -1;
return 1;
},
sort_mmdd: function(a,b)
{
mtch = a[0].match(sorttable.DATE_RE);
y = mtch[3]; d = mtch[2]; m = mtch[1];
if (m.length == 1) m = '0'+m;
if (d.length == 1) d = '0'+d;
dt1 = y+m+d;
mtch = b[0].match(sorttable.DATE_RE);
y = mtch[3]; d = mtch[2]; m = mtch[1];
if (m.length == 1) m = '0'+m;
if (d.length == 1) d = '0'+d;
dt2 = y+m+d;
if (dt1==dt2) return 0;
if (dt1<dt2) return -1;
return 1;
},

shaker_sort: function(list, comp_func)
{
// A stable sort function to allow multi-level sorting of data
// see: http://en.wikipedia.org/wiki/Cocktail_sort
// thanks to Joseph Nahmias
var b = 0;
var t = list.length - 1;
var swap = true;

while(swap)
{
swap = false;
for(var i = b; i < t; ++i)
{
if ( comp_func(list[i], list[i+1]) > 0 )
{
var q = list[i]; list[i] = list[i+1]; list[i+1] = q;
swap = true;
}
} // for
t--;
if (!swap) break;

for(var i = t; i > b; --i)
{
if ( comp_func(list[i], list[i-1]) < 0 )
{
var q = list[i]; list[i] = list[i-1]; list[i-1] = q;
swap = true;
}
} // for
b++;
} // while(swap)
}
}

/**//* ******************************************************************
Supporting functions: bundled here to avoid depending on a library
****************************************************************** */
// Dean Edwards/Matthias Miller/John Resig

/**//* for Mozilla/Opera9 */
if (document.addEventListener)
{
document.addEventListener("DOMContentLoaded", sorttable.init, false);
}

/**//* for Internet Explorer */
/**//*@cc_on @*/
/**//*@if (@_win32)
document.write("<script id=__ie_onload defer src=javascript:void(0)><\/script>");
var script = document.getElementById("__ie_onload");
script.onreadystatechange = function() {
if (this.readyState == "complete") {
sorttable.init(); // call the onload handler
}
};
/*@end @*/

/**//* for Safari */
if (/WebKit/i.test(navigator.userAgent))
{ // sniff
var _timer = setInterval(function()
{
if (/loaded|complete/.test(document.readyState))
{
sorttable.init(); // call the onload handler
}
}, 10);
}

/**//* for other browsers */
window.onload = sorttable.init;
// written by Dean Edwards, 2005
// with input from Tino Zijdel, Matthias Miller, Diego Perini
// http://dean.edwards.name/weblog/2005/10/add-event/

function dean_addEvent(element, type, handler)
{
if (element.addEventListener)
{
element.addEventListener(type, handler, false);
} else
{
// assign each event handler a unique ID
if (!handler.$$guid) handler.$$guid = dean_addEvent.guid++;
// create a hash table of event types for the element
if (!element.events) element.events =
{};
// create a hash table of event handlers for each element/event pair
var handlers = element.events[type];
if (!handlers)
{
handlers = element.events[type] =
{};
// store the existing event handler (if there is one)
if (element["on" + type])
{
handlers[0] = element["on" + type];
}
}
// store the event handler in the hash table
handlers[handler.$$guid] = handler;
// assign a global event handler to do all the work
element["on" + type] = handleEvent;
}
};
// a counter used to create unique IDs
dean_addEvent.guid = 1;

function removeEvent(element, type, handler)
{
if (element.removeEventListener)
{
element.removeEventListener(type, handler, false);
} else
{
// delete the event handler from the hash table
if (element.events && element.events[type])
{
delete element.events[type][handler.$$guid];
}
}
};

function handleEvent(event)
{
var returnValue = true;
// grab the event object (IE uses a global event object)
event = event || fixEvent(((this.ownerDocument || this.document || this).parentWindow || window).event);
// get a reference to the hash table of event handlers
var handlers = this.events[event.type];
// execute each event handler
for (var i in handlers)
{
this.$$handleEvent = handlers[i];
if (this.$$handleEvent(event) === false)
{
returnValue = false;
}
}
return returnValue;
};

function fixEvent(event)
{
// add W3C standard event methods
event.preventDefault = fixEvent.preventDefault;
event.stopPropagation = fixEvent.stopPropagation;
return event;
};
fixEvent.preventDefault = function()
{
this.returnValue = false;
};
fixEvent.stopPropagation = function()
{
this.cancelBubble = true;
}
// Dean's forEach: http://dean.edwards.name/base/forEach.js
/**//*
forEach, version 1.0
Copyright 2006, Dean Edwards
License: http://www.opensource.org/licenses/mit-license.php
*/
// array-like enumeration
if (!Array.forEach)
{ // mozilla already supports this
Array.forEach = function(array, block, context)
{
for (var i = 0; i < array.length; i++)
{
block.call(context, array[i], i, array);
}
};
}
// generic enumeration
Function.prototype.forEach = function(object, block, context)
{
for (var key in object)
{
if (typeof this.prototype[key] == "undefined")
{
block.call(context, object[key], key, object);
}
}
};
// character enumeration
String.forEach = function(string, block, context)
{
Array.forEach(string.split(""), function(chr, index)
{
block.call(context, chr, index, string);
});
};
// globally resolve forEach enumeration
var forEach = function(object, block, context)
{
if (object)
{
var resolve = Object; // default
if (object instanceof Function)
{
// functions have a "length" property
resolve = Function;
} else if (object.forEach instanceof Function)
{
// the object implements a custom forEach method so use that
object.forEach(block, context);
return;
} else if (typeof object == "string")
{
// the object is a string
resolve = String;
} else if (typeof object.length == "number")
{
// the object is array-like
resolve = Array;
}
resolve.forEach(object, block, context);
}
};


浙公网安备 33010602011771号