471,337 Members | 990 Online
Bytes | Software Development & Data Engineering Community
Post +

Home Posts Topics Members FAQ

Join Bytes to post your question to a community of 471,337 software developers and data experts.

Modifying A tag onclick events dynamically - am I crazy

Hi Guys,

I've been battling with this one for hours - I hope that you can help
me!

My code modifies the <aon a page, from a standard document link into
a link with a tailored onclick event.

It works perfectly (assigning the correct images and the correct
onclick events to the correct <atags):
(a) If there's only one link on the page and
(b) If I modify the <atags one at a time - hardcoding (if there's
more than one link on the page).

However, if there's more than one link on the page, my code assigns
each onclick event to all of the previous nodes in the array instead of
each one independently. (I've commented the problematic line of
javascript, with "THIS IS THE PROBLEM LINE"). I must be missing
something!

Here's a page with the code (including a dummy loadDoc function). It
should show the problem as is (the images obviously won't show):

<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0 Transitional//EN">
<html>
<head>
<title>Modify A Links</title>
<link href="ProdsolEpd.css" rel="stylesheet" type="text/css" />
<script type="text/javascript" src="ProdsolEpd.js"></script>
<script language="JavaScript" type="text/javascript">
function ModifyLinks()
{
//Create Document links
var docArray = document.getElementsByTagName('font');
var sourceHTML, sourceHref, path, doc, ext, img, docName, fontNode,
linkNode, imageNode;
for(var d=0;d<docArray.length;d++)
{
if(docArray[d].className=='doc')
{
//Get values
fontNode = docArray[d];
sourceHTML = fontNode.innerHTML;
sourceHref=(sourceHTML.substring(sourceHTML.indexO f('"')+1,sourceHTML.indexOf('">')));
path = sourceHref.substring(sourceHref.indexOf('/',8));
doc = path.substring(path.lastIndexOf('/')+1);
ext = doc.substr(doc.length - 3);
docName = fontNode.innerText;
//Determine image
switch(sourceHTML.substr(sourceHTML.indexOf('>')-4,3))
{
case 'doc' : img="msword.png"; break;
case 'xls' : img="msexcel.png"; break;
case 'ppt' : img="mspowerpoint.png"; break;
case 'pdf' : img="pdf.png"; break;
}
linkNode = fontNode.children(0);
linkNode.setAttribute('href','#');
imageNode =
linkNode.insertBefore(document.createElement('img' ),linkNode.firstChild);
imageNode.src = 'Skins/Standard/'+img;
imageNode.alt = docName;
linkNode.onclick = function(){loadDoc(sourceHref)};//THIS IS THE
PROBLEM LINE
}
}
}
function loadDoc(filespec)
{
//Dummy code to test the onclick event coding
alert(filespec);
}
window.onload = ModifyLinks;
//-->
</script>
</head>

<body>
<h3>Dynamically Modifying A Tags</h3>

<font class='doc'><a
href="http://localhost:1411/UserData/Test1.doc">Document
1</a></font><br />
<font class='doc'><a
href="http://localhost:1411/UserData/Test1.xls">Spreadsheet
1</a></font><br />
<font class='doc'><a
href="http://localhost:1411/UserData/Test1.ppt">Presentation
1</a></font><br />
<font class='doc'><a
href="http://localhost:1411/UserData/Test2.doc">Document
2</a></font><br />

</body>
</html>

I'd be very grateful for your help - can't figure it out!

Thanks very much.

Regards

Gary

gb at prodsol dot co dot nz

Aug 4 '06 #1
11 2794
GaryB wrote:
<snip>
However, if there's more than one link on the page, my code assigns
each onclick event to all of the previous nodes in the array instead of
each one independently. (I've commented the problematic line of
javascript, with "THIS IS THE PROBLEM LINE"). I must be missing
something!
<snip>
for(var d=0;d<docArray.length;d++)
{
if(docArray[d].className=='doc')
{
//Get values
fontNode = docArray[d];
sourceHTML = fontNode.innerHTML;
sourceHref=(sourceHTML.substring(sourceHTML.indexO f('"')+1,sourceHTML.indexOf('">')));
To get the 'href' of the anchor tag I'd suggest using
var anchor = fontNode.getElementsByTagName( 'A' )[0];
var href = anchor.href;
path = sourceHref.substring(sourceHref.indexOf('/',8));
doc = path.substring(path.lastIndexOf('/')+1);
ext = doc.substr(doc.length - 3);
docName = fontNode.innerText;
//Determine image
switch(sourceHTML.substr(sourceHTML.indexOf('>')-4,3))
{
case 'doc' : img="msword.png"; break;
case 'xls' : img="msexcel.png"; break;
case 'ppt' : img="mspowerpoint.png"; break;
case 'pdf' : img="pdf.png"; break;
}
linkNode = fontNode.children(0);
Again,
linkNode = fontNode.getElementsByTagName( 'A' )[0];
if you had a space like this ( underscore representing space )
<font>_<a..>
children(0) == ' ' .. At least that's how it is using DOM childNodes
array
linkNode.setAttribute('href','#');
Don't remove the href
imageNode =
linkNode.insertBefore(document.createElement('img' ),linkNode.firstChild);
imageNode.src = 'Skins/Standard/'+img;
imageNode.alt = docName;
linkNode.onclick = function(){loadDoc(sourceHref)};//THIS IS THE
PROBLEM LINE
}
linkNode.onclick = function() { loadDoc( this.href ); return false };
the return false; statement prevents the browser from taking the
default action, which is to follow the link
}
}
function loadDoc(filespec)
{
//Dummy code to test the onclick event coding
alert(filespec);
}
window.onload = ModifyLinks;
//-->
</script>
</head>

