Issue checking whether element is 'active' in javascript - javascript

I have a sidebar, and I want to use javascript to check when it is 'active'. Here's my code:
#sidebar {
background: #202020;
color: #fff;
display:inline-block;
}
#sidebar.active {
margin-left: -250px;
}
//Check to see whether sidebar has class 'active'
var sideBar = document.getElementById('sidebar')
console.log(sideBar.className)
if (sideBar.className == ('active')){
console.log('active')
}
else (console.log('not active'))
However, this code is not console.logging anything, and so it's reading "not active" even when the sidebar is clearly activated. What am I doing wrong? Thanks.

The problem you are observing is probably because you compare sidebar.className == ('active') directly. The className attribute is a string object which contains the names of all of the classes applied to it. In many cases, there are extra classes automatically added (from various libraries), so checking if it's equal to a single class name often won't do what you want.
The classList attribute is a DOMTokenList and can more reliably be used for this kind of task. So, for this use case, you could try using sidebar.classList.contains('active').
i.e.
var sideBar = document.getElementById('sidebar');
console.log(sideBar.className)
if (sideBar.classList.contains('active')){
console.log('active')
}
else (console.log('not active'))

Related

Adding CSS classes and media to an empty div and append

I'm trying to re-create an Instagram like sort of page with some jQuery included. This is for a course I'm taking, so I'm a student basically.
This particular part of the exercise is asking me to:
- Empty the content of a class div.
- iterate over the media that is given.
- create an empty div and assign two classes, background image and append to the "empty" class.
The code I have so far is the following:
function renderUserMedia (media) {
// The class that is being emptied.
$('.user-media').html('');
// iteration
media.forEach(function (mediaItem) {
// empty div to add to every iterated picture with whatever is needed
var div = $('<div>').addClass('user-media-item u-pull-left').css('background-image', mediaItem).appendTo('.user-media');
});
}
All media is fetched through an API which I have no idea how is being configured (school configuration and what not), and the media is from a "dummy" insta page I guess.
What's happening is that images are not happening on the browser, and I think it has something to do with the .css implementation of the images iterated. The property background-image does not exist in the css file, so there might be something going on.
I have also tried to append to '.user-media' with $('.user-media').append(div); on the next line, but it didn't produce the desired result, which is to have all pictures iterated from forEach with the '.user-media-item' class.
.user-media-item {
margin-right: 10px;
margin-bottom: 10px;
width: 230px;
height: 230px;
overflow: hidden;
background-repeat: no-repeat;
background-size: cover;
background-position: center;
}
Could someone please help me understand what am I doing wrong?
After having checked everything and not being able to retrieve images, the only needed thing was (thanks to #freedomn-m and #CBroe for directions) to include the actual key that holds the location of the file. In this case a local folder.
function renderUserMedia (media) {
$('.user-media').html('');
media.forEach(function (mediaItem) {
var div = $('<div>').addClass('user-media-item u-pull-left').css('background-image', 'url(' + mediaItem.media_url + ')').appendTo('.user-media');
});
}
In case of using the url key, then we should change to .css('background-image', 'url(' + mediaItem.permalink + ')') as it was showing in the object containing the info of the images.

Cannot remove class from div with Javascript

I'm trying to create a class on a div and then delete it. First I thought just do like I did before with toggleClass, but that doesn't seem to work, because I'm adding a class to an ID instead of a Class. I want my header to have a black background top as well with the class: headerbg.
Also I have a small question about the color of my hamburger menu. I wanted to have a toggle for colors of the white lines (orange instead of white) on the class when pressed on the hamburger menu.
My live version where it is on, works only when 1024px or smaller
My Javascript
$(document).ready(function(){
$(".hamburger").click(function(){
$(".hamburger").toggleClass("closed");
$(".menu").toggleClass("show");
$("header").addClass('headerbg');
});
});
My CSS
.hamburger div{
height: 3px;
background-color: white;
margin: 5px 0;
border-radius: 25px;
transition: 0.3s;
}
.hamburger {
width: 30px;
display: none;
margin: 3em 3em 3em 0;
float: right;
transition: all 0.75s 0.25s;
}
.one {
width: 30px;
}
.two {
width: 20px;
}
.three {
width: 25px;
}
.hamburger:hover div {
width: 30px;
}
.hamburger.closed {
-webkit-transform: rotate(45deg);
-moz-transform: rotate(45deg);
}
#media only screen and (max-width: 1024px) {
.menu {
width: 100%;
background: #000;
margin: 0;
display: none;
}
.show {
width: 100%;
background: #000;
margin: 0;
display: block;
}
.headerbg {
background: #000;
}
.hamburger {
display: block;
}
}
If anyone maybe could lead me to a good example or even better help me out I would really appreciate it! Just came back after 2,5 years break from HTML/CSS as well.
Thanks for looking at the question!
Your understanding of DOM elements seems to be vague. Let's break it down.
I'm trying to create a class on a div and then delete it.
What is it here, what are you trying to delete? The class or the element?
..., because I'm adding a class to an ID instead of a Class.
That's not technically possible. You can't add a class to an id, nor can you add an id to a class. You can only add/remove/modify the id attribute of a DOM element and you can add/remove classes to the className property of a DOM element, referenced in markup by the class attribute.
To keep it short, using jQuery, you can select one or multiple elements by ID, by class, by attribute or by attribute value (in fact, by any valid CSS selector that matches the element), and you can apply the .toggleClass(), .addClass() or .removeClass() methods (or any other jQuery methods) to that element (or to each element in the collection, if they are more than one).
To clarify things for you here's what your current code does:
$(document).ready(function(){
/* when all the DOM has finished building... */
$(".hamburger").click(function(){
/* do the following when an element with class "hamburger" is clicked: */
$(".hamburger").toggleClass("closed");
/* toggle class `closed` on all elements with class "hamburger"
(not only on clicked one!) */
$(".menu").toggleClass("show");
// toggle class `show` on all elements with class "menu"
$("header").addClass('headerbg');
// add class "headerbg" to all <header> elements in page
});
});
Addition, as per OP comment:
First I want to add the class .headerbg on the <header> when I click on the .hamburger class, then when I click on the .hamburger class again I want to delete/remove the class .headerbg for the <header>
This will do it:
/*
* place the following inside an instance of
* $(document).ready(function(){...})
*/
$('.hamburger').on('click', function(){
$('header').toggleClass('headerbg');
})
Note:
$(selector).click(function(){...}) is a shortcut for
$(selector).on('click', [child-selector,] function(){...}). I personally recommend using the latter for all event binding functions to develop a consistent pattern of binding. It helps in the long run, when maintaining code. Also, it allows binding on elements that are not yet in DOM, by using the optional child selector argument. For example, if you wanted to do the binding before .hamburger was created in DOM, you could have, with the following syntax:
$(window).on('click', '.hamburger', function(){
$('header').toggleClass('headerbg');
})
The main difference is the first syntax binds an event listener on each and every instance of .hamburger it finds at the time the binding is done (document.ready in your case).
The second syntax binds only one event, on window object and evaluates at the moment of click if it was fired from inside an element with class .hamburger or not. This means that if you have 1k elements with class .hamburger, you don't bind an event on each of them (resulting in 1k listeners). Also, it has the great advantage that it will work on elements that are added to the page after the binding is done (because evaluation is done at the click event, not at the ready event.
To be even more precise and clear, there are two syntax choices here.
1. Choose between:
.click(function(){...})
.on('click', function(){...})
I always go for second, because it's consistent across all event listeners (it doesn't matter what I put as first argument, instead of click - also, it allows to bind on more than one event type at once: .on('click tap swipe', function(){...}))
2. Choose between
$(child-selector).on('click', function(){...})
$(parent-selector).on('click', child-selector, function(){...}).
If there is only one instance of child-selector and it's already in DOM at the time you do the binding, choose first. If there are more than one instances of child-selector and you want each one present inside parent-selector, use second.
Theoretically speaking, you want as few event listeners as possible, so instead of 2 listeners, one on each child is better to have a single listener on a parent.
Also, best practice is to use the smallest parent selector possible. For example, if you know all your child-selectors will always be contained in a div holding your content — say $('#main') — it's best to bind on that container rather than on $('<body>') or $(window). This will make your code not be evaluated against a click event triggered outside of $('#main'), which in both theory and practice makes your page faster and lighter, for a better user experience.
in your #header you should toggle the headerbg not just adding it :
then your jquery must be :
$(document).ready(function(){
$(".hamburger").click(function(){
$(".hamburger").toggleClass("closed");
$(".menu").toggleClass("show");
if($("#header").hasClass("headerbg")){
$("#header").removeClass("headerbg");
}
else
{
$("#header").addClass("headerbg");
}
});
});
if you need to add the styles of the ID you should pass it through the attr function . like this
$(document).ready(function(){
$(".hamburger").click(function(){
$(".hamburger").toggleClass("closed");
$(".menu").toggleClass("show");
$("header").addClass('headerbg');
$("header").attr('id','#header');
});
});
and you can delete it like this
$("header").attr('id','');
this way you can toggle it

