Velocity Reviews - Computer Hardware Reviews

Velocity Reviews > Newsgroups > Programming > Javascript > Get all href values in <ul> group and compare with current url

Reply
Thread Tools

Get all href values in <ul> group and compare with current url

 
 
michael
Guest
Posts: n/a
 
      05-03-2005
Is it possible to get all href URLs contained in a unordered list and place
them in an array?
Or in fact two different arrays, differently named one for each <ul> group?

<ul>
<li><a href="lemurs.html">Lemurs</a></li>
<li><a href="chameleons.html">Chameleons</a></li>
</ul>

<ul>
<li><a href="sharks.html">Sharks</a></li>
<li><a href="crocs.html">Crocodiles</a></li>
</ul>

I want to fetch an array of the links within a <ul> group, and
document.write the above, but with class variable in which I can
set a different value, depending on if the current url filename matches
exactly any one of the links within the <ul> group the <li> belongs to.

More specifically, I would like to ...

document.write('<li class'+myvariable+'>')
|
... class 'green' or 'blue' -------'
depending on whether filename in any href contained
in an <li> of the <ul> group it is in.
If an exact match is found, write out green, if not blue.

The file name portion of the current URL I simply get through:

var f = window.location.href;
file = i.substring (f.lastIndexOf('/') +1);

It is for drop-down nav-system whereby all list items would of a ul group
would appear either one of two colours as specified in css properties. All
links are internal links on the same domain so one would always match.

I could naturally do it all by having a pre-typed list of all filenames and
run each <li> through an if statement before writing it out. But as there
will be many <li>'s I would prefer a more typeless method if possible.

Many thanks for any tips!

Michael

--
(1) Everything depends.
(2) Nothing is always.
(3) Everything is sometimes.

 
Reply With Quote
 
 
 
 
Jerome Bei
Guest
Posts: n/a
 
      05-03-2005
Try this:

<script>
uls = document.getElementsByTagName("UL");
for (var u=0; u<uls.length; u++) {
alert("entering list ["+u+"]");
lis=uls[u].getElementsByTagName("LI");
for (var i=0; i<lis.length; i++) {
if (lis[i].childNodes[0] && lis[i].childNodes[0].href) {
alert("found link ["+lis[i].childNodes[0].href+"]");
}
}
}
</script>

(Testes on IE 6.0 only)

--Jerome
 
Reply With Quote
 
 
 
 
michael
Guest
Posts: n/a
 
      05-04-2005
Jerome Bei wrote:

> Try this:
>
> <script>
> uls = document.getElementsByTagName("UL");
> for (var u=0; u<uls.length; u++) {
> alert("entering list ["+u+"]");
> lis=uls[u].getElementsByTagName("LI");
> for (var i=0; i<lis.length; i++) {
> if (lis[i].childNodes[0] && lis[i].childNodes[0].href) {
> alert("found link ["+lis[i].childNodes[0].href+"]");
> }
> }
> }
> </script>
>
> (Testes on IE 6.0 only)
>
> --Jerome


Works nicely, fetches the links if there are, and it works on Mozilla too.

Thanks!
Michael

-
The human animal differs from the lesser primates in his passion for
lists of "Ten Best".
-- H. Allen Smith

 
Reply With Quote
 
RobG
Guest
Posts: n/a
 
      05-04-2005
michael wrote:
> Jerome Bei wrote:
>
>
>>Try this:
>>
>><script>
>> uls = document.getElementsByTagName("UL");
>> for (var u=0; u<uls.length; u++) {
>> alert("entering list ["+u+"]");
>> lis=uls[u].getElementsByTagName("LI");
>> for (var i=0; i<lis.length; i++) {
>> if (lis[i].childNodes[0] && lis[i].childNodes[0].href) {


If anything is inserted between the <li> and <a> tags, even a space,
this will fail as the <a> element will no longer be the first child
of the <li>.

Probably better to use a recursive function to go down the tree from
the <li> to see if it has an <a> element as a descendant.

>> alert("found link ["+lis[i].childNodes[0].href+"]");
>> }
>> }
>> }
>></script>
>>
>>(Testes on IE 6.0 only)
>>
>>--Jerome

