JavaScript: setAttribute works but .style doesn't - javascript

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.

Related

Cannot loop through classNames 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

Can't see animation when using jQuery animate

so I know this question has been asked many times, but I could not find any answer that works for me. I've already included the jQuery Google API line before my script, and I'm pretty sure my syntax is correct as far as I know (since I'm following a tutorial video for this). I've also added a few lines of console.log() in some places and I know for sure that it is going pass the animate function and reaching the end of the code. Here is my code:
index.html (Not all, just a small part to show that I have the API included)
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.0/jquery.min.js"></script>
<script type="text/javascript" src="js/javascript.js"></script>
javascript.js (Also not all, just the part I'm having problem with)
prepareToAttack = function () {
$("#pikachu-img").animate({
top: "-=25px"
}, 200, function () {
$("#pikachu-img").animate({
top: "+=25px"
}, 200);
});
};
Back to index.html (This is where the pikachu image is set up)
<img id="pikachu-img "src="img/pikachu.png" class="absolute" style="height: 115px; top: 40px; right: 46px">
Does anyone have any idea why I'm not seeing the animation?
Maybe the problem caused by img tag, your double quote of id stick with src.
No other problem found in my test:
NOTE: Using the style attribute in HTML is bad practice. Use plain CSS instead! Remember when an elements CSS in dynamically manipulated say whatever.style.color = "red" it will add the style attribute, then and only then it should be used.
Also thanks to HTML5 you can scrap the type="text/javascript" on your script tag.
HTML:
<img id="pikachu-img" src="https://encrypted-tbn3.gstatic.com/images?q=tbn:ANd9GcQtDxj0kmEFUVNCUDF4G6553Hm-1w_ADcyYKhpkQf7pfsusCpHsbYpS3bQm">
CSS:
.pikachu-img {
position: absolute;
height: 115px;
top: 40px;
right: 46px;
}
JS:
$(function() {
$("#pikachu-img").animate({
top: "-=25px"
}, 2000, function() {
$("#pikachu-img").animate({
top: "+=25px"
}, 2000);
});
});

JS add in-line css to html

I'm stuck with something here:
I have a hidden div with some optional filters in a results page.
<div id='b-filters' class='row'>...</div>
Initially it is hidden with display: none;, when click a link it shows with some buttons and selectize combos.
The problem is here:
When div shows up, some JS, I don't know how to find out which; adds some in-line css:
<div id='b-filters' class='row' style='overflow: hidden; display: block;'>...</div>
So it is no possible to see the combos options. Using Chrome debugger I change overflow: hidden to overflow: visible and it works as I'd like.
I have tried:
In my external css file (app.css)
#b-filters{
...
overflow: visible;
...
}
But does not work, and in the same html file:
<head>
...
<style>
div#b-filters{
overflow: visible;
}
</style>
</head>
...
But Chrome inspector always show overflow: visible; crossed out.
Any idea? Thanks.
EDIT
I took #Stephen Thomas answer, but I'd like somebody help me with the way to find out which JS is adding that in-line css.
Without seeing the actual JavaScript, the only suggestion I can offer is
div#b-filters{
overflow: visible !important;
}
But if you show us your code, there is probably a more elegant way.
Instead of adding inline CSS directly to the element, why not abstract the CSS attributes into generalized classes, then just add/remove those classes?!
// style.css
.hide {
display: none;
}
// view.html
<div id="b-filters" class="row hide">...</div>
// app.js
btn.addEventListener('click', function(event){
var el = document.querySelector('#b-filters');
el.classList.remove('hide');
});
var problematicDiv = document.getElementById('b-filters');
if(problematicDiv.hasAttribute('style'))
{
problematicDiv.removeAttribute('style');
problematicDiv.style.display = 'block';
problematicDiv.style.overflow = 'visible';
}
This 'pseudo' js code should work as eventlistener.. haven't tested though, but I think it's ok.

Override HTML-standardized image width, prevent third-party JS blown up photo?

I host my website on Blogger and have a basic understanding of HTML and CSS. I want to add a collaborative add-your-link thingamajig with SimplyLinked. However...
The HTML they gave me was this:
<script type="text/javascript" src="http://www.simply-linked.com/listwidget.aspx?l=60A7D397-F94E-4840-8DFE-BCCB40BA298F"
></script>
But because I have HTML set the width for every photo posted to my website to be 800px, what really should be a small button at the bottom of the list ends up horribly oversized. See pic here.
How can I (or indeed, can I) override the HTML that programs the body of my blog so that the images in third-party javascript are their proper size?
Thank you!!
[EDIT 7/2/14 12:16 AM]
I so appreciate the responses and am quickly realizing just how little I know about this. Thank you for your help and your patience!
Wyzard: You're absolutely right – it is CSS. (I'm still learning!)
ejay_francisco: The CSS (as Wyzard correctly pointed out) is added right before the end of the skin. It's a ton of code, I don't think I can post the whole thing here..? But maybe this excerpt is helpful:
.post-body img {
width: 800px!important;
height: auto!important; }
#sidebar-left-1 {margin: 0 0px 0 -10px;
}
#Blog1 {margin: 0px 0px 0 30px;
}
#HTML6{
margin:60px 0 0 0px;
}
#navbar, #Attribution1{
display:none;
}]]></b:skin>
You can add this code to your HTML (preferably the <head>, but <body> would work):
<style>
.sl_i a img {
width: 181px;
height: 28px;
}
</style>
…Or even better, add it to your CSS, without the <style> and </style> tags.
Feel free to delete the newlines (carriage returns) and reduce strings of multiple spaces down to a single space if you'd like to conserve space:
<style>.sl_i a img{width:181px;height:28px;}</style>
What it does is target any <img> element nested inside an <a> element nested inside an element of class sl_i. I got that definition by opening the href in a browser window, inspecting the image, and noting its position in the DOM.
DEMONSTRATION: http://jsbin.com/gefiq/1/

jQuery element width update problem

I want to get element width using jQuery.
The problem is when I change html inside this element.
I want to get its width and width() returns its parent width instead, it looks like html() doesn't update element width at all.
But... It works perfectly when no DOCTYPE is specified.
I'm using IE in WebBrowser control.
css:
p {
margin: 0;
padding: 0;
}
.name {
font-weight: bold;
}
.description {
color: #444;
width: 190px;
white-space: nowrap;
overflow: hidden;
}
#container {
}
html looks like this:
<div id="container">
<div id="friend0"><p class="name">Name</p><div class="description"><p>Description</p></div>
</div>
js:
var x1 = GetFriend(id).children('.description').width();
var x2 = GetFriend(id).children('.description').children('p').width();
(some jQuery animation code)
and after that:
GetFriend(id).children('.description').children('p').html('some now text here...');
var x3 = GetFriend(id).children('.description').children('p').width();
and x3 is the same as .description with value of 190
but when I don't declare DOCTYPE at the beginning of html it returns correctly updated value.
I need to have DOCTYPE declared because some animation code causes flickering of scrollbars.
Anyone know how to do it correctly?
You already are doing it correctly. Block elements like <p> will use the width of their parent; that's the way the standard box model works. It changes when you drop the DOCTYPE because you're toggling the browser in and out of quirks mode.
(Comment posted as answer ...)

Categories