click-through to underlying element

N

nutso fasst

Hello.

Is there a way to make an element 'transparent' to mouse activity, such that
mouse events go to the underlying element? I have an absolutely-positioned
image element with transparency that partly overlaps another element. I want
mouse events on the overlapping image to go to the underlying element.

Thanks,
nf
 
R

RobG

nutso said:
Hello.

Is there a way to make an element 'transparent' to mouse activity, such that
mouse events go to the underlying element? I have an absolutely-positioned
image element with transparency that partly overlaps another element. I want
mouse events on the overlapping image to go to the underlying element.

Thanks,
nf
Read here on how events work with the DOM.

<URL:http://www.quirksmode.org/js/contents.html#events>

Different browsers have different event models, however the behaviour
that you require is basically standard - or do you have a specific
example of an event not being passed to an 'underlying' element?
 
N

nutso fasst

RobG said:

Thanks for the reply and the link to the informative website. Unfortunately
I did not find what I needed, and perhaps my description of what I crave
wasn't clear.

I have two images. One is a panorama wider than most browser windows, which
I have put into a DIV that has been styled to clip on the right side. The
important part of the image is at the left side, but I want to give the
option to view the whole image. So I set an onclick event for the DIV, which
toggles the overflow property between "clip" and "auto". This way the image
can be scrolled if required but has no ugly scroll bars if not. The problem
is that there is a absolutely-positioned GIF image overlapping the bottom of
the wide image. Most of this overlap is in the transparent part of the GIF,
which presents two problems:

1. When someone clicks in the transparent part of the GIF, it does not
trigger the event attached to the overlapped DIV.

2. When the overflow property of the DIV is changed to "auto", a scrollbar
appears at the bottom of the image. The scrollbar is overlapped by the
transparent GIF, and is therefor inaccessible in the transparent areas of
the GIF.

Problem #1 can be overcome by attaching an event to the overlapping GIF, but
that is messy as I must then determine if the cursor is over the DIV.

So, my hope was that there was some way to deactivate the GIF to mouse
events, so that the handler for the overlapped DIV would get all events
where the GIF is overlapping. Otherwise it appears I'll have to trap events
for the GIF, determine if they are over the DIV, then change the z-order of
the DIV to bring it to the top so the scroll bar will be accessible.

nf
 
R

RobG

nutso said:
Thanks for the reply and the link to the informative website. Unfortunately
I did not find what I needed, and perhaps my description of what I crave
wasn't clear.

I have two images. One is a panorama wider than most browser windows, which
I have put into a DIV that has been styled to clip on the right side. The
important part of the image is at the left side, but I want to give the
option to view the whole image. So I set an onclick event for the DIV, which
toggles the overflow property between "clip" and "auto". This way the image
can be scrolled if required but has no ugly scroll bars if not. The problem
is that there is a absolutely-positioned GIF image overlapping the bottom of
the wide image. Most of this overlap is in the transparent part of the GIF,
which presents two problems:

1. When someone clicks in the transparent part of the GIF, it does not
trigger the event attached to the overlapped DIV.

2. When the overflow property of the DIV is changed to "auto", a scrollbar
appears at the bottom of the image. The scrollbar is overlapped by the
transparent GIF, and is therefor inaccessible in the transparent areas of
the GIF.

Problem #1 can be overcome by attaching an event to the overlapping GIF, but
that is messy as I must then determine if the cursor is over the DIV.

So, my hope was that there was some way to deactivate the GIF to mouse
events, so that the handler for the overlapped DIV would get all events
where the GIF is overlapping. Otherwise it appears I'll have to trap events
for the GIF, determine if they are over the DIV, then change the z-order of
the DIV to bring it to the top so the scroll bar will be accessible.

Below is some code that does what you want. I copied a fair bit of
the stuff from quirksmode.org posted by FredOz a few days ago. It
detects the location of your clipping div, then sees if a click
happens over it based on the location of the click.

If it's a hit, the div's z-index is raised so you can get to the
scroll bars. When the user clicks away from the image, it is lowered
again and the overflow set back to hidden (there is no 'clip' unless
that is a Microsoft invention).

