So I'm generating a paragraph.
I want to add <ul> under the 3rd paragraph.
Here is the code snippet:
var i = 0;
for (i = 0; i < 5; i++) {
const para = document.createElement("p");
const node = document.createTextNode("This is new.");
para.appendChild(node);
const element = document.getElementById("div1");
element.appendChild(para);
// add ul under the 3rd paragraph
}
.nav {
background-color: grey;
text-align: center;
width: 90px;
height: 90px;
margin: 0;
padding: 0;
transition: background .5s;
/* .5s how long transition should take */
}
<ul class="nav">
<p>Test</p>
</ul>
Do you want to inject the ul under your 3rd paragraph in the element with id1?
You can have something like:
// On your "add ul under the 3rd paragraph line
if (i == 2){ //Condition for 3rd paragraph (-1 as the loop starts on 0)
const menu = document.getElementsByClassName("nav")[0]; //get the ul you want to add. getElementsByClassName returns a list, so would need to get the item you want to add. You might want to use an id in case you have multiple elements with class nav.
//Finally, add the element on your div1
document.getElementById("div1").appendChild(menu);
}
Related
I want to dynamically append a child to its parent multiple times when I click the button.
let btn = document.querySelector('.btn');
let starContainer = document.querySelector('.star__container');
let starWin = document.createElement('div');
starWin.classList.add('star__win');
starWin.innerText = 'Test';
btn.addEventListener('click',addItem);
function addItem(){
starContainer.appendChild(starWin);
}
<div class="star__container"></div>
<button class='btn'>Click</button>
You need to create your starWin element each time the addItem method is called. Now, you append the same element several times. It won't be cloned.
let btn = document.querySelector('.btn');
let starContainer = document.querySelector('.star__container');
btn.addEventListener('click', addItem);
function addItem() {
starContainer.appendChild(createElement());
}
function createElement() {
let starWin = document.createElement('div');
starWin.classList.add('star__win');
starWin.innerText = 'Test';
return starWin;
}
<div class="star__container"></div>
<button class='btn'>Click</button>
<div class="star__container"></div>
<button class='btn'>Click</button>
let btn = document.querySelector('.btn');
let starContainer = document.querySelector('.star__container');
btn.addEventListener('click',addItem);
function addItem(){
let starWin = document.createElement('div');
starWin.className = 'star__win';
starContainer.appendChild(starWin);
}
Update
Issue
Expectation: A <div> should to be appended to DOM for each click of a button.
Result: The first click of the button appends a <div> to DOM, but thereafter any further clicking of said button elicits nothing.
Diagnosis: All code concerning the creation of <div> is not within a function, the only time it will run is at page load. When the handler function is triggered by a button click, it finds that <div> that was made at page load and successfully appends the <div> to the DOM. When user clicks the button again, nothing happens because the <div> was made only once.
Solution: Place all of the aforementioned code in the handler function addItem()
Demo 1
let btn = document.querySelector('.starBtn');
btn.addEventListener('click', addItem);
function addItem(event) {
const box = document.querySelector('.starBox');
let star = document.createElement('b');
star.classList.add('stellar');
star.innerText = '⭐';
box.appendChild(star);
}
body {
font-size: 3rem
}
.starBox {
word-wrap: break-word;
}
.starBtn {
position: fixed;
top: 0;
left: 0;
font: inherit;
}
<article class="starBox"></article>
<button class='starBtn'>🤩</button>
Not sure what the problem is, don't care really. If you take a look at this demo it'll help with whatever issue you may have. Details are commented line-by-line in the demo. Apologies in advance -- I'm bored ...
🥱
I'll come back and post a decent answer later. Review the demo in Full Page mode.
Demo 2
// Reference the <form>
const STARS = document.forms.starFactory;
// Define the counter
let s = 0;
// Register the form to the click event
STARS.onclick = makeStar;
// Handler function passes event object
function makeStar(event) {
// Define an array of characters✱
let galaxy = ['★', '☆', '✨', '✩', '✪', '⚝', '✫', '✭', '✯', '✰', '✴', '⭐', '🌟', '🌠', '💫', '🟊', '🤩'];
/*
- "this" is the form
- Collect all <input>, <button>, <output>, etc into a
NodeList
*/
const field = this.elements;
/*
- event.target is always the tag the user interacted with
- In this case it's the <button> because this handler
will not accept but that <button>
*/
const clicked = event.target;
/*
- The NodeList `field` can reference form tags by
suffixing the tag's #id or [name]
- The <fieldset> and <output> are referenced
*/
const jar = field.starJar;
const cnt = field.count;
/*
- By using a simple `if` condition strategically we can
control what and how tags behave when a registered
event.
- The remainder of the handler is explained at the very
end.
*/
if (clicked.id === 'STARt') {
s++;
const star = document.createElement('S');
let index = Math.floor(Math.random() * galaxy.length);
let ico = galaxy[index];
star.textContent = ico;
star.className = 'star';
star.style.zIndex = s;
star.style.left = Math.floor(Math.random() * 85) + 1 +'%';
star.style.bottom = Math.floor(Math.random() * 90) + 1 + '%';
jar.appendChild(star);
cnt.value = s;
}
}
/*
- increment `s` by one
- create a <s>trikethrough tag (aka <s>tar tag JK)
- generate a random number in the range of 0 to 15
- get a character from galaxy Array at the index number
determined from the previous step.
- render the text character in the <s>tar
- assign the class .star to <s>tar
- assign `z-index` to <s>tar (Note: it increases every
click which insures that tags won't collide)
- randomly assign `left` in the range of 1 to 85 to <s>tar
- randomly assign `bottom` in the range of 1 to 90 to
<s>tar
- append <s>tar to #starJar
- increment #count value
*/
:root,
body {
font: 400 5vw/1 Verdana;
background: #123;
}
#starFactory {
display: flex;
justify-content: center;
align-items: center;
}
#starJar {
position: relative;
display: flex;
flex-flow: row wrap;
justify-content: end;
width: 50vw;
height: 50vw;
border: 5px inset rgba(255,255,0,0.3);
border-bottom-left-radius: 12vw;
border-bottom-right-radius: 12vw;
color: gold;
}
legend {
position: relative;
z-index: 5150;
width: max-content;
font-size: 1.5rem;
color: goldenrod;
}
#STARt {
position: relative;
z-index: 5150;
font-size: 1.5rem;
background: none;
padding: 0;
border: 0;
cursor: pointer;
}
#count {
position: relative;
z-index: 9999;
font-size: 1.25rem;
width: 5vw;
overflow-x: visible;
color: cyan;
}
s.star {
position: absolute;
text-decoration: none;
font-size: 1.5rem;
background: none;
padding: 0;
margin: 0;
border: 0;
}
<form id='starFactory'>
<fieldset id="starJar">
<legend>starJar
<button id='STARt' type='button'>
✴️ <output id='count'></output>
</button>
</legend>
</fieldset>
</form>
I want to make fractal tree and if i press left click i suppossed to be add new div and if i press right click it supposed to be decrease div, but the left click function didn't work, its supposed to be recursive but it just add one div and if i press left click again nothing happen and the right click also didn't work, all of the div disappear. this is my code
<head>
<style type="text/css">
div {
position: absolute;
background-color: #e21d27;
opacity: 0.8;
transition: 2s;
}
div#start {
width: 100px;
height: 100px;
transform: translate(300%, 300%);
}
div div {
width: 100%;
height: 100%;
}
div div:nth-child(1) {
transform: translate(-42%, -105%) rotate(-37deg) scale(0.8, 0.8);
}
div div:nth-child(2) {
transform: translate(55%, -91%) rotate(53deg) scale(0.6, 0.6) ;
}
div:hover {
transition: 1s;
opacity: 1;
}
</style>
</head>
<body>
<div id="start"></div>
<script>
var coba =27;
var leftClick = document.getElementById("start");
var rightClick = document.getElementById("start");
leftClick.onclick = function(){
for ( var i = 0; i< coba; i++ ) {
var di = document.createElement('div');
leftClick.appendChild(di);
}
}
rightClick.oncontextmenu = function(){
for ( var i = 0; i< coba; i++ ) {
var removedi = document.getElementById("start");;
removedi.parentNode.removeChild(removedi);
}
}
</script>
</body>
thank you so much for your help
Your rightclick function is removing the whole "start" div. removedi is set to that div and then you are calling removeChild on its parent, causing it to be removed. That's probably why everything is getting removed when you right click. Instead, you should remove child nodes of the start div.
You probably want something like:
var start = document.getElementById('start');
for (var i = 0; i < start.childNodes.length; i++) {
var child = start.childNodes[i];
start.removeChild(child);
}
I'm not sure why your left-click handler is not doing what you want.
I'm looking to learn how to do this left menu :
http://js.devexpress.com/New/15_2/#HTML_5_JS_Core
When you scroll down the page, the "active" menu item change.
p.s.
Is there a name for this type of menu?
regards,
yaniv
Scroll Navigation
That is how we call these type of navigation bars. Basically you have to listen to the scroll event and calculate which element is in the viewport at the moment than you add a class to your navigation that marks the current menu element.
There is a nice demo built in jQuery but because jQuery is a thing of the past, I built one in Vanilla JS. See comments for explanations.
There are different ways to define which is the current element. In my Example it is the last one whose top line just passed the top line of the browser.
Working demo
window.onscroll = onScroll;
function onScroll() {
var removeActiveClass = function (elements) {
for (var i = 0; i < elements.length; ++i) {
elements[i].classList.remove('active');
}
}
var anchors = document.querySelectorAll('#menu-center a');
var previousRefElement = null;
for (var i = 0; i < anchors.length; ++i) {
// Get the current element by the id from the anchor's href.
var currentRefElement = document.getElementById(anchors[i].getAttribute('href').substring(1));
var currentRefElementTop = currentRefElement.getBoundingClientRect().top;
// Searching for the element whose top haven't left the top of the browser.
if (currentRefElementTop <= 0) {
//The browser's top line haven't reached the current element, so the previous element is the one we currently look at.
previousRefElement = anchors[i];
// Edge case for last element.
if (i == anchors.length - 1) {
removeActiveClass(anchors);
anchors[i].classList.add("active");
}
} else {
removeActiveClass(anchors);
previousRefElement.classList.add("active");
break;
}
}
}
body, html {
margin: 0;
padding: 0;
height: 100%;
width: 100%;
}
.menu {
width: 100%;
height: 75px;
position: fixed;
background-color:rgba(4, 180, 49, 0.6);
}
#menu-center {
width: 980px;
height: 75px;
margin: 0 auto;
}
#menu-center ul {
margin: 15px 0 0 0;
}
#menu-center ul li {
list-style: none;
margin: 0 30px 0 0;
display: inline;
}
.active {
font-size: 14px;
color: #fff;
text-decoration: none;
line-height: 50px;
}
a {
font-size: 14px;
color: black;
text-decoration: none;
line-height: 50px;
}
.content {
height: 100%;
width: 100%;
}
#portfolio {background-color: grey;}
#about {background-color: blue;}
#contact {background-color: red;}
<div class="menu">
<div id="menu-center">
<ul>
<li><a class="active" href="#home">Home</a></li>
<li>Portfolio</li>
<li>About</li>
<li>Contact</li>
</ul>
</div>
</div>
<div id="home" class="content"></div>
<div id="portfolio" class="content"></div>
<div id="about" class="content"></div>
<div id="contact" class="content"></div>
This is not exactly menu type, it is the way how you can position objects by html.
You can use position:Abosule property to achieve this effect:
http://www.w3schools.com/css/tryit.asp?filename=trycss_position_fixed
By this given divs are "flying" above the res of the page. In your case it could be a menu.
EDIT:
To sync this you need to detect when given anchor is currently seen.
It can be done by jQuery, this is sample draft of code, should explain clue of solution:
// list of header on page
var positions = [
$("#anchor1").offset().top,
$("#anchor2").offset().top,
$("#anchor3").offset().top,
];
var menu_objects= [
"#menu1",
"#menu2",
"#menu3"
];
var $w = $(window).scroll(function(){
// clear old
for(var v in menu_objects)
$(v).css({"color","white"});
for(var i=positions.length-1;i>=0;i--)
{
if(positions[i]>=$w.scrollTop())
{
$(menu_objects[i]).css({"color","red"});
break;
}
}
});
Apologies in advance is this is a duplicate. I'm new here and new to javascript. I'll begin by describing what I am aiming to do, then show the code.
Basically. I have a HTML page with a simple navigation bar (the usual ul li arrangement). When one of the options is clicked, it will show the relevant 'page' (which are tags) by removing the .hide class on the target article, and adding the .hide class to the page that was visible. Previously I simply just used the 'getElementByID' to grab each element by id, showing whats' meant to show and hiding whats meant to be hidden.
As you can imagine, it ends up in repeating that many times in a function. I'm looking for a more efficient way to do this. The way I thought I'd try would be to grab all the navigation elements and place them in an array, then grab all the 'page' elements and put them in an array. When the option in the navigation is clicked, it returns the index position in the array, which can be compared the the index position of the pages in the other array. If they match, remove the .hide class to make the 'page' visible. Anything else that doesnt match, add the .hide class to the remaining 'page' elements
Here is my attempt so far:
HTML:
<!doctype html> <html> <head> <title>Practice to improve javascripting</title> <link rel="stylesheet" type="text/css" href="css/style.css" /> <script type="text/javascript" src="js/practice.js"></script> </head>
<body onload="indexNum()"> <div id="pageContainer"> <ul> <li>Test</li> <li>Test</li> <li>Test</li> </ul>
<article id="one"> <h4>Page one</h4> <p>Page one is now displayed</p> </article>
<article id="two" class="hide"> <h4>Page two</h4> <p></p> </article>
<article id="three" class="hide"> <h4>Page three</h4> <p></p> </article>
</div><!-- end of pageContainer div-->
</body> </html>
CSS:
/*CSS Document */
body { background-color:whiteSmoke;
font-family: Verdana, Geneva,sans-serif; font-size: 12pt; margin:0; padding:0;
}
#pageContainer {margin: 20px auto 40px auto;
padding:0; width: 600px; height:auto;
background-color:snow;
border: 1px solid gainsboro; border-radius: 3px; /*end of set-up code*/
}
/*navbar styles*/
ul {
background-color:white;
border: 1px solid violet;
border-radius: 3px;
width: 550px; height: 20px;
margin: 15px auto 15px auto;
list-style-type:none;
padding: 0;
}
li {
float:left;
width:33%; height:20px;
text-align:center;
}
.select li {
background-color:violet;
color: snow; font-weight:bold;
}
a {color: black;}
/*page styles*/
article {
width: 600px; height: 400px;
border-top: 1px solid gainsboro;
margin:0; padding:0;
}
h4, p {margin: 10px 20px 10px 20px}
.hide {display:none;}
and here is my mess of javascript lol:
//create global variables
var nav = document.getElementsByTagName
('a');
var page = document.getElementsByTagName
('article');
/*create a function that will be called on
page load to find the index position of the
navigation buttons:*/
function indexNum(){
nav; //calling the nav global variable
//search array for index positions
for(var index = 0; index < nav.length; index++) {
//store index number in variable?
nav[index].indexNumber = index;
//now search array of page index position
for(var indexPages = 0; indexPages < page.length; indexPages++){
//store index number in variable?
nav[indexPages].indexedNumber = indexPages;
//function to return index of element clicked
nav[index].onclick = function() {
if (this.indexNumber == page[indexPages]) {
page.className = "";
} else if (this.indexNumber !== page[indexPages]) {
page.className = "hide";
}
}
}
}
I'm probably going about this the wrong way, but I want to be able to add as many options on the navigation bar, with the corresponding pages. Even add as many navigation bars (for sub navigation on a page) with as many sub pages. So this is the reason for my madness lol.
Many thanks in advance
Ok, here it goes. I commented every step of the way in the JavaScript so you can learn exactly what's going on here.
This is completely dynamic. You can add and remove articles as needed, and your navigation menu will update automatically and without any limitations.
var doStuff = function () {
// Get all of the articles
var articles = document.getElementsByTagName("article");
// Define an empty array to hold the id's of the articles
var navIds = [];
// Loop through the articles
for (var i = 0; i < articles.length; i++) {
// Get the classes for the current article
var classes = articles[i].classList;
var hidden = false;
// Loop through the class list for the current article
for (var a = 0; a < classes.length; a++) {
// If the current class equals "hide"
if (classes[a] === "hide") {
// Set the variable "hidden" to true
hidden = true;
// Get out of the loop
break;
}
}
// If the article is hidden, add the ID to the navIds array so we can add it to the navigation
if (hidden) {
navIds.push(articles[i].id);
}
}
// If there are hidden articles
if (navIds.length > 0) {
// Clear the navigation
document.getElementById("nav").innerHTML = "";
}
// Loop through the navIds
for (var i = 0; i < navIds.length; i++) {
// Get the nav element (ul)
var navElem = document.getElementById("nav");
// Create a new li element
var liElem = document.createElement("li");
// Add the li element to the nav (ul) element
navElem.appendChild(liElem);
// Create a new a element
var aElem = document.createElement("a");
// Set the href on the new a element
aElem.href = "#"
// Set the "data-article" attribute to the id of the article to show when clicked
aElem.setAttribute("data-article", navIds[i]);
// Here, we're going to set the navigation title to the contents of the h4 element in the article
// Get the current article
var article = document.getElementById(navIds[i]);
// Get the children of the current article
var children = article.childNodes;
// Define an empty variable to hold the h4 element when we find it
var h4Elem;
// Loop through the children of the current article
for (var a = 0; a < children.length; a++) {
// If the current child is an h4 element
if (typeof children[a].tagName !== "undefined" && children[a].tagName.toLowerCase() === "h4") {
// Set the h4Elem variable to the current child element
h4Elem = children[a];
// Get out of the loop
break;
}
}
// Since we defined h4Elem as an empty variable, we need to make sure it's a valid HTMLElement object
if (h4Elem instanceof HTMLElement) {
// Set the Inner HTML of the new a element to the Inner HTML of the article's h4 element
aElem.innerHTML = h4Elem.innerHTML;
}
// Add the new a element to the new li element in the navigation
liElem.appendChild(aElem);
// Add a click event handler on the new a element in the navigation
aElem.addEventListener("click", function () {
// Get all of the articles
var articles = document.getElementsByTagName("article");
// Loop through the articles
for (var i = 0; i < articles.length; i++) {
// Get the classes for the current article
var classes = articles[i].classList;
// Define a hidden variable and set it to false
var hidden = false;
// Loop through the classes of the current article
for (var a = 0; a < classes.length; a++) {
// If the class is "hide"
if (classes[a] === "hide") {
// Set the hidden variable to true
hidden = true;
// Get out of the loop
break;
}
}
// If the article is not hidden
if (!hidden) {
// hide it
articles[i].classList.add("hide");
}
}
// Get the id of the article to show
var elemIdToShow = this.getAttribute("data-article");
// Get the element to show
var elemToShow = document.getElementById(elemIdToShow);
// Remove the hidden class from it
elemToShow.classList.remove("hide");
// Re-run the doStuff() function to regenerate the navigation and event handlers
doStuff();
});
}
}
// Run the doStuff() function
doStuff();
/* Your original CSS, I didn't change anything */
body {background-color: whiteSmoke;font-family: Verdana, Geneva,sans-serif;font-size: 12pt;margin: 0;padding: 0;}
#pageContainer {margin: 20px auto 40px auto;padding: 0;width: 600px;height: auto;background-color: snow;border: 1px solid gainsboro;border-radius: 3px;}
ul { background-color: white;border: 1px solid violet;border-radius: 3px;width: 550px; height: 20px;margin: 15px auto 15px auto;list-style-type: none;padding: 0;}
li {float: left;width: 33%;height: 20px;text-align: center;}
.select li {background-color: violet;color: snow;font-weight: bold;}
a {color: black;}
article {width: 600px;height: 400px;border-top: 1px solid gainsboro;margin: 0;padding: 0;}
h4, p {margin: 10px 20px 10px 20px;}
.hide {display: none;}
<div id="pageContainer">
<ul id="nav"><!-- Empty ul for dynamic navigation --></ul>
<!-- Each article is a separate "page" -->
<article id="one">
<h4>Page one</h4>
<p>Page one is now displayed</p>
</article>
<article id="two" class="hide">
<h4>Page two</h4>
<p>Page two is now displayed</p>
</article>
<article id="three" class="hide">
<h4>Page three</h4>
<p>Page three is now displayed</p>
</article>
</div>
I am trying to create a hovering menu, but it doesn't work. I create a menu and set it with a high z-index value. I then generate a table using javascript, but then I scroll down the table goes in front of my menu buttons.
Edit:
I am just trying to get this to work for FF8.
Edit 2:
This code will actually work. In order to make my buttons appear on top I just set my table z-index to -1;
#blackHead
{
width:100%;
background-color:White;
}
#table
{
position:relative;
width: 40%;
left: 30%;
z-index: -1;
}
#header
{
position: fixed;
top:3%;
left:30%;
width:40%;
z-index: 100;
}
.inv
{
visibility:hidden;
width:30px;
}
.headerButton
{
text-decoration:none;
position:relative;
font-family:Arial;
font-weight:bold;
color:White;
border: solid 1px black;
background-color: Black;
border-radius: 5px;
padding: 5px;
z-index: 101;
}
.headerButton:hover
{
background-color: White;
color: Black;
}
#myTable {
position: absolute;
top:10%;
}
#button1
{
position: absolute;
top:0%;
left:0%;
}
#button2
{
position: absolute;
top:0%;
right:0%;
}
#button3
{
position: absolute;
top:0%;
left:50%;
}
#button4
{
position: absolute;
top:10%;
left:50%;
}
#button5
{
position: absolute;
top:10%;
right:0%;
}
</style>
<html>
<head>
<title>Table</title>
</head>
<body>
<div id="header" class="headerBar">
Create Table
<span class="inv">" "</span>
Update Table
<span class="inv">" "</span>
Quit
<span class="inv">" "</span>
Send Json
<span class="inv">" "</span>
Start Timer
<span class="inv">" "</span>
Stop Timer
</div>
</body>
</html>
<script type="text/javascript">
function create_table() {
// get the reference for the body
var body = document.getElementsByTagName("body")[0];
// creates a <table> element and a <tbody> element
var tbl = document.createElement("table");
tbl.id = "table";
var tblBody = document.createElement("tbody");
tbl.style.zIndex = -1;
// creating all cells
var xmlDoc = getXML();
var x = xmlDoc.getElementsByTagName("Registers");
for (var i = 0; i < x.length; i++) {
// creates a table row
var row = document.createElement("tr");
// Create a <td> element and a text node, make the text
// node the contents of the <td>, and put the <td> at
// the end of the table row
var name = document.createElement("td");
name.style.width = "80%";
var nameText = document.createTextNode(x[i].getElementsByTagName("name")[0].childNodes[0].nodeValue);
name.appendChild(nameText);
row.appendChild(name);
var number = document.createElement("td");
number.style.width = "10%";
var numberText = document.createTextNode(x[i].getElementsByTagName("number")[0].childNodes[0].nodeValue);
number.appendChild(numberText);
row.appendChild(number);
var value = document.createElement("td");
value.style.width = "10%";
var valueText = document.createTextNode(x[i].getElementsByTagName("value")[0].childNodes[0].nodeValue);
value.appendChild(valueText);
row.appendChild(value);
row.addEventListener("dblclick", modify_value, false);
// add the row to the end of the table body
tblBody.appendChild(row);
}
// put the <tbody> in the <table>
tbl.appendChild(tblBody);
// appends <table> into <body>
body.appendChild(tbl);
// sets the border attribute of tbl to 2;
tbl.setAttribute("border", "2");
tbl.style.position = "absolute";
tbl.style.top = "30%";
}
</script>
myTable has position: absolute; - that will always go over something with position: static;
z-index will work, but both elements (the table and the menu have to both have z-index and position: absolute;
Without seeing the HTML it's pretty hard to detect the problem.
Example
Here's a fiddle describing the problem: http://jsfiddle.net/rZysU/
.a1's z-index is set to 1000 but it still is not visible. b1 is visible although its z-index is only 1. (it even is the same with -1)
In General
If you nest HTML elements then each nesting level creates its own z-index stack. If you set the z-index of an element inside a deeper node in the DOM tree then it might happen that although you've set the z-index to a high value it still will be underneath other elements that reside in a higher hierarchy level of the DOM.
Example:
div1
div1a
a (z-index= 100)
b (z-index= 101)
c (z-index= 102)
div1b
d (z-index= -1)
e (z-index= 1)
d will still be drawn on top of a as div1b is given a higher z-index because it is listed after div1a and HTML renderers draw one node after another and define z-indicies by that way if you don't provide it by your CSS definition.