Get font css property shorthand from an element [duplicate]

window.getComputedStyle give the style's value in Chrome, but in firefox and Microsoft Edge it gives an empty string and in Internet Explorer, it say that it doesn't support that method. Here is my code.
Whenever the Upvote image is clicked it fires the upDownVote() function, passing two arguments. This is the HTML.
<div id="upvote" title="Click to UpVote" onClick="upDownVote('increment',<?php echo $id; ?>);"></div>
<div id="downvote" title="Click to DownVote" onClick="upDownVote('decrement',<?php echo $id; ?>);"></div>
I passed three variables to my php script through ajax; Id, type, applicable.
Type can store one value, either increment or decrement.
I wanted, even upvote button is clicked. Vote value is increase by 1 and background of button is changed. Same for the button downvote, but here is decrease in vote value. I handle this with type variable.
When upvote is clicked again (or double clicked by the user), then there must be decrement in vote value not increment. I handled this with a nested if condition inside the if condition (when type is increment). In that condition I checked if applicable is greater than one. If it is, I changed the type to decrement and applicable to 0, also the background to its original image.
But what if when user clicked the upvote button after the clicking the downvote button. In that condition applicable value is more than 1. And then must change the type to decrement. That should not happen. for this In my that nested if condition I add check the background of downvote button also. It must be the same as before when the page load.
when applicable value is more than 1 (when user clicked upvote before clicking the downvote). In my php script I increase the vote value by two.
Same logic for the downvote button.
and here is the JavaScript.
var applicable = 0; // determine applicable to vote or not.
var upvote = document.getElementById("upvote");
var downvote = document.getElementById("downvote");
var upvoteBlack = window.getComputedStyle(upvote).getPropertyValue("background");
var downvoteBlack = window.getComputedStyle(downvote).getPropertyValue("background");
function upDownVote(x, id) {
debugger;
var type = x; // determine the type(increment or decrement).
if (type === "increment") {
upvote.style.background = "url(img/image-sprite-1.jpg) 0px -40px";
applicable++; // increment in the applicable.
if (applicable > 1 && window.getComputedStyle(downvote).getPropertyValue("background") === downvoteBlack) {
type = "decrement";
applicable = 0;
upvote.style.background = "url(img/image-sprite-1.jpg) 0px 0px";
}
downvote.style.background = "url(img/image-sprite-1.jpg) -40px 0px";
} else {
downvote.style.background = "url(img/image-sprite-1.jpg) -40px -40px";
applicable++;
if(applicable > 1 && window.getComputedStyle(upvote).getPropertyValue("background") === upvoteBlack) {
type = "increment";
applicable = 0;
downvote.style.background = "url(img/image-sprite-1.jpg) -40px 0px";
}
upvote.style.background = "url(img/image-sprite-1.jpg) 0px 0px";
}
// Ajax started here.
}
CSS of upvote and downvote.
div#upvote {
width: 40px;
height: 40px;
background: url(../img/image-sprite-1.jpg);
background-position: 0px 0px;
margin: 0px auto;
margin-top: 10px;
cursor: pointer;
}
div#downvote {
width: 40px;
height: 40px;
background: url(../img/image-sprite-1.jpg) -40px 0px;
background-position: -40px 0px;
margin: 0px auto;
cursor: pointer;
}
Everything works fine but now I'm stuck. How to get the background value of buttons as window.getComputedStyle not working fine all the browsers.
I want to know is there any other property by which I can have the background property.
Also, I want to know how can I do the same thing with different logic. If I can't have the solution for window.getComputedStyle.
The shorthand property problem
background is a shorthand property, a combination of background related properties. When you set a background of pink, it is actually setting a number of background properties, just one of which is backgroundColor. For instance, it is probably actually doing the equivalent of rgb(255, 165, 0) none repeat scroll 0% 0% / auto padding-box border-box.
getComputedStyle will not return the value of shorthand properties, except in Chrome as you've discovered.
To get the computed style, look for the value of primitive properties such as backgroundColor, not that of shorthand properties such as background.
A different approach?
However, this is not really how you want to be doing things. Instead of setting styles on your elements directly, you're going to find your code to be much cleaner if you add and remove classes from your elements, and then define the rules for the classes. As you've found, setting styles directly on elements may require you to then go back and query the style, whereas with classes, you can easily query the existing class with elt.classList.has(), or toggle with .toggle(), or add, or remove.
More on getComputedStyle
getComputedStyle is a rather specialized API that should only be necessary in special situations.
For more on the issue of getComputedStyle and shorthand properties, see this question. A bug was reported against FF and you can find it here.
See this MDN page. It says that CSSStyleDeclaration (which is what is returned by getComputedStyle) has a getPropertyCSSValue method which
returns ... null for Shorthand properties.

