0

I'm fairly new to JS and I can do DOM manipulation and if/else statements by hand. Now I'm trying for something out of my league, combining iteration with arrays, and I have a bit of a hard time understanding both of them.

With this in mind: Considering this div: <div id="firstAnchor"> would act as an anchor to this link: <a href="#firstAnchor"></a>

I want to store the ID of these div's (id's should be able to be anything):

<div id="firstAnchor" style="display: inline-block;">First title</div>
<div id="secondAnchor" style="display: inline-block;">Second title</div>
<div id="thirdAnchor" style="display: inline-block;">Third title</div>

into an array, and then create these three links automatically* placed in a div called "anchorLinks":

<a href="#firstAnchor">Link to first title</a>
<a href="#seconAnchor">Link to second title</a>
<a href="#thirdAnchor">Link to third title</a>

How would I go about this?

* for example within this function:

(function create_anchor_link_list() {
 //placed here
})();

Edit:

Here is what I have tried to begin with. I first had data-anchor="firstAnchor" etc. on my div elements until I realized I couldn't link to div elements based on data- attributes values. So with the data- attributes I tried:

(function anchorsInPage2(attrib) {
    console.log("=#=#=#=#=#=#=#=#=#=#=#=#=#=#=#=#=#=#=#=#=#=#");
    console.log("=#=#=#=#=# anchorsInPage2 function #=#=#=#=#");
    console.log("=#=#=#=#=#=#=#=#=#=#=#=#=#=#=#=#=#=#=#=#=#=#");
    console.log("                                            ");

    var elements = document.getElementsByTagName("*");
    var foundelements = [];

    for (var i = 0; i < elements.length; i++) {
        if (elements[i].attributes.length > 0) {
            for (var x = 0; x < elements[i].attributes.length; x++) {
                if (elements[i].attributes[x].name === attrib) {
                    foundelements.push(elements[i]);
                }
            }
        }
    }
    return foundelements;

    console.log("                                              ");
    console.log("=#=#=#=#=#=#=#=#=#=#=#=#=#=#=#=#=#=#=#=#=#=#=#");
    console.log("=#=#=#=#=# / anchorsInPage2 function #=#=#=#=#");
    console.log("=#=#=#=#=#=#=#=#=#=#=#=#=#=#=#=#=#=#=#=#=#=#=#");
})();







function anchorsInPage3() {
    console.log("=#=#=#=#=#=#=#=#=#=#=#=#=#=#=#=#=#=#=#=#=#=#");
    console.log("=#=#=#=#=# anchorsInPage3 function #=#=#=#=#");
    console.log("=#=#=#=#=#=#=#=#=#=#=#=#=#=#=#=#=#=#=#=#=#=#");
    console.log("                                            ");

    var elements = document.getElementsByTagName("*");
    var foundelements = [];

    for (var i = 0; i < elements.length; i++) {
        if (elements[i].attributes.length > 0) {
            for (var x = 0; x < elements[i].attributes.length; x++) {
                if (elements[i].attributes[x].name === "anchor") {
                    foundelements.push(elements[i]);
                }
            }
        }
    }
    return foundelements;

    console.log("                                              ");
    console.log("=#=#=#=#=#=#=#=#=#=#=#=#=#=#=#=#=#=#=#=#=#=#=#");
    console.log("=#=#=#=#=# / anchorsInPage3 function #=#=#=#=#");
    console.log("=#=#=#=#=#=#=#=#=#=#=#=#=#=#=#=#=#=#=#=#=#=#=#");
}





(function anchorsInPage1() {
    console.log("=#=#=#=#=#=#=#=#=#=#=#=#=#=#=#=#=#=#=#=#=#=#");
    console.log("=#=#=#=#=# anchorsInPage1 function #=#=#=#=#");
    console.log("=#=#=#=#=#=#=#=#=#=#=#=#=#=#=#=#=#=#=#=#=#=#");
    console.log("                                            ");

    var anchors = document.querySelectorAll('[anchor]');

    for(var i in anchors){
        console.log(i);
    }

    console.log("                                              ");
    console.log("=#=#=#=#=#=#=#=#=#=#=#=#=#=#=#=#=#=#=#=#=#=#=#");
    console.log("=#=#=#=#=# / anchorsInPage1 function #=#=#=#=#");
    console.log("=#=#=#=#=#=#=#=#=#=#=#=#=#=#=#=#=#=#=#=#=#=#=#");
})();

