slow response in table cells <TD> to mouseover with IE6 but fine inFirefox.

M

markszlazak

I'm a relatively slow response of table cells changing their
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').firstChild.value = '';"CLEAR
</div>
<div
id="appointment"
class="draggable"
onclick="this.style.visibility = 'hidden';"&nbsp;&nbsp;
</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/isMouseLeaveOrEnter/

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 = '&nbsp;&nbsp;' + 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.className !== 'calendarHeader') {
addSlotControl(slots); // 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>
 
M

markszlazak

Works same in both browsers for me

yukabuk, I need to test this also on very old computers like 500 Mhz /
256 MB systems. I'm see a big difference on the same system in how
fast Firefox and IE respond to moving the cursor over the tables
cells. IE is quite slow, I'm wondering why and what can be done about
it.

Thanks.
 
M

markszlazak

Again, does anyone have an idea why IE6 is so much slower in changing
the background color of table cells when the cursor moves relatively
quickly over a table column in the script I posted? If so, could they
please show me the reason, point me to it or tell me how would I test
the idea.

Thank you.
 
T

Tom Cole

Works same in both browsers for me

I have to agree with Yukabuk. I see no difference at all. My machine
has a dual core 2.4 GHz processor and 4 GB of RAM, maybe that is why.
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Members online

Forum statistics

Threads
473,744
Messages
2,569,484
Members
44,903
Latest member
orderPeak8CBDGummies

Latest Threads

Top