>
>
> Works nicely, fetches the links if there are, and it works on Mozilla too.


But will fall over if you insert anything between the <li> and <a>
tags, as that will insert another element and the parent/child
relationship is broken. Below is a script that runs down the tree
to the first <a> and returns that (if there is one).


<script type="text/javascript">
function getULs() {
var h, i, u, lena, lenb, lis, uls;
uls = document.getElementsByTagName("UL");
for ( u=0, lena=uls.length; u<lena; u++) {
alert("entering list [" + u + "]");
lis = uls[u].getElementsByTagName("LI");
for (i=0, lenb=lis.length; i<lenb; i++) {
if ( (h = hasAchild(lis[i])) ) {
alert("found link [" + h.id + "]");
}
}
}
}

// Given an element ref, descend element tree until an <a> is found
// Return a reference to the element or null if not found
function hasAchild(x){
isA = false; // global
if (x.nodeName == 'A') {
isA = x;
return isA; // Stop descent on first A element
}
for (var i=0; i<x.childNodes.length; i++) {
// Descend if not found an A yet
if (!isA) hasAchild(x.childNodes[i]);
}
return isA;
}

</script>
</head>
<body id="theBody">
<ul>
<li><span>spacer</span> <a id="a0" href="blah" onclick="getULs();
return false;">the ref</a></li>
<li><a id="a1" href="blah" onclick="getULs(); return false;">the
ref</a></li>
<li>no ref</li>
</ul>


--
Rob
 
Reply With Quote
 
RobG
Guest
Posts: n/a
 
      05-04-2005
RobG wrote:
> michael wrote:

[...]
>
> // Given an element ref, descend element tree until an <a> is found
> // Return a reference to the element or null if not found
> function hasAchild(x){
> isA = false; // global
> if (x.nodeName == 'A') {
> isA = x;
> return isA; // Stop descent on first A element
> }
> for (var i=0; i<x.childNodes.length; i++) {
> // Descend if not found an A yet
> if (!isA) hasAchild(x.childNodes[i]);
> }
> return isA;
> }


Had a bit of fun with this, here's a neater version:

function hasAchild(x){
isA = ( 'A' == x.nodeName)? x : false;
for (var i=0, j=x.childNodes.length; !isA && i<j; i++) {
hasAchild(x.childNodes[i]);
}
return isA;
}


--
Rob
 
Reply With Quote
 
Michael Winter
Guest
Posts: n/a
 
      05-04-2005
On 04/05/2005 08:35, RobG wrote:

[snip]

> If anything is inserted between the <li> and <a> tags, even a space,
> this will fail as the <a> element will no longer be the first child
> of the <li>.
>
> Probably better to use a recursive function to go down the tree from
> the <li> to see if it has an <a> element as a descendant.


Probably better to use getElementsByTagName to find any A elements
within a list, directly. An A element would only be valid within a list
item, so it seems rather pointless to spend time walking through the tree.

[snip]

Mike

--
Michael Winter
Replace ".invalid" with ".uk" to reply by e-mail.
 
Reply With Quote
 
michael
Guest
Posts: n/a
 
      05-04-2005
> Probably better to use getElementsByTagName to find any A elements

There are obvsiously many ways and maybe this one would be the best. I'm a
bit lost however as how to piece it all together.
Therefore I shall try and explain a bit more what I'm looking for:

I plan to generate a drop-down menu with CSS hover effects that would
simply work on top of bare-bone unordered lists and which will be
javascript generated by a central.js file for easy cross-site modifications.

Disregarding style issues for this example sake, the navigation may be
described simply as a bunch of links, within <LI>'s, within different
groups of <UL>'s.

These UL's will be horizontally aligned in CSS navbar style, and only the
first link of each UL group will be visible until the mouse hovers over it,
at which point the complete array of links of the UL group appears below it.

The first and always visible link of each UL would simply lead to an
overview page containing a summary of contents for its group of links.
So the top-level links, would function a bit like a subject headings,
although they may be considered by the javascript as any of the links
contained within their groups.

The javascript would define a class property for all LI's in each group, as
either:
The active, green class, if the user is on any page linked within its group.
OR
Non-active, blue class, for all other UL's and their LI's contained within.