<body>
<h3>Dynamically Modifying A Tags</h3>

<font class='doc'><a
href="http://localhost:1411/UserData/Test1.doc">Document
1</a></font><br />
<font class='doc'><a
href="http://localhost:1411/UserData/Test1.xls">Spreadsheet
1</a></font><br />
<font class='doc'><a
href="http://localhost:1411/UserData/Test1.ppt">Presentation
1</a></font><br />
<font class='doc'><a
href="http://localhost:1411/UserData/Test2.doc">Document
2</a></font><br />

</body>
</html>

I'd be very grateful for your help - can't figure it out!

Thanks very much.

Regards

Gary

gb at prodsol dot co dot nz
Aug 4 '06 #2

GaryB wrote:
Hi Guys,

I've been battling with this one for hours - I hope that you can help
me!

My code modifies the <aon a page, from a standard document link into
a link with a tailored onclick event.

It works perfectly (assigning the correct images and the correct
onclick events to the correct <atags):
(a) If there's only one link on the page and
(b) If I modify the <atags one at a time - hardcoding (if there's
more than one link on the page).

However, if there's more than one link on the page, my code assigns
each onclick event to all of the previous nodes in the array instead of
each one independently. (I've commented the problematic line of
javascript, with "THIS IS THE PROBLEM LINE"). I must be missing
something!