remove / reset inherited css from an element [duplicate]

This question already has answers here:
How to reset/remove CSS styles for a specific element or selector only
(17 answers)
Closed last month.
I know this question was asked before, but before marking it as a duplicate, I want to tell you that my situation is a little different from what I found on the internet.
I'm building and embedded script that people can put it on their sites. This script creates a div with a certain width/height and some information in it.
My problem is that some websites declare styles for div that are inherited by my div as well.
for example:
div{
background-color:red;
}
so if I don't set any background color to my div, it will show red even if I don't want that.
The only solutions I come along is to overwrite as many css proprieties, this way my div will show exactly as I want.
The problem with this solution is that there are too many css proprieties to overwrite and I want my script to be as light as it can be.
So my question is if you know another solution to my problem.
It can be in css/javascript /jQuery.
Thanks
"Resetting" styles for a specific element isn't possible, you'll have to overwrite all styles you don't want/need. If you do this with CSS directly or using JQuery to apply the styles (depends on what's easier for you, but I wouldn't recommend using JavaScript/JQuery for this, as it's completely unnecessary).
If your div is some kind of "widget" that can be included into other sites, you could try to wrap it into an iframe. This will "reset" the styles, because its content is another document, but maybe this affects how your widget works (or maybe breaks it completely) so this might not be possible in your case.
Only set the relevant / important CSS properties.
Example (only change the attributes which may cause your div to look completely different):
background: #FFF;
border: none;
color: #000;
display: block;
font: initial;
height: auto;
letter-spacing: normal;
line-height: normal;
margin: 0;
padding: 0;
text-transform: none;
visibility: visible;
width: auto;
word-spacing: normal;
z-index: auto;
Choose a very specific selector, such as div#donttouchme, <div id="donttouchme"></div>. Additionally, you can add `!important before every semicolon in the declaration. Your customers are deliberately trying to mess up your lay-out when this option fails.
You could try overwriting the CSS and use auto
I don't think this will work with color specifically, but I ran into an issue where i had a parent property such as
.parent {
left: 0px;
}
and then I was able to just define my child with something like
.child {
left: auto;
}
and it effectively "reset" the property.
Technically what you are looking for is the unset value in combination with the shorthand property all:
The unset CSS keyword resets a property to its inherited value if it inherits from its parent, and to its initial value if not. In other words, it behaves like the inherit keyword in the first case, and like the initial keyword in the second case. It can be applied to any CSS property, including the CSS shorthand all.
.customClass {
/* specific attribute */
color: unset;
}
.otherClass{
/* unset all attributes */
all: unset;
/* then set own attributes */
color: red;
}
You can use the initial value as well, this will default to the initial browser value.
.otherClass{
/* unset all attributes */
all: initial;
/* then set own attributes */
color: red;
}
As an alternative:
If possible it is probably good practice to encapsulate the class or id in a kind of namespace:
.namespace .customClass{
color: red;
}
<div class="namespace">
<div class="customClass"></div>
</div>
because of the specificity of the selector this will only influence your own classes
It is easier to accomplish this in "preprocessor scripting languages" like SASS with nesting capabilities:
.namespace{
.customClass{
color: red
}
}
Try this: Create a plain div without any style or content outside of the red div. Now you can use a loop over all styles of the plain div and assign then to your inner div to reset all styles.
Of course this doesn't work if someone assigns styles to all divs (i.e. without using a class. CSS would be div { ... }).
The usual solution for problems like this is to give your div a distinct class. That way, web designers of the sites can adjust the styling of your div to fit into the rest of the design.
As long as they are attributes like classes and ids you can remove them by javascript/jQuery class modifiers.
document.getElementById("MyElement").className = "";
There is no way to remove specific tag CSS other than overriding them (or using another element).
you may use this below option.
<style>
div:not(.no_common_style){
background-color:red;
}
</style>
now , if their any place where you do not want to apply default style you can use 'no_common_style' class as class.
ex:
<div class="no_common_style">
It will not display in red
</div>
From what I understand you want to use a div that inherits from no class but yours. As mentioned in the previous reply you cannot completely reset a div inheritance. However, what worked for me with that issue was to use another element - one that is not frequent and certainly not used in the current html page. A good example, is to use instead of then customize it to look just like your ideal would.
area { background-color : red; }
One simple approach would be to use the !important modifier in css, but this can be overridden in the same way from users.
Maybe a solution can be achieved with jquery by traversing the entire DOM to find your (re)defined classes and removing / forcing css styles.