The purpose of the CSS class is only to indicate in which section the user
currently is, which should make more sense in the CSS version, as only the
first link is displayed, and as the mouse hovers over the currently active
group with its current page on display, or when its over a non-active group.

An example with only two link groups below, if viewed as a page named
"lemurs.html" would style all background of the "flora_and_fauna" group of
links light-green, whilst if viewed as a page named "hiking.html", all
links in the "activities" group would be light-blue. Or, a page not linked
from anywhere within the js menu itself, all groups would remain light-blue.

Note that each link would appear only in one place or the navigation system
woudl not be clear to the user.

My so-called javascript below requires all links and groups pre-defined,
and filenames in the if statements explicity typed out etc.
This may be OK for a few links only but to be used in a => 50 links
nav-system that one can easily modified its not a very good solution.
But anyway, the functionality could be more or less same as below mock-up:

<style>
..green { background-color:lightgreen }
..blue { background-color:lightblue; }
</style>

var f = window.location.href; /* get file name portion of URL */
file = f.substring (f.lastIndexOf('/') +1);


function display_links(group){ /* run function with group argument */
var state = "green";

/* explicity type possible combinations for each group */
if (group == "flora_and_fauna" && file == "flora_and_fauna.html" || group
== "flora_and_fauna" && file == "lemurs.html" || group == "flora_and_fauna"
&& file == "chameloens.html" || group == "flora_and_fauna" && file ==
"mangroves.html"){
return state;
}

/* and again ... */
else if (group == "activities" && file == "activities.html" || group ==
"activities" && file == "hiking.html" || group == "activities" && file ==
"diving.html"){
return state;
}

/* if none is matched, eg. a user is on a page not linked within the .js
navigation system itself, all groups light-blue */
else {
return "blue";
}

}