Here's a page with the code (including a dummy loadDoc function). It
should show the problem as is (the images obviously won't show):

<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0 Transitional//EN">
Consider moving into the 21st century and use 4.01 strict.
[...]
<script language="JavaScript" type="text/javascript">
The language attribute has been deprecated for many years, you can
remove it.

function ModifyLinks()
{
//Create Document links
var docArray = document.getElementsByTagName('font');
Consider replacing the deprecated font elements with spans - but in any
case, the document.links collection gives you all the links (A
elements) anyway.

Please don't use tabs, use 2 or 4 spaces for indenting posted code and
wrap it at about 70 characters to prevent auto-wrapping (which
invariably introduces more errors).

var sourceHTML, sourceHref, path, doc, ext, img, docName, fontNode,
linkNode, imageNode;
for(var d=0;d<docArray.length;d++)
You could use the links collection here:

var link, links = document.links;
for (var i=0, len=links.length; i++){
link = links[i];
{
if(docArray[d].className=='doc')
It may be better to test if 'doc' is one of the class names, rather
than the only class name. Elements can have multiple CSS classes
assigned to them.

{
//Get values
fontNode = docArray[d];
sourceHTML = fontNode.innerHTML;
sourceHref=(sourceHTML.substring(sourceHTML.indexO f('"')+1,sourceHTML.indexOf('">')));
That is a very convoluted way to get the href value. Using the links
collection:

sourceHref = link.href;

path = sourceHref.substring(sourceHref.indexOf('/',8));
doc = path.substring(path.lastIndexOf('/')+1);
ext = doc.substr(doc.length - 3);
docName = fontNode.innerText;
innerText is an IE proprietary property, it is not well supported by
other browsers. The W3C equivalent is textContent, search the archives
for cross browser solutions - but it isn't needed here anyway. All you
seem interested in is the extension:

var ext = sourceHref.substr(sourceHref.length - 3);

//Determine image
switch(sourceHTML.substr(sourceHTML.indexOf('>')-4,3))
Didn't you already put the extension into 'ext'?

{
case 'doc' : img="msword.png"; break;
case 'xls' : img="msexcel.png"; break;
case 'ppt' : img="mspowerpoint.png"; break;
case 'pdf' : img="pdf.png"; break;
}
You could also do that with an object:

var extObj = {
doc : 'msword.png',
xls : 'msexcel.png',
ppt : 'mspowerpoint.png',
pdf : 'pdf.png'
}
img = extObj[ext];

linkNode = fontNode.children(0);
linkNode.setAttribute('href','#');
Why didn't you do that to get the link in the first place, instead of
innerHTML? Anyhow, now you already have a reference to the link:

link.href = '#';

imageNode =
linkNode.insertBefore(document.createElement('img' ),linkNode.firstChild);
imageNode.src = 'Skins/Standard/'+img;
imageNode.alt = docName;
linkNode.onclick = function(){loadDoc(sourceHref)};//THIS IS THE
PROBLEM LINE
You are creating a closure back to the local variable sourceHref. Each
onclick event is passed the same value, which is whatever value
sourceHref had when the function exited.

Search the archives for fixes. The simplest (though maybe not 'best'),
given that sourceHref is a string, is to use another small function to
add the onclick, something like:

...
addOnclick(linkNode, loadDoc, sourceHref);
...

function addOnclick(obj, func, parm){
obj.onclick = function(){func(parm);}
}
It seems a complete waste of time to replace a perfectly good href with
an onclick that is problematic. Why not just add the images/icons and
leave well enough alone?

}
}
}
function loadDoc(filespec)
{
//Dummy code to test the onclick event coding
alert(filespec);
}
window.onload = ModifyLinks;
//-->
Do not use HTML comment delimiters inside script elements - they are
completely unnecessary and may cause problems (but the one above
doesn't, it is interpreted as a comment line and is ignored).
</script>
</head>

<body>
<h3>Dynamically Modifying A Tags</h3>

<font class='doc'><a
href="http://localhost:1411/UserData/Test1.doc">Document
1</a></font><br />
Do not use XHTML syntax in an HTML document - the browser is quite
within its rights to display the closing '>' (but probably wont). It
is also invalid HTML to put an A element inside a FONT element.
[...]

--
Rob

Aug 5 '06 #3

RobG wrote:

[...]
It is also invalid HTML to put an A element inside a FONT element.
Ooops, not it's not - I got a bit over-zealous there! :-)
--
Rob

Aug 5 '06 #4
GaryB wrote:
Hi Guys,

I've been battling with this one for hours - I hope that you can help
me!

My code modifies the <aon a page, from a standard document link into
a link with a tailored onclick event.

It works perfectly (assigning the correct images and the correct
onclick events to the correct <atags):
(a) If there's only one link on the page and
(b) If I modify the <atags one at a time - hardcoding (if there's
more than one link on the page).

However, if there's more than one link on the page, my code assigns
each onclick event to all of the previous nodes in the array instead of
each one independently. (I've commented the problematic line of
javascript, with "THIS IS THE PROBLEM LINE"). I must be missing
something!

Here's a page with the code (including a dummy loadDoc function). It
should show the problem as is (the images obviously won't show):

<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0 Transitional//EN">
<html>
<head>
<title>Modify A Links</title>
<link href="ProdsolEpd.css" rel="stylesheet" type="text/css" />
<script type="text/javascript" src="ProdsolEpd.js"></script>
<script language="JavaScript" type="text/javascript">
function ModifyLinks()
{
//Create Document links
var docArray = document.getElementsByTagName('font');
var sourceHTML, sourceHref, path, doc, ext, img, docName, fontNode,
linkNode, imageNode;
for(var d=0;d<docArray.length;d++)
{
if(docArray[d].className=='doc')
{
//Get values
fontNode = docArray[d];
sourceHTML = fontNode.innerHTML;
sourceHref=(sourceHTML.substring(sourceHTML.indexO f('"')+1,sourceHTML.indexOf('">')));
path = sourceHref.substring(sourceHref.indexOf('/',8));
doc = path.substring(path.lastIndexOf('/')+1);
ext = doc.substr(doc.length - 3);
docName = fontNode.innerText;
//Determine image
switch(sourceHTML.substr(sourceHTML.indexOf('>')-4,3))
{
case 'doc' : img="msword.png"; break;
case 'xls' : img="msexcel.png"; break;
case 'ppt' : img="mspowerpoint.png"; break;
case 'pdf' : img="pdf.png"; break;
}
linkNode = fontNode.children(0);
linkNode.setAttribute('href','#');
imageNode =
linkNode.insertBefore(document.createElement('img' ),linkNode.firstChild);
imageNode.src = 'Skins/Standard/'+img;
imageNode.alt = docName;
linkNode.onclick = function(){loadDoc(sourceHref)};//THIS IS THE
PROBLEM LINE
}
}
}
function loadDoc(filespec)
{
//Dummy code to test the onclick event coding
alert(filespec);
}
window.onload = ModifyLinks;
//-->
</script>
</head>

<body>
<h3>Dynamically Modifying A Tags</h3>

<font class='doc'><a
href="http://localhost:1411/UserData/Test1.doc">Document
1</a></font><br />
<font class='doc'><a
href="http://localhost:1411/UserData/Test1.xls">Spreadsheet
1</a></font><br />
<font class='doc'><a
href="http://localhost:1411/UserData/Test1.ppt">Presentation
1</a></font><br />
<font class='doc'><a
href="http://localhost:1411/UserData/Test2.doc">Document
2</a></font><br />

</body>
</html>

I'd be very grateful for your help - can't figure it out!

Thanks very much.

Regards

Gary
When you're remaking event functions in javascript, the easiest thing
to pass reliably is "this". eg:

<script>
mylink.onclick = function() {window.alert(this.href);}
</script>

which is like:

<a onclick='window.alert(this.href);'
href="http://dilbert.com">asdfds</a>

Also don't use innerHTML, seriously, it will simplify things a great
deal if you don't. For text nodes use nodeValue;

hope this helps

---
http://darwinist.googlepages.com/htmldesktop.html
(lots of working examples)
gb at prodsol dot co dot nz
Aug 5 '06 #5
Thanks very much, Guys - used something from each of your comments.

The only thing I'm not sure of, Rob, is how to "...test if 'doc' is one
of the class names, rather than the only class name...".

Thanks very much.

Regards

Gary

Aug 6 '06 #6
So what is the http://darwinist.googlepages.com/htmldesktop.html link
all about?

Regards

Gary

Aug 6 '06 #7
GaryB wrote:
So what is the http://darwinist.googlepages.com/htmldesktop.html link
all about?

Regards

Gary
It's a bunch of free javascript showing how to make and move and resize
and delete and otherwise manipulate document objects.

The source has comments and whitespace, and so is bigger than it might
be for readability, but still only 31k and 751 lines, at present. It
has a simple windowing system that shows how to make movable, trackable
windows in an html environment (images not included).

Pictures and server code would fit easily, but are left out of this
copy to keep the size down and focus on the javascript.

The command box allows you to test stuff immediately and interact with
the virtual desktop and its objects (see the examples), which is
10000x10000 px by default but can be changed. Dragging windows past the
edge of the desktop enlarges it, too.

Web browsers can handle virtually large objects pretty easily, since
they only have to paint the current screen, and html is pretty slim to
keep in memory (don't try to "stretch" a background picture over that
distance though). You can use this knowledge to make fairly large
environments as long as you know which information to get all at once
and you don't bloat yourself too much with overly complex or overly
generalised code.

For example you can simulate the "tabbed" dialog box that windows uses,
by making the tabs links to parts of the document. Some people try to
hide the scrollbars, but what's the point, really. This system uses two
dimensional "tabs" on the navigation box to give you a hundred desktop
areas of a thousand by a thousand pixels each.

You can "goto" or "fetch" open windows and you can rename them while
they are open to keep track of them in the desktop. It's not an
alternative to browser tabs, but an addition to them, since you don't
always want every url to take up all your screen, and keeping track of
titles when you have lots of tabs open can be a pain.

You can steal and customise the code to whatever purpose you desire.
Well, try not to kill anyone, obviously.

Aug 6 '06 #8
Cool! Thanks very much. I'll let you know when I use it.

Regards

Gary

Aug 6 '06 #9
GaryB wrote:
Thanks very much, Guys - used something from each of your comments.

The only thing I'm not sure of, Rob, is how to "...test if 'doc' is one
of the class names, rather than the only class name...".
The usual trick is to test it with a regular expression, e.g. to test if
someElement's className attribute contains the class name 'someClass' as
a single word (i.e. delimited by word breaks):

var classTest = new RegExp('\\bsomeClass\\b');

if ( someEl.className && classTest.test(someEl.className))
{
/* The element's className contains someClass as a word */
}
--
Rob
Aug 6 '06 #10
Hmmm. I'm not very sure but may be in this way will be mutch easily.
more code ...
*********************************************
linkNode.onclick = function(evt){
/*************************************************
In this way the variable linkEmt is
a instance of the link that was
clicked. You can try with different
values for the href attribute. In
Internet explorer the evt is
undefined and we have a additional info
in the event object. Otherwise it
have a target property and several
usefull things.
*************************************************/
var linkEmt= typeof evt == 'undefined' ? window.event.srcElement :
evt.target;

loadDoc(linkEmt.href);
};//THIS IS THE
*****************************************
more code ..
*****************************************
function loadDoc(filespec)
{
//Dummy code to test the onclick event coding
alert(filespec);
}
GaryB написа:
Hi Guys,

I've been battling with this one for hours - I hope that you can help
me!

My code modifies the <aon a page, from a standard document link into
a link with a tailored onclick event.

It works perfectly (assigning the correct images and the correct
onclick events to the correct <atags):
(a) If there's only one link on the page and
(b) If I modify the <atags one at a time - hardcoding (if there's
more than one link on the page).

However, if there's more than one link on the page, my code assigns
each onclick event to all of the previous nodes in the array instead of
each one independently. (I've commented the problematic line of
javascript, with "THIS IS THE PROBLEM LINE"). I must be missing
something!

Here's a page with the code (including a dummy loadDoc function). It
should show the problem as is (the images obviously won't show):

<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0 Transitional//EN">
<html>
<head>
<title>Modify A Links</title>
<link href="ProdsolEpd.css" rel="stylesheet" type="text/css" />
<script type="text/javascript" src="ProdsolEpd.js"></script>
<script language="JavaScript" type="text/javascript">
function ModifyLinks()
{
//Create Document links
var docArray = document.getElementsByTagName('font');
var sourceHTML, sourceHref, path, doc, ext, img, docName, fontNode,
linkNode, imageNode;
for(var d=0;d<docArray.length;d++)
{
if(docArray[d].className=='doc')
{
//Get values
fontNode = docArray[d];
sourceHTML = fontNode.innerHTML;
sourceHref=(sourceHTML.substring(sourceHTML.indexO f('"')+1,sourceHTML.indexOf('">')));
path = sourceHref.substring(sourceHref.indexOf('/',8));
doc = path.substring(path.lastIndexOf('/')+1);
ext = doc.substr(doc.length - 3);
docName = fontNode.innerText;
//Determine image
switch(sourceHTML.substr(sourceHTML.indexOf('>')-4,3))
{
case 'doc' : img="msword.png"; break;
case 'xls' : img="msexcel.png"; break;
case 'ppt' : img="mspowerpoint.png"; break;
case 'pdf' : img="pdf.png"; break;
}
linkNode = fontNode.children(0);
linkNode.setAttribute('href','#');
imageNode =
linkNode.insertBefore(document.createElement('img' ),linkNode.firstChild);
imageNode.src = 'Skins/Standard/'+img;
imageNode.alt = docName;
linkNode.onclick = function(){loadDoc(sourceHref)};//THIS IS THE
PROBLEM LINE
}
}
}
function loadDoc(filespec)
{
//Dummy code to test the onclick event coding
alert(filespec);
}
window.onload = ModifyLinks;
//-->
</script>
</head>

<body>
<h3>Dynamically Modifying A Tags</h3>

<font class='doc'><a
href="http://localhost:1411/UserData/Test1.doc">Document
1</a></font><br />
<font class='doc'><a
href="http://localhost:1411/UserData/Test1.xls">Spreadsheet
1</a></font><br />
<font class='doc'><a
href="http://localhost:1411/UserData/Test1.ppt">Presentation
1</a></font><br />
<font class='doc'><a
href="http://localhost:1411/UserData/Test2.doc">Document
2</a></font><br />

</body>
</html>

I'd be very grateful for your help - can't figure it out!

Thanks very much.

Regards

Gary

gb at prodsol dot co dot nz
Aug 6 '06 #11

Georgi Naumov wrote:
Hmmm. I'm not very sure but may be in this way will be mutch easily.
Please don't top-post here. Reply below a trimmed quote of what you
are replying to.

more code ...
*********************************************
linkNode.onclick = function(evt){
[...]
var linkEmt= typeof evt == 'undefined' ? window.event.srcElement :
evt.target;

loadDoc(linkEmt.href);
};//THIS IS THE
That is unnecessary and assumes that the funciton call has not bubbled
up from some element lower in the DOM tree. A function reference can
be attached simply using:

linkNode.onclick = loadDoc;
Then a reference to the element that called the function will be held
in the function object's 'this' object when executed:

function loadDoc(){
alert(this.href);
}
--
Rob

Aug 7 '06 #12

This discussion thread is closed

Replies have been disabled for this discussion.

Similar topics

3 posts views Thread by EviL KerneL | last post: by
20 posts views Thread by David | last post: by
6 posts views Thread by Cockroach | last post: by
reply views Thread by Yama | last post: by
reply views Thread by Diane Yocom | last post: by
6 posts views Thread by tuxedo | last post: by
3 posts views Thread by ICPooreMan | last post: by

By using Bytes.com and it's services, you agree to our Privacy Policy and Terms of Use.

To disable or enable advertisements and analytics tracking please visit the manage ads & tracking page.