Cannot loop through classNames JavaScript - javascript

[The S/O-thread I based my solution upon]
Orignal question: Trying to implement the same thing, almost. But I can't get it to work. What am I missing here? When triggering the function I just get "undefined" in the DOM inspector:
Better formulated question: The function triggers. But it simply refuses to apply the style to the element. I know it's triggered as the last alert method triggers. I also know the loop is not working as the console.log isn't triggered (should be triggered twice). The style SHOULD be applied as it is added by JS directly to the elements and also has the !important definition, and it's also loaded after bundle.js that generates the object from the beginning, according to the priority of CSS rules/order of operations.
There are TWO elements with the class name of "fcc_test_ui"..
The code and https://codepen.io/Luggruff/pen/dQLYow:
HTML:
<!doctype html>
<html>
<head>
<title>TITLE HERE</title>
<!--METAs-->
<meta name="theme-color" content="#191c1f"/><!-- Update this! -->
<meta charset="utf-8">
<meta http-equiv="Content-Type" content="text/html; charset=utf-8">
<meta name="msapplication-tap-highlight" content="no">
<meta name="viewport"
content="width=device-width, height=device-height, initial-scale=1.0, maximum-scale=1.0, user-scalable=no, minimal-ui">
<!--Main CSS-->
<link rel="stylesheet" href="css.css?1543867233">
</head>
<body>
<!----------------- START --------------------->
<h1 id="title">Title with h1 text</h1>
<p id="description" onclick="classes()" style="top: 350px; position: absolute; border: 1px solid black;">Click me to trigger the classes() function!</p>
<!----------------- END --------------------->
<script src="https://cdn.freecodecamp.org/testable-projects-fcc/v1/bundle.js"></script>
<script src="script.js"></script>
</body>
</html>
CSS:
/* DON'T TOUCH THIS! */
#fcc_test_suite_wrapper {
position: relative !important;
z-index: 99999 !important;
position: absolute !important;
right: 0 !important;
left: unset !important;
display: block !important;
}
div.fcc_test_ui {
position: fixed;
left: 0;
top: unset !important;
position: fixed;
right: 0 !important;
left: unset !important;
bottom: 0 !important;
margin-bottom: 214px !important;
margin-right: 325px !important;
}
.fcc_test_ui {
position: fixed !important;
left: 0 !important;
top: unset !important;
position: fixed !important;
right: 0 !important;
left: unset !important;
bottom: 0 !important;
margin-bottom: 214px !important;
margin-right: 325px !important;
}
/* DON'T TOUCH THIS! */
JS:
document.getElementById("fcc_test_suite_wrapper").style.position = "";document.getElementById("fcc_test_suite_wrapper").style.position = "absolute";
function classes() {
var elements = document.getElementsByClassName("fcc_test_ui");
for (let i = 0; i < elements.length; i++) {
elements[i].style.position = "fixed !important";
elements[i].style.left = "0 !important";
elements[i].style.top = "unset !important";
elements[i].style.right = "0 !important";
elements[i].style.left = "unset !important";
elements[i].style.bottom = "0 !important";
elements[i].style.marginBottom = "214px !important";
elements[i].style.bottom = "325px !important";
console.log("Hey!"); //Just to check that they are looped through..
}
alert("Triggered");
}
Full site: https://skriptkiddy.com/fcc/
EDIT: Made a CodePen in addition to the actual live website, and also posted all the code here.
The end result wanted can be seen below. And as you can also see by the image below, the CSS I try to add via JS is all that should be needed to add in order to manipulate the object to go to the bottom right. So size of the two elements with the "fcc_test_ui" class does not matter.
Update 2:
I've found that defining the style via JS worked fine when I changed for example "0px !important" to "0px" (thus the !important part seems to ruin things). I tested this by simply adding three more DIV's with the classnames of "exampleClass" and running the code without the !important part to the string. HOWEVER, when I simply change the selector from "exampleClass" back to "fcc_test_ui" class, then it behaves differently (even though there are two DIV's with that class in the DOM, and three with the class of "exampleClass" in the DOM (so they should not behave differently):
(the CodePen has also been updated for "hotswapping" between the two classes for testing at line 12 in the JS)
UPDATE 3: So, it seems that the element #shadow-root is preventing any manipulation of the elements within itself, as demonstrated by adding a DIV with the same class name outside of it, then triggering the function:
I have also found this S/O thread that speaks about manipulating the elements within #shadow-root, but they have it defined as a variable, witch bundle.js does not. How the #shadow-root element seems to be generated within bundle.js:
document.body.appendChild(y),
HTMLElement.prototype.attachShadow ? y.attachShadow({
mode: "open"
}) : y);
..thus, I am clueless how to formally "address" the root..

