| 1 |
berupon |
4 |
// |
| 2 |
|
|
// Resizable Table Columns. |
| 3 |
|
|
// version: 1.0 |
| 4 |
|
|
// |
| 5 |
|
|
// (c) 2006, bz |
| 6 |
|
|
// |
| 7 |
|
|
// 25.12.2006: first working prototype |
| 8 |
|
|
// 26.12.2006: now works in IE as well but not in Opera (Opera is @#$%!) |
| 9 |
|
|
// 27.12.2006: changed initialization, now just make class='resizable' in table and load script |
| 10 |
|
|
// |
| 11 |
|
|
function preventEvent(e) { |
| 12 |
|
|
var ev = e || window.event; |
| 13 |
|
|
if (ev.preventDefault) ev.preventDefault(); |
| 14 |
|
|
else ev.returnValue = false; |
| 15 |
|
|
if (ev.stopPropagation) |
| 16 |
|
|
ev.stopPropagation(); |
| 17 |
|
|
return false; |
| 18 |
|
|
} |
| 19 |
|
|
|
| 20 |
|
|
function getStyle(x, styleProp) { |
| 21 |
|
|
if (x.currentStyle) |
| 22 |
|
|
var y = x.currentStyle[styleProp]; |
| 23 |
|
|
else if (window.getComputedStyle) |
| 24 |
|
|
var y = document.defaultView.getComputedStyle(x,null).getPropertyValue(styleProp); |
| 25 |
|
|
return y; |
| 26 |
|
|
} |
| 27 |
|
|
|
| 28 |
|
|
function getWidth(x) { |
| 29 |
|
|
if (x.currentStyle) |
| 30 |
|
|
// in IE |
| 31 |
|
|
var y = x.clientWidth - parseInt(x.currentStyle["paddingLeft"]) - parseInt(x.currentStyle["paddingRight"]); |
| 32 |
|
|
// for IE5: var y = x.offsetWidth; |
| 33 |
|
|
else if (window.getComputedStyle) |
| 34 |
|
|
// in Gecko |
| 35 |
|
|
var y = document.defaultView.getComputedStyle(x,null).getPropertyValue("width"); |
| 36 |
|
|
return y || 0; |
| 37 |
|
|
} |
| 38 |
|
|
|
| 39 |
|
|
function setCookie (name, value, expires, path, domain, secure) { |
| 40 |
|
|
document.cookie = name + "=" + escape(value) + |
| 41 |
|
|
((expires) ? "; expires=" + expires : "") + |
| 42 |
|
|
((path) ? "; path=" + path : "") + |
| 43 |
|
|
((domain) ? "; domain=" + domain : "") + |
| 44 |
|
|
((secure) ? "; secure" : ""); |
| 45 |
|
|
} |
| 46 |
|
|
|
| 47 |
|
|
function getCookie(name) { |
| 48 |
|
|
var cookie = " " + document.cookie; |
| 49 |
|
|
var search = " " + name + "="; |
| 50 |
|
|
var setStr = null; |
| 51 |
|
|
var offset = 0; |
| 52 |
|
|
var end = 0; |
| 53 |
|
|
if (cookie.length > 0) { |
| 54 |
|
|
offset = cookie.indexOf(search); |
| 55 |
|
|
if (offset != -1) { |
| 56 |
|
|
offset += search.length; |
| 57 |
|
|
end = cookie.indexOf(";", offset) |
| 58 |
|
|
if (end == -1) { |
| 59 |
|
|
end = cookie.length; |
| 60 |
|
|
} |
| 61 |
|
|
setStr = unescape(cookie.substring(offset, end)); |
| 62 |
|
|
} |
| 63 |
|
|
} |
| 64 |
|
|
return(setStr); |
| 65 |
|
|
} |
| 66 |
|
|
// main class prototype |
| 67 |
|
|
function ColumnResize(row) { |
| 68 |
|
|
if (row.tagName != 'TR') return; |
| 69 |
|
|
|
| 70 |
|
|
this.id = row.id; |
| 71 |
|
|
|
| 72 |
|
|
// ============================================================ |
| 73 |
|
|
// private data |
| 74 |
|
|
var self = this; |
| 75 |
|
|
|
| 76 |
|
|
var dragColumns = row.cells; // first row columns, used for changing of width |
| 77 |
|
|
if (!dragColumns) return; // return if no table exists or no one row exists |
| 78 |
|
|
|
| 79 |
|
|
var dragColumnNo; // current dragging column |
| 80 |
|
|
var dragX; // last event X mouse coordinate |
| 81 |
|
|
|
| 82 |
|
|
var saveOnmouseup; // save document onmouseup event handler |
| 83 |
|
|
var saveOnmousemove; // save document onmousemove event handler |
| 84 |
|
|
var saveBodyCursor; // save body cursor property |
| 85 |
|
|
|
| 86 |
|
|
var setupFlags = new Array(dragColumns.length); |
| 87 |
|
|
|
| 88 |
|
|
// ============================================================ |
| 89 |
|
|
// methods |
| 90 |
|
|
|
| 91 |
|
|
// ============================================================ |
| 92 |
|
|
// do changes columns widths |
| 93 |
|
|
// returns true if success and false otherwise |
| 94 |
|
|
this.changeColumnWidth = function(no, w) { |
| 95 |
|
|
if (!dragColumns) return false; |
| 96 |
|
|
|
| 97 |
|
|
if (no < 0) return false; |
| 98 |
|
|
if (dragColumns.length < no) return false; |
| 99 |
|
|
|
| 100 |
|
|
if (parseInt(dragColumns[no].style.width) <= -w) return false; |
| 101 |
|
|
if (dragColumns[no+1] && parseInt(dragColumns[no+1].style.width) <= w) return false; |
| 102 |
|
|
|
| 103 |
|
|
dragColumns[no].style.width = parseInt(dragColumns[no].style.width) + w +'px'; |
| 104 |
|
|
// if (dragColumns[no+1]) |
| 105 |
|
|
// dragColumns[no+1].style.width = parseInt(dragColumns[no+1].style.width) - w + 'px'; |
| 106 |
|
|
|
| 107 |
|
|
return true; |
| 108 |
|
|
} |
| 109 |
|
|
|
| 110 |
|
|
// ============================================================ |
| 111 |
|
|
// do drag column width |
| 112 |
|
|
this.columnDrag = function(e) { |
| 113 |
|
|
|
| 114 |
|
|
if (!setupFlags[dragColumnNo]) { |
| 115 |
|
|
setupFlags[dragColumnNo] = true; |
| 116 |
|
|
self.setup(dragColumnNo); |
| 117 |
|
|
} |
| 118 |
|
|
|
| 119 |
|
|
var e = e || window.event; |
| 120 |
|
|
var X = e.clientX || e.pageX; |
| 121 |
|
|
if (!self.changeColumnWidth(dragColumnNo, X-dragX)) { |
| 122 |
|
|
// stop drag! |
| 123 |
|
|
self.stopColumnDrag(e); |
| 124 |
|
|
} |
| 125 |
|
|
|
| 126 |
|
|
dragX = X; |
| 127 |
|
|
// prevent other event handling |
| 128 |
|
|
preventEvent(e); |
| 129 |
|
|
return false; |
| 130 |
|
|
} |
| 131 |
|
|
|
| 132 |
|
|
// ============================================================ |
| 133 |
|
|
// stops column dragging |
| 134 |
|
|
this.stopColumnDrag = function(e) { |
| 135 |
|
|
var e = e || window.event; |
| 136 |
|
|
if (!dragColumns) return; |
| 137 |
|
|
|
| 138 |
|
|
// restore handlers & cursor |
| 139 |
|
|
document.onmouseup = saveOnmouseup; |
| 140 |
|
|
document.onmousemove = saveOnmousemove; |
| 141 |
|
|
document.body.style.cursor = saveBodyCursor; |
| 142 |
|
|
|
| 143 |
|
|
// remember columns widths in cookies for server side |
| 144 |
|
|
var colWidth = ''; |
| 145 |
|
|
var separator = ''; |
| 146 |
|
|
for (var i=0; i<dragColumns.length; i++) { |
| 147 |
|
|
colWidth += separator + parseInt( getWidth(dragColumns[i]) ); |
| 148 |
|
|
separator = '+'; |
| 149 |
|
|
} |
| 150 |
|
|
var expire = new Date(); |
| 151 |
|
|
expire.setDate(expire.getDate() + 365); // year |
| 152 |
|
|
document.cookie = self.id + '-width=' + colWidth + |
| 153 |
|
|
'; expires=' + expire.toGMTString(); |
| 154 |
|
|
|
| 155 |
|
|
preventEvent(e); |
| 156 |
|
|
} |
| 157 |
|
|
|
| 158 |
|
|
this.setup = function(i) { |
| 159 |
|
|
// dragColumns[i].width = ""; // for sure |
| 160 |
|
|
dragColumns[i].style.width = parseInt( getWidth(dragColumns[i]) ) + "px"; |
| 161 |
|
|
|
| 162 |
|
|
/* |
| 163 |
|
|
// set up current columns widths in their particular attributes |
| 164 |
|
|
// do it in two steps to avoid jumps on page! |
| 165 |
|
|
var colWidth = new Array(); |
| 166 |
|
|
for (var i=0; i<dragColumns.length; i++) |
| 167 |
|
|
colWidth[i] = parseInt( getWidth(dragColumns[i]) ); |
| 168 |
|
|
for (var i=0; i<dragColumns.length; i++) { |
| 169 |
|
|
dragColumns[i].width = ""; // for sure |
| 170 |
|
|
dragColumns[i].style.width = colWidth[i] + "px"; |
| 171 |
|
|
} |
| 172 |
|
|
*/ |
| 173 |
|
|
} |
| 174 |
|
|
|
| 175 |
|
|
// ============================================================ |
| 176 |
|
|
// init data and start dragging |
| 177 |
|
|
this.startColumnDrag = function(e) { |
| 178 |
|
|
var e = e || window.event; |
| 179 |
|
|
|
| 180 |
|
|
// if not first button was clicked |
| 181 |
|
|
//if (e.button != 0) return; |
| 182 |
|
|
|
| 183 |
|
|
// remember dragging object |
| 184 |
|
|
dragColumnNo = (e.target || e.srcElement).parentNode.parentNode.cellIndex; |
| 185 |
|
|
dragX = e.clientX || e.pageX; |
| 186 |
|
|
|
| 187 |
|
|
saveOnmouseup = document.onmouseup; |
| 188 |
|
|
document.onmouseup = self.stopColumnDrag; |
| 189 |
|
|
|
| 190 |
|
|
saveBodyCursor = document.body.style.cursor; |
| 191 |
|
|
document.body.style.cursor = 'col-resize'; //'w-resize'; |
| 192 |
|
|
|
| 193 |
|
|
// fire! |
| 194 |
|
|
saveOnmousemove = document.onmousemove; |
| 195 |
|
|
document.onmousemove = self.columnDrag; |
| 196 |
|
|
|
| 197 |
|
|
preventEvent(e); |
| 198 |
|
|
} |
| 199 |
|
|
|
| 200 |
|
|
var wasActive = (document.activeElement != null); |
| 201 |
|
|
var activeElemID = wasActive ? document.activeElement.id : ""; |
| 202 |
|
|
var activeElemName = wasActive ? document.activeElement.name : ""; |
| 203 |
|
|
|
| 204 |
|
|
// prepare table header to be draggable |
| 205 |
|
|
// it runs during class creation |
| 206 |
|
|
for (var i=0; i<dragColumns.length; i++) { |
| 207 |
berupon |
14 |
dragColumns[i].innerHTML = "<div style='position:relative;width:100%;'>"+ |
| 208 |
berupon |
4 |
"<div style='"+ |
| 209 |
|
|
"background-color:transparent/*#aaa*/;position:absolute;height:100%;width:5px;margin-right:-5px;"+ |
| 210 |
|
|
"left:100%;top:0px;cursor:col-resize/*w-resize*/;z-index:10;'>"+ |
| 211 |
|
|
"</div><div>"+ |
| 212 |
|
|
dragColumns[i].innerHTML+ |
| 213 |
|
|
"</div></div>"; |
| 214 |
|
|
// BUGBUG: calculate real border width instead of 5px!!! |
| 215 |
|
|
dragColumns[i].firstChild.firstChild.onmousedown = this.startColumnDrag; |
| 216 |
|
|
} |
| 217 |
|
|
|
| 218 |
|
|
if (wasActive && ((activeElemID&&activeElemID.length) || (activeElemName&&activeElemName.length))) { |
| 219 |
|
|
var activeEl = activeElemID ? $(activeElemID) : document.getElementsByName(activeElemName)[0]; |
| 220 |
|
|
if (activeEl) { |
| 221 |
|
|
activeEl.focus(); |
| 222 |
|
|
activeEl.select(); |
| 223 |
|
|
} |
| 224 |
|
|
} |
| 225 |
|
|
} |
| 226 |
|
|
|
| 227 |
|
|
// select all rows and make resizable those that have 'resizable' class |
| 228 |
|
|
var resizableRows = new Array(); |
| 229 |
|
|
|
| 230 |
|
|
function ResizableColumns() { |
| 231 |
berupon |
14 |
resizableRows.clear(); |
| 232 |
berupon |
4 |
var rows = document.getElementsByTagName('tr'); |
| 233 |
|
|
for (var i=0; i<rows.length; i++) { |
| 234 |
|
|
if (rows[i].className.match(/resizable/)) { |
| 235 |
|
|
// generate id |
| 236 |
|
|
if (!rows[i].id) rows[i].id = 'tr'+(i+1); |
| 237 |
|
|
// make rows resizable |
| 238 |
|
|
resizableRows[resizableRows.length] = new ColumnResize(rows[i]); |
| 239 |
|
|
} |
| 240 |
|
|
} |
| 241 |
|
|
} |
| 242 |
|
|
|
| 243 |
|
|
// execute earlier to avoid overriding other startup modifiers since this replaces HTML and kill previously-attached event listeners. |
| 244 |
|
|
document.observe('dom:loaded', ResizableColumns); |
| 245 |
|
|
|