why mouse coodrinates not showing up - javascript

i am learning javascript DOM . wrote this code , there was lots of errors in console . finally everything is sorted out. but the mouse coordinates are not showing . learning about addEventListener and using querySelector. where am i doing wrong. stuck on it since two days.
Here is the JSFiddle : https://jsfiddle.net/088a9at5/
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<meta http-equiv="X-UA-Compatible" content="ie=edge">
<title>MouseEvent</title>
<link rel="stylesheet" href="style.css">
</head>
<body>
<h1 onmouseover="style.color='red'" onmouseout="style.color='black'">Mouse over this text</h1>
<div class="coordinateBox"></div>
<div class="result"></div>
<script src="script.js"></script>
</body>
</html>
.coordinateBox {
width: 400px;
height: 200px;
border: 2px solid black;
}
const RECT = document.querySelector(".coordinateBox");
const ANS = document.querySelector("result");
function mouseCoordinate(e) {
var x = e.clientX;
var y = e.clientY;
var coo = "X : " + x + " Y : " + y;
document.querySelector("result").innerHTML = coo
}
if(ANS){
ANS.onclick = mouseCoordinate;
}

Apart from corrrecting the selector name in querySelector to querySelector('.result'),
if you target the click on the element ANS it will never get fired because the element is of height and width 0;
Instead if you target RECT it works,
https://jsfiddle.net/088a9at5/4/

You were missing two . in .result and you need to create a listener on the rectangle, not on the result.
const RECT = document.querySelector(".coordinateBox");
const ANS = document.querySelector(".result");
function mouseCoordinate(e) {
var x = e.clientX;
var y = e.clientY;
var coo = "X : " + x + " Y : " + y;
document.querySelector(".result").innerHTML = coo
}
if(ANS){
RECT.onclick = mouseCoordinate;
}
.coordinateBox {
width: 400px;
height: 200px;
border: 2px solid black;
}
<h1 onmouseover="style.color='red'" onmouseout="style.color='black'">Mouse over this text</h1>
<div class="coordinateBox"></div>
<div class="result"></div>

You're missing the . in document.querySelector("result") which should be document.querySelector(".result").
The other major issue is that you haven't added an event listener.
RECT.addEventListener('mousemove', mouseCoordinate)
Here is your jsfiddle, which is now working.
Also, here is a very, simple codepen which illustrates the nuts and bolts.
P.S. In your jsfiddle, you haven't styled ANS, so it's hard to tell what you want the click event to be attached to? And for some reason it's not letting me style the .result element :/

Based on your fiddle
Because you just missed the class identifier . in this line
const ANS = document.querySelector("result"); before result
It should be like this
const ANS = document.querySelector(".result");
Same thing with document.querySelector("result").innerHTML = coo this line.
And provide some height and width to your result div and border too so you can see in which area you have to click.

Related

Printed hex color code doesn't match with real background color

