Javascript + DOM - links within same page - javascript

I have a existing page with several entries(divs), and I loop trough all of them to fetch the wanted content(headers) to create a list of links.
In the process I assign each header a unique ID, but I can't seem to get my list of links to "connect" to the specific entries.
Javascript:
var entries = document.getElementsByClassName('entry');
var ul = document.createElement('ul');
for (var i = 0; i < entries.length; i++) {
var li = document.createElement('li');
var heading = entries[i].getElementsByTagName('h2')[0];
var addId = heading.setAttribute("id", "#entry" + i);
var x = heading.getAttribute("id");
var headingText = document.createTextNode(heading.firstChild.nodeValue);
var link = document.createElement('a');
link.setAttribute("href", x);
link.appendChild(headingText);
li.appendChild(link);
ul.appendChild(li);
}
var target = document.getElementById('newdiv');
target.appendChild(ul);
What am I missing, or doing wrong?
When I hover over my list with links, they show the link as supposed - but nothing happens when I click it. If I inspect the DOM I can also see that all of the headers got assigned a unique ID.

Remove # from :
var addId = heading.setAttribute("id", "entry" + i);//("id", "#entry" + i)
and Add # to :
link.setAttribute("href", "#"+x);//("href",x)

Related

Pure JS: Store list of data- attributes in array, then iterate

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:
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":
Link to first title
Link to second title
Link to third title
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
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);
});
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>
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);
});

jquery auto width function doesn't work when dynamically created ul>li by javascript

I am new to stackoverflow and this is my first question here. Please overlook if I made any mistake.
Here is my problem : First I create jquery to define auto width to list.
(function(){
var items = $('.main-menu>li');
var maxitems = items.length; //items.length;
var current = items[0];
$('.main-menu li').css('width', (100 / maxitems | 0) + '%');
})();
Then I write these codes to create li element dynamically. But unfortunately this newly created li items are not taking auto width functionality that I previously coded.
function topMenu() {
document.getElementById('addTopMenu').onclick = addTopMenu;
}
function addTopMenu() {
var el = document.getElementById("main-menubar");
var node = document.createElement("li");
node.id = "main-menubar";
var link = document.createElement("a");
link.innerText = data = prompt("Type A Name For New Menu","");
var value = prompt("Type The href Of The Menu","");
link.setAttribute("href", value);
node.appendChild(link);
el.appendChild(node);
}
Please help me out this situation. Thanks in advance.

Removing an array element by clicking an HTML <li>