Change CSS of class in Javascript?

I've got a class with the display set to none I'd like to in Javascript now set it to inline I'm aware I can do this with an id with getElementById but what's the cleanest way to do it with a class?
You can do that — actually change style rules related to a class — using the styleSheets array (MDN link), but frankly you're probably better off (as changelog said) having a separate style that defines the display: none and then removing that style from elements when you want them no longer hidden.
Do you mean something like this?
var elements = document.getElementsByClassName('hidden-class');
for (var i in elements) {
if (elements.hasOwnProperty(i)) {
elements[i].className = 'show-class';
}
}
Then the CSS
.hidden-class { display: none; }
.show-class { display: inline; }
You can use getElementsByClassName in which you'll get an array of elements. However this is not implemented in older browsers. In those cases getElementsByClassName is undefined so the code has to iterate through elements and check which ones have the desired class name.
For this you should use a javascript framework such as jQuery, mootools, prototype, etc.
In jQuery it could be done with a one-liner as this:
$('.theClassName').css('display', 'inline')
you can create new style rule instead.
var cssStyle = document.createElement('style');
cssStyle.type = 'text/css';
var rules = document.createTextNode(".YOU_CLASS_NAME{display:hidden}");
cssStyle.appendChild(rules);
document.getElementsByTagName("head")[0].appendChild(cssStyle);
$("#YOUR_DOM_ID").addClass("YOUR_CLASS_NAME");
You may like to exploit/rewrite this function:
function getStyleRule(ruleClass, property, cssFile) {
for (var s = 0; s < document.styleSheets.length; s++) {
var sheet = document.styleSheets[s];
if (sheet.href.endsWith(cssFile)) {
var rules = sheet.cssRules ? sheet.cssRules : sheet.rules;
if (rules == null) return null;
for (var i = 0; i < rules.length; i++) {
if (rules[i].selectorText == ruleClass) {
return rules[i].style[property];
//or rules[i].style["border"]="2px solid red";
//or rules[i].style["boxShadow"]="4px 4px 4px -2px rgba(0,0,0,0.5)";
}
}
}
}
return null;
}
to scan all style sheets attached pass "" as third argument, otherwise something like "index.css"
ruleClass contains starting '.'
if (rules[i].selectorText && rules[i].selectorText.split(',').indexOf(property) !== -1) condition improvement found here https://stackoverflow.com/a/16966533/881375
don't forget to use javascript syntax over css properties, e.g. box-shadow vs. boxShadow
Although this is long gone, here a few remarks:
Using display: inline to make things visible again may spoil the
page flow. Some elements are displayed inline, others block etc. This
should be preserved. Hence, only define a .hidden style and remove it
to make things visible again.
How to hide: There are (at least) two ways to hide elements, one is
the above mentioned display: none which basically makes the element
behave as if it was not there, and the visibility: hidden which
renders the element invisible but keeps the space it occupies.
Depending on what you want to hide, the visibility may be a better
choice, as other elements will not move when showing/hiding an
element.
Adding/removing classes vs. manipulating CSS rules: The result is
quite different. If you manipulate the CSS rules, all elements having
a certain CSS class are affected - now and in the future, i.e. new
elements dynamically added to the DOM are also hidden, whereas when
you add/remove a class, you must make sure that newly added elements
also have the class added/removed. So, I'd say adding/removing
classes works well for static HTML, whereas manipulating CSS rules
might be a better choice for dynamically created DOM elements.
To change CLASS you need to edit document stylesheets
[...document.styleSheets[0].cssRules].find(x=> x.selectorText=='.box')
.style.display='inline';
[...document.styleSheets[0].cssRules].find(x=> x.selectorText=='.box')
.style.display='inline';
.box {
margin: 10px;
padding: 10px;
background: yellow;
display: none
}
<div class="box" >My box 1</div>
<div class="box" >My box 2</div>
<div class="box" >My box 3</div>
Best way to do it is to have a hidden class, like so:
.hidden { display: none; }
After that, there is a className attribute to every element in JavaScript. You can just manipulate that string to remove occurrences of the hidden class and add another one.
One piece of advice: Use jQuery. Makes it easier to deal with that kind of stuff, you can do it like:
$('#element_id').removeClass('hidden').addClass('something');

Categories