Forum Moderators: open
onclick events to make a user-generated popup when clicking on a thumbnail. Currently I have this (radically simplified for clarity, in reality it's a lot worse): <div class="photohold">
<ol class="phindex">
<li><a href="/photos/s01.php" [b]onclick="ouvreMoi('/photos/s01.php','s01');return false;"[/b]><img src="/photos/s-050902-1.jpg" width="57" height="75" alt=""></a></li>
<li><a href="/photos/s02.php" [b]onclick="ouvreMoi('/photos/s02.php','s02');return false;"[/b]><img src="/photos/s-050805-1.jpg" width="76" height="75" alt=""></a></li>
<li><a href="/photos/s03.php" [b]onclick="ouvreMoi('/photos/s03.php','s03');return false;"[/b]><img src="/photos/s-050903-1.jpg" width="84" height="75" alt=""></a></li>
</ol>
</div> With the following very simple Javascript:
function ouvreMoi(theURL,winName){
newWindow = window.open(theURL,winName,'top=20,left=15,scrollbars=yes,resizable=yes,width=700,height=565');
} Rather than having to repeat everything, I would like the markup to resemble this::
<div class="photohold">
<ol class="phindex">
<li><a href="/photos/s01.php"><img src="/photos/s-050902-1.jpg" width="57" height="75" alt=""></a></li>
<li><a href="/photos/s02.php"><img src="/photos/s-050805-1.jpg" width="76" height="75" alt=""></a></li>
<li><a href="/photos/s03.php"><img src="/photos/s-050903-1.jpg" width="84" height="75" alt=""></a></li>
</ol>
</div> ie. with no
onclick at all. As you can see, the thumbnails are in an unordered list within a div - each with a specific id or class which is only used for the section where I need the popups to appear. My question is this: is it possible with Javascript to target the links within a specific
id or class and make them generate a popup without having to have all the redundant inline scripting?
This one will attach the function below as the onclick method to all <a> tags that are within any <div class="photohold"> in the document.
The className is tested by a regular expression, so a className like "doo photohold" will also be accepted.
The script checks all the document's DIVs for the className. If there are many divs of all kinds, it may be worth targeting a common parent (if there is one) for efficiency.
There is enough info in the link's href to use for the opening function.
onload = function()
{
var regTargetClass = /\bphotohold\b/;
var divs = document.getElementsByTagName('div');
// loop divs
for(var i=0, div; div=divs[i++];)
{
// reject non-photohold divs
if(! regTargetClass.test(div.className) ) continue;
// attach onclick event to each <a>
var links = div.getElementsByTagName('a');
for(var j=0, link; links=links[j++];)
links.onclick = ouvreMoi;
}}
//!: Corrupted pipe char, ¦, will need to be replaced with a proper one.
function ouvreMoi()
{
newWindow = window.open(
this.href,
this.href.replace(/^.*\/¦\.[^\.]*$/g, ''), // #1
'top=20,left=15,scrollbars=yes,resizable=yes,width=700,height=565'
);
}
#2 is the "usual approach". I'm trying to convince Rambo Tribble of the merits of an approach that I'm championing. There's no need for the script to go round adding event handlers all over the place, which could take time.
document.onclick = function(e)
{
var elm = getEventSrc(e);
// filter clicks from images that are
// descendants of elms with class, "photohold"
if( elm.tagName.toUpperCase = 'IMG'
&& getAncestor(elm.parentNode, 'className',/\bphotohold\b/)
){
ouvreMoi(elm.parentNode);
preventDefault(e); // stop href being followed.
}
}function ouvreMoi(link)
{
newWindow = window.open(
link.href,
link.href.replace(/^.*\/¦\.[^\.]*$/g, ''),
'top=20,left=15,scrollbars=yes,resizable=yes,width=700,height=565'
);
}//---------------------------------------------------------
// Utilities used
//---------------------------------------------------------function preventDefault(e)
{
e? e.preventDefault() : event.returnValue = false;
}function getEventSrc(e)
{
var targ = (e¦¦event).target;
if(targ)
return targ.nodeType==1?targ:targ.parentNode
else
return event.srcElement;}
function getAncestor(elm,prop,regVal)
{
while(elm)
{
if(regVal.test(elm[prop])) return elm;
elm = elm.parentNode;
}
}//---------------------------------------------------------
[edited by: jatar_k at 3:34 pm (utc) on Oct. 5, 2005]
[edit reason] remove old url [/edit]
onload = function()
{
var regTargetClass = /\bphotohold\b/;
var divs = document.getElementsByTagName('div');
// loop divs
for(var i=0, div; div=divs[i++];)
{
// reject non-photohold divs
if(! regTargetClass.test(div.className) ) continue;
// attach onclick event to each <a>
var links = div.getElementsByTagName('a');
for(var j=0, link; link=links[j++];)
link.onclick = ouvreMoi;
}
}
//---------------------------------------------------------
I'm not clear which one you are recommending
Nor am I, encyclo!
The first one pretty much standard fare, and won't confuse anybody.
The second is more experimental. I think it's better, but I don't want to be responsible for leading you down the garden path.
The drawbacks of the first are (these are commonly discussed issues)
1) The initialising process cannot be done until after the link elements themselves have loaded. Using the onload event as a trigger will mean that thisprocess doesn't even start until all images have loaded, which could possibly be a few seconds.
Only IE has a document.onContentReady event, so the only sensible cross-browser work-around is to place a small script block, containing a call to the initialising function, at the bottom of the document. Some people feel uncomfortable will this, but Tribble says that Snoop Dogg told him it's OK.
2) When the initialisiation is triggered, if there's a lot of event handler attachment to do, this can also take time.
The event handlers are 'manually' attached to all the links and, before that, all the documents DIVs need to be checked. Not a big deal in all but the most DIV-heavy documents, but you may still notice a little iniation delay.
The second script only needs an event handler on the document. This can be done immediately (since the document always exists).
Yet, if you're not in the mood for the BM adventure of script 2, script 1 can be improved.
I understood (or at least, allowed for) the possibility that there might be more than one "photohold" DIV in a document. If, in fact, there will only ever be one of these, then the efficiency can be improved by targetting it directly. To do this, the div will need an id instead of, or as well as, a className.
If there is just one div, with an id (say, "photoholder"). The onload function can be simply.
onload = function()
{
var links = document.getElementById('photoholder')
.getElementsByTagName('a');
for(var k=0, link; link=links[k++];)
link.onclick = ouvreMoi;
}