Here is a code pen, you simply did not call the function anywhere in the code.
https://codepen.io/damPop/pen/VVNLmQ
<div class="fcc_test_ui" onclick="classes()">boom</div>
I have added a click handlerright in the div attributes, for brevity, as they say:-)
You could call the function, anywhere, after a window.setTimeout, on mousenter, on click of some element etc. Click the first div and see.
Now, you would not see much because you are giving ll the elements a fixed position stacked on eachother. That is why I made the color and one background change on click.
Read this about the chrome console thing, this should explain that undefined
Why does JavaScript variable declaration at console results in "undefined" being printed?

Actually there is no need to loop through classes
Just simply follow these 2 simple steps
1: Add all you styles to a CSS Class
Example .test { margin-bottom: 50px; color: red;} and etc
2: add the below script in you page
<script>
$(document).ready(function(){
var element = $(".fcc_test_ui");
element.addClass("testClass");
});
</script>
this is the easiest and the simplest way to achieve what you want
hope this answers your question

Related

JavaScript: setAttribute works but .style doesn't

NOTE: I have no problem using setAttribute in my project. This is merely a question as to why something is not working.
I have made a basic .js, .html and .css file. Here is the code for each:
//Load Document
window.onload = () => {
//get Body Height and Width
let body = document.body;
let html = document.documentElement;
let bH = Math.max(body.offsetHeight, body.scrollHeight, body.clientHeight, html.offsetHeight, html.scrollHeight, html.clientHeight);
let bW = Math.max(body.offsetWidth, body.scrollWidth, body.clientWidth, html.offsetWidth, html.scrollWidth, html.clientWidth);
console.log(`Body Height: ${bH}px`);
//get document elements
const menu = document.getElementById("getMenu");
const menuMarginTB = (bH - menu.offsetHeight) / 2;
//menu.setAttribute("style", "margin:"+menuMarginTB+"px auto;");
menu.style.margin = `${menuMarginTB}px auto;`;
};
* {
margin: 0;
padding: 0;
box-sizing: border-box;
}
body,
html {
height: 100%;
}
.container {
position: absolute;
top: 0;
left: 0;
background-color: black;
height: 100%;
width: 100%;
}
.menu {
height: 400px;
width: 600px;
border: 1px solid white;
}
<!DOCTYPE html>
<html>
<head>
<title>Random Website</title>
<link href="./main.css" type="text/css" rel="stylesheet" />
<script defer src="./main.js" type="text/javascript"></script>
</head>
<body>
<div id="getContainer" class="container">
<div id="getMenu" class="menu">
</div>
</div>
</body>
</html>
I have commented out setAttribute because it works, but when I try to use .style.margin it doesn't work. There are no errors that pop up in Console (I'm using Google Chrome). I don't know why it's not working. Here is what I tried:
I tried using document.onload and document.addEventListener("DOMContentLoaded", ...); but these failed. I am currently using window.onload, and it doesn't work either.
I tried removing defer from the script tag; however, defer is only suppose to run this script after every HTML element was parsed (to my knowledge), I don't know how removing or keeping it in will have an affect on .style.margin, if any.
I tried changing the id name from "menu" to "getMenu". I assumed that having the same name for both id and class was not only bad practice, but affecting the way .style.margin worked. However, it didn't really seem to help when I chaned it.
I tried concatenating the string instead of interpolating it. I assumed that maybe template interpolation didn't work in the was I was using it, but string concatenation didn't seem to help.
[NOTE: I may have tried more things, but I can't remember.]
I think this problem extends to all .style properties because upon looking at the Dev Tool for Google Chrome, all of the properties are blank, even though they are assigned in the .css file.
Proof 1
I already assigned height to 400px but here it shows up as "". The same thing happens after I run the last line of the .js file is run using a breakpoint. When I hover over menu.style.margin, it, too, results in "". Proof 2
The only thing I can think of is that maybe something didn't load in causing this to happen, but even it it didn't load in, I don't know how to fix it. Any help on the matter is much appreciate.
This is actually a very simple error :)
element.style = value only works if value is a valid value for this css property. In the code you posted it is not: you may not include the semicolon in the string.

Activate animations at specific scroll positions

