background color with mouseover/our in IE6 (Win 2K) but the response
is fine (fast) in Firefox. Why? The code is below. Sorry about the
length.
<html>
<head>
<title>Rapid Blocking Interface</title>
<style>
.calendar {
position:relative;
cursor:default;
}
.calendarHeader {
background-color:lightgreen;
text-align:center;
font-family:sans-serif;
width:140;
}
.calendarRow {
height:30;
}
#calendar1 {
top:20;
left:10;
background-color:white;
}
#appointment {
position:absolute;
width:300;
height:200;
background-color:lightyellow;
border:2px black solid;
font-weight:bold;
font-family:sans-serif;
visibility:hidden;
}
#output {
position:absolute;
top:35;
left:750
}
#clear {
position:absolute;
top:460;
left:750;
width:80;
background-color:lightgrey;
border:2px black solid;
color:black;
text-align:center;
font-weight:bold;
font-family:sans-serif;
cursor:default;
}
</style>
</head>
<body>
<table id='calendar1' class='calendar' border='1' cellpadding='0'
cellspacing='0'>
<tr>
<td class="calendarHeader">0</td>
<td class="calendarHeader">1</td>
<td class="calendarHeader">2</td>
<td class="calendarHeader">3</td>
<td class="calendarHeader">4</td>
</tr>
<tr class='calendarRow'>
<td></td>
<td></td>
<td></td>
<td></td>
<td></td>
</tr>
<tr class='calendarRow'>
<td></td>
<td></td>
<td></td>
<td></td>
<td></td>
</tr>
<tr class='calendarRow'>
<td></td>
<td></td>
<td></td>
<td></td>
<td></td>
</tr>
<tr class='calendarRow'>
<td></td>
<td></td>
<td></td>
<td></td>
<td></td>
</tr>
<tr class='calendarRow'>
<td></td>
<td></td>
<td></td>
<td></td>
<td></td>
</tr>
<tr class='calendarRow'>
<td></td>
<td></td>
<td></td>
<td></td>
<td></td>
</tr>
<tr class='calendarRow'>
<td></td>
<td></td>
<td></td>
<td></td>
<td></td>
</tr>
<tr class='calendarRow'>
<td></td>
<td></td>
<td></td>
<td></td>
<td></td>
</tr>
<tr class='calendarRow'>
<td></td>
<td></td>
<td></td>
<td></td>
<td></td>
</tr>
<tr class='calendarRow'>
<td></td>
<td></td>
<td></td>
<td></td>
<td></td>
</tr>
<tr class='calendarRow'>
<td></td>
<td></td>
<td></td>
<td></td>
<td></td>
</tr>
<tr class='calendarRow'>
<td></td>
<td></td>
<td></td>
<td></td>
<td></td>
</tr>
<tr class='calendarRow'>
<td></td>
<td></td>
<td></td>
<td></td>
<td></td>
</tr>
<tr class='calendarRow'>
<td></td>
<td></td>
<td></td>
<td></td>
<td></td>
</tr>
<tr class='calendarRow'>
<td></td>
<td></td>
<td></td>
<td></td>
<td></td>
</tr>
<tr class='calendarRow'>
<td></td>
<td></td>
<td></td>
<td></td>
<td></td>
</tr>
<tr class='calendarRow'>
<td></td>
<td></td>
<td></td>
<td></td>
<td></td>
</tr>
<tr class='calendarRow'>
<td></td>
<td></td>
<td></td>
<td></td>
<td></td>
</tr>
</table>
<div id="output"><textarea cols=25 rows=25></textarea></div>
<div
id="clear"
onmousedown="return false;"
onclick="document.getElementById('output').firstCh ild.value = '';"
>CLEAR
</div>
<div
id="appointment"
class="draggable"
onclick="this.style.visibility = 'hidden';"
>
</div>
<script>
(function () {
var calendar = document.getElementById('calendar1'),
rows = calendar.getElementsByTagName('tr'),
slots = calendar.getElementsByTagName('td');
/*debug*/ var output = document.getElementById('output').firstChild;
/*debug*/ output.value = '';
var apt = document.getElementById('appointment');
apt.appendChild(document.createTextNode(''));
function addSlotControl(el) {
var sc = document.createElement('div');
sc.style.position='relative';
sc.style.backgroundColor='lightgrey';
sc.style.borderWidth='1px';
sc.style.borderColor='black';
sc.style.borderStyle='solid';
sc.style.margin='0px';
sc.style.padding='0px';
sc.style.visibility='hidden';
sc.style.top=0;
sc.style.left=100;
sc.style.height=13;
sc.style.width=28;
sc.style.textAlign='center';
sc.style.fontSize=10;
sc.style.fontFamily='sans-serif';
sc.appendChild(document.createTextNode('SC'));
el.appendChild(sc);
}
var selectMode = false,
initialControlState,
columnSelected,
firstRowSelected,
previousRowSelected,
lastRowSelected,
selectionCancelled,
downOn = null;
function mousedownHandler(e) {
e.returnValue = false;
if (e.preventDefault) {e.preventDefault();}
var target = getEventTarget(e);
if (target.nodeName !== 'DIV') {
if (target.nodeName === 'TD') {
downOn = target;
}
return false;
}
addEvent(calendar, 'selectstart', selectStartHandler, false);
var slot = target.parentNode;
selectMode = true;
selectionCancelled = false;
initialControlState = target.style.backgroundColor;
columnSelected = slot.cellIndex;
firstRowSelected = lastRowSelected = slot.parentNode.rowIndex;
slot.firstChild.style.visibility = 'hidden';
slot.style.backgroundColor
= (initialControlState === 'lightgrey')? '#FF9966':'#FFCC99';
return false;
}
/
************************************************** *********************
Distinguishing onmouseover/out of child elements from those of the
parent element.
Mouseover fires first but mouseout fires when the mouse moves over
the child (DIV) element. The problem is not just about bubbling,
because when you move the mouse over the DIV, you are not moving out
of anything contained in the table cell (TD) nor are you moving out
of the area contained by the TD. A mouseout event fires simply
because a mouseover event fires for another element.
See: http://www.faqts.com/knowledge_base/view.phtml/aid/1606
http://www.quirksmode.org/js/events_mouse.html
http://www.dynamic-tools.net/toolbox...eLeaveOrEnter/
Also, the try/catch blocks handle a related version of the
"Permission denied to get property HTMLDivElement.parentNode"
bug in Firefox/Mozilla. Moving the mouse cursor fast enough from the
grid over the textarea will cause this bug to occur.
See: https://bugzilla.mozilla.org/show_bug.cgi?id=208427
https://bugzilla.mozilla.org/show_bug.cgi?id=214340
************************************************** *********************/
function mouseoverHandler(e) {
if (selectionCancelled) { return; }
var err, target = getEventTarget(e);
if (target.nodeName !== 'TD'
&&
target.nodeName !== 'DIV') { return; } // Mouse did not enter
// calendar slot.
/** Get the element the mouse comes from. **/
var relTarget = e.relatedTarget || e.fromElement;
try {
if (relTarget.parentNode === target // Mouse moves
|| // from child
target.parentNode === relTarget) { return; } // over parent
} // target element
catch (err) { return; } // or vice versa.
/** Mouse actually entered TD. Handle event. **/
if (target.nodeName === 'DIV') { target = target.parentNode; }
if (target.className === 'calendarHeader') { // Mouse moved into
if (selectMode) { cancelSelection(); } // calendar header.
}
else if (!selectMode) {
target.style.backgroundColor
= (target.firstChild.style.backgroundColor === 'lightgrey')?
'lightyellow':'lightgrey';
target.firstChild.style.visibility = "visible";
}
else if (target.cellIndex === columnSelected)
{
// First detect missed mouse events with fast cursor movement.
var rowT = target.parentNode.rowIndex,
rowRT = (relTarget.nodeName === 'TD')?
relTarget.parentNode.rowIndex:relTarget.parentNode .parentNode.rowIndex;
if (rowRT !== undefined
&&
Math.abs(rowRT - rowT) 1) // Cancel if slot events missed.
{
cancelSelection();
return;
}
previousRowSelected = lastRowSelected;
lastRowSelected = target.parentNode.rowIndex;
var slot,
sc,
vector = Math.abs(lastRowSelected - firstRowSelected) -
Math.abs(previousRowSelected - firstRowSelected);
if (vector 0) // Moving away from first selection.
{
sc = target.firstChild;
sc.style.visibility = 'hidden';
target.style.backgroundColor
= (sc.style.backgroundColor === 'lightgrey')?
'#C6E2FF':'#9FB6CD';
}
else if (vector < 0) // Moving toward first selection.
{
slot = rows[previousRowSelected].cells[columnSelected];
slot.style.backgroundColor
= (slot.firstChild.style.backgroundColor === 'lightgrey')?
'white':'lightgrey';
}
}
}
function mouseoutHandler(e) {
if (selectionCancelled) { return;}
var err, target = getEventTarget(e);
if (target.nodeName !== 'TD'
&&
target.nodeName !== 'DIV') { return; } // Mouse did not exit
// calendar slot.
/** Get the element the mouse goes to **/
var relTarget = e.relatedTarget || e.toElement;
try { // Mouse moves
if (relTarget.parentNode === target // to child
|| // out from
target.parentNode === relTarget) { return; } // parent target
} // or vice versa.
catch (err) {
if (!selectMode
&&
target.style.backgroundColor) // IE related issue.
{
target.style.backgroundColor
= (target.firstChild.style.backgroundColor === 'lightgrey')?
'white':'lightgrey';
target.firstChild.style.visibility = "hidden";
}
return;
}
/** Mouse actually left TD. Handle event. **/
if (target.nodeName === 'DIV') { target = target.parentNode; }
if (target.className === 'calendarHeader') { return; }
if (!selectMode) {
target.style.backgroundColor
= (target.firstChild.style.backgroundColor === 'lightgrey')?
'white':'lightgrey';
target.firstChild.style.visibility = "hidden";
}
else if (relTarget.cellIndex !== columnSelected)
{ cancelSelection(); }
}
function mouseupHandler(e) {
var coord, target = getEventTarget(e);
if (target.nodeName === 'DIV')
{
target = target.parentNode;
}
if (target.nodeName === 'TD'
&&
target.parentNode.className === 'calendarRow')
{
if (selectMode) {
if (!selectionCancelled) { finalizeSelection(); }
}
else if (downOn === target) {
if (target.style.backgroundColor !== 'lightgrey') {
apt.innerHTML = ' ' + target.parentNode.rowIndex + ',
'+ target.cellIndex;
apt.style.left = e.pageX || e.clientX + document.body.scrollLeft
+ document.body.clientLeft;
apt.style.top = e.pageY || e.clientY + document.body.scrollTop +
document.body.clientTop;
apt.style.visibility = 'visible';
}
downOn = null;
}
}
selectMode = selectionCancelled = false; // Whether true or false,
calendar.onselectstart = null; // set to false.
}
function selectStartHandler(e) {
e.returnValue = false;
return false;
}
function finalizeSelection() {
var c = columnSelected, r, slot, slotBgC, scBgC;
if (initialControlState === 'lightgrey') {
slotBgC = 'lightgrey';
scBgC = 'white';
}
else {
slotBgC = 'white';
scBgC = 'lightgrey';
}
if (firstRowSelected <= lastRowSelected) {
for (r = firstRowSelected; r <= lastRowSelected; r++) {
(slot = rows[r].cells[c]).style.backgroundColor = slotBgC;
slot.firstChild.style.backgroundColor = scBgC;
}
}
else {
for (r = firstRowSelected; r >= lastRowSelected; r--) {
(slot = rows[r].cells[c]).style.backgroundColor = slotBgC;
slot.firstChild.style.backgroundColor = scBgC;
}
}
initialControlState = null;
firstRowSelected = null;
lastRowSelected = null;
columnSelected = null;
}
function cancelSelection() {
var c = columnSelected, r, slot, slotBgC;
selectionCancelled = true;
if (firstRowSelected <= lastRowSelected) {
for (r = firstRowSelected; r <= lastRowSelected; r++) {
slotBgC = ((slot =
rows[r].cells[c]).firstChild.style.backgroundColor === 'white')?
'lightgrey':'white';
slot.style.backgroundColor = slotBgC;
}
}
else {
for (r = firstRowSelected; r >= lastRowSelected; r--) {
slotBgC = ((slot =
rows[r].cells[c]).firstChild.style.backgroundColor === 'white')?
'lightgrey':'white';
slot.style.backgroundColor = slotBgC;
}
}
initialControlState = null;
firstRowSelected = null;
lastRowSelected = null;
columnSelected = null;
}
function elXY(el) {
var c = {x:0, y:0};
while (el) {
c.x += el.offsetLeft;
c.y += el.offsetTop;
el = el.offsetParent;
}
return c;
}
function evtXY(e) {
return {
x:e.offsetX || e.clientX + window.pageXOffset,
y:e.offsetY || e.clientY + window.pageYOffset
}
}
function addEvent(el, evtType, listener, captures) {
if (el.addEventListener) {
el.addEventListener(evtType, listener, captures);
return true;
}
else if (el.attachEvent) {
return el.attachEvent('on' + evtType, listener);
}
else {
el['on' + evtType] = listener;
}
}
function getEventTarget(e) {
return (window.event)? window.event.srcElement:(e)? e.target:null;
}
function stopBubbling(e) {
if (!e) { var e = window.event; }
e.cancelBubble = true;
if (e.stopPropagation) { e.stopPropagation(); }
}
for (var i=0; i < slots.length; i++) {
if (slots[i].className !== 'calendarHeader') {
addSlotControl(slots[i]); // Add slot control as
} // slots first child.
}
addEvent(document, 'mouseup', mouseupHandler, false);
addEvent(calendar, 'mousedown', mousedownHandler, false);
addEvent(calendar, 'mouseover', mouseoverHandler, false);
addEvent(calendar, 'mouseout', mouseoutHandler, false);
})();
</script>
</body>
</html>