0

[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. enter image description here

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): enter image description here (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: enter image description here 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..

2 Answers2

1

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?

ptts
  • 1,022
  • 8
  • 18
  • Thank you! I just tried to add an onclick event to an element on the page like you did, and then an alert outside of the "for" function to islolate where the issue occurs.. and the alert works: [link](https://skriptkiddy.com/fcc/) – Streching my competence Dec 03 '18 at 20:00
  • The styles, for me, is not applied like in your example /: – Streching my competence Dec 03 '18 at 20:01
  • Your function triggers, but your fcc_test_ui has size 0*0, therefore, it is not visible. Give it a red border and width 100 px , height 100px. – ptts Dec 03 '18 at 20:12
  • @Strechingmycompetence, yeah looks like the function is not the problem, give the target classes some size to see what is happening, I cannot see the whole code. – ptts Dec 03 '18 at 20:13
  • I've added the whole code. Also tried adding the lines ````elements[i].style.width = "100px !important";elements[i].style.height = "100px !important";```` but it didn't change anything (and it shouldn't have to. The styles generated by the external JS file from FreeCodeCamp is sufficient. I have replicated this easily by simply adding the CSS to the actual element manually (via the inspector of course, as it's a generated element), and that works. Something is blocking the JS styles from being applied however.. – Streching my competence Dec 03 '18 at 20:15
  • I added an example of what I mean in the main question at the bottom – Streching my competence Dec 03 '18 at 20:21
  • Also, the console.log is not triggered either.. so the loop seems broken somehow, for some reason. – Streching my competence Dec 03 '18 at 20:27
  • Hey man, that whole website is generated by JS, somewhere deep, deep in the bundle.js file, I have found this: var t=document.createElement("div");t.className="fcc_test_ui",t.innerHTML=u.default,b.appendChild(t);var So yeah, just give it a CSS class,the code is minifies, huge and barely readable. Here is the file https://cdn.freecodecamp.org/testable-projects-fcc/v1/bundle.js – ptts Dec 03 '18 at 20:37
  • yes, I know. That's why I'm using js to update the style of the element, as the bundle.js is applying it to the element directly, and thus, it will override any CSS in the CSS file (even if it's declared !important). The only way to override it, is to actually apply it to the element itself, as the bundle.js does. That's also why I'm loading my custom JS after I'm loading the bundle.js. Btw, the minified thing and readability isn't an issue, as you just click the {} icon at the bottom when you go to Sources -> Bundle.JS in the inspector (chrome will beautify it if you do) – Streching my competence Dec 03 '18 at 20:41
  • Order of priority/operations in CSS is (from least important to most important): CSS file -> from top to bottom (If one is declared ````!important````, that is overriden even if the definition is above the later definition without the ````!important```` declaration) -> Style applied directly to an element (this also trumps any ````!important```` declarations within the CSS-file) – Streching my competence Dec 03 '18 at 20:45
  • it seems the issue is much larger (I've updated with extra info as I've found quite a bit while troubleshooting). What I've done is ask FCC (FreeCodeCamp) directly instead, as well.. it's a bad design choice to have the "test box" placed "top left" to begin with.. and it seems it's no easy task solving the repositioning because of how they designed it (within a #shadow-root element) – Streching my competence Dec 03 '18 at 22:32
0

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

Mohammad
  • 71
  • 1
  • 10
  • Isn't that jQuery though? – Streching my competence Dec 03 '18 at 20:03
  • Yes it is jQuery but It Is simpler maintainable , than what you have done – Mohammad Dec 04 '18 at 06:58
  • come on man. I'm seriously not implementing a huuuge library at the cost of my users just to change a few CSS-rules (not that this is going to be used in a real enviroment, but you get the point, it's principal). That's just bad programming in every sense! Especially when you know how to do it in pure JS. This jQuery BS needs to die already. – Streching my competence Dec 04 '18 at 09:36