First update after further testing:

Barmar's example was used. The text below is a direct answer to Barmar (too long for the other comment field)

Test: http://jsfiddle.net/e5u03g4p/5/

My reply:

With the first variable you found all element with the attribute data-anchor, so I guess the brackets in querySelectorAll tells it which specific attribute we mean instead of what elements ID's we want, which is the "standard" writing document.querySelectorAll("tagName") instead of document.querySelectorAll("[attributeName]").

With the second variable you found the first element with the ID of anchorLinks. The hashtag is needed to specify ID as querySelector represents div so the result is div#anchorLinks(?).

You then take the variable anchors (which results in an array of the data-anchor value of the div's with the data-anchor attribute) and for each of them, a function triggers where the d argument of the function equals the element ID of the elements with the data-anchor attribute. Everything within this function repeats for each of the elements with data-anchor attribute (ie. the variable anchors).

What's happening within the function is:

-You create a variable (a) which contains the element creation of an <a> element

-You then set the href attribute of the newly created <a> element to the ID of the data-anchor elements.

-I then assign the attribute title of the <a> elements to the content of the data-anchor elements (instead of the original thought where it was textContent that was set to the <a> elements`as I want the links to be images instead of text)

-I then also added a new class attribute to the <a> elements in order to style them

  • StackOverflow is not a free coding service. SO expects you to [try to solve your own problem first](https://meta.stackoverflow.com/questions/261592). Please update your question to show what you have already tried in a [mcve]. For further information, please see [ask], and take the [tour] :) – Barmar Sep 28 '18 at 22:56
  • How do you know which DIVs should be stored? Are they all children of a particular element? Do they have a common class? You need some way to distinguish these DIVs from all the other DIVs on your page. – Barmar Sep 28 '18 at 22:58
  • Actually, how rude of you to think that I haven't already tried. What I have tried seems to be of extremely little concern to you, as I have obviously failed my attempts and have clearly and concisely pointed out what I am trying to achieve. With that said, I have updated the question. – Streching my competence Sep 28 '18 at 22:59
  • 1
    We want to help you learn by pointing out what you did wrong and how to fix it. How can we do that if you don't show your attempt? – Barmar Sep 28 '18 at 23:02
  • I don't see the question update. – Barmar Sep 28 '18 at 23:04
  • It's updated. And I first had data-anchor="" to identify them. – Streching my competence Sep 28 '18 at 23:06
  • 1
    And instead of looping over all attributes checking `attributes[x].name == "anchor"`, just call `elements[i].getAttribute("anchor")` and see if it returns a result. – Barmar Sep 28 '18 at 23:12
  • There's no `anchor` attribute, did you mean `data-attribute`? – Barmar Sep 28 '18 at 23:12
  • An ID on a DIV element acts as name="" on an a="" element. So a DIV's ID is an achor, so there is an anchor attribute (id="") – Streching my competence Sep 28 '18 at 23:34
  • I can't figure out what you're trying to say there. `attributes[x].name == "anchor"` will only match an element that has `anchor="something"`. It won't match `data-anchor="something"`. – Barmar Sep 28 '18 at 23:36
  • 1
    Are you trying to look for IDs that end with `Anchor`, like `firstAnchor`, `secondAnchor`, etc.? – Barmar Sep 28 '18 at 23:37
  • 1
    You can use `if (element[x].id.test(/Anchor$/))` – Barmar Sep 28 '18 at 23:38
  • @Barmar I have now updated my question with a fiddle and also an explanation of how I've understood your code. I changed a bit (not much). That's also explained in the example. – Streching my competence Sep 29 '18 at 13:21
  • So all that's left (for this question) is just skipping the part where we get the ````data-anchor```` value, and instead straightly get the ID instead. The code as is now is doing double work to get that value as of now, but I'm leaving it in for the sake of illustrating the options if anyone else reads it. – Streching my competence Sep 29 '18 at 13:39
  • I also looked closer at your solution for getting all IDs that end with Anchor. It makes sense, but I haven't tried it. It did however expand my imagination by miles. Thanks for that! :D – Streching my competence Sep 29 '18 at 14:28
  • Now (after of course fixing that little unnecessary step in the code and removing the data-anchor attributes since I really don't need them), if I combine this result with something like the answer by user @vsync here https://stackoverflow.com/questions/11760898/find-element-thats-on-the-middle-of-the-visible-screen-viewport-on-scroll (when I have learned it myself) I can match the value of the ID's and HREFs in order to position a circle element placed beneath the dots and I should end up with a pagination indicator in the style of a chip dropped or raised in a column of 4-in-a-row. – Streching my competence Sep 29 '18 at 14:38

3 Answers3

1

How about this:

document.getElementsByTagName('div').forEach(function(d) {
    var a = document.createElement('a');
    a.setAttribute('href', '#' + d.id);
    a.innerHTML = 'Link to ' + d.textContent.toLowerCase();
    document.getElementById('anchorLinks').appendChild(a);
});

Or if you have more divs (of course) and they have a specific class, you can do:

document.getElementsByClassName('your-class-name').forEach(function(d) {
    var a = document.createElement('a');
    a.setAttribute('href', '#' + d.id);
    a.innerHTML = 'Link to ' + d.textContent.toLowerCase();
    document.getElementById('anchorLinks').appendChild(a);
});
enys
  • 483
  • 3
  • 9
  • Thanks for the reply. I just got hit by a serious migraine (literally and unrelated to this). I will check this out as soon as possible and see what I can make of it and get back to you! – Streching my competence Sep 28 '18 at 23:44
  • Hi again! This was a great example as long as the div's in the example were the only div's in my page. I have understood (mostly, I think) however, how to fix that. I'm upvoting this answer. – Streching my competence Sep 29 '18 at 13:15
1

If you craft the query selector correctly you can get all of the "anchor" elements at once, then iterate over them to add the relevant links.

var links = document.getElementById('anchorLinks');
document.querySelectorAll('#anchors div[id]').forEach(function(anchor) {
    var link = document.createElement('a');
    link.href = '#' + anchor.id;
    link.textContent = 'Link for ' + anchor.textContent;
    links.appendChild(link);
});
<div id="anchors">
  <div id="firstAnchor" style="display: inline-block;">First title</div>
  <div id="secondAnchor" style="display: inline-block;">Second title</div>
  <div id="thirdAnchor" style="display: inline-block;">Third title</div>
</div>
<div id="anchorLinks">
</div>
Jake Holzinger
  • 4,610
  • 1
  • 14
  • 30
  • Thanks for the reply. I just got hit by a serious migraine (literally and unrelated to this). I will check this out as soon as possible and see what I can make of it and get back to you! – Streching my competence Sep 28 '18 at 23:43
  • Hey again! Looks somewhat like the example from Barmar, though I don't understand the .forEach as an addon to the querySelectorAll, and I don't get what it means to put "#anchors div[id]" inside it. Could you elaborate on the syntax there? The rest I understand fine. – Streching my competence Sep 29 '18 at 13:36
  • 1
    `document.querySelectorAll` returns an iterable type, the `forEach` method takes a callback that is called for each element of the iterable. The selector `#anchors` finds an element with id "anchors", the selector `div[id]` finds div elements that have an id attribute, put them together and it finds the all the div elements that have an id that are children of an element with id "anchors". – Jake Holzinger Sep 29 '18 at 20:03
  • Ahh. You explained that extremely well. Thanks! ^^ – Streching my competence Sep 29 '18 at 20:08
1

If you used data-anchor="something" in your DIVs, then you should use

var anchors = document.querySelectorAll('[data-anchor]');

not [anchor].

You can then loop over them with forEach()

var anchorLinks = document.querySelector("#anchorLinks");
anchors.forEach(function(d) {
    var a = document.createElement('a');
    a.href = '#' + d.id;
    a.textContent = 'Link to ' + d.textContent.toLowerCase();
    anchorLinks.appendChild(a);
});
Barmar
  • 596,455
  • 48
  • 393
  • 495
  • Thanks for the reply. I just got hit by a serious migraine (literally and unrelated to this). I will check this out as soon as possible and see what I can make of it and get back to you! – Streching my competence Sep 28 '18 at 23:44
  • Marking this as the solution as it is what got me to the end result. Please compare final result with this and read my final comments in the original post to see what I modified and why. – Streching my competence Sep 29 '18 at 14:40
  • If you have a final result that does everything you want, you should post it as an answer and accept it, rather than putting the details in the question. – Barmar Sep 29 '18 at 17:09
  • Answers should be posted here, not at third-party sites. – Barmar Sep 29 '18 at 18:09