Careful with IE, clicks outside the div are not always in the
document (IE's page does not fill the window like other browsers do)
so sometimes clicking outside the image does not lower it again.
Just click over something.

Uses getElementById without testing, but otherwise should be pretty
solid. Lightly commented and tested in IE and Firefox.

The images I used are the logos from Google (a.gif) and Yahoo
(b.gif) - the Yahoo one has transperancy too.

Make sure you specify all needed dimensions in px as IE has a habit
of reporting things in whatever units they are set in (%, em, etc.)
where as Firefox tends to always report px if appropriate.


<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01//EN"
"http://www.w3.org/TR/html4/strict.dtd">
<html>
<head>
<title> Image Overlap </title>
<meta http-equiv="Content-Type"
content="text/html; charset=ISO-8859-1">

<style type="text/css">
..container { border: 1px solid red;}
</style>

<script type="text/javascript">

// Remember if we've raised the div with the image or not
var raised = false;

function doClick(e){
e = e || window.event;
var x = document.getElementById('OuterDiv');
var xTLx, xTLy, xBRx, xBRy, msg;

// Get location of click
var eX = e.clientX + pXoffset();
var eY = e.clientY + pYoffset();

// Get bounding co-ords of image
xTLx = findPosX(x); // top left x
xTLy = findPosY(x); // top left y

// Add width & height
if (x.style && x.style.width) {
xBRx = xTLx + +x.style.width.replace(/px/,'');
}
if (x.style && x.style.height) {
xBRy = xTLy + +x.style.height.replace(/px/,'');
}
// Purely for show
msg = xTLx + ', ' + xTLy + '<br>' + xBRx + ', ' + xBRy;
msg += '<br>' + e.clientX + ', ' + e.clientY;

if ( eX > xTLx && eX < xBRx
&& eY > xTLy && eY < xBRy) {
if (!raised) {
x.style.overflow = 'auto';
x.style.zIndex -= -100; // -ve converts z-index to number
raised = true;
}
msg += '<br><b>HIT</b>'; // Just for show

} else {
if (raised) {
x.style.overflow = 'hidden';
x.style.zIndex -= 100;
raised = false;
}
msg += '<br>miss'; // Just for show
}
// More for show
msg += '<br>Raised: ' + raised + '<br>z-index: '
+ x.style.zIndex;
document.getElementById('xx').innerHTML = msg; // Just for show
}

// From quirksmode.org
function findPosX(obj) {
var curleft = 0;
if (obj.offsetParent) {
while (obj.offsetParent) {
curleft += obj.offsetLeft
obj = obj.offsetParent;
}
} else if (obj.x) {
curleft += obj.x;
}
return curleft;
}

// From quirksmode.org
function findPosY(obj) {
var curtop = 0;
if (obj.offsetParent) {
while (obj.offsetParent) {
curtop += obj.offsetTop
obj = obj.offsetParent;
}
} else if (obj.y) {
curtop += obj.y;
}
return curtop;
}

// From quirksmode.org
function pXoffset(){
if (self.pageXOffset) { // all except Explorer
return self.pageXOffset;
} else if (document.documentElement
&& document.documentElement.scrollTop) {// Explorer 6 Strict
return document.documentElement.scrollLeft;
} else if (document.body) { // all other Explorers
return document.body.scrollLeft;
}
}

// From quirksmode.org
function pYoffset(){
if (self.pageYOffset) { // all except Explorer
return self.pageYOffset;
} else if (document.documentElement
&& document.documentElement.scrollTop) {// Explorer 6 Strict
return document.documentElement.scrollTop;
} else if (document.body) { // all other Explorers
return document.body.scrollTop;
}
}

</script>
</head>
<body onclick="doClick(event)">

<div class="container" id="OuterDiv" style="
overflow: hidden; position: absolute; top: 50px; left: 100px;
z-index: 1; width: 100px; height: 100px;
">
<img src="a.gif" name="imageA"></div>
<div class="container" style="
position: absolute; top: 100px; left: 100px; z-index: 5;"<img src="b.gif" name="imageB" style="z-index: 5"></div>
<br><span id="xx"></span>

</body>
</html>
 
R

RobB

nutso said:
Thanks for the reply and the link to the informative website. Unfortunately
I did not find what I needed, and perhaps my description of what I crave
wasn't clear.

I have two images. One is a panorama wider than most browser windows, which
I have put into a DIV that has been styled to clip on the right side. The
important part of the image is at the left side, but I want to give the
option to view the whole image. So I set an onclick event for the DIV, which
toggles the overflow property between "clip" and "auto". This way the image
can be scrolled if required but has no ugly scroll bars if not. The problem
is that there is a absolutely-positioned GIF image overlapping the bottom of
the wide image. Most of this overlap is in the transparent part of the GIF,
which presents two problems:

1. When someone clicks in the transparent part of the GIF, it does not
trigger the event attached to the overlapped DIV.

2. When the overflow property of the DIV is changed to "auto", a scrollbar
appears at the bottom of the image. The scrollbar is overlapped by the
transparent GIF, and is therefor inaccessible in the transparent areas of
the GIF.

Problem #1 can be overcome by attaching an event to the overlapping GIF, but
that is messy as I must then determine if the cursor is over the DIV.

So, my hope was that there was some way to deactivate the GIF to mouse
events, so that the handler for the overlapped DIV would get all events
where the GIF is overlapping. Otherwise it appears I'll have to trap events
for the GIF, determine if they are over the DIV, then change the z-order of
the DIV to bring it to the top so the scroll bar will be accessible.

nf


Hi there nutso. I think there's a design flaw inherent in the whole
concept here, but I'll play along anyway. Calling one event handler
from another is no big deal, but attempting to use a system scrollbar
when it's underneath something...eesh. btw mozilla scrollbars are not
ugly! #:=)

Anyway...

<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01//EN"
"http://www.w3.org/TR/html4/strict.dtd">
<html>
<head>
<style type="text/css">

body {
background:
url(http://www.light-speed-web-graphics.com/stripes_horiz_different/fastest_00008.GIF);
}
#container {
position: relative;
width: 97%;
margin: 20px auto;
background: #000;
z-index: 2;
}
#xpander {
position: absolute;
left: 0;
top: 0;
width: 100%;
border: 4px #fff outset;
overflow: hidden;
}
#xpander img {
display: block;
border: none;
}
#cthru {
position: absolute;
left: 416px;
top: 386px;
width: 140px;
height: 140px;
z-index: 3;
}