/* write out each ul, li and link, and run function to set class value */
document.write('<ul>')
document.write('<li class='+display_links('flora_and_fauna')+'><a
href="flora_and_fauna.html">Flora & Fauna</a></li>')
document.write('<li class='+display_links('flora_and_fauna')+'><a
href="lemurs.html">Lemurs</a></li>')
document.write('<li class='+display_links('flora_and_fauna')+'><a
href="chameleons.html">Chameleons</a></li>')
document.write('<li class='+display_links('flora_and_fauna')+'><a
href="mangroves.html">Mangroves</a></li>')
document.write('</ul>')


document.write('<ul>')
document.write('<li class='+display_links('activities')+'><a
href="activities.html">Activities</a></li>')
document.write('<li class='+display_links('activities')+'><a
href="hiking.html">Hiking</a></li>')
document.write('<li class='+display_links('activities')+'><a
href="diving.html">diving</a></li>')
document.write('</ul>')

Any ideas, and especially short code would be greatly appreciated!

Many thanks,
Michael
--

You know the great thing about TV? If something important happens
anywhere at all in the world, no matter what time of the day or night,
you can always change the channel.
-- Jim Ignatowski
 
Reply With Quote
 
RobG
Guest
Posts: n/a
 
      05-04-2005
Michael Winter wrote:
> On 04/05/2005 08:35, RobG wrote:
>
> [snip]
>
>> If anything is inserted between the <li> and <a> tags, even a space,
>> this will fail as the <a> element will no longer be the first child
>> of the <li>.
>>
>> Probably better to use a recursive function to go down the tree from
>> the <li> to see if it has an <a> element as a descendant.

>
>
> Probably better to use getElementsByTagName to find any A elements
> within a list, directly. An A element would only be valid within a list
> item, so it seems rather pointless to spend time walking through the tree.


Killjoy.


--
Rob
 
Reply With Quote
 
RobG
Guest
Posts: n/a
 
      05-05-2005
michael wrote:
>>Probably better to use getElementsByTagName to find any A elements

>
>
> There are obvsiously many ways and maybe this one would be the best. I'm a
> bit lost however as how to piece it all together.
> Therefore I shall try and explain a bit more what I'm looking for:
>

[...]

>')
>
> Any ideas, and especially short code would be greatly appreciated!
>


Yes, there are a zillon ways to do this, google "DHTML menu".

Forget 'document.write' to create your menu as the page loads, that
will guarantee that non-JavaScript browsers can't use your site.

To get further help:

1. Create your menus as static HTML.

2. Add DHTML behaviour as an add-on, that way non-JavaScript browsers
can still navigate your pages.

3. As part of the above, you can see if a UL group contains an HREF
with the same filename as the current page. If so, change its
parent UL class to 'active'.

I've posted a bit of code that just does the class thing, I've
included multiple classes so I can detect the 'head' ULs (I'm not
interested in descendant ULs, you may be) as an example, but my idea
of what you are trying to do is probably very different to what you
are actually doing.

Note you don't have to define 'convenience' classes like head and sub
if you don't want to.



<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01//EN"
"http://www.w3.org/TR/html4/strict.dtd">
<html>
<head>
<title> Z 0 </title>
<meta http-equiv="Content-Type"
content="text/html; charset=ISO-8859-1">
<style type="text/css">
..high {background-color: #99FFCC; color: black;}
..low {background-color: #33CC00; color: white;}
</style>
<script type="text/javascript">

function doClass(){
var As, ff, x;
var a = RegExp('.*/'); // Needed many times, compile for speed
var f = document.URL.replace(a,''); // filename of current page
var d = document.getElementById('menu');
var uls = d.getElementsByTagName('ul');

for (var i=0, j=uls.length; i<j; i++){
x = uls[i];

// If the UL className string includes word 'head'
if ( /\bhead\b/.test(x.className) ){

// Get its A elements
As = x.getElementsByTagName('a');

// Search for matching file names
for (var k=0, m=As.length; k<m; k++) {
ff = As[k].href.replace(a,'');

// If match, modify the className string of the parent UL
if ( ff == f ){
x.className = x.className.replace(/\blow\b/,'high');

// No need to continue once we've found one
return;
}
}
}
}
}
</script>
</head>
<body onload="doClass();">
<div id="menu">
<ul class="head low" id="blah">
<li><a href="z0.html">Flora&nbsp;&amp;&nbsp;funa</a>
<ul class="sub">
<li><a href="z1.html">Pretty&nbsp;flowers</a></li>
<li><a href="z2.html">Deadly&nbsp;vines</a></li>
</ul>
</li>
</ul>
<ul class="head low">
<li><a href="z3.html">Aquatic&nbsp;creatures</a>
<ul class="sub">
<li><a href="z4.html">Pretty&nbsp;fish</a></li>
<li><a href="z5.html">Don&#39t&nbsp;eat</a></li>
</ul>
</li>
</ul>
</div>
</body>
</html>


--
Rob
 
Reply With Quote
 
RobG
Guest
Posts: n/a
 
      05-05-2005
RobG wrote:
> michael wrote:
>

[...]
>>
>> Any ideas, and especially short code would be greatly appreciated!
>>

[...]

> var f = document.URL.replace(a,''); // filename of current page


Sorry, forgot IE doesn't do document.URI, try this:

var f = document.location.href.replace(a,'');

[...]

--
Rob
 
Reply With Quote
 
 
 
Reply

Thread Tools

Posting Rules
You may not post new threads
You may not post replies
You may not post attachments
You may not edit your posts

BB code is On
Smilies are On
[IMG] code is On
HTML code is Off
Trackbacks are On
Pingbacks are On
Refbacks are Off


Similar Threads
Thread Thread Starter Forum Replies Last Post
BASE HREF and A HREF="#" onclick="..." Vincent van Beveren Javascript 2 07-06-2006 08:33 AM
href="javascript:func()" vs href="#" onclick="javascript:func()" CRON HTML 24 06-20-2006 08:05 PM
onClick method question (this.href and document.location.href) yogesh.bhardwaj@gmail.com Javascript 2 02-03-2005 02:38 PM
difference between location.href and window.location.href? saiho.yuen Javascript 3 09-14-2004 06:51 PM
Problem: Setting MSIE iframe innerHTML change relative href/src to absolute href/src Soren Vejrum Javascript 4 07-05-2003 01:47 PM



Advertisments