The purpose of my website is to find a hex color code by hitting a button, while the website's background is randomly changed by itself. However, when the button is clicked, the printed color code does not match with the current background color. how can I fix this?
const infiniteColorChange = setInterval(() => {
setColor()
}, 5000);
function setColor() {
document.body.style.backgroundColor = getRandomColor();
}
function getRandomColor() {
for(let y = 0; y < 16777215; y++) {
const randomNumber = Math.floor(Math.random()*16777215);
return "#" + randomNumber.toString(16);
}
}
function stopColor() {
clearInterval(infiniteColorChange);
document.getElementById("hexcode").innerHTML = getRandomColor(); // printed code does not match with bg
}
<html lang="en">
<head>
<meta charset="UTF-8">
<!--<meta http-equiv="X-UA-Compatible" content="IE=edge">-->
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>What color is it</title>
</head>
<body>
<h1>What color is it ...</h1>
<h2 id="hexcode"></h2>
<div id="center">
<input type="button" onclick="stopColor()" class="button" value="Find A Color Code For Me">
</div> <!-- onclick stop loop -->
</body>
</html>
Why are you generating another random color to show? You're literally never getting the color you've set.
You should have retrieved it from the style attribute (or store it somewhere).
document.getElementById("hexcode").innerHTML = document.body.style.backgroundColor;
This at least shows something like rgb(123, 45, 67) that matches the background color. You may need some extra work if you want the #rrggbb format.
You are calling getRandomColor twice: once for the background and once for the hex code display. They won't match. Instead, use a variable and set it to the result of the function
let randomColor;
const infiniteColorChange = setInterval(() => {
setColor()
}, 5000);
function setColor() {
randomColor = getRandomColor();
document.body.style.backgroundColor = randomColor;
}
function getRandomColor() {
for(let y = 0; y < 16777215; y++) {
const randomNumber = Math.floor(Math.random()*16777215);
return "#" + randomNumber.toString(16);
}
}
function stopColor() {
clearInterval(infiniteColorChange);
document.getElementById("hexcode").innerHTML = randomColor;
}
Your code in the stopColor function invokes the getRandomColor function, which generates a new random color, rather than using the one that was present when the button was clicked.
You can solve this by adding a new variable that always has the current color in it and referencing that variable in the stopColor function. (You could also just access the current document background color, but storing it in a variable is a bit more scalable.)
Also (FYI), don't use .innerHTML if you can avoid it (which is almost always) because it has security and performance implications to it. Since you aren't reading or writing HTML anyway, use .textContent.
let currentColor = null; // Will always hold the current color
const infiniteColorChange = setInterval(() => {
setColor()
}, 5000);
function setColor() {
currentColor = getRandomColor(); // Store the color for use elsewhere
document.body.style.backgroundColor = currentColor;
}
function getRandomColor() {
for(let y = 0; y < 16777215; y++) {
const randomNumber = Math.floor(Math.random()*16777215);
return "#" + randomNumber.toString(16);
}
}
function stopColor() {
clearInterval(infiniteColorChange);
document.getElementById("hexcode").textContent = currentColor; // Access current color
}
<html lang="en">
<head>
<meta charset="UTF-8">
<!--<meta http-equiv="X-UA-Compatible" content="IE=edge">-->
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>What color is it</title>
</head>
<body>
<h1>What color is it ...</h1>
<h2 id="hexcode"></h2>
<div id="center">
<input type="button" onclick="stopColor()" class="button" value="Find A Color Code For Me">
</div> <!-- onclick stop loop -->
</body>
</html>

How to make a function for an element to run continously or never end?