</style>
<script type="text/javascript">

function expcon(obj)
{
if (document.getElementById)
{
obj.style.overflowX = /\bscroll\b/.test(obj.style.overflowX) ?
'hidden' : 'scroll';
obj.style.overflow = /\bauto\b/.test(obj.style.overflow) ? 'hidden' :
'auto';
if ('undefined' != typeof obj.scrollLeft)
obj.scrollLeft = 0;
if (obj = document.getElementById('cthru'))
obj.style.zIndex = /((^$)|0|3)/.test(obj.style.zIndex) ? '1' : '3';
}
}

function routeclick(id)
{
var el;
if (document.getElementById
&& (el = document.getElementById(id))
&& 'undefined' != typeof el.onclick)
el.onclick();
}

</script>
</head>
<body>
<div id="container">
<div id="xpander"
title="click to expand / contract"
onclick="return expcon(this)">
<img src="http://www.leaney.org/walks/photos/20040430jp.jpg" />
</div></div>
<img id="cthru"
onclick="routeclick('xpander')"
src="http://www.ueda.info.waseda.ac.jp/~hiroto/Graphics/sample1.gif" />
</body>
</html>
 
R

RobG

nutso said:
Wowza, thanks a bunch, but I'd already implemented it as I figured I'd have
to and it works fine. I set the onclick event for the two elements in
question. Then the only coordinate I need to be concerned with is the bottom
Y of the DIV. If the cursor is above or equal it's OK. The code:

This is an interesting issue. If that is what you are going to do,
you may as well use RobB's method and fire the onclick from both
images - it's the simplest by far.

The issue is that the click goes down to the lowest element in the
branch of the DOM tree that was clicked on, not the one with the
lowest visual representation. So if the GIF you want to raise is on
a separate limb of the tree, its onclick won't be fired when you
click on the the transparent GIF.

An image can't be a child of another image, but you can wrap them
both in a div, put the onclick on that then let bubbling fire the
div's onclick but....