I'm creating a CV page, where I included animations - some of them work with additional library: Animate css. It works, but animations start when page is fully loaded - and I want them to happen when scrolled to position where div starts (It's in the middle of page)
I've tried to do that with element .scrollTop, but then I could include value only in px - and i need responsive page ( I use calc() )
There was also possibility that i did something wrong - but i haven't noticed
Just like I said - I want to start animations when div would become in range of sight.
This is possbile, if you combine JQuery with JavaScript DOM or with just JavaScript DOM.
My function might not be the best way, but it works and is fairly simple.
My example starts an Animation when the grey divs Top offset relative to the viewport is lower than 100.
(If you would like to use this make 2 css classes (1 with an animation, 1 without) and set the ID Strings to your HTML Ids)
.Initial{
background-color: #ccc;
color: black;
position: fixed;
}
.AfterScroll{
background-color: #fff;
color: green;
position: fixed;
animation-name: Anim;
animation-duration: 1.4s;
}
#keyframes Anim{
25% {color: red;}
50% {color: blue;}
}
<!DOCTYPE html>
<html>
<head>
<script src="https://ajax.googleapis.com/ajax/libs/jquery/3.4.0/jquery.min.js"></script>
<script type="text/javascript">
$( "#AnimationElementID" ).addClass("AfterScroll");
var set = false; // will be false on page load
$( window ).scroll(function() { //On Scroll Event Handler, Could also be window.onscroll (DOM)
// JS HTML DOM get element position relative to viewport
var rect = document.getElementById("AnimationElementTriggerDivID").getBoundingClientRect();
// This is the offset at where your animation would start, 100 = div is 100px from viewport top
if( rect.top <100 && set==false){
$( "#AnimationElementID" ).toggleClass("Initial");
$( "#AnimationElementID" ).toggleClass("AfterScroll");
set=true; // so we only toggle the class once
}
});
</script>
</head>
<body>
<p class="Initial" id="AnimationElementID">
Hi im a text and I will change color if you scroll
</p>
<div id="AnimationElementTriggerDivID" style="background-color: #ccc; position: relative; top:200px; width:20px; height:2000px"> </div>
</body>
</html>
Maybe someone else can provide a better JQuery only option, or a cleaner function, but until then, feel free to use this.
PS: if possible, please provide Code snippets in order for people to be able to help you better and faster.

Change value of a class variable with one click? (simplest way)

I'm looking for a way to easily change one of variable's value. There's a chat in a browser game that I want to make taller. Changing height in dev tools does the work:
<div class="tsbchat" style="position: relative; width: 100%; height: 160px; margin-bottom: 20px;">
But can I make i.e. a script and put it in bookmarks that will allow me to change this value with one click? How would it look like? I know it's a trivial question but I'm a noob, you can remove the question and I will find help somewhere else. Thanks in advance!
The simplest solution is to type
document.getElementsByClassName('tsbchat')[0].style.height='600px'
in your console.
Remember to add [0], because getElementsByClassName returns an array
Another way is using jQuery
function handleClick(){
$(".tsbchat").css("height", "100px"); //choose the amount you want
}
.tsbchat{
position : relative;
width : 100%;
height : 160px;
margin-bottom: 20px;
border: 1px solid black;
}
<body>
<div class="tsbchat" onclick="handleClick()">Hello</div>
</body>
This way you can make bigger your div but only once
Use this script instead if you need to use several times:
function handleClick(){
$(".tsbchat").css("height", function(){
return $(".tsbchat").css() + 100;
});
}
Note: not sure if this way you have to specify the "px" but i'm quite sure this works
For using a javascript function as bookmark you need to use bookmarklet.You can read up more here about it Bookmarklet.
For example.
javascript:( alert(' Hello i am clicked from bookmark '));
Add this to destination of bookmark. so as soon as you click on bookmark you will see a Hello i am clicked from bookmark alert.
You can do it like this
Here handleClick is a function which will be called when you click on div.Than we select the element by class name and change it's style.
function handleClick(){
let element = document.getElementsByClassName('tsbchat');
element[0].style.height = "1000px"; //chnage to amount you want
}
.tsbchat{
position : relative;
width : 100%;
height : 160px;
margin-bottom: 20px;
border: 1px solid black;
}
<body>
<div class="tsbchat" onclick="handleClick()">Hello</div>
</body>

Change website background from gif to color on click