Hello I'm pretty new to JS and HTML and was trying to make something close to a text editor component like Monaco Editor.
How it works-
function Ventify() takes an element and adds a gutter and a textarea. So I made an if statement in this function that checks the no of lines in the textarea and create gutter lines accordingly. the problem I experienced while doing this was that the function only numbers the lines of the text when it was loaded because the function ended. Is there a way in which I can make the function/if statement never end.
Here is a codepen for the project: https://codepen.io/chrismg/pen/qgxOxg .
JS(with JQuery):
function Ventify(element){
element.style.display="flex";
element.style.flexDirection = "row";
var gutter = document.createElement("div");
var textarea = document.createElement("textarea");
gutter.className = "gutter";
textarea.className = "ventiEditor";
gutter.style.width = "100px";
gutter.style.height = "100%";
gutter.style.backgroundColor = "#1d252c";
textarea.style.width = "calc(100% - 100px)";
textarea.style.overflowY= "scroll";
textarea.style.whiteSpace = "pre";
textarea.style.resize = "none";
textarea.style.height = "100%";
textarea.style.margin = "0px 0px 0px 0px"
textarea.style.border = "0px solid rgb(255,255,255)"
textarea.style.backgroundColor = "#1d252c";
textarea.value = "\n\n\n\n";
element.appendChild(gutter);
element.appendChild(textarea);
if(gutter.childNodes.length != $(textarea).val().split("\n").length){
while(gutter.childNodes.length < $(textarea).val().split("\n").length){
var gutterChild = document.createElement("div");
gutterChild.style.width = "100%";
gutterChild.style.color = "rgba(58,74,88,1)"
gutterChild.style.textAlign = "center";
gutter.appendChild(gutterChild);
gutterChild.innerHTML = `${gutter.childNodes.length}`
}
}
}
Ventify(document.getElementsByClassName("container")[0])
HTML:
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Test Ground</title>
<style>
html,body{
height: 100%;
margin: 0px 0px 0px 0px;
}
.container{
height: 50%;
}
</style>
</head>
<body>
<div class="container"></div>
</body>
</html>
You can use input event attached to <textarea> element to perform a task at user input. See How to continually add typed characters to a variable?.
If you are trying to check if an element childList or attributes have changed you can use MutationObserver. See call function on change of value inside <p> tag.
A better approach will be using a onKeydown ( or similar events ) event on a input or textarea. Like in below example
function handle(){
let element = document.getElementById('inp').value;
console.log(element, 'called on change')
}
<input id='inp' onKeydown=handle() />
In your code can use setInterval. And clearinterval when you want to stop.
setInterval(Ventify(document.getElementsByClassName("container")[0]),200)
Codepen
You can use the onchange event to fire your function every time the user updates the content.
const element = document.getElementsByClassName("container")[0];
element.onchange = (event) => Ventify(event.target, 200);

Javascript loading speed issue as variable increases

I am having an issue with page loading time. Currently right now I am running UBUNTU in Oracle Vm Virtual Box. I am using mozilla firefox as my browser and I am working on an etchasketch project from "The odin project".
My problem is the page loading time. The code takes a prompt at the start and generates a grid for the etch a sketch based on that prompt. I have not given it the minimum and maximum values (16 and 64) respectively, however any number when prompted at the beginning that is beyond 35 doesn't load or takes ages to load.
How do I speed up the process time? / why is it moving so slow? / how can I avoid this ? / is there a fix that I am over looking that can make this work a lot faster? / feel free to tackle any and all of those questions!
This is my HTML CODE:
<!DOCTYPE html>
<html>
<head>
<link rel="stylesheet" type="text/css" href="style.css">
<meta charset="utf-8"/>
<title>
</title>
</head>
<body>
<div class="etchhead">
<p> Choose your grid size </p>
<input type = "text"></input>
<button id="startOver"> Clear Grid </button>
<p> Change color </p>
</div>
<div id="grid">
</div>
<script src="eas.js"></script>
</body>
</html>
And this is my CSS code:
p {
color: blue;
display: inline;
}
#grid {
display: grid;
width: 800px;
max-width: 800px;
height: 800px;
max-height: 800px;
line-height: 0;
}
.gridBox {
border: 1px solid black;
background-color: lightgrey
}
And this is my JAVASCRIPT code:
gridStart();
function gridStart(){
var boxes = 0
var selectBody = document.querySelector("#grid");
var addBox = document.createElement("div");
var boxCountStart = prompt("enter a number between 16 and 64");
var boxDimensions = (boxCountStart * boxCountStart);
function rowsAndColumns() {
var selectBody = document.querySelector("#grid");
var gridTemplateColumns = 'repeat('+boxCountStart+', 1fr)';
selectBody.style.gridTemplateColumns= gridTemplateColumns;
selectBody.style.gridTemplateRows= gridTemplateColumns;
};
function hoverColor(){
var divSelector = selectBody.querySelectorAll("div");
divSelector.forEach((div) => {
div.addEventListener("mouseover", (event) => {
event.target.style.backgroundColor = "grey";
});
});
};
rowsAndColumns();
for (boxes = 0; boxes < boxDimensions ; boxes++) {
var selectBody = document.querySelector("#grid");
var addBox = document.createElement("div");
addBox.classList.add("gridBox");
addBox.textContent = (" ");
selectBody.appendChild(addBox);
hoverColor();
};
};
There are two components to your issue. One is that you are repeatedly modifying the DOM in a loop. You can fix it by appending all your boxes to a DocumentFragment and then adding that to the DOM after your loop finishes. You are also calling hoverColor(); inside your loop which results in adding tons of event listeners that all do the same thing (since inside hoverColor you are adding a listener to every single div). You can fix both those issues like this:
var fragment = document.createDocumentFragment( );
for (var i = 0; i < boxDimensions ; i++) {
var addBox = document.createElement("div");
addBox.classList.add("gridBox");
addBox.textContent = (" ");
fragment.appendChild(addBox);
}
document.querySelector("#grid").appendChild( fragment );
hoverColor();
Here is a JSFiddle with your original code, and here is one with the modification.
You could also benefit from only having one event listener total. You don't need to loop and add an event listener to every div. Just add one to #grid and use event.target (like you already do, to find the div that the event originated from). Something like this:
function hoverColor(){
document.querySelector("#grid").addEventListener( 'mouseover', function ( event ) {
event.target.style.backgroundColor = "grey";
} );
}