Put a div around both images (even one limited to the size of
the clipping div) and its onclick will be fired when the click
bubbles up from the clipped image. But it also gets fired from
events bubbling up from the transparent GIF too because it's higher
up the same branch of the DOM tree, so the result is exactly the same
as if you just put the onclick on both images.

So do that and keep things simple - anything based on pixel-perfect
locations of elements in the page is bound to fail sooner rather than
later.
 
R

RobB

nutso said:
Wowza, thanks a bunch, but I'd already implemented it as I figured I'd have
to and it works fine. I set the onclick event for the two elements in
question. Then the only coordinate I need to be concerned with is the bottom
Y of the DIV. If the cursor is above or equal it's OK. The code:

var ediv = 0;
var eimg = 0;
var bot = 0;
var scroll = false;

function togglescroll(e) {
var cury = 0;
if (!e) var e = window.event;
if (e.pageY) {
cury = e.pageY;
} else {
if (e.clientY) cury = e.clientY + document.body.scrollTop;
}
if(cury <= bot) {
if(scroll) {
ediv.style.overflow="hidden";
scroll = false;
ediv.style.zIndex=0;
} else {
ediv.style.overflow="auto";
scroll = true;
ediv.style.zIndex=20;
}
}
}
// get global variables onload to streamline toggleclip
function getvars() {
if(document.getElementById) {
ediv=document.getElementById("clipdiv");
eimg=document.getElementById("absoimg");
} else {
if(document.all) {
ediv = document.all.clipdiv;
eimg = document.all.absoimg;
}
}
if(ediv) {
ediv.onclick = togglescroll;
eimg.onclick = togglescroll;
bot = ediv.offsetTop + 150; // the height won't change
}
}

<body onload="getvars()">

Clicking on the image toggles the scrollbar. In FF only the bottom bar
appears, in IE both bottom and left bars appear. Property 'clip' isn't MS,
t'was a typo.

take care,
nf

[note: apologies if this is a duplicate post]

Hi there nutso. I think there's a design flaw inherent in the whole
concept here, but I'll play along anyway. Calling one event handler
from another is no big deal, but attempting to use a system scrollbar
when it's underneath something...eesh. btw mozilla scrollbars are not
ugly! #:=)

Anyway...

<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01//EN"
"http://www.w3.org/TR/html4/strict.dtd">
<html>
<head>
<style type="text/css">

body {
background: url(

http://www.light-speed-web-graphics.com/stripes_horiz_different/fastest_00008.GIF);
}
#container {
position: relative;
width: 97%;
margin: 20px auto;
background: #000;
z-index: 2;
}
#xpander {
position: absolute;
left: 0;
top: 0;
width: 100%;
border: 4px #fff outset;
overflow: hidden;
}
#xpander img {
display: block;
border: none;
}
#cthru {
position: absolute;
left: 422px;
top: 386px;
width: 140px;
height: 140px;
z-index: 3;
}

</style>
<script type="text/javascript">

function expcon(obj)
{
if (document.getElementById)
{
obj.style.overflowX = /\bscroll\b/.test(obj.style.overflowX) ?
'hidden' : 'scroll';
obj.style.overflow = /\bauto\b/.test(obj.style.overflow) ?
'hidden' : 'auto';
if ('undefined' != typeof obj.scrollLeft)
obj.scrollLeft = 0;
obj.title = /version/.test(obj.title) ?
' click to reset...' : ' click for full-size version...';
if (obj = document.getElementById('cthru'))
obj.style.zIndex = /((^$)|0|3)/.test(obj.style.zIndex) ?
'1' : '3';
}
}

function routeclick(id)
{
var el;
if (document.getElementById
&& (el = document.getElementById(id))
&& 'undefined' != typeof el.onclick)
el.onclick();
}

</script>
</head>
<body>
<div id="container">
<div id="xpander"
title=" click for full-size version..."
onclick="return expcon(this)">
<img src="http://www.leaney.org/walks/photos/20040430jp.jpg" />
</div></div>
<img id="cthru"
onclick="routeclick('xpander')"
src="http://www.ueda.info.waseda.ac.jp/~hiroto/Graphics/sample1.gif" />
</body>
</html>
 
N

nutso fasst

Hi, Rob. Your example looks pretty straightforward, but it doesn't account
for 'cthru' only partially overlapping 'xpander'. Also, I don't understand
statements like "/\bscroll\b/.test(obj.style.overflowX)." Can you explain?

