Hi,
I'm trying to understand how to work the dom, and all I'm trying to do
is insert a link right before another link in the html based on it's
href value. This isn't a real world example - I'm just trying to do
this in phases to understand what's going on. I'm getting an error
(Object doesn't support this property or method) in IE and I can't
figure out what I'm doing wrong. Can anyone tell me?
Don't use tabs for indents in posted code, use 2 (preferred) or 4
spaces. Manually wrap code at about 70 characters to prevent
auto-wrapping, otherwise errors may be introduced there weren't in the
original code.
if (navigator.appName == "Microsoft Internet Explorer")
Ditch that straight away, browser sniffing has been out of vogue for
many years, feature detection is all the rage.
{
var browser="IE";
}
else
{
var browser="notIE";
}
var e = document.getElementById('contentWrapper');
It is much better to give your variables meaningful names, single
letters are OK for counters and such, your choice.
var wrapper;
if (document.getElementById){
wrapper = document.getElementById('contentWrapper');
Good, you check that getElementById returned something.
{
var a=e.getElementsByTagName('a');
'a' is now a collection of the 'A' elements that are decedents of
'contentWrapper'. A feature of such collections is that they are live -
as you add A elements to contentWrapper in your code below, they are
also added to the collection.
This has ramifications for your loop below - the length keeps getting
longer and because you insertBefore the current node, it will keep
inserting forever once the if condition is true.
for (var i=0;i<a.length;i++)
It is more efficient (though often not noticeably so) to get the length
of the collection once only. Getting the length every time in this case
will cause you go to into an endless loop because you keep inserting
nodes before the current one - better to loop from the end back to the
start using while, then the inserted nodes are beyond where you are
currently checking:
var i = a.length;
while (i--){
Ditch that.
{
if (a.getAttribute('href') != null &&
a.getAttribute('href',2).indexOf("://") >= 0 &&
a.getAttribute('href',2).indexOf("bcbsal.org") == -1)
It is easier to access properties directly, though it's not standard it
is better supported than get/setAttribute. It is also better to get a
reference to the element once and use that rather than lookup a
multiple times:
var i = a.length;
while (i--){
tmp = a;
indexOf is pretty efficient, but rather than doing all those tests you
might consider using a regular expression and just the one test:
if ( /bcbsal\.org/.test(temp.href) )
The above will return false if either the element doesn't have a value
for the href attribute or it doesn't match "bcbsal.org". You might want
to also make the test case insensitive:
if ( /bcbsal\.org/i.test(temp.href) )
{
var iconLink = e.createElement('a');
This is the line that is causing your error: 'e' is a reference to an
element, elements implement the HTML element interface which doesn't
have a createElement() method, that belongs to the HTML document
interface so you have to call it with 'document':
var iconLink = document.createElement('a');
Some links:
DOM 2 Core Document Interface:
<URL:http://www.w3.org/TR/DOM-Level-2-Core/core.html#i-Document>
DOM 2 Core Element Interface:
<URL:http://www.w3.org/TR/DOM-Level-2-Core/core.html#ID-745549614>
There are further interfaces defined in the DOM 2 HTML spec:
The problem here is that you insert an A element before a node, which
makes the node the i+1 node in the collection, so the next loop tests
the same node, matches the href, inserts another link, moves the node +1
again, etc. /ad infinitum/.
iconLink.title = 'This link takes you to another web site.';
iconLink.appendChild(e.createTextNode('Test'));
Again, createTextNode is a method of document, not element:
iconLink.appendChild(document.createTextNode('Test'));
a.title = 'This link takes you to another web site.';
a.parentNode.insertBefore(iconLink,a);
}
}
else....
Putting it all together:
<div id="contentWrapper"><br>
<a href="http://www.bcbsal.org">bcbsal.org</a><br>
<a href="http://www.apple.com">Apple a</a><br>
<a href="">Empty a</a><br>
</div>
<script type="text/javascript">
if (document.getElementById){
var wrapper = document.getElementById('contentWrapper');
if (wrapper){
var a = wrapper.getElementsByTagName('a');
var tmp;
var iconLink;
var i = a.length;
while (i--){
tmp = a;
if ( /bcbsal\.org/.test(tmp.href) ){
iconLink = document.createElement('a');
iconLink.href = tmp.href;
iconLink.title = 'This link takes you to another web site.';
iconLink.appendChild(document.createTextNode('Test'));
tmp.title = 'This link takes you to another web site.';
tmp.parentNode.insertBefore(iconLink,tmp);
}
}
}
}
</script>