Why is my z-index not working? - javascript

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.

Related

How do I stop the moving of a button while clicking another?

The following code contains 2 buttons and their respective drop-down contents.
When I click the first button, the other moves by itself. How do I stop this from happening?
var coll = document.getElementsByClassName("button");
var i;
for (i = 0; i < coll.length; i++) {
coll[i].addEventListener("click", function() {
this.classList.toggle("active");
var content = this.nextElementSibling;
if (content.style.display === "block")
content.style.display = "none";
else
content.style.display = "block";
});
}
.content {
display: none;
}
<button type="button" class="button" style="position: static; left: 100;">For Copper Rollers</button>
<div class="content" style=" width: 48%; background-color: lightblue; padding: 10px; border-radius: 10px; margin-right: 5px; ">
</div>
<button class="button" type="button" style="position: static; left: 175px; ">For Rubber Rollers</button>
<div class="content" style="margin-left:50%; float: left; width: 48%; background-color: lightblue; padding: 10px; border-radius: 10px;">
</div>
If you assign position:absolute you can do some rudimentary calculations in Javascript to determine the position the content should appear at. Is this more or less the desired effect?
document.querySelectorAll('button').forEach(( bttn, index )=>bttn.addEventListener('click',function(e){
this.classList.toggle("active");
// get the bounding box for the button so we can
// get a suitable height offset for content
let bb=this.getBoundingClientRect();
// find the content and toggle display state
let div=this.nextElementSibling;
div.style.display=div.style.display=='block' ? 'none' : 'block';
// find the current style properties for the content
let style=getComputedStyle( div );
let bbd=div.getBoundingClientRect();
// calculate x / y positions for content
let x=( Math.ceil( bbd.width ) + parseInt( style.paddingLeft ) - parseInt( style.marginLeft ) ) * index;
let y=Math.ceil( bb.height ) + Math.ceil( bb.bottom );
// apply those positions to the content
div.style.top=`${y}px`;
div.style.left=`${x}px`;
// identify content by parent
div.textContent=this.textContent.replace('For ','');
}));
body{
width:100%;
height:100vh;
}
button.button{
padding:0.25rem;
}
/*
assign the absolute position
to the content divs but let
javascript calculate x/y positions.
*/
.content {
position:absolute;
display: none;
width: calc( 50% - 3rem );
background-color:lightblue;
padding:1rem;
border-radius:10px;
border:1px solid grey;
float:none;
clear:none;
margin:0 0.25rem;
}
.content:first-of-type{
background:pink;
}
.active{
color:green
}
<!--
let css do the styling and positioning as `inline` styles
make updating a pain in the proverbial
-->
<button type="button" class="button">For Copper Rollers</button>
<div class="content"></div>
<button class="button" type="button">For Rubber Rollers</button>
<div class="content"></div>
I would go with making the dropdown content have a position: asolute (css), that way it won't affect any other elements on the page.
PS: make sure to keep accessibility in mind when making dropdowns, your current snippet unfortunately isn't.

Make Javascript generated grid cells resize for the users screen size

I made a simple game on Javascript but can't figure out how to make the cells resize dynamically based on the screen size of the user. I only got it to work with giving the cells a 200px size, but obviously it doesn't work on mobile or larger grid sizes. The game asks which size of a game area-grid you would like to generate and then creates it. I would like the grid cells to automatically resize based on how much size they have available. I have hosted the game on this page so you can see how it functions: http://localhost:8383/JWTHarkkaty%C3%B6/index.html
And the css looks like this:
.row {
height: auto;
width: auto;
}
.box {
display: inline-block;
height: 200px;
width: 200px;
border: solid darkgray;
background-color: darkgray;
background: no-repeat center;
background-size: cover;
}
.div{
display:inline-block;
text-align:center;
}
.parentButton {
display:block;
float:left;
}
body{
background-image: url("background.jpg");
}
#scoreText{
color:white;
font-size: 20px;
}
And the Javascript part that generates the grid based on user input:
function generateGrid(){
var empty = document.getElementById("container");
if(empty !== null){
empty.remove();
}
gridSize = parseInt(prompt("Give grid size"));
var container = document.createElement('div');
container.id = "container";
for(var i = 0; i < gridSize; i++){
var row = document.createElement('div');
row.className = "row";
row.id = "row" + i;
for(var a = 0; a <gridSize; a++){
var box = document.createElement('div');
box.className = "box";
row.appendChild(box);
}
container.appendChild(row);
}
console.log(container);
document.getElementById("gameArea").appendChild(container);
}
I tried margin:auto but it just rendered the whole grid useless.