Thanx,
nf
 
N

nutso fasst

RobG said:
This is an interesting issue. If that is what you are going to do,
you may as well use RobB's method and fire the onclick from both
images - it's the simplest by far.

But also fires over the overlapping image where it doesn't overlap.
So do that and keep things simple - anything based on pixel-perfect
locations of elements in the page is bound to fail sooner rather than
later.

Bound to fail? What I wrote works with FF and with IE all the way back to
v.4.0, and standardization is improving. But there is a way to do it that
doesn't rely on coordinates and doesn't need an event on the overlapping
image: another div that overlaps both. Simple, really. I've removed IE 4's
document.all support for clarity...

<!-- nutso fasst's umpteenth solution -->
<script type="text/javascript">

var cdiv=0;
var tdiv=0;

function togglescroll(e) {
if(cdiv.style.zIndex!=0) {
cdiv.style.overflow="hidden";
cdiv.style.zIndex=0;
tdiv.style.zIndex=10;
} else {
cdiv.style.overflow="auto";
cdiv.style.zIndex=10;
tdiv.style.zIndex=0;
}
}

function getvars() {
cdiv=document.getElementById("clipdiv");
tdiv=document.getElementById("topdiv")
cdiv.onclick = togglescroll;
document.getElementById("topclick").onclick = togglescroll;
}
</script>

<style type="text/css">
..rel { position: relative }
#topdiv { position: relative; z-index: 10 }
#topclick { position: absolute; text-align: left;
width: 100%; height: 150px }
#clipdiv { position: relative; width: 100%; height: 150px;
text-align: left; overflow: hidden }
#absimg { position: absolute; top: -60px }
</style>

<body onload="getvars()">
<div id="topdiv"><div id="topclick">&nbsp;</div></div>
<div id="clipdiv"><img height=150 src="images/wideimg.jpg" alt="wide
image"></div>
<table align="right" width=300 cellpadding=0 cellspacing=0 border=0>
<tr>
<td width=300 height=228 valign="top" align="left"><div class="rel"><img
id="absimg" width=300 height=288 src="images/diamondshape.gif"
alt=""></div></td>
</tr>
....

With document.all support added works with IE4 and later, also works with
FF.
 
R

RobG

nutso said:
But also fires over the overlapping image where it doesn't overlap.




Bound to fail?

Page co-ord methods may be OK now, but in future you may introduce
new stuff that messes with some browsers. The news site that I use
recently 'updated' their site so now Firefox has issues with
overlapping text and images until I force a re-fresh by
increasing/decreasing the font size. Not fatal, but a real PITA.

I would expect that page co-ord stuff would have problems in the
above scenario.
What I wrote works with FF and with IE all the way back to
v.4.0, and standardization is improving. But there is a way to do it that
doesn't rely on coordinates and doesn't need an event on the overlapping
image: another div that overlaps both. Simple, really. I've removed IE 4's
document.all support for clarity...

Ah yes, I was most of the way there but my implementation was flawed.
Put the overlying div with the onclick in a separate branch so
neither image gets in the way. Musta been tired...

[...]
With document.all support added works with IE4 and later, also works with
FF.

Clean, tidy, exactly as specified and no posX/Y - congratulations :)
 
N

nutso fasst

Hmm, just noticed another nice thing about this solution. If I add some
titles to the HTML, e.g.:

<div id="topdiv"><div id="topclick" title="click to scroll the
image...">&nbsp;</div></div>
<div id="clipdiv" title="click to hide the scroll bar..."><img height=150
src="images/wideimg.jpg" alt="wide
image"></div>

Presto, contextual instructions!

nf
 
R

RobB

nutso said:
Hi, Rob. Your example looks pretty straightforward, but it doesn't account
for 'cthru' only partially overlapping 'xpander'.

That's pretty cryptic...you said initially:

....which is exactly what I gave you. Make sure that the post wasn't
corrupted, there might be a control character or two in there, and that
long url is truncated.
Also, I don't understand
statements like "/\bscroll\b/.test(obj.style.overflowX)." Can you
explain?

obj.style.overflowX = /\bscroll\b/.test(obj.style.overflowX) ?
'hidden' : 'scroll';

