Affect an element when another element is hovered - javascript

How can I affect an element when another element is hovered, and the two elements are in this structure:
<div id="parent_element">
<div id="class-open-1"></div>
<div id="class-close-1"></div>
</div>
or they might be in this structure:
<div id="parent_element">
<div id="div1">
<div id="class-open-1"></div>
</div>
</div>
<div id="parent_element"></div>
<div id="div2">
<div id="class-close-1"></div>
</div>
</div>
I have tried this solution which works perfectly for the first case, but does not work for the second case:
_style.innerHTML = ".class-open" + j + ":hover{ background-color: cyan; } .class-open-" + j + ":hover ~ .class-close-" + j + " { background-color: cyan; }
the j changes , so I am only hovering the classnames that have the same j
this solution works for the case one, but doesnt work for both cases.
I have also tried this :
_style.innerHTML = ".class-open" + j + ":hover{ background-color: cyan; } .class-open-" + j + ":hover .class-close-" + j + " { background-color: cyan; }
But this changes the background-color, and doesn't only hover.
I only need css or javascript to solve this, any suggestions?
I am looking for a solution that works for BOTH cases.

You're going to need to use JavaScript mouseover or jQuery .hover(). This shows mouseover from the MDN.
myElement.addEventListener("mouseover", (event) => {
// do something to the other element.
}

Try this friend:
div#one
{
background-color:red;
}
div#one:hover ~ div#two
{
background-color:yellow;
}
<div id="one">
ONEE
</div>
<div>
SIMPLE DIV
</div>
<div>
SIMPLE DIV
</div>
<div>
SIMPLE DIV
</div>
<div>
SIMPLE DIV
</div>
<div>
SIMPLE DIV
</div>
<div id="two">
two
</div>

if (/\bclass-/.test(target.className)) {
var _style = document.createElement('style');
var j = target.className.match(/\d+$/)[0];
target.style.backgroundColor = "red";
_style.innerHTML = ".class-close-" + j + " { background-color: red; }";
setTimeout(function () {
target.style.backgroundColor = "";
_style.innerHTML = '.class-close-' + j + ' { background-color: ""; }';
}, 500);
document.head.appendChild(_style);
}
Here is the solution I made, but still looking for the "good effect" of Hover instead of just deleting the style after the 500ms..
Hope this helps someone.

If you can control the template code [which I believe we do in most cases], then if one element is inside other element, it can be solved just using css.
Else, if they have different parent, JS would be the direction which people have already suggested.

Related

How to set an attribute as percentage in jQuery?

I am unable to set css attribute {left: $numberEquivalentToPercent} in jQuery
var targets = $('.parallax__layer__cell');
var i = 1;
for(i = 1; i <= targets.length; i++)
{
if (targets.parents('.parallax__layer--bg').length) {
//apply to only those element that have a parent having class "parallax__layer--bg"
targets.eq(i).css('left', toString(60*i)+ "%");
}
}
The above code(in JS) is expected to produce the same effect as below(in CSS)
.parallax__layer__cell:nth-child(1) { left: 0%; }
.parallax__layer__cell:nth-child(2) { left: 60%; }
.parallax__layer__cell:nth-child(3) { left: 120%; }
.parallax__layer__cell:nth-child(4) { left: 180%; }
.parallax__layer__cell:nth-child(5) { left: 240%; }
Basically I am trying to convert a static code to dynamic code
What if you put 60 * i into a variable called numPercent and then do numPercent.toString() to convert it to a string?
var targets = $('.parallax__layer__cell');
var i = 1;
for(i = 1; i <= targets.length; i++)
{
if (targets.parents('.parallax__layer--bg').length) {
//apply to only those element that have a parent having class "parallax__layer--bg"
var numPercent = 60*i;
targets.eq(i).css('left', numPercent.toString() + "%");
}
}
Here is working code:
var targets = $('.parallax__layer__cell');
var i ;
for(i = 0; i < targets.length; i++)
{
if (targets.eq(i).parents('div.parallax__layer--bg').length) {
targets.eq(i).css('left', 60*i + "%");
}
}
.parallax__layer__cell{
position:absolute;
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<div class="wrap">
<div class="parallax__layer--bg">
<div class="parallax__layer__cell">a</div>
</div>
<div class="parallax__layer--bg">
<div class="parallax__layer__cell">b</div>
</div>
<div class="parallax__layer--bg">
<div class="parallax__layer__cell">c</div>
</div>
<div class="parallax__layer--bg">
<div class="parallax__layer__cell">d</div>
</div>
<div class="parallax__layer--bg">
<div class="parallax__layer__cell">e</div>
</div>
<div>
<div class="parallax__layer__cell">--no parent--</div>
</div>
</div>
I believe this is a timing issue between parallax script and your script. Since css loads first parallax script works fine. But if you remove css and run your script after parallax script it may not do the same effect. Make sure your script runs before actual parallax script.

How to change an HTML class with JavaScript using getElementsByClassName [duplicate]

This question already has answers here:
How to add/remove a class in JavaScript?
(13 answers)
Closed 5 years ago.
How to change a class with Javascript using getElementsByClassName. I got it to work a little but it won't change the class one at the time bet only do it one time to.
I click the button to change css class it do it on all the div and I can do it more in one time.
Here is my Code
function Button_Color(Show_This) {
var x = document.getElementById("Color_box");
var i;
var Show_This;
if (Show_This == 1)
{
var d = document.getElementsByClassName("id_blue");
d[0].className = "hid";
var o = document.getElementsByClassName("id_red");
o[0].className = " uhid";
}
if (Show_This == 2) {
var d = document.getElementsByClassName("id_blue");
d[0].className = "hid";
var o = document.getElementsByClassName("id_red");
o[0].className = " uhid";
}
}
Here is a like to show you how it looks now with html css js
https://jsfiddle.net/ee51o5h5/1/
I want it to show red only when you click the little red one and blue only when you click the little blue one.
i am dyslexic and from a non-english speaking country so sorry for any miss up.
i try this :
<body>
<section class="section-button-box">
<div class="box-button box-color01" onClick="Button_Color(1);">
</div>
<div class="box-button box-color02" onClick="Button_Color(2);">
</div>
</section>
<section class="section-color-box" id="Color_box">
<div class="main-color id_blue">
<div class="box-size box-color01">
</div>
</div>
<div class="main-color id_red">
<div class="box-size box-color02">
</div>
</div>
<div class="main-color id_blue">
<div class="box-size box-color01">
</div>
</div>
<div class="main-color id_red">
<div class="box-size box-color02">
</div>
</div>
</section>
</body>
JS:
/*| Blue box |*/
function Button_Color(Show_This) {
var x = document.getElementById("Color_box");
var i;
var Show_This;
var list = document.getElementsByClassName("main-color");
for(var i = 0 ; i < list.length; i ++ ){
if (Show_This == 1)
{
console.log(list[i].classList.contains("id_blue"));
if(list[i].classList.contains("id_blue")){
list[i].classList.add("uhid");
list[i].classList.remove("hid");
}
if(list[i].classList.contains("id_red")){
list[i].classList.add("hid");
list[i].classList.remove("uhid");
}
}
if (Show_This == 2) {
console.log(list[i].classList.contains("id_blue"));
if(list[i].classList.contains("id_blue")){
list[i].classList.add("hid");
list[i].classList.remove("uhid");
}
if(list[i].classList.contains("id_red")){
list[i].classList.add("uhid");
list[i].classList.remove("hid");
}
}
}
}
and css :
/*| Button Box |*/
.section-button-box{
height:100px;
width:100%;
background-color:aqua;
}
.box-button{
height:50px;
width:50px;
float:left;
}
/*| Color Box |*/
.section-color-box{
height:300px;
background-color:#c1c1c1;
width:100%;
}
.box-size{
height:100px;
width:100px;
float:left;
}
.box-color01{
background-color:blue;
}
.box-color02{
background-color:red;
}
.hid , .hid .box-size {
height:0px;
width:0px;
}
.uhid{
height:100px;
width:100px;
}
i add something to your code . Hope to sovle your issue.
you just need to find all elements in the desired class, iterate them and change their classes to the class that makes their color:
if (Show_This == 1)
{
document.getElementsByClassName("box-color02").forEach(function(element){
element.className = "box-size box-color01";});
}
if (Show_This == 2)
{
document.getElementsByClassName("box-color01").forEach(function(element){
element.className = "box-size box-color02";});
}

Insert div on next line when element is clicked

I am trying to make something similar to what you find in google images. When a picture is clicked, a div with the image appears on the next line over the other images that is under the clicked one.
I have a set of divs with float:left and position:relative. They have different widths. When i click on a div i want a new full width div to appear on the next line. The divs under the clicked one should be bushed down under the full width one.
I tried to do this by looping through the divs and compare the position of the divs to the clicked one like this:
$(".Wrapper").on("click", ".testDivs", function () {
var thisTop = $(this).position().top;
$(".testDivs").each(function(i, obj) {
var otherTop = $(obj).position().top;
if(thisTop < otherTop){
$(".fullWidthDiv").insertBefore(obj);
return;
}
});
});
This doesn't work and I don't really know how I should do this. Any tips/solutions?
This requires a lot of information to explain. So I'd rather suggest reading a blog post on this topic.Hope this will help you.
https://www.sitepoint.com/recreating-google-images-search-layout-css/
Here is a way to achieve that. It will not keep scroll position but that would be another easy fix.
<div class="wrapper">
<div class="row1 row">
<div class="img1 img"></div>
<div class="img2 img"></div>
<div class="img3 img"></div>
</div>
<div class="row2 row">
<div class="img1 img"></div>
<div class="img2 img"></div>
<div class="img3 img"></div>
</div>
<div class="row3 row">
<div class="img1 img"></div>
<div class="img2 img"></div>
<div class="img3 img"></div>
</div>
</div>
I only applied some styling ti increase visibility of the changes.
.img {
width: 32%;
height: 100px;
background-color: #ccc;
display: inline-block;
}
.row {
border: 1px solid green
}
.big-img {
height: 300px;
}
And finally the JS:
$('.img').click(function() {
var expandedImg = '<div class="big-img"></div>';
$('.big-img').remove();
$(this).parent().append(expandedImg);
})
Fiddle: https://jsfiddle.net/a5fm2dup/
why don't you just do
$(".Wrapper").on("click", ".testDivs", function () {
$(this).after($(".fullWidthDiv"));
});
Ended up making a solution based on my initial code. This doesn't require all the CSS the other solution that was postet suggested. Adding rows dynamically was also suggested, but this became very complicated when making it responsive to window resizing. Feel free to reply if you have any comments on this
function positionDiv() {
var checker = false;
var n;
var thisTop = clickedElement.position().top;
$(".testDivs").each(function(i, obj) {
var otherTop = $(obj).position().top;
if(thisTop < otherTop){
$(".testDivs:eq(" + (i-1) + ")").after($(".fullWidthDiv"));
checker = true;
return false;
}
n = i;
});
if (!checker) {
$(".testDivs:eq(" + n + ")").after($(".fullWidthDiv"));
}
}
var clickChecker = null;
$(".wrapper").on("click", ".testDivs", function () {
if (clickChecker === this){
$(".fullWidthDiv").hide();
clickChecker = null;
} else {
$(".fullWidthDiv").show();
clickChecker = this;
}
clickedElement = $(this);
positionDiv();
});
window.onresize = function(event) {
if( clickedElement != null) {
$(".tagTextWrapper").hide();
positionDiv();
$(".tagTextWrapper").show();
}
}

Read and print the CSS values of a class with pure Javascript

I am trying to create a function, which:
Grabs an element with a specific data element, i.e. "data-findDeclaration = element"
From this element, the class is read
It reads out all the css values appointed to this class
Displays inside another specific data element (i.e. data-writeDeclaration="element") all the classes' rules/values.
Here's where I am so far:
HTML:
<span class="slap0" data-finddeclaration="element">The great white fox</span>
<div class="description" data-writedeclaration="element">
</div>
<span class="slap1" data-finddeclaration="element">The great white fox</span>
<div class="description" data-writedeclaration="element">
</div>
<span class="slap2" data-finddeclaration="element">The great white fox</span>
<div class="description" data-writedeclaration="element">
</div>
<span class="slap3" data-finddeclaration="element">The great white fox</span>
<div class="description" data-writedeclaration="element">
</div>
JS:
function readOutCssRules() {
var dataElement = document.querySelectorAll('[data-finddeclaration="element"]');
var classRules = document.styleSheets[0].rules || document.styleSheets[0].cssRules;
var writeDataElement = document.querySelectorAll('[data-writedeclaration="element"]');
for (var i = 0; i < dataElement.length; i++) {
dataElement[i].className;
if (classRules[i].selectorText == "." + dataElement[i].className) {
console.log(classRules[i].cssText);
writeDataElement[i].innerHTML = classRules[i].cssText;
}
}
}
readOutCssRules();
But the function is not working as expected.
Any ideas?
Thanks in advance.
Your code is working.
You just have to remove one line in the for loop:
for (var i = 0; i < dataElement.length; i++) {
//dataElement[i].className; --> remove this
if (classRules[i].selectorText == "." + dataElement[i].className) {
console.log(classRules[i].cssText);
writeDataElement[i].innerHTML = classRules[i].cssText;
}
}
After that changes it will work, as you can see in this fiddle.
Check this
https://jsfiddle.net/g6tu77mg/1/
var element = classRules[i].cssText
var css= element.substring(element.lastIndexOf("{")+1,element.lastIndexOf("}"));
writeDataElement[i].innerHTML = css;
Output:
The great white fox
color: blue;
The great white fox
color: red;
The great white fox
color: yellow;

JavaScript - Expand/Collapsing Issue While Using Multiple Classes

There a lot of similar questions and I've looked at a lot of them, but couldn't figure out or find one that addressed this problem.
The issue is I'm trying to apply event listeners to a particular class (success for the most part), and each of those classes have their own elements with a separate class.
group.addEventListener("click", toggle, false);
group is a class which will have the click event.
function toggle() {
var contents = this.getElementsByClassName('content');
for (i = 0; i < contents.length; i++) {
if (contents[i].style.display == "block") {
contents[i].style.display = "none";
}
else {
contents[i].style.display = "block";
}
}
}
contents is another class nested within group. There will be a lot of contents, but only a handful of group.
Using .addEventListener works, but the click event for it expands/collapses every contents, not just the ones under that particular group which is what I want. I click on any one of the group and all of the contents on the page will expand/collapse. How can I fix this? By the way, these are just snippets of the code (it's a lot to post). I tried to use this to provide scope, but I'm just doing it wrong since it's producing the same results anyway. Thank you in advance.
Edit:
More about the HTML
group.innerHTML += String.format("<div class='group' style='display: block;'>" +
"<h3 style='display: inline-block; color: #000; margin: 0px; padding: 0px;'>{0}</h3>" +
"<img src='https:\/\/my.blah.com\/_layouts\/15\/images\/ecbarw.png' style='margin: 5px;' alt='Click to expand-collapse.' />" +
"{1}</div>", trimmedKey, groups[key]);
group.addEventListener("click", toggle, false);
I'm using this for a SharePoint web part. It's within display templates so that's why there's a lot of unrelated code to post, but I'll include the relevant HTML for group and contents.
var content = String.format('<div class="content" style="display: none; margin: 30px 0px;"><span id="{0}" class="ms-srch-item-title">' +
'<h3 class="ms-srch-ellipsis">{1}</h3>' +
'</span>' +
'<span style="margin-right: 10px;"><span style="font-weight:bold;">Assigned To: </span>{2}</span>' +
'<span style="margin-right: 10px;"><span style="font-weight:bold;">Due Date: </span>{3}</span>' +
'<span style="margin-right: 10px;"><span style="font-weight:bold;">Task Status: </span>{4}</span></div>', $htmlEncode(id + Srch.U.Ids.title), titleHtml, assignedTo, dueDate, status);
search.Grouping.push(grouping, content);
The content is getting pushed to a function (not shown here) that sorts them into groups. The groups[key] is basically the same thing as content.
I am not sure why it is not working in your case but I have prepared a simple demo for you here:
// get all the elements with class 'group'
var groups = document.getElementsByClassName('group');
// add click event listener to each group
for (var i = 0; i < groups.length; i ++)
groups[i].addEventListener("click", toggle, false);
// function to toggle group contents
function toggle() {
// get all the elements within this group with class 'content'
var contents = this.getElementsByClassName('content');
// if the content is visible then hide it and vice-versa
for (i = 0; i < contents.length; i++) {
if (contents[i].style.display == "block") {
contents[i].style.display = "none";
}
else {
contents[i].style.display = "block";
}
}
}
.content {
display: None;
padding-left: 10px;
}
.group {
margin-top: 10px;
}
<div class="group">
Group1
<div class="content another">
Group 1 Content 1
</div>
<div class="content another">
Group 1 Content 2
</div>
</div>
<div class="group">
Group2
<div class="content another">
Group 2 Content 1
</div>
<div class="content another">
Group 2 Content 2
</div>
</div>

Categories