I'm trying to create a tile with random colors in a list that would fill the entire page.
There's a couple of questions that I want to ask here. The random_color variable only applies to the first box and not the second box. Also, how would I dynamically and automatically create divs that would have random background colors, just like the first box?
var version_1 = ['#111111', '#222222', '#333333', '#444444'];
var random_color = version_1[Math.floor(Math.random() * version_1.length)];
document.getElementById('box').style.background = random_color;
html, body {
margin: 0;
padding: 0;
}
#box {
width: 5%;
padding-bottom: 5%;
background: #00F;
color: #FFF;
position: relative;
}
#innerContent {
position: absolute;
left: 10px;
right: 10px;
top: 10px;
bottom: 10px;
}
<div id="box">
<div id="innerContent">
Box 1
</div>
</div>
<div id="box">
<div id="innerContent">
Box 2
</div>
</div>
Id is not for multiple elements. It should be unique in the document. I recommend you a 'class' for this.
<div class="box">
<div class="innerContent">
Box 1
</div>
</div>
<div class="box">
<div class="innerContent">
Box 2
</div>
</div>
Also if you want to dynamically create div elements, use document.createElement("div"). This will return HTMLElement object and you can manipulate it with javascript.
const newDiv = document.createElement("div");
newDiv.className = "box";
newDiv.innerText = "New Box!";
newDiv.style.backgroundColor = "#ff8888";
Finally, for a random background colors, you should use Math.random() properly. Because, Math.random() returns random value between 0 and 1, so if you want to use them as color, you should multiply 255 to them.
const r = Math.random() * 255;
const g = Math.random() * 255;
const b = Math.random() * 255;
div.style.backgroundColor = `rgb(${r}, ${g}, ${b})`;
You want to change the id to a class. Secondly, you want to change you logic for determining color as right now, every box will be the same color since random_color is only being determined once. Try this
const version_1 = ['#111111', '#222222', '#333333', '#444444'];
const boxEls = document.getElementsByClassName('box');
for (let el of boxEls) {
let random_color = version_1[Math.floor(Math.random() * version_1.length)];
el.style.backgroundColor = random_color;
}
With this code above, you are running the Math.random() for each box.
Use querySelectorAll to select all the divs with box id and then change the backgroundColor of every box using forEach loop.
var version_1 = ['#111111', '#222222', '#333333', '#444444'];
var random_color = version_1[Math.floor(Math.random() * version_1.length)];
let boxes = document.querySelectorAll('#box');
boxes.forEach((box) => box.style.backgroundColor = random_color);
html, body {
margin: 0;
padding: 0;
}
#box {
width: 5%;
padding-bottom: 5%;
background: #00F;
color: #FFF;
position: relative;
}
#innerContent {
position: absolute;
left: 10px;
right: 10px;
top: 10px;
bottom: 10px;
}
<div id="box">
<div id="innerContent">
Box 1
</div>
</div>
<div id="box">
<div id="innerContent">
Box 2
</div>
</div>
Related
I have a HTML and I'm trying to randomize each layer top margin attribute.
function randomize() {
let r;
let list = document.querySelectorAll("span");
for (let i = 0; i < list.length; i++) {
r = Math.floor(Math.random() * 50);
list.forEach((list) => {
style.top = `${r} + px`;
});
}
}
span {
position: absolute;
height: 20px;
width: 20px;
border-radius: 100%;
z-index: -2;
}
<div class="parallax">
<span class="layer" data-speed="-5">10110</span>
<span class="layer" data-speed="-5">0</span>
</div>
What am I getting wrong here? I can't find the proper solution.
A few things:
To use the top CSS property, the element needs to have a position defined. You can set that in the CSS (position: relative) or set it in the JS. (EDIT OP added CSS that they had already which set the position. Leaving this here for people that use top without setting an element's position)
You need to move the randomization into the forEach otherwise it will have the same value for all span elements
You need to attach the style prop to the element you are passing in the forEach, e.g., list.style.styleProp
function randomize() {
let r;
let list = document.querySelectorAll("span");
for (let i = 0; i < list.length; i++) {
list.forEach((list) => {
r = Math.floor(Math.random() * 50);
list.style.top = r + 'px';
});
}
}
randomize();
span {
position: absolute;
height: 20px;
width: 20px;
border-radius: 100%;
z-index: -2;
}
<div class="parallax">
<span class="layer" data-speed="-5">10110</span>
<span class="layer" data-speed="-5">0</span>
</div>
Because <span> is natively an inline element, and margin has no effect.
Change your <span>s to <div>s.
I Have Tried to add grid-2 when we press a key, but it's not working as I expected.
When it is displaying grid-2 I want the grid to disappear (I don't know how to do).
(background):-
I have searched and found there is a visibility property in CSS, but don't know how to apply to the whole grid and undo the visibility property and make them visible.
I have tried to add the grid-2 by getElementById but both the grids are appearing at a time.
(don't know how to make them appear one after another).
let curr_div_on = 0,curr_div_off = 0;
const key = document.getElementsByClassName('keys');
function setPlayingOn() {
key[curr_div_on % 4].classList.add("playing");
curr_div_on = (curr_div_on + 1) % 4;
}
function setPlayingOff() {
key[curr_div_off % 4].classList.remove("playing");
curr_div_off = (curr_div_off + 1) % 4;
}
setInterval(setPlayingOn, 500);
setTimeout(() => setInterval(setPlayingOff, 500), 500);
document.addEventListener('keypress', function(){
if(curr_div_on ==1){
var element = document.getElementsByClassName("grid-2");
element.classList.add("grid");
}
})
.grid{
display: grid;
grid-template-columns: auto auto;
grid-gap:10px;
}
.key{
padding: 20px;
border: 1px solid;
background-color: #2196F3;
text-align:center;
}
.playing{
transform: scale(1,1);
border-color: #ffc600;
box-shadow: 0 0 1rem #ffc600;
}
<html>
<div class='grid'>
<div class='key'>ABCD</div>
<div class='key'>EFGH</div>
<div class='key'>IJKL</div>
<div class='key'>LMNO</div>
</div>
<div class='grid-2'>
<div class='button'>A</div>
<div class='button'>B</div>
<div class='button'>C</div>
<div class='button'>D</div>
</div>
</html>
I think the code is wrong in these two points:
const key = document.getElementsByClassName('keys'); --> The selector should be 'key'
var element = document.getElementsByClassName("grid-2"); --> The result is a list (DomTokenList), so you should take the first element (var element = document.getElementsByClassName("grid-2")[0];)
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'm trying to generate 100 random coloured boxes within the div with the existing by clicking generate button that has top and left position 0-400. Also if I hover over any coloured box it disappears until the last that will give me an alert last box with last box left.
I managed to create a box that generates different colours but im not sure how to generate a 100 let alone hover over and delete the boxes when it is, how would one go about doing that?
My HTML:
<!doctype html>
<html lang="en">
<head>
<title> Generator </title>
<meta charset="utf-8">
<script src="prototype.js"></script>
<script src="task4.js"></script>
<style>
#container {
height: 500px;
}
p {
width: 70px;
height: 70px;
background-color: rgb(100, 100, 255);
border: solid 2px black;
position: absolute;
}
</style>
</head>
<body>
<div id="container">
</div>
<button id="myButton"
onclick="createBoxes()"> Generate More
</button>
</body>
</html>
My JS
window.onload = function()
{
createBoxes();
}
function createBoxes()
{
var colors = ["red", "green", "blue", "purple", "yellow"];
var newP = document.createElement("p");
var top = 10 + "px";
var left = 10 + "px";
newP.style.top = top;
newP.style.left = left;
newP.style.backgroundColor = colors[ Math.floor( Math.random() *5 )];
$("container").appendChild(newP);
}
window.onload = function() {
createBoxes();
}
Let's get this done step by step.
While creating box element, you should not use p tag, div is the best choice here.
I have implemented as far as I understood from your question.
Let me know in the comments if I missed something.
I added comments in the code, check if you get it.
window.onload = function() {
createBoxes();
}
function createBoxes() {
var left = 0;
var top = 0;
var colors = ["red", "green", "blue", "purple", "yellow"];
// create a for loop and run 99 times;
for (var i = 1; i < 100; i++) {
var newDiv = document.createElement("div");
newDiv.classList.add('box')
newDiv.style.backgroundColor = colors[Math.floor(Math.random() * 5)];
newDiv.style.top = top + 'px';
newDiv.style.left = left + 'px';
// now add the event on this one;
newDiv.addEventListener('mouseover', removeBoxes);
$("#container").append(newDiv);
left += 70; // increase left 70px each time in the loop
if (i % 5 == 0) { // if the we have 5 boxes in one row, reset left to 0px and increase top property by 70px to get another row;
left = 0;
top += 70;
}
}
}
// function to remove the boxes on hover;
function removeBoxes() {
$(this).remove();
}
// add the mouseover event listener;
$('div.box').on('mouseover', removeBoxes);
#container {
min-height: 200px;
}
div.box {
width: 70px;
height: 70px;
background-color: rgb(100, 100, 255);
border: solid 2px black;
display: inline-block;
position: absolute;
box-sizing: border-box;
}
#myButton {
position: absolute;
right: 0;
top: 0;
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<div id="container">
</div>
<button id="myButton" onclick="createBoxes()"> Generate 99 More
</button>
I am currently building a form with Material Design Lite.
My form is similar to this one. A discrete slider, with a teardrop label, would then be the best solution for easily defining parts of an amount in my form.
But MDL doesn't include a slider with a teardrop label by default. Angular Material includes one, though.
How can I include a teardrop label similar to the one in the Material Design Guidelines ?
You can make a MDL continuous slider into a discrete slider by adding a step attribute. Ex. step="10".
As for the teardrop label, that's a bit harder. MDL doesn't have an built-in style for that so you'd need to add it yourself. The following should get you started.
Note: the calculation for the positioning (labelPosX) is a bit wonky and I'm sure a few minutes thinking about it would clean it up.
Demo
const demoInput = document.getElementById('demo');
const labelMaker = function (e) {
const input = e.target || e;
const label = input.parentElement.querySelectorAll('.label')[0] || document.createElement('div');
const labelInner = label.firstChild || document.createElement('div');
const parentWidth = input.parentElement.offsetWidth;
const inputWidth = input.offsetWidth ;
const labelOffset = (parentWidth - inputWidth) / 2;
const labelPosX = inputWidth * (input.value/100) + ((100 - input.value) * 14)/100;
label.classList.add('label');
if (input.value == 0) {
label.classList.add('zeroed');
} else {
label.classList.remove('zeroed');
}
labelInner.innerText = input.value;
label.appendChild(labelInner);
label.style.left = labelPosX + 'px';
input.parentElement.appendChild(label);
}
demoInput.addEventListener('input', labelMaker);
window.onload = function() {
labelMaker(demoInput)
};
body {
padding: 100px 0 0 0;
}
.label {
display: block;
position: absolute;
top: -55px;
width: 25px;
height: 25px;
border-radius: 0 50% 50% 50%;
background-color: rgb(63, 81, 181);
transform: rotate(-135deg);
margin-top: 20px;
}
.label div {
line-height: 25px;
color: #ffffff;
font-size: 10px;
font-weight: 300;
letter-spacing: 1px;
text-align: center;
transform: rotate(135deg);
}
.label.zeroed {
background-color: rgba(0, 0, 0, 0.3);
}
<script src="https://code.getmdl.io/1.3.0/material.min.js"></script>
<link href="https://code.getmdl.io/1.3.0/material.indigo-pink.min.css" rel="stylesheet" />
<div class="mdl-grid">
<div class="mdl-cell mdl-cell--12-col">
<input class="mdl-slider mdl-js-slider" type="range" min="0" max="100" value="20" tabindex="0" step="10" id="demo">
</div>
</div>