Uses the regular expression /\bscroll\b/, which will match the string
'scroll' (could have used /^scroll$/ or simply /scroll/ also); if it
matches, RegExp.test returns true which assigns 'hidden' to the
overflowX property, otherwise assigning 'scroll'. A toggle, in other
words. Note that, first time around, this property will be the empty
string, a result of the CSS having cascaded from a global stylesheet
rather than being assigned in the element's HTML and setting the Style
object directly. So the toggle works both initially, and after the
property is set.

obj.style.overflow = /\bauto\b/.test(obj.style.overflow) ?
'hidden' : 'auto';

Same for the overflow property. Setting both is required to suppress
the vertical scrollbar cross-browser.

if ('undefined' != typeof obj.scrollLeft)
obj.scrollLeft = 0;

Returns image to flush left if 'unexpanded'. Seemed logical.

obj.title = /version/.test(obj.title) ?
' click to reset...' : ' click for full-size version...';

Swaps title (prompt).

if (obj = document.getElementById('cthru'))
obj.style.zIndex = /((^$)|0|3)/.test(obj.style.zIndex) ?
'1' : '3';

Flips z-index; if empty string ^$ (first-time around, Gecko, others)
sets to '1', 'underlapping' gif; if '0' (MSIE, first-time, illogically,
as it's also cascaded) does same; if '3' (2nd+ time, all), ditto;
otherwise sets to '3', restoring overlap).

The other function simply causes clicks on the gif to invoke the
onclick handler of the inner container div.

The above is easily modifiable for a variety of different behaviors;
kept it simple as I wasn't entirely sure how you wanted it to work.
Fire away...

cheers, Rob
 
R

RobB

nutso said:
Hi, Rob. Your example looks pretty straightforward, but it doesn't account
for 'cthru' only partially overlapping 'xpander'.

Aargh...not all that 'cryptic' after all...I get it.

Rather than the rigmarole of getting click position, comparing to
graphic bottom position, etc. - took the easy way out, superimposing a
bottom-clipped version of the same gif within a common container, and
used that for event 'routing'. Not quite perfect cross-browser
(positioning variances) but very close. I'd normally use some simple
CSS hacks to equalize the display if this were my page (google 'css
hacks', if interested, for ways to hide rules from various browsers).
See if this is better:

<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01//EN"
"http://www.w3.org/TR/html4/strict.dtd">
<html>
<head>

<style type="text/css">

body {
background: url(
http://www.light-speed-web-graphics.com/
stripes_horiz_different/fastest_00008.GIF);
}
#container {
position: relative;
width: 97%;
margin: 20px auto;
background: #000;
z-index: 2;
}
#xpander {
position: absolute;
left: 0;
top: 0;
width: 100%;
border: 4px #fff outset;
overflow: hidden;
cursor: e-resize;
}
#xpander img {
display: block;
border: none;
}
#cthru {
position: absolute;
left: 422px;
top: 386px;
width: 140px;
height: 140px;
z-index: 3;
}
#cthru #trigger {
position: absolute;
left: 0;
top: 0;
width: 140px;
height: 140px;
clip: rect(auto auto 78px auto);
cursor: e-resize;
z-index: 2;
}
#cthru img {
position: absolute;
left: 0;
top: 0;
width: 140px;
height: 140px;
z-index: 1;
}

</style>
<script type="text/javascript">

function expcon(obj)
{
if (document.getElementById)
{
obj.style.overflowX = /\bscroll\b/.test(obj.style.overflowX) ?
'hidden' : 'scroll';
obj.style.overflow = /\bauto\b/.test(obj.style.overflow) ?
'hidden' : 'auto';
if ('undefined' != typeof obj.scrollLeft)
obj.scrollLeft = 0;
obj.title = /version/.test(obj.title) ?
' ~ click to reset ~ ' : ' ~ click for full-size version ~ ';
if (obj = document.getElementById('cthru'))
obj.style.zIndex = /((^$)|0|3)/.test(obj.style.zIndex) ?
'1' : '3';
}
}

function routeclick(id)
{
var el;
if (document.getElementById
&& (el = document.getElementById(id))
&& 'undefined' != typeof el.onclick)
el.onclick();
}