Place new divs above / move old divs below

I have some toast notifications. I gave them a position "absolute" and want them to place themselves on their own.
New toasts should place themselves above the already existing ones. The old one would move down then.
So this is my important Div:
CreateWrapper(toastMessage, foreColor, borderColor, backgroundColorIconDiv, backgroundColorContentDiv) {
var wrapperDiv = document.createElement("div");
var width = 350;
wrapperDiv.id = "toast_" + this.toastCounter;
wrapperDiv.style.position = "absolute";
wrapperDiv.style.left = "50%";
wrapperDiv.style.display = "none";
wrapperDiv.style.width = width + "px";
wrapperDiv.style.height = "100px";
wrapperDiv.style.border = "2px solid " + borderColor;
wrapperDiv.style.borderRadius = "10px";
wrapperDiv.onclick = function() {
wrapperDiv.remove(); // Destroy the toast by clicking on it
}
document.body.appendChild(wrapperDiv);
}
and after creating it I use this code for some animations and destroying it:
var thisToast = this.toastCounter - 1; // get the toast Id
$(document).find("#toast_" + thisToast)
.fadeIn(750)
.delay(3000)
.fadeOut(750, function() {
$(this).remove(); // Destroy the toast
});
Here's a picture of what I am looking for
Check out this JSBIN.
You can use Bootstrap's grid system to make things a little easier.
You should never really use absolute layout, it makes responsive webpages impossible - take a look at what happens when you resize your browser.
You will want to have a look at the Element API.
var container = document.querySelector('div.container');
var newDiv = document.createElement('div');
newDiv.innerHTML = "HELLO WORLD";
container.prepend(newDiv);
And the accompanying HTML
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<link href="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.6/css/bootstrap.min.css" rel="stylesheet" type="text/css" />
<meta name="viewport" content="width=device-width">
<title>JS Bin</title>
</head>
<body>
<script src="https://code.jquery.com/jquery.min.js"></script>
<script src="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.6/js/bootstrap.min.js"></script>
<script src="https://unpkg.com/#reactivex/rxjs#5.0.3/dist/global/Rx.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/expect/1.20.2/expect.js"></script>
<div class="container">
hey
</div>
</body>
</html>
The method you are looking for is prepend()

An infinite carousel with vanilla JavaScript