So I'm doing a playlist manager for youtube (using the ytb api) and for the graphic part I'm doing, such as youtube has, a list of every thumbnail there is in a given playlist. I use an HTML 'ul' and add every thumbnail as a 'li'.
Everything is working fine but id like to add a feature so the user could click on one of the thumbnails to remove it from the playlist.
First, let me explain how the important part is coded.
I use an array as a queue to stock every video ID that will be played (this is the playlist) :
var queue = []
And for the thumbnail list I use this function :
function refreshThumbnailsQueue() {
var thumbnailsUl = document.getElementById('thumbnailslist');
while(thumbnailsUl.firstChild) {
thumbnailsUl.removeChild(thumbnailsUl.firstChild );
}
for (var i = 0; i <= queue.length - 1; i++) {
var thumbnail = 'http://img.youtube.com/vi/' + queue[i] + '/maxresdefault.jpg';
var newLi = document.createElement('li');
newLi.className = 'thumbnailLi';
newLi.onclick = function() {
removeFromQueue();
}
var newImg = document.createElement('img');
newImg.className = 'thumbnailImg';
newImg.src = thumbnail;
newLi.appendChild(newImg);
thumbnailsUl.appendChild(newLi);
}
}
So I'm just removing every child the ul has and then filling it with every thumbnail of the video IDs there are in my queue var.
As you can see, there is a removeFromQueue() function called with an onclick event on each li in the code, and this is what I try to code.
Basicaly, if you click the third li, it should remove the third element of my queue var.
If you have any ideas, please let me know. (and BTW sorry for the mistakes English isn't my main language)
Thanks!
Note : I dont want to use jQuery.
If jQuery is an option, you can simply do the following :
$( "li" ).click(function(){
$( this ).remove();
})
As simple as that. If you want more information, I'll update my answer.
You can also visit this page for plain old javascript. Here is the important part :
var elem = document.getElementById("myDiv");
elem.parentNode.removeChild(elem);
As for the index of the li element
When you insert the list item in the DOM, you also set it's ID like this :
function refreshThumbnailsQueue() {
...
for (var i = 0; i <= queue.length - 1; i++) {
...
// Create the li.
var newLi = document.createElement('li');
newLi.id = "song-" + i;
// Create the onclick listening
li.onclick = function(){
// Remove from DOM.
var elem = document.getElementById(this.id);
elem.parentNode.removeChild(elem);
// We keep only the integer (index)
// In this example, '5' cuts away the "song-".
var index = parseInt((this.id+"").substring(5));
// Then, we remove it from the list.
YourProgram.removeIndex(index);
}
...
thumbnailsUl.appendChild(newLi);
}
}
This way, you know what it's index is.
Hope it helps.
Pass the index of the element to remove to the removeFromQueue(), like removeFromQueue(i). Then remove the item from queue.
function removeFromQueue(index) {
queue.splice(index, 1)
refreshThumbnailsQueue()
}

Change InnerHTML based on anchor click

I'm a little new to Web Development so I was hoping someone could answer this for me.
I'm building a prototype for a "Web Messenger" similar to Facebook messenger. I have a sidebar that I populate with a UL of anchor tags when the window loads and it looks like this. Here is the code for it
var toAdd = document.createDocumentFragment();
var newUL = document.createElement('ul');
newUL.id = 'menu-content';
newUL.className = 'menu-content collapse out';
for(var i = 0; i < 5; i++){
var newLI = document.createElement('li');
var newA = document.createElement('a');
newA.id = 'chat' + i;
newA.setAttribute('href', "#");
newA.innerHTML = "Chat" + (i + 1);
newLI.appendChild(newA);
newUL.appendChild(newLI);
}
toAdd.appendChild(newUL)
document.getElementById("menu-list").appendChild(toAdd);
I also have a Div at the top of the page which will display some details about the current chat, but for the time being will simply display the name of the chat, same as on the anchor tags.
Now based on another StackOverflow post the correct way to call a JS function from an anchor tag is
var c0 = document.getElementById("chat0");
//Set code to run when the link is clicked
// by assigning a function to "onclick"
c0.onclick = function(id) {
//Change Title Name here
//Do other stuff in the future
return false;
}
However I could have 20+ chats on the sidebar at any one time, so this seems like a lot of repetitive code to write.
Is there a better way to do this?
Give your chats a general class instead example chat then attach the click event to all the chat's in the same time using .getElementsByClassName().
So you could add className just after newA.id :
newA.id = 'chat' + i;
newA.className = 'chat';
Then attach the click event :
var chats = document.getElementsByClassName('chat');
for (var i=0; i < chats.length; i++) {
chats[i].addEventListener('click', chatClick, false);
}
function chatClick(){
//chat is clicked
//The 'this' object here refer to clicked element
}
You could use .addEventListener() instead of onclick.
NOTE : You can attach the click event directly after node creation :
for(var i = 0; i < 5; i++){
var newLI = document.createElement('li');
var newA = document.createElement('a');
newA.id = 'chat' + i;
newA.setAttribute('href', "#");
newA.innerHTML = "Chat" + (i + 1);
newA.addEventListener('click', chatClick, false); //Attach click event HERE
newLI.appendChild(newA);
newUL.appendChild(newLI);
}
Hope this help.
Yap sure. You can give them all a class and after load just use a simple jQuery code to bind onclick for all of them:
$('a.className').click(function() {
// Your code here
});
Now if the a tags are added after execution of the code you just simply need to call this again or bind to those elements manually.

How to disable a dynamically created <li> element?

i have created <ul> containing three <li>.i want to make disable one of my <li> on certain condition and insert some text in other <li> but failed.!
code
var d = document.createElement('div');
d.className = "dataTables_paginate paging_bootstrap pagination";
var UL = document.createElement('ul');
var L1 = document.createElement('li');
L1.className = 'prev';
var A1 = document.createElement('a');
A1.appendChild(document.createTextNode('← Previous'));
A1.id = 'B1';
L1.appendChild(A1);
UL.appendChild(L1);
var L3 = document.createElement('li');
L3.className = 'active';
var A3 = document.createElement('a');
A3.appendChild(document.createTextNode('1'));
L3.appendChild(A3);
UL.appendChild(L3);
d.appendChild(UL);
var L2 = document.createElement('li');
L2.className = 'next';
var A2 = document.createElement('a');
A2.appendChild(document.createTextNode('Next →'));
L2.appendChild(A2);
A2.id = 'B2';
UL.appendChild(L2);
var root = document.getElementById('rose');
root.appendChild(d);
i want to B1 disable. i have tried following code:
script
$('#B1').attr("disabled", true);
try with .off():
$('#B1').off("click");
FYI:
Only form input elems are having property to get disabled, whether that is type text, select checkbox buttons etc.
While there is no disabled state for a li element, you can simulate the desired behavior like this:
$('#B1').css("color","gray").css("text-decoration","none");
Which will make it appear as if disabled (it will not be underlined and will appear grayed-out).
If in addition you need to disable the event listeners attached to it, you will have to use off():
$('#B1').off("click");
Furthermore, if the element is a link, you will have to prevent it from being clickable, in the following way:
$('#B1').click(function() {
$(this).preventDefault(); // prevent the default action
$(this).stopPropagation(); // prevent event from bubbling up
return false; // just to be sure
}

Categories

Resources