</script>
</head>
<body>
<div id="container">
<div id="xpander"
title=" ~ click for full-size version ~ "
onclick="return expcon(this)">
<img src="http://www.leaney.org/walks/photos/20040430jp.jpg" />
</div></div>
<div id="cthru">
<img id="trigger"
onclick="routeclick('xpander')"
src="http://www.ueda.info.waseda.ac.jp/~hiroto/Graphics/sample1.gif" />
<img
src="http://www.ueda.info.waseda.ac.jp/~hiroto/Graphics/sample1.gif" />
</div>
</body>
</html>

You'll need to paste that body {background: url(...); into a single
long url.
 
N

nutso fasst

RobG said:
Clean, tidy, exactly as specified and no posX/Y - congratulations :)

Thanks. Most folks would consider it time badly spent, but sometimes the
solving of the problem is more important than the usefulness of the
solution.

nutso "the joy is in the journey" fasst
 
N

nutso fasst

RobB said:
Uses the regular expression /\bscroll\b/, which will match the string
'scroll' (could have used /^scroll$/ or simply /scroll/ also); if it
matches, RegExp.test returns true which assigns 'hidden' to the
overflowX property, otherwise assigning 'scroll'. A toggle, in other
words.

Ah, yes. I understand the toggle, I wasn't clear on the use of the regex.
Isn't
obj.style.overflow = (obj.style.overflow=='auto') ? 'hidden' : 'auto';
more efficient, and testing on the numeric value of zIndex more efficient
still? Having determined the zIndex, other tests are unnecessary, and one
'if()' is more efficient than multiple toggles.
Same for the overflow property. Setting both is required to suppress
the vertical scrollbar cross-browser.

I was under the impression overflowX was a subset of overflow, setting
overflow sets both overflowX and overflowY.
if ('undefined' != typeof obj.scrollLeft)
obj.scrollLeft = 0;

Returns image to flush left if 'unexpanded'. Seemed logical.

Good idea! Thanks.

Your 2nd solution looks good, tho it seems to me either an empty div or a
1-pixel-high totally-transparent gif sized with CSS to the overlapping area
would work better than a clipped duplicate of the overlapped image. On the
off chance of no stylesheet support, it wouldn't significantly affect
appearance. I put "&nbsp;" in my overlapping div out of fear that some
browser might ignore a click on an empty element, but perhaps that isn't
necessary. It works without it in IE and FF.

nf
 
R

RobB

nutso said:
:)

Thanks. Most folks would consider it time badly spent, but sometimes the
solving of the problem is more important than the usefulness of the
solution.

nutso "the joy is in the journey" fasst

As they say on that *Millionaire* show..."yes, final answer".

<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01//EN"
"http://www.w3.org/TR/html4/strict.dtd">
<html>
<head>
<style type="text/css">

body {
background:
url(http://www.light-speed-web-graphics.com/stripes_horiz_different/fastest_00008.GIF);
}
#container {
position: relative;
width: 95%;
margin: 20px auto;
background: #000;
z-index: 2;
}
#xpander {
position: absolute;
left: 0;
top: 0;
width: 100%;
border: 4px #eef outset;
overflow: hidden;
cursor: e-resize;
}
#xpander img {
display: block;
border: none;
}
#cthru {
position: absolute;
left: 422px;
top: 386px;
width: 140px;
height: 140px;
z-index: 3;
}
#cthru #trigger {
position: absolute;
left: 0;
top: 0;
width: 140px;
height: 140px;
cursor: e-resize;
z-index: 2;
}
#cthru img {
position: absolute;
left: 0;
top: 0;
width: 140px;
height: 140px;
z-index: 1;
}

</style>
<script type="text/javascript">

function expcon(obj)
{
if (document.getElementById)
{
obj.style.overflowX = /scroll/.test(obj.style.overflowX) ?
'hidden' : 'scroll';
obj.style.overflow = /auto/.test(obj.style.overflow) ?
'hidden' : 'auto';
if ('undefined' != typeof obj.scrollLeft)
obj.scrollLeft = 0;
obj.title = /version/.test(obj.title) ?
' ~ click to reset ~ ' : ' ~ click for full-size version ~ ';
if (obj = document.getElementById('cthru'))
obj.style.zIndex = /((^$)|0|3)/.test(obj.style.zIndex) ?
'1' : '3';
}
}

