Hello and welcome to our community! Is this your first visit?
Register
Enjoy an ad free experience by logging in. Not a member yet? Register.
Results 1 to 15 of 15
  1. #1
    New Coder
    Join Date
    Nov 2004
    Posts
    17
    Thanks
    0
    Thanked 0 Times in 0 Posts

    Links Collection

    Hi!

    Every link on a page is a member of links collection and has its unique number (index) from 0 to document.links.width. Well.
    But can I get that index directly for link being clicked without looping through all links members and comparing against clicked link.

    Thank you
    Honza

  • #2
    Senior Coder
    Join Date
    Jun 2002
    Posts
    1,404
    Thanks
    2
    Thanked 32 Times in 32 Posts
    Assume you have a reason for this. You're basically going to loop one way or another, afaik, so, might as well do it up front.


    Code:
    <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0 Transitional//EN" 
        "http://www.w3.org/TR/html4/loose.dtd">
    
    <html>
    <head>
    <title>untitled</title>
    <style type="text/css">
    
    a { display: block; }
    
    </style>
    <script type="text/javascript">
    
    function initLinks()
    {
    	var link, idx = 0;
    	while (link = document.links[idx])
    		link.idx = idx++;
    }
    
    onload = initLinks;
    
    </script>
    </head>
    <body>
    
    <a href="#null" onclick="alert(this.idx)">This is link 0.</a>
    <a href="#null" onclick="alert(this.idx)">This is link 1.</a>
    <a href="#null" onclick="alert(this.idx)">This is link 2.</a>
    <a href="#null" onclick="alert(this.idx)">This is link 3.</a>
    <a href="#null" onclick="alert(this.idx)">This is link 4.</a>
    
    </body>
    </html>
    Don't necessarily need to wait till the page is loaded, probably better to embed the script below all the links (and 'de-functionize' it).
    Last edited by adios; 11-11-2004 at 08:27 PM.

  • #3
    New Coder
    Join Date
    Nov 2004
    Posts
    17
    Thanks
    0
    Thanked 0 Times in 0 Posts
    Hi adios,

    Your code is very inspiriting, elegant (also very hard to understand) and I thank you very much.
    The reason for my question is simple. I use one menu across some website. So I need to remember (in cookie) which link (in menu) was clicked and later (on "subpage") highlight this link as current by means of simple command like
    Code:
    document.links[ClickedLink].style.blahblah="somevalue"
    By the way: yesterday I discovered some other solution without cookies. I need not to remember clicked link any more and only on a new page I loop through all links in menu looking for coincidence with URL of that page
    Code:
    //code fragment...
    if (document.getElementsByTagName("A")[i]== location.href)
       {
       // this link correspondents to current page so highlight it
       document.links[i].style.backgroundColor="#FFFFFF"
       }
    This is quite new I think.
    Honza

  • #4
    Senior Coder
    Join Date
    Jun 2002
    Posts
    1,404
    Thanks
    2
    Thanked 32 Times in 32 Posts
    Thanks for the compliment (I think!). afaik the only difference between using the DOM 0 host collection document.links[] and the document.getElementsByTagName('A') method is that the latter will collect page anchors as well as links, and the collection isn't guaranteed to be in the same order as the HTML source (although I can't recall ever seeing it ordered differently). I'd use one or the other....


    Code:
    onload = function()
    {
    	var url = self.location.href,
    	i = 0,
    	link;
    	while (link = document.getElementsByTagName('A')[i++])
    		if (link.href && url.search(link.href) != -1)
    			link.style.background = '#ffffff';
    }
    Last edited by adios; 11-15-2004 at 06:05 PM.

  • #5
    New Coder
    Join Date
    Nov 2004
    Posts
    17
    Thanks
    0
    Thanked 0 Times in 0 Posts
    Hi adios,
    Your JavaScript teacher had to be a great man. Congratulations.
    It took me three days to fully understand your
    Code:
    var link, idx = 0;
    	while (link = document.links[idx])
    		link.idx = idx++;
    ...
    At least I find that there is single "=" in condition. Does it mean that condition for entering "While" is true if assigning "document.links[idx]" to variable "link" is successful (e.g. document.links[idx] exists)? Am I right?
    By the way your code ľ for (to me) unknown reasons - can't be debugged using some Alert.
    Will you kindly give me a little explanation?
    Thank you
    Honza

  • #6
    Master Coder
    Join Date
    Feb 2003
    Location
    Umeň, Sweden
    Posts
    5,575
    Thanks
    0
    Thanked 83 Times in 74 Posts
    Honza: No, it doesn't mean that. Assignments can only fail if the property or variable you are assigning to is read only, which is a very rare event indeed. And anyway, when that occurs an exception will be thrown. No, it will perform the assignment, and then the while will cast whatever condition it is given to boolean, and determine whether it should continue depending on that.
    liorean <[lio@wg]>
    Articles: RegEx evolt wsabstract , Named Arguments
    Useful Threads: JavaScript Docs & Refs, FAQ - HTML & CSS Docs, FAQ - XML Doc & Refs
    Moz: JavaScript DOM Interfaces MSDN: JScript DHTML KDE: KJS KHTML Opera: Standards

  • #7
    Senior Coder
    Join Date
    Jun 2002
    Posts
    1,404
    Thanks
    2
    Thanked 32 Times in 32 Posts
    This:

    Code:
    while (link = document.links[idx])
    		link.idx = idx++;
    ...is simply a 'compressed' version of this:

    Code:
    while (document.links[idx])
    {
    	link = document.links[idx];
    	link.idx = idx;
    	idx++;
    }
    Just 1) doing an assignment, for efficiency/convenience, 2) evaluating a conditional for the while loop (Object == true), 3) assigning a new property - the one with the data you requested (probably should have named it 'index'), and 4) bumping up the counter. The assignment tends to confuse people, who expect a comparison (==) with two operands present, but the interpreter performs the assignment, and then evaluates the right-hand operand solely (not much point in doing both). That's my (un)educated guess, in any event. This is a bit more compressed:

    Code:
    while (link = document.getElementsByTagName('A')[i++])
    ...as it post-increments the counter in the same line. Lately (inspired in part by liorean) I've been jamming more and more expressions into each line of code. My goal is to make it completely unreadable so people will be impressed. Seems to be working with you.

    Would need to see an example of that debug dilemma.

    cya, adios

  • #8
    Master Coder
    Join Date
    Feb 2003
    Location
    Umeň, Sweden
    Posts
    5,575
    Thanks
    0
    Thanked 83 Times in 74 Posts
    A thing to note:
    Code:
    var
        elm,
        col=document.getElementsByTagName('a'),
        i=0;
    while(elm=col.item(i++))
        doSomethingWith(elm);
    is the absolutely most effective way to circle through a DOM collection there is.

    The shortcut way that adios used, which could be summarised as
    Code:
    while(elm=col[i++])
    is NOT recommended, since it at the end would try accessing an element that does not exist and consequently raise an exception instead of nicely returning null when the index does not contain a an element. The exception breaks execution, but the null is cast to false. and thus allows further execution.









    Adios: Jamming more and more expressions into one line of code is not a good rule of thumb. Keep code readable and keep your personal coding conventions consistent. However, it is a good idea to reduce the number of statements and expressions altogether in your code, and one of the best ways to do that is to inline expressions in other expressions where that can be done. That doesn't mean it's a good idea to jam the entire expression or statement into one single line, however. Consider this example
    Code:
    document
        .getElementsByTagName('head')
        .item(0)
        .appendChild(
            script=document.createElement('script'));
    
    // or
    
    document
        .getElementsByTagName('head').item(0)
        .appendChild(script=document.createElement('script'));
    
    // or
    
    document.getElementsByTagName('head').item(0)
        .appendChild(script=document.createElement('script'));
    
    // or
    
    document.getElementsByTagName('head').item(0).appendChild(
        script=document.createElement('script'));
    
    // or
    
    document.getElementsByTagName('head').item(0).appendChild(script=document.createElement('script'));
    Now, that is a single expression. It looks nice as a five-liner. It looks pretty nice as a three-liner as well. The first two-liner is okay, but the second one is clumsy. The one-liner is bad coding.
    Last edited by liorean; 11-16-2004 at 08:46 PM.
    liorean <[lio@wg]>
    Articles: RegEx evolt wsabstract , Named Arguments
    Useful Threads: JavaScript Docs & Refs, FAQ - HTML & CSS Docs, FAQ - XML Doc & Refs
    Moz: JavaScript DOM Interfaces MSDN: JScript DHTML KDE: KJS KHTML Opera: Standards

  • #9
    Senior Coder
    Join Date
    Jun 2002
    Posts
    1,404
    Thanks
    2
    Thanked 32 Times in 32 Posts
    Hi David. Always look forward to your assessments. Think you took my comments a bit too literally, particularly in re that 'one line' business. I was thinking of this monster:


    Code:
    Number.prototype.toOrdinal=function(m){
        return (this +
            ["th","st","nd","rd"][(!(
                ((m=this%10) >3) ||
                (Math.floor(this%100/10)==1)
            ))*m]);
    }
    ...whose multi-line formatting mitigates none of its fabulous algorithmic density. But you've heard that a million times by now.

    Interesting:
    The shortcut way that adios used, which could be summarised as while(elm=col[i++]) is NOT recommended...
    What's interesting is that I've always done it the way you illustrated, encapsulating the looping in the .item() method, until recently I was 'corrected' by someone, who cited PPK (scroll to bottom), a source I generally trust. Maybe you could explain why some (JS) out-of-bounds situations seem to throw exceptions and others seem to fail gracefully...or is that just my imagination?

  • #10
    Master Coder
    Join Date
    Feb 2003
    Location
    Umeň, Sweden
    Posts
    5,575
    Thanks
    0
    Thanked 83 Times in 74 Posts
    Quote Originally Posted by adios
    Hi David. Always look forward to your assessments. Think you took my comments a bit too literally, particularly in re that 'one line' business.
    Well, I CHOSe to do that interpretation, since it would give me an excuse to write an explanation why that interpretation was a bad one for those other readers of this thread that would do that interpretation.
    I was thinking of this monster:
    Code:
    Number.prototype.toOrdinal=function(m){
        return (this +
            ["th","st","nd","rd"][(!(
                ((m=this%10) >3) ||
                (Math.floor(this%100/10)==1)
            ))*m]);
    }
    ...whose multi-line formatting mitigates none of its fabulous algorithmic density. But you've heard that a million times by now.
    I think I did a quite good job at the formatting of that considering it's highly mathematical nature... Of course, some code is harder to make nice and readable than other code.
    Interesting: What's interesting is that I've always done it the way you illustrated, encapsulating the looping in the .item() method, until recently I was 'corrected' by someone, who cited PPK (scroll to bottom), a source I generally trust.
    That is something I wouldn't do. From my experience PPK is heavily biased towards the way he's always been doing things and the "it works, it must be right", he doesn't consult the documentation and specifications before he draws his conclusions, he's hasty at making assumptions that are in no way given, and he doesn't listen very much to others. His tables are based on tests, and those test results I generally trust (but not blindly). But never trust his conclusions until you have tested that they are accurate as well.
    liorean <[lio@wg]>
    Articles: RegEx evolt wsabstract , Named Arguments
    Useful Threads: JavaScript Docs & Refs, FAQ - HTML & CSS Docs, FAQ - XML Doc & Refs
    Moz: JavaScript DOM Interfaces MSDN: JScript DHTML KDE: KJS KHTML Opera: Standards

  • #11
    jkd
    jkd is offline
    Senior Coder jkd's Avatar
    Join Date
    May 2002
    Location
    metro DC
    Posts
    3,163
    Thanks
    1
    Thanked 18 Times in 18 Posts
    I'd venture on those examples that, regardless of format, sticking the variable assignment outside of it is much nicer:

    Code:
    var script = document
                         .getElementsByTagName("head").item(0)
                         .appendChild(document.createElement("script"));
    Than assigning to the variable inside the appendChild. It's just sloppy really.

  • #12
    Senior Coder
    Join Date
    Jun 2002
    Posts
    1,404
    Thanks
    2
    Thanked 32 Times in 32 Posts
    If the two of you would like to duke it out over this I'd enjoy reading that.

    Also: what ever happened to 'JavaScript strict warnings'? I thought they were set to derail habits like object detection without the typeof operator, but it doesn't seem to have happened.

    Agree on PPK, his site in itself is a nightmare to navigate. Doesn't bode well for his accuracy.

  • #13
    Master Coder
    Join Date
    Feb 2003
    Location
    Umeň, Sweden
    Posts
    5,575
    Thanks
    0
    Thanked 83 Times in 74 Posts
    Jason: Of course, you're right about that...

    Adios: Well, the DOM guarantees that all elements of a collection are nodes, and that collections are compact. That means that we know that the only time iterating over a collection and getting a value that typecasts to false is when we hit the end of the collection. That means that the while and item(i++) method of doing it is guaranteed by the specs to work in any single threaded language. It also has the benefits of both being clean coding and being the absolutely fastest method of iterating over a collection devised so far.
    liorean <[lio@wg]>
    Articles: RegEx evolt wsabstract , Named Arguments
    Useful Threads: JavaScript Docs & Refs, FAQ - HTML & CSS Docs, FAQ - XML Doc & Refs
    Moz: JavaScript DOM Interfaces MSDN: JScript DHTML KDE: KJS KHTML Opera: Standards

  • #14
    Senior Coder
    Join Date
    Jun 2002
    Posts
    1,404
    Thanks
    2
    Thanked 32 Times in 32 Posts
    And the debate continues....

    OK, how 'bout...

    Code:
    var
        elm,
        col=document.getElementsByTagName('a'),
        i=col.length;
    if (i)
        do
        {
            elm=col[--i];
            doSomethingWith(elm);
        }
        while (i);
    As noted here, 'downwards' iteration is more efficient ('Flipped Loop with Reversed Count' et al).

  • #15
    Regular Coder
    Join Date
    Aug 2004
    Location
    codegoboom@yahoo.com
    Posts
    999
    Thanks
    0
    Thanked 0 Times in 0 Posts
    To me, it looks to be browser dependent. The really odd thing is that the optimal loop for Moz is the one and only construct that saps the heck out of IE (which is usually twice as fast with anything other than liorean's example).
    *this message will self destruct in n-seconds*


  •  

    Posting Permissions

    • You may not post new threads
    • You may not post replies
    • You may not post attachments
    • You may not edit your posts
    •