Pure JavaScript replacement for :hover - javascript

My goal, essentially, is to have the CSS :hover replaced by JavaScript. The reason is that I need a loop to be executed on a variable number of divs that will be nested inside the parent div that should react upon :hover.
The problem, however, is that I have no idea how to target just the div being hovered over without hard-coding in specific IDs - something that I will not be able to do once applied to my project, a tumblr theme.
HTML
<div id="motherbox">
<div class="middlebox">
<div class="childbox">One</div>
<div class="childbox">Two</div>
<div class="childbox">Three</div>
</div>
</div>
<div id="motherbox">
<div class="middlebox">
<div class="childbox">One</div>
<div class="childbox">Two</div>
<div class="childbox">Three</div>
<div class="childbox">Four</div>
<div class="childbox">Five</div>
</div>
</div>
CSS
#motherbox {
width:30%;
height:100px;
margin:100px auto;
background-color:gray;
}
JavaScript
document.getElementById("motherbox").onmouseenter = function(){
this.style.backgroundColor = 'blue';
};
document.getElementById("motherbox").onmouseleave = function(){
this.style.backgroundColor = "gray";
};
JSFiddle
My question is - how do I cause divs with the same class or id to react individually (or, rather, not all at once) on hover using javascript, rather than CSS?
Thank you for your time.

Basically you can select elements having a particular class using getElementsByClassName.
Here is a working demo.
var elements = document.getElementsByClassName('childbox');
for(var i=0; i<elements.length; i++) {
elements[i].onmouseleave = function(){
this.style.backgroundColor = "blue";
};
}

So use instead of getElementById this:
http://www.w3schools.com/jsref/met_document_getelementsbyclassname.asp
And provide classess for your divs, where you want have that event.

Related

Make parent div cursor-pointer including child elements with inline styling?

I want to make an entire div cursor-pointer with inline CSS, but it currently only affects the whitespace around the child elements. I've tried position and z-index to no avail.
I do not and cannot have an external stylesheet.
<div className="cursor-pointer">
<checkbox>
<label>
</div>
Is there any way to do this without applying the cursor-pointer to every element? There's conditional logic as well so that would get pretty cluttered.
Since you allow the usage of JS, you could use querySelectorAll to select all child elements and apply the same class to it:
let el = document.querySelectorAll('.cursor-pointer *');
el.forEach(ele => ele.classList.add('cursor-pointer'));
/* just for demonstration purpose */
.cursor-pointer {
cursor: not-allowed;
}
<div class="cursor-pointer">
<input type="checkbox">
<label>Label</label>
</div>
Using javascript, this solution loops through the parent and children and applies the cursor directly to each element.
let pointers = document.querySelectorAll(".cursor-pointer");
pointers.forEach(function(el) {
let children = el.querySelectorAll("*");
children.forEach(function(c) {
c.style.cursor = "pointer";
});
el.style.cursor = "pointer";
});
<div class="cursor-pointer">
<input type="checkbox">
<label>A</label>
</div>

Hide element with same text on the page

I'm trying to hide any text on the page that appears inside a div (with a specific class) more than once. For example, if my page has:
<div class="year"><h3>2015</h3></div>
<div class="year"><h3>2016</h3></div>
<div class="year"><h3>2016</h3></div>
<div class="year"><h3>2016</h3></div>
<div class="year"><h3>2017</h3></div>
In this example, I want to use jQuery to check if there is more than one div (with the class of "year") that has the same child h3 text. If so, then hide all except the first, resulting in this:
<div class="year"><h3>2015</h3></div>
<div class="year"><h3>2016</h3></div>
<div class="year"></div>
<div class="year"></div>
<div class="year"><h3>2017</h3></div>
Any help would be much appreciated! Thanks
What I would recommend doing is grabbing all of the elements with $('.year'), and then setting up an array to store the .innerHTML of each element. You can then loop over the elements, and check if their .innerHTML is in this array. If it's not, it gets added to the array. If it already exists, hide the element:
var elements = $('.year');
var existing_content = [];
for (var i = 0; i < elements.length; i++) {
if (existing_content.indexOf(elements[i].innerHTML) === -1) {
existing_content.push(elements[i].innerHTML);
}
else {
$(elements[i]).hide();
}
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<div class="year"><h3>2015</h3></div>
<div class="year"><h3>2016</h3></div>
<div class="year"><h3>2016</h3></div>
<div class="year"><h3>2016</h3></div>
<div class="year"><h3>2017</h3></div>
Note that this assumes that the .year elements all have identical content. If only part of the .year content is the same, you will need to update the elements selector to be more specific, and target the elements with identical content directly.
Hope this helps! :)