function routeclick(id)
{
var el;
if (document.getElementById
&& (el = document.getElementById(id))
&& 'undefined' != typeof el.onclick)
el.onclick();
}

function getTopBottom(id)
{
var obj = document.getElementById(id),
ht = obj.offsetHeight,
y = obj.offsetTop;
while ((obj = obj.offsetParent) != null)
y += obj.offsetTop;
return {top: y, bottom: y + ht};
}

function init()
{
if (document.getElementById)
{
var xb, ct, tg, bclip, adj = 4,
cp = 'rect(auto auto 0px auto)';
if ((xb = getTopBottom('xpander').bottom)
&& (ct = getTopBottom('cthru').top)
&& (tg = document.getElementById('trigger'))
&& !isNaN(bclip = (xb - ct - adj)))
{
tg.style.clip = cp.replace(/0/, bclip);
}
}
}

window.onload = init;

</script>
</head>
<body>
<div id="container">
<div id="xpander"
title=" ~ click for full-size version ~ "
onclick="return expcon(this)">
<img src="http://www.leaney.org/walks/photos/20040430jp.jpg">
</div></div>
<div id="cthru">
<img id="trigger"
title=" ~ click for full-size version ~ "
onclick="routeclick('xpander')"
src="http://www.ueda.info.waseda.ac.jp/~hiroto/Graphics/sample1.gif">
<img
src="http://www.ueda.info.waseda.ac.jp/~hiroto/Graphics/sample1.gif">
</div>
</body>
</html>

If you need to see the efficacy of this, add 'background: red;' to the
CSS for #cthru #trigger. 'adj' trims the clip to deactivate the border
area.

Again, googlegroups will probably mangle this, so, repaste any
truncated urls as needed, close tags, open in Notepad and look for any
control characters (dashes) inserted. Been haranguing those pinheads
for a week...
 
R

RobB

nutso said:
Ah, yes. I understand the toggle, I wasn't clear on the use of the regex.
Isn't
obj.style.overflow = (obj.style.overflow=='auto') ? 'hidden' : 'auto';
more efficient, and testing on the numeric value of zIndex more efficient
still? Having determined the zIndex, other tests are unnecessary, and one
'if()' is more efficient than multiple toggles.

Suit yourself, it's not a repetitive/recursive routine. Go ahead and
fine-tune if you like, the gains will likely be minimal. It's also not
necessarily turn-key, this is a free forum !

z-index is a string, btw.
I was under the impression overflowX was a subset of overflow, setting
overflow sets both overflowX and overflowY.

I used to be under a lot of impressions, too, until I started playing
around with CSS in different browsers. One ends up using what works. If
you can find another approach, more power to you. Read some CSS
ngs/forums/blogs to see how unstraightforward presentational coding can
get. #;=)

(snip)
Your 2nd solution looks good, tho it seems to me either an empty div or a
1-pixel-high totally-transparent gif sized with CSS to the overlapping area
would work better than a clipped duplicate of the overlapped image.

No (see below). Why download that old 1-pixel-transparency when you
have the perfect item at hand: the very *same* transparency, ready for
'layering'.
On the off chance of no stylesheet support [ .. ]
F-them.

I put "&nbsp;" in my overlapping div out of fear that some
browser might ignore a click on an empty element, but perhaps that isn't
necessary. It works without it in IE and FF.

It does? Not here (ie6win2k)...
 
N

nutso fasst

It does? Not here (ie6win2k)...

True on ie6winXP as well. Sheee-it. Earlier IE do work OK. Well, this has
definitely been interesting. I dumped the overlapping div and put a
fully-transparent gif over the other image overlap and pointed its onclick
to togglescroll. AFICT this does work on IE4-6, FF and Opera. As for
overhead in getting the gif...it's 46 bytes, and I'm more concerned about
the possibility of misalignment.

Thanks much for all your input.

This is gratis work for a local library support group, BTW. Prob'ly only one
fellow (besides me) at the far right of the wide image who'll use the
scroll.

nf
 

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

No members online now.

Forum statistics

Threads
473,772
Messages
2,569,593
Members
45,111
Latest member
VetaMcRae
Top