|
|
Yossi Admon
Bipolar (III) Inmate
From: Israel Insane since: Nov 2001
|
posted 11-20-2003 10:20
Hi,
We have a problem with displaying HTML DIV elements on top of HTML SELECT boxes.
Description:
The problem is that the SELECT boxes are displayed on top of the entire page DIVS regardless of the SELECT box z-index (order in the page).
Reason:
The reason for the problem is with the implementation of the HTML SELECT box.
The SELECT box is implemented as a separate window (transparent to the user) on top of our window therefore the z-index is irrelevant in the window scope.
Solution:
We are investigating this problem for a long time and we came out with a lot of complicated solutions.
Last night I?ve had lighting with this issue and I?ve found a solution for the problem.
The solution is to position HTML IFRAME under the DIV need to be displayed and to hide it whenever hiding the DIV.
JavaScript Code Example (for simple use):
var HELPER_IFRAME_ID = "IFrmHelper";
var topDivZIndex = 10000;
// Add dynamic div to the page
function _init(){
// Creating and adding dynamic iframe to the page source.
var oBody = document.getElementsByTagName("BODY").item(0);
var oHelperIframe = document.createElement("IFRAME");
oHelperIframe.setAttribute("id", HELPER_IFRAME_ID);
oHelperIframe.style.border = 0;
oHelperIframe.width = 0;
oHelperIframe.height = 0;
oHelperIframe.style.position = "absolute";
oBody.appendChild(oHelperIframe);
}
// Should return the div actual width.
function getDivWidth(divId){...}
// Should return the div actual height.
function getDivHeight(divId){...}
// Will show the div and the helper iframe.
function showDiv(divId){
var oBody = document.getElementsByTagName("BODY").item(0);
var oHelperIframe = document.getElementById(HELPER_IFRAME_ID);
var oDiv = document.getElementById(divId);
oDiv.style.zIndex = topDivZIndex;
oHelperIframe.style.zIndex = topDivZIndex - 1000;
topDivZIndex += 1;
oHelperIframe.style.top = oDiv.style.top;
oHelperIframe.style.left = oDiv.style.left;
oHelperIframe.width = getDivWidth(divId) - 1;
oHelperIframe.height = getDivHeight(divId) - 1;
oHelperIframe.style.visibility = 'visible';
oDiv.style.visibility = 'visible';
}
// Will hide the div and the helper iframe.
function hideDiv(divId){
var oHelperIframe = document.getElementById(HELPER_IFRAME_ID);
var oDiv = document.getElementById(divId);
oHelperIframe.style.visibility = 'hidden';
oDiv.style.visibility = 'hidden';
}
// Will move the div and the helper iframe to the given X and Y position
function moveDiv(divId, Xpos, Ypos){
var oHelperIframe = document.getElementById(HELPER_IFRAME_ID);
var oDiv = document.getElementById(divId);
oHelperIframe.style.top = Ypos + 1;
oHelperIframe.style.left = Xpos + 1;
oDiv.style.top = Ypos;
oDiv.style.left = Xpos;
}
// Attach to the onload event
if(typeof(window.addEventListener) != "undefined") {
window.addEventListener("load", _init, false);
} else {
window.attachEvent("onload", _init);
}
Yossi Admon
|
poi
Paranoid (IV) Inmate
From: France Insane since: Jun 2002
|
posted 11-20-2003 17:01
Yossi Admon: The problem already popped in the :FAQ: Why does my DHTML menu not go over my Flash movie/frames, iframes?. I had suggested a raw IFRAME based solution/workaround, but never minded to implement it. Your solution is slightly different and really makes sense. At the point that I wonder how nobody thought about it ealier
Is there any particular reason to substract 1000 to the zIndex of the IFrame ? substracting only 1 works in IE6.0 and FB0.7. On the other hand, the onload event puzzles me in your implementation, couldn't you pick an IFrame named divId_iframe in the showDiv() function, and create it if does not already exist. That way the code would work with any number of DIVs and wouldn't override the onload event of the body.
Congrats for that nice shot.
Mathieu "POÏ" HENRI
[This message has been edited by poi (edited 11-20-2003).]
|
Yossi Admon
Bipolar (III) Inmate
From: Israel Insane since: Nov 2001
|
posted 11-20-2003 19:35
-- First the code i've added is a demo code only that should give a basic idea about how to implement solution for this problem.
-- I've used z-index 10000 so it will be the max in the page (no special reason).
-- The onload attachement is not canceling the user onLoad method but adds another call to my code. this is not the complete code for attaching to element events, following is the real code i've used for this attachement:
***********************************************************************************
function _attachToEvent (obj, name, func) {
name = name.toLowerCase();
// Add the hookup for the event.
if(typeof(obj.addEventListener) != "undefined") {
if(name.length > 2 && name.indexOf("on") == 0) name = name.substring(2, name.length);
obj.addEventListener(name, func, false);
} else if(typeof(obj.attachEvent) != "undefined"){
obj.attachEvent(name, func);
} else {
if(eval("obj." + name) != null){
// Save whatever defined in the event
var oldOnEvents = eval("obj." + name);
eval("obj." + name) = function(e) {
try{
func(e);
eval(oldOnEvents);
} catch(e){}
};
} else {
eval("obj." + name) = func;
}
}
}
//Initialization hook up (attache to the window onLoad event)
_attachToEvent(window, "onload", _init);
***********************************************************************************
|
poi
Paranoid (IV) Inmate
From: France Insane since: Jun 2002
|
posted 11-20-2003 20:02
Yossi Admon: I wasn't talking about the default value of topDivZIndex but about the following lines : code:
oDiv.style.zIndex = topDivZIndex;
oHelperIframe.style.zIndex = topDivZIndex - 1000; // <-- I was talking about that line
topDivZIndex += 1;
That can be replaced by : code:
oHelperIframe.style.zIndex = topDivZIndex++;
oDiv.style.zIndex = topDivZIndex;
Well, there's no big deal here
Your _attachToEvent( ... ) is another great piece of code. Thank you for sharing.
Mathieu "POÏ" HENRI
[This message has been edited by poi (edited 11-20-2003).]
|
Nevel
Bipolar (III) Inmate
From: Amsterdam Insane since: Jun 2002
|
posted 11-23-2003 15:44
|
Yossi Admon
Bipolar (III) Inmate
From: Israel Insane since: Nov 2001
|
posted 11-23-2003 18:45
Following is a sample use for tooltip:
===========================
<HTML>
<HEAD>
<TITLE>Simple ToolTip</TITLE>
<SCRIPT language="JavaScript">
/************************************************************************************
* Note:*******************************************************************************
* The use of methods with oToolTip._ prefix is for internal use only (I wish there was a private/public)*
* In order to use this code you just need to use the oToolTip.showToolTip and the oToolTip.hideToolTip*
* methods.****************************************************************************
*************************************************************************************/
var oToolTip = new Object();
oToolTip._topDivZIndex = 10000;
oToolTip._oBody = null;
oToolTip._oHelperIframe = null;
oToolTip._oToolTipDiv = null;
oToolTip._mousePos = new Object();
// Add dynamic div to the page
oToolTip._init = function(){
// Creating and adding dynamic iframe to the page source.
oToolTip._oBody = document.getElementsByTagName("BODY").item(0);
oToolTip._oHelperIframe = document.createElement("IFRAME");
oToolTip._oHelperIframe.style.border = 0;
oToolTip._oHelperIframe.width = 0;
oToolTip._oHelperIframe.height = 0;
oToolTip._oHelperIframe.style.position = "absolute";
oToolTip._oBody.appendChild(oToolTip._oHelperIframe);
// Creating and adding dynamic DIV to the page source (for the tool-tip).
oToolTip._oToolTipDiv = document.createElement("DIV");
oToolTip._oToolTipDiv.style.border = 0;
oToolTip._oToolTipDiv.width = 0;
oToolTip._oToolTipDiv.height = 0;
oToolTip._oToolTipDiv.style.position = "absolute";
oToolTip._oBody.appendChild(oToolTip._oToolTipDiv);
oToolTip._attachToEvent(document, 'onmousemove', oToolTip._mousemove);
}
// Should return the div actual width.
oToolTip._getToolTipDivWidth = function(){
// We are checking the inner table because of a bug in NS/Mozilla with the DIV-->offsetWidth
var tableWidth = "" + oToolTip._oToolTipDiv.getElementsByTagName("table").item(0).offsetWidth;
if(tableWidth.indexOf('px') > -1){
return parseInt(tableWidth.substring(0, tableWidth.infexOf('px')));
} else {
return tableWidth;
}
}
// Should return the div actual Height.
oToolTip._getToolTipDivHeight = function(){
// We are checking the inner table because of a bug in NS/Mozilla with the DIV-->offsetHeight
var tableHeight = "" + oToolTip._oToolTipDiv.getElementsByTagName("table").item(0).offsetHeight;
if(tableHeight.indexOf('px') > -1){
return parseInt(tableHeight.substring(0, tableHeight.infexOf('px')));
} else {
return tableHeight;
}
}
oToolTip._mousemove = function(e){
if(typeof(e) == 'undefined')e = event;
oToolTip._mousePos.Y = e.clientY;
oToolTip._mousePos.X = e.clientX;
if(oToolTip._oToolTipDiv.style.visibility == 'visible'){
oToolTip._fixTipPosition();
}
}
// Will move the div and the helper iframe to the given X and Y position
oToolTip._fixTipPosition = function(){
// Set the Y position
if(oToolTip._mousePos.Y > Math.round(oToolTip._oBody.clientHeight / 2)){
// Open to top
oToolTip._oHelperIframe.style.top = oToolTip._mousePos.Y - oToolTip._getToolTipDivHeight() + oToolTip._oBody.scrollTop;
} else {
// Open to bottom
oToolTip._oHelperIframe.style.top = oToolTip._mousePos.Y + oToolTip._oBody.scrollTop;
}
// Set the X position
if(oToolTip._mousePos.X > Math.round(oToolTip._oBody.clientWidth / 2)){
// Open to left
oToolTip._oHelperIframe.style.left = oToolTip._mousePos.X - oToolTip._getToolTipDivWidth() + oToolTip._oBody.scrollLeft;
} else {
// Open to right
oToolTip._oHelperIframe.style.left = oToolTip._mousePos.X + 5 + oToolTip._oBody.scrollLeft;
}
oToolTip._oToolTipDiv.style.top = oToolTip._oHelperIframe.style.top;
oToolTip._oToolTipDiv.style.left = oToolTip._oHelperIframe.style.left;
}
oToolTip._attachToEvent = function(obj, name, func) {
name = name.toLowerCase();
// Add the hookup for the event.
if(typeof(obj.addEventListener) != "undefined") {
if(name.length > 2 && name.indexOf("on") == 0) name = name.substring(2, name.length);
obj.addEventListener(name, func, false);
} else if(typeof(obj.attachEvent) != "undefined"){
obj.attachEvent(name, func);
} else {
if(eval("obj." + name) != null){
// Save whatever defined in the event
var oldOnEvents = eval("obj." + name);
eval("obj." + name) = function(e) {
try{
func(e);
eval(oldOnEvents);
} catch(e){}
};
} else {
eval("obj." + name) = func;
}
}
}
// Will show the div and the helper iframe.
oToolTip.showToolTip = function(toolTipMessage){
oToolTip._oHelperIframe.style.zIndex = oToolTip._topDivZIndex++;
var divContent = "<table style='border:1px solid black;background-color:LightGoldenrodYellow' cellspacing='0' cellpading='0'><tr><td>" + toolTipMessage + "</td></tr></table>";
oToolTip._oToolTipDiv.innerHTML = divContent;
oToolTip._mousePos
oToolTip._oToolTipDiv.style.zIndex = oToolTip._topDivZIndex++;
oToolTip._oHelperIframe.style.top = oToolTip._oToolTipDiv.style.top;
oToolTip._oHelperIframe.style.left = oToolTip._oToolTipDiv.style.left;
oToolTip._oHelperIframe.width = oToolTip._getToolTipDivWidth();
oToolTip._oHelperIframe.height = oToolTip._getToolTipDivHeight();
oToolTip._oHelperIframe.style.visibility = 'visible';
oToolTip._oToolTipDiv.style.visibility = 'visible';
oToolTip._fixTipPosition();
}
// Will hide the div and the helper iframe.
oToolTip.hideToolTip = function(){
oToolTip._oHelperIframe.style.visibility = 'hidden';
oToolTip._oToolTipDiv.style.visibility = 'hidden';
}
// Attach to the onload event
oToolTip._attachToEvent(window, 'onload', oToolTip._init);
</SCRIPT>
</HEAD>
<BODY>
<span onMouseOver="oToolTip.showToolTip('Over the span tag')" onMouseOut="oToolTip.hideToolTip()">Move mouse over this text</span>
<BR>
Move mouse over the select box
<SELECT onMouseOver="oToolTip.showToolTip('Selected text is: ' + this.options[this.selectedIndex].text)" onMouseOut="oToolTip.hideToolTip()">
<OPTION>Peace</OPTION>
<OPTION>Salam</OPTION>
<OPTION>Shalom</OPTION>
</SELECT>
</body>
</html>
[This message has been edited by Yossi Admon (edited 11-23-2003).]
[This message has been edited by Yossi Admon (edited 11-23-2003).]
|
nokiko
Obsessive-Compulsive (I) Inmate
From: Utrecht,Utrecht, the Netherlands Insane since: Nov 2003
|
posted 11-27-2003 09:51
or you can do what we did
http://www.nokiko.com/dhtml_select/inspiration.html
completely rewrite the dhtml select box in dhtml javascript ( check out the yellow one )
- you have values that are passed and ones that are displayed
fully stylable with css
custom images
abillity to include function to the standard selectbox events and more
Armand
|
Yossi Admon
Bipolar (III) Inmate
From: Israel Insane since: Nov 2001
|
posted 11-27-2003 19:56
nokiko: you have decided to rewrite the select box, most of us would like to keep using the select box defined in the language.
I'm suggesting a workaround for a problem that I hope will be solved in the browsers next generation (among with a lot more bugs).
Anyway it looks like you have done a very nice work (specially the drag and drop).
P.S. The select box you wrote looks bad in NS7.
Yossi Admon
|
vladimir12345
Obsessive-Compulsive (I) Inmate
From: Insane since: Dec 2003
|
posted 12-21-2003 13:43
It doesn't work in IE 5.0 !
Any idea ?
|
Yossi Admon
Bipolar (III) Inmate
From: Israel Insane since: Nov 2001
|
posted 12-22-2003 19:48
Who works with IE5.0? Why?
I think the document.getElementsByTagName and the document.createElement methods are not working in IE 5.0.
|
skaue
Neurotic (0) Inmate Newly admitted
From: Insane since: Jan 2004
|
posted 01-21-2004 11:54
Please state browser compatiblity. Is it only IE 5.5+ ?
|
skaue
Neurotic (0) Inmate Newly admitted
From: Insane since: Jan 2004
|
posted 01-21-2004 11:59
Hehe.... just noticed the IFrame below the DIV shows if you place a tooltp close the the border og the browser. While the tooltip layer wraps, the IFrame doesnt.
Try resize the window so its narrow/small enough
|
Yossi Admon
Bipolar (III) Inmate
From: Israel Insane since: Nov 2001
|
posted 01-21-2004 20:24
skaue: please specify the exact body content and the browser you are using.
|
kayzersoze
Obsessive-Compulsive (I) Inmate
From: Melbourne, Australia Insane since: Apr 2004
|
posted 04-07-2004 01:48
RE: IE 5.0 - You would probably find that a lot of corporate-type companies still use this browser version. Indeed most of the clients of the place I work for in Australia still uses it, much to my annoyance.
Another possible reason this solution may not work in 5.0 (other than certain object methods like getElementsByTagName etc), is that I don't think you can place a DIV over an IFRAME in 5.0. At least, I certainly couldn't when I tried. My solution was to create the IFRAME to the same size and position as the div, then insert the HTML of the DIV into it.
Cheers,
bj.
There are ten types of people in this world - those who understand binary, and those who don't.
|