Create dynamic Rectangle collection in html using js

Hello All I am a beginner in html and js, and I am trying to create a webpage containing a rectangle collection in which when a new rectangle is created is placed beside the previous rectangle.
I have created a div element and trying to add newly created div (rectangle shape with background color different based on condition), but I am not able to get the desired result.
<html>
<head>
<title>parkIn</title>
<meta charset="utf-8" />
</head>
<style>
.ParkSlots {
border: solid 1px;
width: 60%;
height: 400px;
top: 50%;
left: 50%;
position: fixed;
transform: translate(-50%, -50%);
display: inline;
}
.row:before,
.row:after {
content: "";
display: table;
clear: both;
}
.col-1 {
width: 15%;
margin-left: 10px;
height: 350px;
padding: 2px;
}
</style>
<body onload="viewCreate()">
<div class="ParkSlots">
<div class="row" id="content">
</div>
</div>
</body>
<script language="javascript">
function viewCreate() {
for (int i = 0; i < 5; i++) {
if (i % 2 == 0) {
createGreenBox();
} else {
createRedBox();
}
}
}
function createRedBox() {
var = document.createElement('div');
div.className = 'col-1';
div.style.backgroundColor = 'red';
document.getElementById('content').appendChild(div);
}
function createGreenBox() {
var = document.createElement('div');
div.className = 'col-1';
div.style.backgroundColor = 'lightgreen';
document.getElementById('content').appendChild(div);
}
</script>
</html>
I want an output that looks something like this:
Just in glancing at your code, I see at least two typos:
for (int i = 0; i < 5; i++) { - in JS, int is not used in this way. Use var i = 0...
var = document.createElement('div'); - you're missing a variable name on this line in both create box functions. I assume, from the rest of the code you need var div = document.createElement('div');
The rest will be CSS. In your stylesheet you're applying the border to the outter most containing div, from you're example, you need to apply that to the .col-1 class. You'll also want to use display:inline-block on that class, and set widths and margins to play nicely with the border size. I took the liberty of creating a jsfiddle for you with my recommended changes.

How to dinamically update the child div width after insert other elements in the parent div

I have a main div (with fixed height and scroll-x and scroll-y):
<div style="position:relative;border:solid 2px #000;overflow-y:scroll;overflow-x:scroll; height:200px; width:100%;" id="pippo">
</div>
and a bunch of child div created dynamically in js and inserted in the parent div with absolute position:
<div style='z-index:3;position:absolute; top: 50px; left: "+pos+"px;border:solid 1px;'>m</div>
This divs can be created everywhere, also beyond the parent div height and width (I don't care because I get the scrollbars).
My problem is:
there are other child divs (created in js) that represent a background like a chart. The divs have a border and a width of 100%. An example of one of them:
<div style='z-index:2;border-bottom:solid 1px #ccc; color:#ccc;position:absolute;width:100%;bottom:"+yyy+"px;'>0</div>
When javascript create dynamically the divs, the background don't update his width to the new one (if the divs go beyond the parent measures).
So, if you scroll on the right, you don't see the background.
How can I do to give the right width (100%) to the background when the parent width is dynamically changed?
http://jsfiddle.net/4x2KP/157/
Thanks everybody!
I've do an work around to it, if you can add specific class to the axis divs.
You can listen to the scroll event on the #pippo and adjust the offset of the axis, as its fixed horizontally inside the #pippo. But you may have to separate the digit part and axis-line part to make the digit part movable by the scrollbar.
var t = 250;
var $axis;
var offsets;
$(document).ready(function(){
crea_bg();
setTimeout(function(){ pippo(); }, t);
});
var pos = 0;
function pippo(){
pos = pos + 30;
$("#pippo").append("<div style='z-index:3;position:absolute; top: 50px; left: "+pos+"px;border:solid 1px;'>m</div>");
setTimeout(function(){ pippo(); }, t);
}
function crea_bg(){
var yyy = 0;
$("#pippo").append("<div class='axis' style='z-index:2;border-bottom:solid 1px #ccc; color:#ccc;position:absolute;width:100%;bottom:"+yyy+"px;'>0</div>");
for (i = 25; i <= 300; i=i+25) {
$("#pippo").append("<div class='axis' style='z-index:2;border-bottom:solid 1px #ccc; color:#ccc;position:absolute;width:100%;bottom:"+(yyy+(-i))+"px;'>"+(-i)+"</div>");
$("#pippo").append("<div class='axis' style='z-index:2;border-bottom:solid 1px #ccc; color:#ccc;position:absolute;width:100%;bottom:"+(yyy+(i))+"px;'>"+i+"</div>");
}
$axis = $('.axis').css('left', 0);
}
$('#pippo').scroll(function() {
//var currentLeft = parseFloat($axis.css('left'));
//console.log($axis.css('left'), currentLeft, $axis.position().left);
//$axis.css('left', currentLeft - $axis.position().left);
$axis.css('left', '-=' + $axis.position().left);
});
<script src="https://ajax.googleapis.com/ajax/libs/jquery/1.6.4/jquery.min.js"></script>
<div style="position:relative;border:solid 2px #000;overflow-y:scroll;overflow-x:scroll; height:200px; width:100%;" id="pippo">
</div>
I'm not sure if this is what you are asking for, but this code creates those background lines at the same time that the letters are written.
You can adjust it easily changing the "width" var.
var t = 250;
$(document).ready(function(){
crea_bg();
setTimeout(function(){ pippo(); }, t);
});
var pos = 0;
function pippo(){
pos = pos + 30;
crea_bg();
$("#pippo").append("<div style='z-index:3;position:absolute; top: 50px;"
+" left: "+pos+"px;border:solid 1px;'>m</div>");
setTimeout(function(){ pippo(); }, t);
}
function crea_bg(){
var yyy = 0;
var width = pos + 30;
$("#pippo").append("<div style='z-index:2;border-bottom:solid 1px #ccc;"
+"color:#ccc;position:absolute;width:"+width+"px;bottom:"+yyy+"px;'>0</div>");
for (i = 25; i <= 300; i=i+25) {
$("#pippo").append("<div style='z-index:2;border-bottom:solid 1px #ccc;"
+" color:#ccc;position:absolute;width:"+width+"px;bottom:"+(yyy+(-i))+"px;'>"+(-i)+"</div>");
$("#pippo").append("<div style='z-index:2;border-bottom:solid 1px #ccc;"
+ "color:#ccc;position:absolute;width:"+width+"px;bottom:"+(yyy+(i))+"px;'>"+i+"</div>");
}
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/1.6.4/jquery.min.js"></script>
<div style="position:relative;border:solid 2px #000;overflow-y:scroll;overflow-x:scroll; height:200px; width:100%;" id="pippo">
</div>
Avoiding the typical document flow
If you must avoid the typical document flow, you'll need to insert another container between <div id="pippo"> and its child elements, then manually update the new container's width/height as needed.
Staying within the typical document flow
If you don't need to work around the normal document flow and are just searching for any possible way to make a parent expand, use a combination of display: inline-block and white-space: nowrap:
$(document).ready(function() {
setInterval(function() {
$('#pippo').append('<div class="childDiv">m</div>')
}, 250);
});
#pippo {
border: solid 2px #000;
height: 200px;
width: 100%;
overflow-y: scroll;
overflow-x: scroll;
white-space: nowrap;
}
.childDiv {
display: inline-block;
border: solid 1px #000;
margin: 5px;
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/1.6.4/jquery.min.js"></script>
<div id="pippo"></div>

creating navigation & page in pure javascript

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>

Categories

Resources