I am trying to build my own carousel with pure JavaScript.
I'm struggling with picking up the most efficient way to add an infinite carousel option.
For some reasons, every element (photo, generic object) must have an id
The algorithm I see goes like that:
You check if the carousel is overflown (the are enough objects to fit
the whole container)
If not: append to the back a copy of the first element, then
a copy of the second element and so on. (But there will be an issue with the ids, because this object will have the same id)
- If the user is scrolling to the last object (to right) then append
the first DOM object to the array back
- If the user is scrolling to
the first object (to left) then add the last DOM child to array
front.
Is this going to work? Is there any other efficient way of doing an infinite carousel?
I have also heard that it's better to use translate property rather than changing the left, right properties, so it there would be more work for the GPU than for CPU.
I created a simple slider with css transformations as the animation technique and plain Javascript.
var img = document.getElementsByClassName("img")[0];
img.style.transform = 'translate('+value+'px)';
You can test it in this codepen snippet.
http://codepen.io/TobiObeck/pen/QKpaBr
A press on a button translates all images in the respective direction along the x-axis. An image on the edge, is set transparent outerImg.style.opacity = '0'; and translated to the other side. You can add or remove image elements in HTML and it still works.
In this second codepen snippet you can see how it works. The opacity is set to 0.5 so it is observable which image switches the side. Because overflow: hidden is removed, you can see how the images on the edge enqueue on the other side.
http://codepen.io/TobiObeck/pen/WGpdLE
Moreover it is notworthy that it is checked wether the animation is complete, otherwise the simultaneously added translations would look odd. Therefore a click won't trigger another animation until unless the animation is completed.
img.addEventListener("transitionend", transitionCompleted, true);
var transitionCompleted = function(){
translationComplete = true;
}
leftBtnCLicked(){
if(translationComplete === true){
//doAnimation
}
}
you can use this code to manipulate slides. This basically rotates the array back and front
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<style>
body {
width: 100%;
height: 100%;
}
.parentDiv {
height: 30%;
width: 100%;
display: flex;
}
</style>
<title>test</title>
</head>
<body>
<button class="fwd"> Fwd! </button>
<button class="bkwd"> Bkwd! </button>
<script type="text/javascript">
const arr = ['red', 'blue', 'coral', 'green', 'yellow'];
let narr = ['red', 'blue', 'coral'];
const parentDiv = document.createElement('div');
parentDiv.setAttribute('class', 'parentDiv');
document.body.insertAdjacentElement('afterbegin', parentDiv);
window.onload = ()=> {
narr.forEach(color => {
while(parentDiv.children.length < narr.length){
const childDiv = document.createElement('div');
parentDiv.appendChild(childDiv);
};
});
Array.from(parentDiv.children).forEach((child, index) => {
child.style.border = '1px #000 dotted';
child.style.minWidth = '20%';
child.style.minHeight = '20vh';
child.style.backgroundColor = narr[index]
});
};
document.querySelector('.fwd').addEventListener('click', ()=>{
narr.shift();
if(narr[narr.length-1] === arr[arr.length-1]){
narr.push(arr[0])
} else {
narr.push(arr[arr.indexOf(narr[narr.length-1])+1])
}
narr.forEach(color => {
while(parentDiv.children.length < narr.length){
const childDiv = document.createElement('div');
parentDiv.appendChild(childDiv);
};
});
Array.from(parentDiv.children).forEach((child, index) => {
child.style.border = '1px #000 dotted';
child.style.minWidth = '20%';
child.style.minHeight = '20vh';
child.style.backgroundColor = narr[index];
});
})
document.querySelector('.bkwd').addEventListener('click', ()=>{
narr.pop();
if(narr[0] === arr[0]){
narr.unshift(arr[arr.length-1])
} else {
narr.unshift(arr[arr.indexOf(narr[0])-1])
}
narr.forEach(color => {
while(parentDiv.children.length < narr.length){
const childDiv = document.createElement('div');
parentDiv.appendChild(childDiv);
};
});
Array.from(parentDiv.children).forEach((child, index) => {
child.style.border = '1px #000 dotted';
child.style.minWidth = '20%';
child.style.minHeight = '20vh';
child.style.backgroundColor = narr[index]
});
})
</script>
</body>
</html>

Categories