I know there are plenty of questions about changing background color, but they don't seem to work with my site, where I have a gif as the initial background.
Start of my html file:
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8"> <!-- to load my bloody euro sign-->
<title>
CV - Rogier
</title>
<style>
body{ background: url(https://media.giphy.com/media/ko7twHhomhk8E/giphy.gif) no-repeat center center fixed;
background-size: cover;
}
So how can I change the background to a solid color by pressing a button?
(Either by using a black picture link or color:black , but I prefer the latter)
I was thinking about something like this, but I have no clue how to call the background property:
<button style="font-size: 200%;color: white" onclick="document.body.style.background:url(https://vignette4.wikia.nocookie.net/joke-battles/images/5/5a/Black.jpg/revision/latest?cb=20161223050425) = 'black';">Click here if the page lags</button>
To change the background, you must simply remove the background image assuming that you have previously set the background color. While you can use JQuery to do this, it's kind of overkill.
Also, don't use inline HTML event attributes (onclick, onmouseover, etc.) as they:
Create "spaghetti code" that is difficult to read and debug.
Lead to duplication of code.
Don't scale well
Don't follow the separation of concerns development methodology.
Create anonymous global wrapper functions around your attribute values that alter the this binding in your callback functions.
Don't follow the W3C Event Standard.
Instead, do all your work in JavaScript and use .addEventListener() to set up event handlers.
Similarly, try to avoid inline CSS styles when you can.
Here's the code:
// Get references to the DOM elements you'll work with
var bdy = document.body;
var btn = document.getElementById("btnChange");
// Set up the button to have a click event handler:
btn.addEventListener("click", function(){
/* Just remove the image and the page will revert to the previously set color */
bdy.style.backgroundImage = "url('')";
});
body{
background: url(https://media.giphy.com/media/ko7twHhomhk8E/giphy.gif) no-repeat center center fixed #000;
background-size: cover;
}
#btnChange {
font-size: 200%;
color: white;
}
<button id="btnChange">Click here if the page lags</button>
You were on the right track. Your onclick attribute needs to be fixed up a little bit. Here's a working example:
body {
height: 100vh;
background: url(https://upload.wikimedia.org/wikipedia/commons/2/24/Male_mallard_duck_2.jpg) no-repeat center center fixed;
background-size: cover;
}
<head>
<meta charset="UTF-8"> <!-- to load my bloody euro sign-->
<title>
CV - Rogier
</title>
</head>
<body>
<button style="font-size: 200%;color: white" onclick="document.body.style.background = 'black';">Click here if the page lags</button>
</body>
As pointed out by #ScottMarcus, you should avoid using inline event handlers (like onclick). A cleaner and more manageable way to do that would be to add the event handler through JavaScript, like this:
document.getElementsByTagName('button')[0].addEventListener('click', function() {
document.body.style.background = 'black';
});
here is jquery code for change background
$('button').click(function()
{
$('body').css("background","url(/myimage.jpg) #000");
});

Click link, div slides out, linked div slides in, click to close and reload first div

I wish I knew how to write this myself.
http://www.cubancouncil.com/work/project/coppola-winery/
The linked page has the exact function I would like to use. How I believe their script works. Click an image which hides the container div for that image by sliding it off to the right and loads/slides in a larger image from the right to left which is in a fixed position.
If someone here is nice enough to answer this question with a solution would you mind taking it a step further and commenting on portions of your code so I can link it to the proper html?
I think understanding this one script would set me on a path to nailing down more advanced Javascript & Jquery. Thanks.
EDIT: I found a better example with some code provided. Go to the section where it talks about how to slide your element left. If you have questions, just let us know.
I've also taken the liberty to give you a full working example (exact same as the one in the article) so you can just run it in your browser
<!DOCTYPE html>
<html>
<head>
<script src="http://ajax.googleapis.com/ajax/libs/jquery/1.5/jquery.min.js"></script>
<style>
.slide {
position: relative;
background-color: gray;
height: 100px;
width: 500px;
overflow: hidden;
}
.slide .inner {
position: absolute;
left: -500px;
bottom: 0;
background-color:#e3e3e3;
height: 30px;
width: 500px;
}
</style>
<script>
$(document).ready(function() {
$('#slideleft button').click(function() {
var $lefty = $(this).next();
$lefty.animate({
left: parseInt($lefty.css('left'),10) == 0 ?
-$lefty.outerWidth() :
0
});
});
});
</script>
</head>
<body style>
<div id="slideleft" class="slide">
<button>slide it</button>
<div class="inner">Slide to the left</div>
</div>
</body>
</html>
The article explains most of it but I'll give you a quick run-down. In essence what we're doing is we're making it so that whatever you're trying to slide, we are altering the left position so that it comes out. Initially, I set the CSS to be -500px so it is outside the screen. The javascript then listens for the button click and moves the div by changing the left position. Jquery's animate() function does most of the work though.
The confusing bit about this is the ternary operator. You can find more info on that here. Essentially it just checks the left property to see if it's 0. If it is, we want to move it back outside to -500px. If the left isn't 0px, we know it must be outside the screen, so we move it back to 0px.
If there is anything else you're confused about let us know.
Created simple fiddle for you (notice it WORKS ON HOVER!!) but it should get you going, it's kinda late in my country so my brain doesn't work properly:)
Fiddle here
$(document).ready(function(){
var innerHeigth = $(".inner").outerHeight();
$(".wrapper").hover(function(){
$(".inner").stop().animate({top:-innerHeigth},1000);
//alert(innerHeigth)
},function(){
$(".inner").stop().animate({top:0},1000);
});
});

Categories