slideDown does not work for the first time

I'm adding animation to show a hidden div when a checkbox is changed,
The first time it's clicked the div appears with no animation but it works both ways after the first time.
How can I make it work also on the first time?
Here is my div (also using bootstrap)
var postOptionsSourcesWrapper = $("#post-options-sources-wrapper");
var postOptionsExclusiveCheckbox = $("#post-exclusive-cb");
postOptionsExclusiveCheckbox.change(function() {
if ($(this).is(":checked")) {
postOptionsSourcesWrapper.slideUp(300, "easeOutCirc", function() {
postOptionsSourcesWrapper.addClass("hidden");
});
} else {
postOptionsSourcesWrapper.removeClass("hidden");
postOptionsSourcesWrapper.slideDown(300, "easeOutCirc");
}
});
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<div id="post-options-sources-wrapper" class="margin-b-5 hidden">
<label class="text-md thick-600">Original post references</label>
<div class="box-marker box-marker-white">
<div class="thick-600 color-gray text-sm text-uppercase">
Add one or multiple sources.
</div>
</div>
</div>
UPDATE: this issue is solved by adding display:none; to the div
When adding the bootstrap class .hidden to hide for some reason it's not adding the display:none; that is part of the .hidden class in bootstrap... not sure why, but adding the style display:none; or calling postOptionsSourcesWrapper.hide() solves this issue.
This code will achieve what you want to achieve.
You just have to replace your script with this one.
var postOptionsSourcesWrapper = $("#post-options-sources-wrapper");
var postOptionsExclusiveCheckbox = $("#post-exclusive-cb");
postOptionsSourcesWrapper.hide();
postOptionsExclusiveCheckbox.change(function() {
postOptionsSourcesWrapper.slideToggle(300,postOptionsSourcesWrapper.is(":checked"));
});

Replacing inline css - not as simple as it may look

Ok, so listen. I got something like this:
<div class="theinsideofclass" style="theinsideofstyle" ...></div>
<div class="theinsideofclass" style="theinsideofstyle" ...></div>
<div class="theinsideofclass" style="theinsideofstyle" ...></div>
<div class="theinsideofclass" style="theinsideofstyle" ...></div>
And they are dynamically changed(each time in different time) and I don't have any control of the source code.
The thing is, I want simply override the theinsideofstyle, but all my attempts are failed. I tried with the !important; but it didn't go. Isn't it suppose to override the inline css? Anyway, what are my options here? Obviously simple JS won't help me here as the entire divs are changed/replaced each time with the same code.
Just shoot with any idea, folks... Perhaps it will navigate for some solution.
You could write some JS that is executed once the entire page is loaded, with all resources loaded, etc:
function load()
{
var els = document.getElementsByClassName("theinsideofclass");
for(var i = 0; i < els.length; i++) {
els[i].removeAttribute("style");
}
}
window.onload = load;
.theinsideofclass {
color: green;
}
<div class="theinsideofclass" style="color: red;">
My inline style is color: black
</div>
<div class="theinsideofclass" style="color: red;">
My inline style is color: black
</div>
<div class="theinsideofclass" style="color: red;">
My inline style is color: black
</div>
As you can see, without the JS the inline style (font color of red) would normally override the external CSS style (green). However, my JS is removing the style attribute from the elements with the class of theinsideofclass so you can style with normal CSS WITHOUT using !important (I never use !important unless all my other options are exhausted).
Hey you could wrap the elements in a div and loop through them + add a custom class which you could then use to define style to these divs.
PLEASE NOTE: I assume by your question that the css-class is also dynamic/changing and you have no control of it.
HTML:
<div id="outerdiv">
<div class="theinsideofclass" style="theinsideofstyle"></div>
<div class="theinsideofclass" style="theinsideofstyle"></div>
<div class="theinsideofclass" style="theinsideofstyle"></div>
<div class="theinsideofclass" style="theinsideofstyle"></div>
</div>
JS:
var children = document.getElementById('outerdiv').children;
for (var i = 0; i < children.length; i++) {
var child = children[i];
child.classList.add('myclass'); // this will add the class "myclass" to all the children divs inside the outerdiv
}
CSS:
.myclass {
background-color: red !important; // which ever style you want to overwrite
}
You could even go as far as removing the style attribute from the div with:
child.removeAttribute('style');
This way you won't need to use the !important in your css.
EDIT:
Based on OP's comment.
You could also try wrapping all these divs in an outer div, if you can control where they are rendered:
<div id="outerdiv">
<div class="theinsideofclass" style="theinsideofstyle"></div>
<div class="theinsideofclass" style="theinsideofstyle"></div>
<div class="theinsideofclass" style="theinsideofstyle"></div>
<div class="theinsideofclass" style="theinsideofstyle"></div>
</div>
Then in your css:
#outerdiv > div {
background-color: red !important;
}
Hi you can set style attribute to blank like below:
jQuery
$(document).ready(function(){
$('.theinsideofclass').attr('style','');
});
Kinda working demo here : https://jsfiddle.net/nm77md0L/ , https://jsfiddle.net/nm77md0L/1/
Since divs are generated on the fly and recreated when style attribute gets removed, try using setProperty on its CSSStyleDeclaration with third argument set to important.
//document.getElementsByClassName("theinsideofclass")[0].setAttribute('style', 'color: purple !important'); // recreates div
document.getElementsByClassName("theinsideofclass")[0].style.setProperty('color', 'blue', 'important'); // maybe won't?
.theinsideofclass{color: green !important}
<div class="theinsideofclass" style="color: red !important">TXT</div>
I can't guarantee it will work since we can't see what causes the divs to get regenerated and how, but give it a try, maybe the code is recreated when style attribute changes directly.

targeting a div in an ocean of nested dynamically added divs

I'm using the liferay framework and I need to add a JavaScript detected inline height to a very very specific div in my page. The problem is I need to target it going through an unknown number of dynamically added divs with dynamically added classes and IDs. To complicate this even further, the divs are randomly siblings or nested in each other.
Here's what it looks like:
<div class="known-class">
<div class="unknown dynamicallygenerated"></div>
<div class="unknown dynamicallygenerated">
<div class="unknown dynamicallygenerated">
<div class="unknown dynamicallygenerated"></div>
<div class="unknown dynamicallygenerated">
<div class="DIV-I-WANT-TO-TARGET">this is the div i need to Target with my css/javascript</div>
</div>
</div>
</div>
obviously I can't target it simply with
function resize() {
var heights = window.innerHeight;
jQuery('.DIV-I-WANT-TO-TARGET').css('height', heights + "px");
}
resize();
Because that class is present elsewhere, I would rather target it with something like.
jQuery('.known-class .DIV-I-WANT-TO-TARGET')
Which obviously doesn't work because there's a ton of other divs in the middle and my div is not a child of ".known-class"
I was asking myself if there was any jQuery that could help. Something like:
Catch any div with .DIV-I-WANT-TO-TARGET class that is "generically" inside another div that has .known-class
Is this possible? thanks a lot for your help!
Something like this would work:
// this will target the known-class and find all children with DIV-I-WANT-TO-TARGET
$('div.known-class').find('div.DIV-I-WANT-TO-TARGET');
// this will target the known-class and find the first DIV-I-WANT-TO-TARGET
$('div.known-class').find('div.DIV-I-WANT-TO-TARGET').first();
$('div.known-class').find('div.DIV-I-WANT-TO-TARGET:first');
$('div.known-class').find('div.DIV-I-WANT-TO-TARGET:eq(0)');
$('div.known-class').find('div.DIV-I-WANT-TO-TARGET').eq(0);
You can try in your css file
.known-class div div div div{}
The last div being the DIV-I-WANT-TO-TARGET
Assuming that you are adding the divs starting from the outer to the inner
Assign an equal name plus a number starting from 1
<div class="known-class">
<div class="unknown dynamicallygenerated" id="dynamicdiv1"></div>
<div class="unknown dynamicallygenerated" id="dynamicdiv2">
<div class="unknown dynamicallygenerated" id="dynamicdiv3">
<div class="unknown dynamicallygenerated" id="dynamicdiv4"></div>
<div class="unknown dynamicallygenerated" id="dynamicdiv5">
<div class="DIV-I-WANT-TO-TARGET" id="dynamicdiv6"></div>
</div>
</div>
</div>
The use jQuery [.each][1] to loop through all the divs on the document
$( document.body ).click(function() {
$( "div" ).each(function( i ) {
if ( this.style.color !== "blue" ) {
this.style.color = "blue";
} else {
this.style.color = "";
}
});
});
When you reach the last item in numeric order. (you can use any split function) add the attributes to that div
you need to select last div inside the known-class:
$('.known-class').find('div:last').css('background', 'Red')
OR if you want to select all the .known-class :
$('.known-class').each(function() {$(this).find('div:last').css('background', 'Red')});
Actually your selector works just fine:
$('.known-class .DIV-I-WANT-TO-TARGET')
With a space, selectors will find any descendant.
The search is only limited to direct descendants (immediate children) if you use the > operator.
So $('.known-class > .DIV-I-WANT-TO-TARGET') would not find what you wanted.

Categories

Resources